The steps below use Flutter's WebView to create a mobile app from an existing web application.
1. System requirements
Flutter depends on one of these tools being available in your OS environment.
- Windows PowerShell 5.0 or newer (this is pre-installed with Windows 10) – https://docs.microsoft.com/en-us/powershell/scripting/install/installing-windows-powershell
- or Git for Windows 2.x – https://git-scm.com/download/win
2. Install Flutter
1. Download flutter here: https://flutter.dev/docs/get-started/install
2. Extract the zip file and place the contained flutter directory iton the desired installation location for the Flutter SDK (for example, C:\flutter
– do not install Flutter in a directory like C:\Program Files\
that requires elevated privileges).
3. Add Flutter to the PATH environment variable:
From the Start search bar, enter env
and select Edit environment variables for your account
. Under User variables
check if there is an entry called Path
:
- If the entry exists, append (add to the end) the full path to flutter\bin using
;
as a separator from existing values (for example,C:\flutter\flutter\bin
). - If the entry doesn’t exist, create a new user variable named
Path
with the full path to flutter\bin as its value.
Important: Note that you have to close and reopen any existing console windows for these changes to take effect.
3. Set up an editor
Android Studio System Requirements (Windows)
- 64-bit Microsoft® Windows® 8/10
- x86_64 CPU architecture; 2nd generation Intel Core or newer, or AMD CPU with support for a Windows Hypervisor
- 8 GB RAM or more
- 8 GB of available disk space minimum (IDE + Android SDK + Android Emulator)
- 1280 x 800 minimum screen resolution
Android Studio System Requirements (Linux)
- Any 64-bit Linux distribution that supports Gnome, KDE, or Unity DE; GNU C Library (glibc) 2.31 or later.
- x86_64 CPU architecture; 2nd generation Intel Core or newer, or AMD processor with support for AMD Virtualization (AMD-V) and SSSE3
- 8 GB RAM or more
- 8 GB of available disk space minimum (IDE + Android SDK + Android Emulator)
- 1280 x 800 minimum screen resolution
1. To install Android Studio (recommended), go here: https://developer.android.com/studio
Alternatively, you can install Visual Studio Code here: https://code.visualstudio.com/download
In Android Studio, install the Flutter and Dart plugins for Linux or Windows:
a. Open plugin preferences (File > Settings > Plugins
).
b. Select Marketplace, select the Flutter plugin and click Install.
c. Select the Dart plugin and click Install.
2. Run Flutter Doctor
From a console window that has the Flutter directory in the path (see above), run the following command to see if there are any platform dependencies you need to complete the setup:
$ cd C:\flutter
$ flutter doctor
You should see output similar to (the output below assumes that you installed Android Studio and VS Code):
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.5.3, on Microsoft Windows [Version 6.3.9600], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[√] Chrome - develop for the web
[√] Android Studio (version 2020.3)
[√] VS Code (version 1.61.2)
[√] Connected device (1 available)
• No issues found!
You should see output with No issues found!
:
If there are any issues, go here: https://flutter.dev/docs/get-started/install/windows
4. Create the mobile app in Android Studio
1. Open Android Studio and select New Flutter Project
.
2. Verify the Flutter SDK path is set to the correct directory you set up when installing Flutter (ex: C:\flutte\flutter
) and click Next
3. Enter the Project name and Project location (defaults to ...\AndroidStudioProjects\projectname
). The Project type should be set to Application
and fill in the Organization field (ex com.yourdomain). You can leave the defaults for the other settings (Android language is set to Kotlin and Platforms are set to Android and iOS). Click Finish.
Note: When creating a new Flutter app, Android Studio asks for a company domain name in reverse order, something like com.example. The company domain name and project name are used together as the package name for Android (the Bundle ID for iOS) when the app is released. If you think that the app might be released, it’s better to specify the package name now. The package name can’t be changed once the app is released, so make the name unique.
5. Adding WebView for Flutter
1. Open the pubspec.yaml
file (double-click) located in the project root. Under dependencies > flutter
, add the webview_flutter
line of code like below (pay attention to the formatting):
dependencies:
flutter:
sdk: flutter
webview_flutter: ^2.3.0
Then, click Pub get
located at the upper right hand side of the screen.
2. Open main.dart
located at lib > main.dart
and replace all the code with the code below. Modify the following lines:
- title: ‘Flutter Demo', (line 15)
- title: Text(‘Top Navigation Text'), (line 58)
- initialUrl: ‘https://yourdomain.com‘, (line 61) (This is the URL of your existing web app/website)
- The colors within
colorScheme: ColorScheme(... ...)
starting on line 27. See color availability here: https://material.io/design/color/the-color-system.html#tools-for-picking-colors
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:io';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
colorScheme: ColorScheme(
brightness: Brightness.light,
surface: Colors.white,
onSurface: Colors.blue,
// Colors that are not relevant to AppBar in DARK mode:
primary: Colors.blue,
onPrimary: Colors.white,
primaryVariant: Colors.grey,
secondary: Colors.grey,
secondaryVariant: Colors.grey,
onSecondary: Colors.grey,
background: Colors.grey,
onBackground: Colors.grey,
error: Colors.grey,
onError: Colors.grey,
),
),
home: Body(),
);
}
}
class Body extends StatefulWidget {
@override
_BodyState createState() => _BodyState();
}
class _BodyState extends State<Body> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Top Navigation Text'),
),
body: WebView(
initialUrl: 'https://yourdomain.com',
javascriptMode: JavascriptMode.unrestricted,
),
);
}
}
3. Add the code below to the bottom of AndroidManifest.xml
located at android > app > src > main > AndroidManifest.xml
– After </application> and before the last line </manifest>:
...
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
4. Modify the minSdkVersion (WebView requires an Android SKD version of at least 19). Open build.gradle
located at android > app > build.gradle
, scroll down to the defaulConfig
section and change the minSdkVersion to 19 (line 47)
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.yourdomain.yourdomain"
minSdkVersion 19
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
6. Run the app
On the Android Studio toolbar, select an Android device for running the app in the Target selector (https://flutter.dev/docs/get-started/test-drive). To create and manage virtual devices, see https://developer.android.com/studio/run/managing-avds. Make sure that main.dart
is displayed in the Config selector, and click the run icon (or menu itme Run > Run
.
Once the Android simulator pops up you should see the URL of the web app/website you configured above. When I first tried to find a simple way to do this I came across a constant stream of errors in Android Studio that I had to find solutions too. Once Android Studio and especially gradle were set correctly, the code ran smoothly. So good luck and see the bottom of this page for some errors and solutions.
To build a test apk to view on your mobile device, from the menu select Build > Flutter > Build APK
. When complete, the APK will be located in your project folder inside build > app > outputs > flutter-apk
.
7. Add a splash screen
1. Open the pubspec.yaml
file located in the project root.
2. Under dependencies > flutter
, add the flutter_native_splash
line of code like below (pay attention to the formatting):
dependencies:
flutter:
sdk: flutter
webview_flutter: ^2.3.0
flutter_native_splash: ^1.3.1
3. Next, inside the same pubspec.yaml
file, add this code to the bottom:
...
flutter_native_splash:
# color or background_image is the only required parameter. Use color to set the background
# of your splash screen to a solid color. Use background_image to set the background of your
# splash screen to a png image. This is useful for gradients. The image will be stretch to the
# size of the app. Only one parameter can be used, color and background_image cannot both be set.
color: "#1e73be"
#background_image: "assets/background.png"
# Optional parameters are listed below. To enable a parameter, uncomment the line by removing
# the leading # character.
# The image parameter allows you to specify an image used in the splash screen. It must be a
# png file and should be sized for 4x pixel density.
image: assets/splash.png
# The color_dark, background_image_dark, and image_dark are parameters that set the background
# and image when the device is in dark mode. If they are not specified, the app will use the
# parameters from above. If the image_dark parameter is specified, color_dark or
# background_image_dark must be specified. color_dark and background_image_dark cannot both be
# set.
#color_dark: "#042a49"
#background_image_dark: "assets/dark-background.png"
#image_dark: assets/splash-invert.png
To customize the splash screen, see the comments located in the code. I found that a splash screen image is best displayed when using the image
parameter rather than the background_image
parameter as it fits the image to the screen better. This also means that you can use both the background color
parameter and the image
parameter. Note that when using a splash screen image, you must create a folder in the root of the project named assets
and place the image(s) (.png) in it.
After adding your settings, run the following commands in the Android Studio terminal (located at the bottom left hand corner):
flutter pub get
flutter pub run flutter_native_splash:create
When the package finishes running, your splash screen is ready.
Note: The splash screen may not appear when you launch the app from Android Studio in the simulator. However, it should appear when you launch by clicking on the launch icon in your Android device. For more info and a recommendation on why and how to add a secondary splash screen, see https://pub.dev/packages/flutter_native_splash.
8. Changing the app's launcher icon
1. Open the pubspec.yaml
file and add the code after the code you already added:
...
dependencies:
flutter:
sdk: flutter
webview_flutter: ^2.3.0
flutter_native_splash: ^1.3.1
flutter_launcher_icons: "^0.9.2"
flutter_icons:
android: "launcher_icon"
ios: true
image_path: "assets/icon/icon.png"
...
2. Create a directory named icon
and add an image (a .png with a recommended size of 1024×1024)
3. Run the commands below in the Android Studio terminal:
flutter pub get
flutter pub run flutter_launcher_icons:main
In the above configuration, the package is setup to replace the existing launcher icons in both the Android and iOS project with the icon located in the image path specified above and given the name “launcher_icon” in the Android project and “Example-Icon” in the iOS project. For more attribues that can be configured, see https://pub.dev/packages/flutter_launcher_icons.
9. Deploying the app
1. Create an upload keystore. Modify the location where the upload-keystore.jks
file will be created.
Run the following command (substituting yourkeystorename
for whatever name you want):
keytool -genkey -v -keystore yourkeystorename.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
When prompted, enter a keystore, key password and other information requested. This command stores the .jks file in your home directory (c:\Users\USER_NAME\). Copy this .jks file to your project folder inside /android/app/
. Keep the keystore file private; don’t check it into public source control!
If you get the following output bash: keytool: command not found
when trying to run the command above then the keytool command might not be in your path -it’s part of Java, which is installed as part of Android Studio. To get the path, run flutter doctor -v
from the command line and locate the path printed after Java binary at:
(example, Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
).
Next, from the Start search bar, enter env
and select Edit the system environment variables
. Then click Environmental Variables
at the bottom of the prompt. Under System variables
, locate the Variable Path
and click Edit
. Append the full path to the Java binary we found above using ;
as a separator from existing values without \java
at the end (example, ;C:\Program Files\Android\Android Studio\jre\bin
).
Close and reopen any existing console windows for these changes to take effect and the rerun the keytool command from above.
2. Create a file inside the android
directory of your project folder named key.properties
that contains a reference to your keystore. Add the code below filling in the necessary information (leave keyAlias=upload as it is):
storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=upload
storeFile=yourkeystorename.jks
Warning: Keep the key.properties
file private; don’t check it into public source control.
3. Configure gradle to use your upload key when building your app in release mode by editing the /android/app/build.gradle
file.
Add the keystore information from your properties file before the android block:
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
4. Find the buildTypes block:
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now,
// so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
and replace with:
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
5. Reviewing the app manifest
Review the default App Manifest file, AndroidManifest.xml
, located in /android/app/src/main
and verify that the values are correct, especially the following:
application
Edit the android:label
in the application tag to reflect the final name of the app.
6. Reviewing the build configuration
Review the default Gradle build file, build.gradle, located in /android/app
and verify the values are correct, especially the following values in the defaultConfig block:
applicationId
Specify the final, unique (Application Id) appid
versionCode & versionName
Specify the internal app version number, and the version number display string. You can do this by setting the version property in the pubspec.yaml
file.
7. Building the app for release
You have two possible release formats when publishing to the Play Store.
- App bundle (The Google Play Store prefers the app bundle format)
- APK
From the Android Studio menu, select Build > Flutter > Build App Bundle
or from the command line, change into your project folder and build:
cd yourprojectfolder
flutter build appbundle
(Running flutter build defaults to a release build.)
The release bundle for your app is created at /build/app/outputs/bundle/release/app-release.aab
.
By default, the app bundle contains your Dart code and the Flutter runtime compiled for armeabi-v7a (ARM 32-bit), arm64-v8a (ARM 64-bit), and x86-64 (x86 64-bit)
To build the APK (where you quickly download and test on your mobile device), from the Android Studio menu select Build > Flutter > Build APK
. The APK for your app is created at /build/app/outputs/flutter-apk/app-release.apk
.
8. Test the app bundle
An app bundle can be tested in multiple ways – this section describes two.
A. Offline using the bundle tool
- Download bundletool from the GitHub repository.
- Generate a set of APKs from your app bundle.
- Deploy the APKs to connected devices.
B. Online using Google Play
- Upload your bundle to Google Play to test it. You can use the internal test track, or the alpha or beta channels to test the bundle before releasing it in production.
- Follow these steps to upload your bundle to the Play Store
IMPORTANT: When you upload the app bundle to Google Play, you may see the error:
Warning
This App Bundle contains native code, and you've not uploaded debug symbols. We recommend you upload a symbol file to make your crashes and ANRs easier to analyze and debug.
1. Install the NDK and CMake in Android Studio:
- With a project open, click
Tools > SDK Manager
. - Click the
SDK Tools
tab. - Select the NDK (Side by side) and CMake checkboxes and click OK.
2. Once they both are installed, open the file build.gradle
(android/app/build.gradle) and add this line to the bottom:
...
android.buildTypes.release.ndk.debugSymbolLevel = 'FULL'
3. Open the file local.properties
and add the path to NDK – making sure to verify the ndk version (substitute USER_NAME
in both sdk.dir and ndk.dir as necessary):
sdk.dir=C:\\Users\\USER_NAME\\AppData\\Local\\Android\\sdk
flutter.sdk=C:\\flutter\\flutter
flutter.buildMode=release
flutter.versionName=1.0.0
flutter.versionCode=1
ndk.dir=C:\\Users\\USER_NAME\\AppData\\Local\\Android\\sdk\\ndk\\23.1.7779620
Now build and upload the app bundle again and the error message is gone.
REFERENCES
https://flutter.dev/docs/get-started/install/windows
https://flutter.dev/docs/get-started/install
https://flutter.dev/docs/get-started/editor
https://flutter.dev/docs/get-started/test-drive
https://pub.dev/packages/webview_flutter/
https://pub.dev/documentation/webview_flutter/latest/webview_flutter/WebView-class.html
https://developer.android.com/studio
https://developer.android.com/guide/webapps
https://developer.android.com/reference/android/webkit/WebView
https://blog.logrocket.com/render-webpages-using-flutter-webview/
https://github.com/flutter-prjs/webviewprj
https://stackoverflow.com/questions/51740339/how-can-we-change-appbar-background-color-in-flutter
https://pub.dev/packages/flutter_native_splash
https://stackoverflow.com/questions/43879103/adding-a-splash-screen-to-flutter-apps
https://pub.dev/packages/flutter_launcher_icons
https://github.com/fluttercommunity/flutter_launcher_icons
https://flutter.dev/docs/deployment/android
https://developer.android.com/studio/publish/app-signing#sign-apk
https://codewithandrea.com/articles/keytool-command-not-found-how-to-fix-windows-macos/
https://developer.android.com/studio/build/shrink-code#native-crash-support
https://github.com/flutter/flutter/issues/60240
https://stackoverflow.com/questions/62568757/playstore-error-app-bundle-contains-native-code-and-youve-not-uploaded-debug
https://stackoverflow.com/questions/63373245/how-to-add-debug-symbols-to-build-gradle/63436935#63436935
https://developer.android.com/studio/projects/install-ndk
Some kind of not supported type of webview flutter in windows error is giving
Good day,
Can you help me with the following errors
I don’t know what they mean or how to correct them.
The named parameter ‘primaryVariant’ isn’t defined.
The named parameter ‘secondaryVariant’ isn’t defined.
The constructor being called isn’t a const constructor.
Thank you in advance for your help.
Kind regards