We are developing PWA application to submit it to Play Store. We used TWA, followed all concepts but somehow we cant manage to hide the URL BAR.
Digital asset links are configured and tested. We have connected website with TWA, we have successfully tested mapping editor, we have added intent filter, association with assetlinks.json was successfully tested
Android Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="eu.clubforceone.mobile">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/appName"
android:supportsRtl="true"
android:theme="#style/Theme.LauncherActivity">
<meta-data
android:name="asset_statements"
android:resource="#string/assetStatements" />
<activity
android:name="android.support.customtabs.trusted.LauncherActivity"
android:label="#string/appName">
<tools:validation testUrl="https://login.clubforce.eu" />
<meta-data
android:name="android.support.customtabs.trusted.DEFAULT_URL"
android:value="#string/launchUrl" />
<meta-data
android:name="android.support.customtabs.trusted.STATUS_BAR_COLOR"
android:resource="#color/colorPrimary" />
<meta-data
android:name="android.support.customtabs.trusted.SPLASH_IMAGE_DRAWABLE"
android:resource="#drawable/splash" />
<meta-data
android:name="android.support.customtabs.trusted.SPLASH_SCREEN_BACKGROUND_COLOR"
android:resource="#color/whiteColor" />
<meta-data
android:name="android.support.customtabs.trusted.SPLASH_SCREEN_FADE_OUT_DURATION"
android:value="300" />
<meta-data
android:name="android.support.customtabs.trusted.FILE_PROVIDER_AUTHORITY"
android:value="#string/providerAuthority" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="login.clubforce.eu" />
</intent-filter>
</activity>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="#string/providerAuthority"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
<service
android:name="android.support.customtabs.trusted.TrustedWebActivityService"
android:enabled="#bool/enableNotification"
android:exported="#bool/enableNotification">
<intent-filter>
<action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>
build.gradle module app
apply plugin: 'com.android.application'
def twaManifest = [
applicationId: 'eu.clubforceone.mobile',
hostName: 'login.clubforce.eu', // The domain being opened in the TWA.
launchUrl: '/', // The start path for the TWA. Must be relative to the domain.
name: 'Clubforce', // The name shown on the Android Launcher.
themeColor: '#283795', // The color used for the status bar.
backgroundColor: '#F6F6F6', // The color used for the splash screen background.
whiteColor: '#FFFFFF', // The color used for the splash screen background.
enableNotifications: false // Set to true to enable notification delegation
]
android {
compileSdkVersion 28
defaultConfig {
applicationId "eu.clubforceone.mobile"
minSdkVersion 16
targetSdkVersion 28
versionCode 20003
versionName '2.2'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// The name for the application on the Android Launcher
resValue "string", "appName", twaManifest.name
// The URL that will be used when launching the TWA from the Android Launcher
resValue "string", "launchUrl", "https://" + twaManifest.hostName + twaManifest.launchUrl
// The hostname is used when building the intent-filter, so the TWA is able to
// handle Intents to open https://svgomg.firebaseapp.com.
resValue "string", "hostName", twaManifest.hostName
// This variable below expresses the relationship between the app and the site,
// as documented in the TWA documentation at
// https://developers.google.com/web/updates/2017/10/using-twa#set_up_digital_asset_links_in_an_android_app
// and is injected into the AndroidManifest.xml
resValue "string", "assetStatements",
'[{ \\"relation\\": [\\"delegate_permission/common.handle_all_urls\\"],' +
'\\"target\\": {\\"namespace\\": \\"web\\", \\"site\\": \\"https://' +
twaManifest.hostName + '\\"}}]'
// This attribute sets the status bar color for the TWA. It can be either set here or in
// `res/values/colors.xml`. Setting in both places is an error and the app will not
// compile. If not set, the status bar color defaults to #FFFFFF - white.
resValue "color", "colorPrimary", twaManifest.themeColor
// Sets the color for the background used for the splash screen when launching the
// Trusted Web Activity.
resValue "color", "backgroundColor", twaManifest.backgroundColor
// used only for specific situation where white color is needed
resValue "color", "whiteColor", twaManifest.whiteColor
// Defines a provider authority fot the Splash Screen
resValue "string", "providerAuthority", twaManifest.applicationId + '.fileprovider'
// The enableNotification resource is used to enable or disable the
// TrustedWebActivityService, by changing the android:enabled and android:exported
// attributes
resValue "bool", "enableNotification", twaManifest.enableNotifications.toString()
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
productFlavors {
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.github.GoogleChrome.custom-tabs-client:customtabs:91b4a1270b511ce70245d3440e6267762c5f1c6b'
}
assetLinks.json
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "eu.clubforceone.mobile",
"sha256_cert_fingerprints":
["CD:D5:D1:54:AC:8F:17:0B:8A:E6:5D:0F:C2:07:1D:FC:D7:2C:16:EE:66:A4:D9:F6:DA:1C:57:12:1B:57:A5:F9"]
}
}]
I just have no idea what to do...
This is my result from running "keytool -list -printcert -jarfile app-release.apk"
Signer #1:
Signature:
Owner: deleted for privacy reason
Issuer: deleted for privacy reason
Serial number: 6beb859e
Valid from: Sun Apr 01 14:33:45 CEST 2018 until: Thu Aug 17 14:33:45 CEST 2045
Certificate fingerprints:
MD5: 29:FC:96:6C:FC:D0:E4:69:BC:BC:B1:95:01:DA:6D:2D
SHA1: 00:7E:76:27:F9:5E:51:83:6A:77:70:57:90:A1:B7:56:66:66:A3:99
SHA256: CD:D5:D1:54:AC:8F:17:0B:8A:E6:5D:0F:C2:07:1D:FC:D7:2C:16:EE:66:A4:D9:F6:DA:1C:57:12:1B:57:A5:F9
Signature algorithm name: SHA256withRSA
Version: 3
Extensions:
#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 06 A2 63 AE E8 BD 9A 56 00 66 4E 8B 9C 09 EA 13 ..c....V.fN.....
0010: 20 C8 E5 4E ..N
]
]
You could use PWA2APK to simplify the procedure:
PWA2APK
The 'package_name' field in the 'assetlinks.json' file needs to point to the application package-name (which is the same as the applicationId).
Here's what the assetlinks.json file should look like:
[{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "eu.clubforceone.mobile",
"sha256_cert_fingerprints":
["CD:D5:D1:54:AC:8F:17:0B:8A:E6:5D:0F:C2:07:1D:FC:D7:2C:16:EE:66:A4:D9:F6:DA:1C:57:12:1B:57:A5:F9"]
}
}]
If you're letting the Play store manage your signatures, check that your assetlinks.json contains the SHA215 from your Play store settings rather than the one generated by keytool. As described in this other answer.
That said, I'm in the same situation as you. I also can't remove the URL bar from my TWA app.
Related
I have one app which are running fine in debug mode but its not working properly in released mode. I have used google login without firebase and its give me error "platfromException(sign_in_failed,h1.b:10:,null,null)"
This released app is genrated by signed apk.
When i build app from android studio then released.apk is not working(its not installed) but debug apk is working well. Following are the process and code for genrating signed apk, any steps are missed?
Internet permission is available in mainfeast file.
Created new .jks file at the time of genrate signed apk and added following code:
Crated one file in android folder "kep.properties" following code in this file:
storePassword=password from previous step
keyPassword=password from previous step
keyAlias=key0
storeFile=location of the key store file, such as /Users/user name/key.jks
App leve build.gradle
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0.1'
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.mahuva_azadari"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
signingConfigs {
debug {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('mykey.jks')
storePassword 'android'
}
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
debug {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.release
}
}
}
flutter {
source '../..'
}
dependencies {
implementation platform('com.google.firebase:firebase-bom:31.1.1')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'com.google.firebase:firebase-analytics'
}
Mainfeast code
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mahuva_azadari">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<queries>
<intent>
<action android:name="android.intent.action.SENDTO" />
<data android:scheme="mailto" />
</intent>
</queries>
<application
android:label="Azadari Schedule"
android:name="${applicationName}"
android:icon="#mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"
android:usesCleartextTraffic="true">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Google console SHA-1
You have to add sha-1 key into firebase
After that generate apk and try login**
There are many way to generate sha-1, please refer to the below link
Generate SHA-1 for Flutter/React-Native/Android-Native app
After that add sha-1 into firebase project setting
Please enable google sign in from firebase
After generate apk and try to log in
Or
Basically, the error is ApiException: 10. To solve this, you will need register your app with a SHA1 on google cloud console. Go to console.cloud.google.com click credentials > create credentials >OAuth client ID choose the platform in which you want you application to work on. fill in the package name of your application. In order to fill in the SHA1 value, open your command line and cd to the android folder inside you main project folder and type the command ./gradlew signingReport then hit enter.
I am getting this error while running my flutter app.
What went wrong:
Execution failed for task ':app:checkDebugAarMetadata'.
A failure occurred while executing com.android.build.gradle.internal.tasks.CheckAarMetadataWorkAction
The minCompileSdk (31) specified in a
dependency's AAR metadata (META-INF/com/android/build/gradle/aar-metadata.properties)
is greater than this module's compileSdkVersion (android-30).
Dependency: androidx.work:work-runtime:2.7.0-rc01.
AAR metadata file: C:\Users\HP.gradle\caches\transforms-2\files-2.1\8fcba37f766c3622d8dbd30df4e98577\work-runtime-2.7.0-rc01\META-INF\com\android\build\gradle\aar-metadata.properties.
Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 8s
Exception: Gradle task assembleDebug failed with exit code 1
Below is my AndroidManifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.owaslo.sukithasagayo.caregiver">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:label="Sukitha Sagayo Member"
android:icon="#mipmap/launcher_icon">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="#drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
Below is my app/build.gradle file
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location
with flutter.sdk in the local.properties file.")
}
def flutterVersionCode =
localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName =
localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from:
"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
//Load the key.properties file into the keystoreProperties
object.
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new
FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 30
defaultConfig {
// TODO: Specify your own unique Application ID
(https://developer.android.com/studio/build/application-id.html).
applicationId "com.owaslo.sukithasagayo.caregiver"
minSdkVersion 19
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
flutter {
source '../..'
}
Please help !!!
Set kotlin version
kotlin_version = '1.6.0'
in the /android/build.gradle file
Please share your app/ build.gradle file for which sdk version are you using?
seems to be you are using android api level 30 and one of dependency has android api level 31 and its conflicting.
I'm trying to work out how to wire up a Share intent in Android using MAUI.
Am I running into preview bugs, or am I not doing it correctly?
I'm running MAUI Preview 10, with Visual Studio 17.1.0 Preview 1.0.
Version 1
I've added the share intent to the AndroidManifest.xml file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true">
<activity android:name="SomeLongName.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
And then by adding a Name property to the MainActivity class:
[Activity(Name = "SomeLongName.MainActivity", Theme = "#style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (Intent.Type == "text/plain")
{
}
}
}
When I debug the application in MAUI, the app builds correctly and the Output says that the app has deployed. However, in Visual Studio, the debugger fails to run, and there is no evidence of the app on the emulator.
Version 2
In version 2, I've tried to create a separate activity for the Share intent:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:allowBackup="true" android:icon="#mipmap/appicon" android:roundIcon="#mipmap/appicon_round" android:supportsRtl="true">
<activity android:name="SomeLongName.ShareActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
[Activity(Name = "SomeLongName.ShareActivity")]
public class ShareActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
if (Intent.Type == "text/plain" && Intent.Action == "android.intent.action.SEND")
{
//handleSendUrl();
}
base.OnCreate(savedInstanceState);
}
I can now successfully debug the application, but when I try to share to the application, I get an exception on the base.OnCreate call:
Java.Lang.IllegalStateException: 'The specified child already has a parent. You must call removeView() on the child's parent first.'
Seems the issue centres around themes. The solution is in the original question, apply Version 2. With some minor updates. In the MainApplication class add an attribute defining the theme (same as in MainActivity class but could be different).
[Application(Theme = "#style/Maui.SplashTheme")]
public class MainApplication : MauiApplication
{
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
: base(handle, ownership)
{
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
This both works without error and enables debugging.
Without the MainApplication theme setting, when sharing to the android app (incoming), an error thrown:
Java.Lang.IllegalArgumentException: 'The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).'
In my secondary activity, the Activity attribute sets the Theme, but is ignored and error still shown, hence the Application level needed. Not sure why.
[Activity(Theme = "#android:style/Theme.MaterialComponents.Light", Name = "com.somename.receiveurlactivity", MainLauncher = false, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class ReceiveUrlActivity : MauiAppCompatActivity
{
//.... etc
I have tried adding Firebase Messaging to my Flutter app, and according to this tutorial I should add a custom application name to the manifest file.
Problem
App won't launch because Flutter can't find my custom application file
Cause
I have tried integrating FlutterFire / Firebase Cloud Messaging with flutter
Request
All I care about is receiving push notifications (foreground + background) on the Flutter app, if this is not the correct method to go about it, please let tell me how I can enable this for Android devices
Logs & Outputs
My manifest is
package="com.blabla.blabla">
<!-- Default is android:name="io.flutter.app.FlutterApplication" -->
<!-- FOR PUSH NOIFICATION IN BACKGROUND android:name=".Application" -->
<application
android:name=".Application"
android:label="BlaBla"
android:icon="#mipmap/launcher_icon">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- this is the push notification intent -->
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
The application file is located in the same folder as Manifest (app->src->main)
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry?) {
io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(
registry?.registrarFor(
"io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
}
}
And my specific (app->build.gradle) is as follows
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services' // Google Services plugin
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 30
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
applicationId "com.bla.bla"
minSdkVersion 21
targetSdkVersion 30
// multiDexEnabled true
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
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
}
}
splits {
// Configures multiple APKs based on ABI.
abi {
// Enables building multiple APKs per ABI.
enable true
// By default all ABIs are included, so use reset() and include to specify that we only
// want APKs for x86 and x86_64.
// Resets the list of ABIs that Gradle should create APKs for to none.
reset()
// Specifies a list of ABIs that Gradle should create APKs for.
include "x86", "x86_64", "armeabi", "armeabi-v7a", "arm64-v8a"
// Specifies that we do not want to also generate a universal APK that includes all ABIs.
universalApk true
}
}
}
flutter {
source '../..'
}
dependencies {
// implementation "androidx.multidex:multidex:2.0.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Import the BoM for the Firebase platform
implementation platform('com.google.firebase:firebase-bom:26.6.0')
// Declare the dependencies for the Firebase Cloud Messaging and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation 'com.google.firebase:firebase-messaging-ktx:21.0.1'
// implementation 'com.google.firebase:firebase-analytics-ktx'
}
This is the general build.gradle
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.5' // Google Services plugin
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
This is the console output of every launch
E/AndroidRuntime(31070): java.lang.RuntimeException: Unable to instantiate application com.bla.bla.Application: java.lang.ClassNotFoundException: Didn't find class "com.bla.bla.Application" on path: DexPathList[[zip file "/data/app/com.bla.bla-bPPOfcyKzIbhjyMWE3Q9NQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.bla.bla-bPPOfcyKzIbhjyMWE3Q9NQ==/lib/arm64, /data/app/com.bla.bla-bPPOfcyKzIbhjyMWE3Q9NQ==/base.apk!/lib/arm64-v8a, /system/lib64, /system/product/lib64]]
E/AndroidRuntime(31070): at android.app.LoadedApk.makeApplication(LoadedApk.java:1231)
E/AndroidRuntime(31070): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6431)
E/AndroidRuntime(31070): at android.app.ActivityThread.access$1300(ActivityThread.java:219)
E/AndroidRuntime(31070): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1859)
E/AndroidRuntime(31070): at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime(31070): at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime(31070): at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime(31070): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(31070): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:491)
E/AndroidRuntime(31070): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
I DON'T KNOW WHAT ELSE TO DO!! I have spent countless hours trying to solve it, would appreciate it if anybody knows how to fix this issue!!
Currently running on a Google Pixel 2 Android 10 device.
My bad,
I had accidentally put the Application.kt file in the android > app folder instead of android > app > src > your-package-name.
Once I moved the custom Application.kt next to the MainActivity.kt, all seems to work well!
Try modifying your AndroidManifest.xml file to look like below. This is working.
This is only for the <activity </activity> tags. And set your minSdkVersion to 21 in android/app/build.gradle to overcome possible multidex errors.
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="#style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="#drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Describe the bug
I want Installing Location Package with version ^2.3.5 But I get message error like this on my device :
java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
at com.google.android.gms.common.GooglePlayServicesUtilLight.isGooglePlayServicesAvailable(Unknown Source)
at com.google.android.gms.common.GoogleApiAvailabilityLight.isGooglePlayServicesAvailable(Unknown Source)
at com.google.android.gms.common.GoogleApiAvailability.isGooglePlayServicesAvailable(Unknown Source)
at com.google.android.gms.common.internal.GoogleApiAvailabilityCache.getClientAvailability(Unknown Source)
at com.google.android.gms.common.api.internal.GoogleApiManager$zaa.connect(Unknown Source)
at com.google.android.gms.common.api.internal.GoogleApiManager.zab(Unknown Source)
at com.google.android.gms.common.api.internal.GoogleApiManager.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:165)
at android.os.HandlerThread.run(HandlerThread.java:61)
My Configuration
Android -> build.gradle
buildscript {
// ext.kotlin_version = '1.2.71'
ext.kotlin_version = '1.3.21'
repositories {
google()
jcenter()
}
dependencies {
// classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.android.tools.build:gradle:3.3.0'
classpath 'com.google.gms:google-services:4.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
gradle.properties
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
Android -> App -> build.gradle
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "id.zeffry.great_place_app"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
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
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="id.zeffry.great_place_app">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="great_place_app"
android:icon="#mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="#style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in #style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
I'm really sure have added meta tag google service like this in AndroidManifest.xml
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
Tested on:
- Android, API Level 24 Nougat using real device
Can you help me with this error ?
Thank's
You placed the tag inside of <Activity>. It should be within <Application> instead:
<application
android:name="io.flutter.app.FlutterApplication"
android:label="great_place_app"
android:icon="#mipmap/ic_launcher">
<!-- here -->
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity ...>
...
</activity>
</application>
If you use reference to resource #integer/google_play_services_version, make sure you have this value in resources or just replace the reference with your key.
To place value in resources, create .xml file in /res/values:
<resources>
<integer name="google_play_services_version">value</integer>
</resources>