Solving Common Cross-Platform Issues When Working With Flutter
Updated: Jun 28
When mistreatment cross-platform frameworks, folks may forget the nuances of every of the platforms they need their code to run on. This text aims to handle that.
Specifically, people sometimes confuse it with the older Web-based mobile (and desktop) cross-platform frameworks, which basically were just Web pages running within browsers running within a wrapper app.
That was truly cross-platform in the sense that the interfaces were the same anyway because you only had access to the interfaces normally accessible on the Web.
Flutter isn’t that, though: it runs natively on each platform, and it means each app runs just like it would run if it were written in Java/Kotlin or Objective-C/Swift on Android and iOS, pretty much. You need to know that because this implies that you need to take care of the many differences between these very diverse platforms.
Example 1: Storage
I recently wrote on my diary concerning the necessity for a special approach to storing JWTs in net apps compared to mobile apps. That is due to the various nature of the platforms’ storage choices, and therefore the got to recognize every and their native development tools.
When you write a Web app, the storage options you have are:
1. Downloading/uploading files to/from disk, which requires user interaction and is therefore only suitable for files meant to be read or created by the user.
2. Using cookies, which may or may not be accessible from JS (depending on whether or not they’re httpOnly) and are automatically sent along with requests to a given domain and saved when they come as part of a response.
3. Using JS localStorage and sessionStorage, accessible by any JS on the website, but only from JS that is part of the pages of that website.
The situation when it comes to mobile apps is completely different. The storage options are the following:
1. Local app documents or cache storage, accessible by that app.
2. Other local storage paths for user-created/readable files.
3. NSUserDefaults and SharedPreferences respectively on iOS and Android for key-value storage.
4. Keychain on iOS and KeyStore on Android for secure storage of, respectively, any data and cryptographic keys.
If you don’t recognize that, you’re getting to build a multitude of your implementations as a result of you would like to understand what storage answer you’re truly exploitation and what the benefits and downsides area unit.
CROSS-PLATFORM SOLUTIONS: AN INITIAL APPROACH
Using the Flutter shared_preferences package uses localStorage on the Web, SharedPreferences on Android and NSUserDefaults on iOS. Those have utterly completely different implications for your app, particularly if you’re storing sensitive info like session tokens: localStorage are often scan by the shopper, thus it’s a tangle if you’re prone to XSS. although mobile apps aren’t very prone to XSS, SharedPreferences and NSUserDefaults don't seem to be secure storage ways as a result of they will be compromised on the shopper facet since they're not secure storage and not encrypted.
That’s as a result of they're meant for user preferences, as mentioned here within the case of iOS and here within the robot documentation once talking concerning the protection library that is meant to produce wrappers to the SharedPreferences specifically to inscribe the info before storing it.
SECURE STORAGE ON MOBILE
The only secure storage solutions on mobile are Keychain and KeyStore on iOS and Android respectively, whereas there is no secure storage on the Web. The Keychain and KeyStore area unit terribly completely different in nature, though: Keychain could be a generic credentials storage resolution, whereas the KeyStore is employed to store (and will generate) science keys, either stellate keys or public/private keys.
This means that if, for example, you would like to store a session token, on iOS you'll be able to let the OS manage the coding half and simply send your token to the Keychain, whereas on humanoid it’s a small amount a lot of of a manual expertise as a result of you would like to get (not hard-code, that’s bad) a key, use it to cypher the token, store the encrypted token in SharedPreferences and store the key within the KeyStore.
There area unit completely different approaches to it, as area unit most things in security, however the only is perhaps to use stellate coding, as there's no want for public key cryptography since your app each encrypts and decrypts the token. Obviously, you don’t have to be compelled to write mobile platform-specific code that will all of that, as there is a Flutter plugin that does all of that, for instance.
THE LACK OF SECURE STORAGE ON THE WEB
That was, actually, the rationale that compelled ME to put in writing this post. I wrote regarding exploitation that package to store JWT on mobile apps and other people wished the net version of that however, as I said, there's no secure storage on the net. It doesn’t exist. Does that mean your JWT must be get in the open? No, not at all. you'll be able to use httpOnly cookies, can’t you?
Those area unitn’t accessible by JS and are sent solely to your server. the problem thereupon is that they’re continuously sent to your server, notwithstanding one amongst your users clicks on a GET request address on somebody else’s web site which GET request has aspect effects you or your user won’t like. This really works for different request varieties moreover, it’s simply a lot of sophisticated. It’s referred to as Cross-Site Request Forgery and you don’t wish that.
It’s among the net security threats mentioned in Mozilla’s MDN docs, wherever you'll be able to notice a a lot of complete rationalization. There area unit interference strategies. the foremost common one has 2 tokens, actually: one amongst them aiming to the shopper as Associate in Nursing httpOnly cookie, the opposite as a part of the response.
The latter must be hold on in localStorage and not in cookies as a result of we have a tendency to don’t wish it to be sent mechanically to the server.
What if you have both a mobile app and a Web app?
That can be dealt with in one of two ways:
1. Use the same backend endpoint, but manually get and send the cookies using the cookie-related HTTP headers;
2. Create a separate non-Web backend endpoint that generates different token than either token used by the Web app and then allow for regular JWT authorization if the client is able to provide the mobile-only token.
Running Different Code On Different Platforms
Now, let’s see how we can run different code on different platforms in order to be able to compensate for the differences.
CREATING A FLUTTER PLUGIN
Especially to unravel the matter of storage, a technique you'll do this is with a plugin package: plugins offer a typical Dart interface and might run totally different code on different platforms, together with native platform-specific Kotlin/Java or Swift/Objective-C code. Developing packages and plugins is quite complicated, however it’s explained in several places on the net et al. (for example in Flutter books), together with the official Flutter documentation.
For mobile platforms, for example, there already may be a secure storage plugin, and that’s flutter_secure_storage, that you'll notice associate example of usage here, however that doesn’t work on the net, as an example.
On the opposite hand, for easy key-value storage that additionally works on the net, there’s a cross-platform Google-developed first-party plugin package known as shared_preferences, that incorporates a Web-specific part known as shared_preferences_web that uses NSUserDefaults, SharedPreferences or localStorage reckoning on the platform.
TARGETPLATFORM ON FLUTTER
After importing package:flutter/foundation.dart, you can compare Theme.of(context).platform to the values:
and write your functions so that, for each platform you want to support, they do the appropriate thing. This will come especially useful for the next example of platform difference, and that is differences in how widgets are displayed on different platforms.
For that use case, in particular, there is also a reasonably popular flutter_platform_widgets plugin, which simplifies the development of platform-aware widgets.
Example 2: Differences In How The Same Widget Is Displayed
You can’t simply write cross-platform code and fake a browser, a phone, a computer, and a smartwatch area unit a similar factor — unless you wish your humanoid and iOS app to be a WebView and your desktop app to be designed with lepton.
There area unit many reasons to not try this, and it’s not the purpose of this piece to convert you to use frameworks like Flutter instead that keep your app native, with all the performance and user expertise blessings that go with it, whereas permitting you to jot down code that's progressing to be a similar for all platforms most of the time.
That requires care and a focus, though, and a minimum of a basic data of the platforms you wish to support, their actual native genus Apis, and every one of that.
React Native users have to be compelled to pay even additional attention thereto as a result of that framework uses the inherent OS widgets, thus you really have to be compelled to pay even additional attention to however the app appearance by testing it extensively on each platforms, while not having the ability to modify between iOS and Material device on the fly like it’s potential with Flutter..
WHAT CHANGES WITHOUT YOUR REQUEST
There are some aspects of the UI of your app that are automatically changed when you switch platforms. This section also mentions what changes between Flutter and React Native in this respect.
Between Android And iOS (Flutter)
Flutter is capable of rendering Material widgets on iOS (and Cupertino (iOS-like) widgets on Android), however what it DOESN’T do is show precisely the same factor on robot and iOS: Material theming particularly adapts to the conventions of every platform.
For instance, navigation animations and transitions and default fonts area unit completely different, however those don’t impact your app that abundant. What might have an effect on a number of your decisions once it involves aesthetics or wife is that the indisputable fact that some static components conjointly modification.
Specifically, some icons modification between the 2 platforms, app bar titles area unit within the middle on iOS and on the left on robot (on the left of the on the market area just in case there's a back button or the button to open a Drawer (explained here within the Material style pointers and conjointly called a hamburger menu). Here’s what a fabric app with a Drawer feels like on Android:
And what the same, very simple, Material app looks like on iOS:
Between Mobile and Web and With Screen Notches (Flutter)
On the online there's a small amount of a unique state of affairs, as mentioned conjointly during this Smashing article regarding Responsive net Development with Flutter:
specifically, additionally to having to optimize for larger screens and account for the means folks expect to navigate through your web site — that is that the main focus of that article — you have got to stress regarding the very fact that generally widgets square measure placed outside of the browser window.
Also, some phones have notches within the high a part of their screen or different impediments to the proper viewing of your app attributable to some form of obstruction. Both of those issues may be avoided by wrapping your conveniences during a SafeArea widget, that may be a explicit reasonably cushioning convenience that makes certain your widgets comprise an area wherever they will really be displayed empty preventive the users’ ability to envision them, be it a hardware or code constraint.
IN REACT NATIVE
In alternative words, your React Native apps can invariably seem like iOS — with Cupertino UI parts as they're generally known as — and your mechanical man apps can invariably seem like regular Material style mechanical man apps as a result of it’s victimization the platform’s widgets. The distinction here is that Flutter renders its widgets with its own low-level rendering engine, which implies you'll be able to check each app versions on one platform.
Getting Around That Issue
The Other Side: Using The Wrong Widgets For The Right Reasons
But that also means that you can do most of your Flutter development on a Linux or Windows workstation without sacrificing the experience of your iOS users, and then just build the app for the other platform and not have to worry about thoroughly testing it.
Cross-platform frameworks are awesome, but they shift responsibility to you, the developer, to understand how each platform works and how to make sure your app adapts and is pleasant to use for your users. Other small things to consider may be, for example, using different descriptions for what might be in essence the same thing if there are different conventions on different platforms.
It’s great to not have to build the two (or more) apps separately using different languages, but you still need to keep in mind you are, in essence, building more than one app and that requires thinking about each of the apps you are building.
We will be happy to answer your questions on designing, developing, and deploying comprehensive enterprise web, mobile apps and customized software solutions that best fit your organization needs.
As a reputed Software Solutions Developer we have expertise in providing dedicated
remote and outsourced technical resources for software services at very nominal cost. Besides experts in full stacks We also build web solutions, mobile apps and work on system integration, performance enhancement, cloud migrations and big data analytics. Don’t hesitate to get in touch with us!