Android Parse, notifications and buildTypes - android

I am currently using parse to send and receive push notifications on an Android app.
Everything was fine until i added an application id suffix to my build.gradle for the debug build type:
defaultConfig {
applicationId "com.example.myapp"
...
}
buildTypes {
debug {
applicationIdSuffix ".debug"
...
}
release {
...
}
}
Now I can see in Parse that new installations are registered with the applicationId field : com.example.myapp.debug, so into the manifest file I used the following piece of code :
<receiver
android:name="com.parse.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
Doing this i thought the registration would be dynamic according to the build type.
Actually it doesn't work : installations registered with the .debug suffix have no GCMSenderId nor DeviceToken, and so i can't receive any notification. I am obviously missing a point, or I didn't understand how the registration works, but i can't figure how to make it ok.
Does Parse use the applicationId to register the application, or the real package name (used for R) ?
Did anyone manage to handle parse notifications with different buildTypes (applicationId suffix) ?

Ok, I finally figured it out. I forgot to add the dynamic applicationId in the permission declaration...
<permission
android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
Problem solved.

Related

App does not install from Play Store on devices with Android 12 and above

I faced the following problem with my application - it can not be installed from Play Store on devices with Android 12 and above (error dialog from Play Store app at the bottom of the post).
The problem only appeared recently, presumably from the version 31.9.13-21 [0] [PR] 467268234 of Google Play Store.
Some other facts:
Installing application from Android Studio using option "APK from app bundle" in run configuration works fine.
Installing universal APK from Google Play Console works fine.
Installing APK using bundletool works fine.
Removing Play Store updates fixes the ptoblem. Updates can be removed from Play Store app settings.
Logcat contains the following error when installing from Play Store: INSTALL_FAILED_INVALID_APK: Full install must include a base package. It seems that this error is thrown by Android system's class, more specifically here (google source). As far as I understand, this means that invalid set of apks is generated from bundle, without main (or base apk).
App module's build.gradle.kts snippet (without dependencies):
plugins {
id("com.android.application")
kotlin("android")
id("kotlin-parcelize")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("google-play-publisher")
id("appcenter")
id("com.huawei.agconnect")
id("app-gallery-publisher")
}
android {
compileSdk = 31
defaultConfig {
applicationId = "com.some.example"
minSdk = 24
targetSdk = 30
versionCode = Versions.versionCode
versionName = Versions.versionName
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters.addAll(setOf("armeabi-v7a", "x86", "arm64-v8a", "x86_64"))
}
}
compileOptions {
sourceCompatibility(JavaVersion.VERSION_11)
targetCompatibility(JavaVersion.VERSION_11)
}
kotlinOptions {
jvmTarget = "11"
}
buildTypes {
getByName("release") {
isShrinkResources = true
isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
proguardFiles(*fileTree("$rootDir/proguard").files.toTypedArray())
signingConfig = signingConfigs.getByName("release")
}
getByName("debug") {
signingConfig = signingConfigs.getByName("debug")
}
}
packagingOptions {
exclude("META-INF/LICENSE.md")
exclude("META-INF/LICENSE-notice.md")
}
buildFeatures {
viewBinding = true
}
bundle {
language {
enableSplit = false
}
}
}
App module's AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.some.example">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:node="remove"
tools:ignore="ScopedStorage"/>
<application
android:name="AppName"
android:allowBackup="false"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:networkSecurityConfig="#xml/network_security_config"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name="SomeActivityName"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="somescheme"/>
</intent-filter>
<intent-filter android:autoVerify="true" tools:targetApi="m">
<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="some.host"
android:pathPrefix="/prefix" />
<data
android:scheme="https"
android:host="some.host"
android:path="/path/"/>
</intent-filter>
</activity>
</application>
</manifest>
Update you compileSdk and targetSdk to 33 in your build.gradle.kts file.

Firebase InstanceId: binding to the service failed: Kotlin

App successfully lanches but get this error message in debugging. FirebaseInstanceId: binding to the service failed
App Build Gradle:
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId ""
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true // enable mun
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
Android manifest:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".FilterPage"></activity>
<activity android:name=".filterdashboard" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I have added
<uses-permission android:name="android.permission.INTERNET"/>
In my manifest file and got rid of Firebase InstanceId: binding to the service failed. Hope it will help.
I downloaded the newest version of google-service.json (can be done via Firebase Settings). In my case there was a new entry added to oauth_client. After syncing with the file system and rebuilding my app the warning does not seem to appear anymore.
EDIT 20-02-2020: After testing this a bit more it unfortunately doesn't seem to help in the end. In my case the error message only for sure occur when starting the app the first time after an uninstall of the app - in most other cases it does not happen.
Please try to use an actual device. Per my observation, you'll get this kind of error when you use an emulator even though you've already downloaded all the required libraries related to Google Services. I was also able to see other errors from FirebaseInstanceId.
In my case, login to Google Play on emulator (API: R) is fixed the problem. I think it's about Play Services.
Add service tag inside application tag
<application>
....
<activity
....
</activity>
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
Then add a new kotlin file - MyFirebaseMessagingService.kt
import com.google.firebase.messaging.FirebaseMessagingService;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onNewToken(String s) {
super.onNewToken(s);
System.out.println("NEW_TOKEN :::::::::::::::::::::::::: "+s);
}
}
Uninstall the App manually and reinstall. This will work.

How to add different values of string resource for different flavors?

I'm an iOS developer who is trying to make some small changes on android side but with no clue of how to achieve them. My goal is to implement Facebook SDK inside the app, official documentation says:
In /app/res/values/strings.xml add new string element:
<string name="facebook_app_id">Facebook App ID</string>
Then add in AndroidManifest.xml file new meta-data like below:
<application android:label="#string/app_name" ...>
...
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/facebook_app_id"/>
...
</application>
All is understood but my problem is that I have few product flavors based on which I build at the end stand alone apps, for each I have different Facebook App ID. I would appreciate any kind of help. Thanks!
You can create multiple build types or product flavors inside the app-level build.gradle file and then define different strings for each build variant like this
buildTypes {
prod{
resValue "string", "facebook_app_id", "your app id"
}
dev {
resValue "string", "facebook_app_id", "your app id"
}
}
Now you can access this string inside manifest
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/facebook_app_id"/>
There are many ways. But as you already define multiple flavour in build.gradle in app level then you can define the string over there like this
android {
buildTypes {
flavour1 {
buildConfigField "String", "facebook_app_id", "\"first facebook id 1\""
}
flavour2 {
buildConfigField "String", "facebook_app_id", "\"first facebook id 2\""
}
}
}
It automatically initialise the facebook_app_id to the build when you are creating the build of the flavour.
Happy Coding :)
In build.gradle :
productFlavors {
appDev {
applicationId 'com.android.dev'
}
appTest {
applicationId 'com.android.test'
}
}
flavorDimensions "default"
Inside src folder:
create folder with flavors name
-src
-appDev(folder)
-java(folder)
-res(folder)
-values(folder)
-appTest(folder)
-java(folder)
-res(folder)
-values(folder)
inside values folder you can create strings.xml each folder act as different flavor
you need to pass your facebook app_id in the string files.
<string name="facebook_app_id">35166120881***</string>
<string name="fb_login_protocol_scheme">fb35166120881****</string>
...
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="#string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="#string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
...
</application>
Important this
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="#string/facebook_app_id"/>

How do I change the AndroidManifest.xml file based on build variants?

I have an app with multiple build variants. The variants are used to build versions of the same app for different companies. So, I have several different variants that build different apps:
com.acme.app1
com.schmoe.app2
com.yop.app3
etc...
The build.gradle file handles this very well:
productFlavors {
app1 {
applicationId "com.acme.app1"
}
app2 {
applicationId "com.schmoe.app2"
}
app3 {
applicationId "com.yop.app3"
}
}
Here's my problem. I am integrating Dropbox into my apps. The AndroidManifest.xml file must be changed for each variant to include the appropriate app key (stored in my string file). Dropbox has the following addition to the manifest file:
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard">
<intent-filter>
<!-- Change this to be db- followed by your app key -->
<data android:scheme="db-abcdef" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Each build variant needs to change the following line:
<data android:scheme="db-abcdef" />
to the appropriate value for each app variant. In other words, I need to replace part of the above string based on the build variant. For instance
App1
<data android:scheme="db-111111" />
App2
<data android:scheme="db-222222" />
App3
<data android:scheme="db-333333" />
The line is the same for each variant up to the text "db-".
What I need is to dynamically replace the variable portion of the string (the x values) "db-xxxxxx" with a string from my string file.
I think this can be done with gradle scripts but I'm a complete newb with gradle. HELP!
If you can help, please be very specific about what goes where since I SUCK at gradle files and scripting. Thanks in advance!
You can save the string in build.gradle too:
productFlavors {
app1 {
applicationId "com.acme.app1"
resValue "string", "my_app_key", "db-abc"
}
app2 {
applicationId "com.schmoe.app2"
resValue "string", "my_app_key", "db-def"
}
app3 {
applicationId "com.yop.app3"
resValue "string", "my_app_key", "db-ghi"
}
}
And then use it like:
<data android:scheme="#string/my_app_key" />
You can do this the same way you would modify the app name, using a string resource. In your manifest, include:
<data android:scheme="#string/db_scheme" />
Next, you add resources folders for the various build types, and in each, place a custom copy of a resource file, say res/values/flavor.xml:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<resources>
<string name="app_name">Customer 1 App</string>
<string name="db_scheme">db-111111</string>
</resources>
This will allow you to have different API keys, schemes, app-names, icons, etc. for your various flavors.
For people visiting this in 2019: You can use manifestPlaceholders per flavor.
In your case:
productFlavors {
app1 {
applicationId "com.acme.app1"
manifestPlaceholders.scheme = "db-111111"
}
app2 {
applicationId "com.schmoe.app2"
manifestPlaceholders.scheme = "db-222222"
}
app3 {
applicationId "com.yop.app3"
manifestPlaceholders.scheme = "db-333333"
}
}
and then use it in your manifest:
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboard">
<intent-filter>
<!-- Change this to be db- followed by your app key -->
<data android:scheme="${scheme}" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Yet another way that is somewhat similar to Hibbem's answer:
android {
defaultConfig {
manifestPlaceholders = [schemeName: "default-scheme"]
}
...
app1 {
applicationId "com.acme.app1"
manifestPlaceholders = [schemeName: "db-111111"]
}
...
}
And in your manifest:
<intent-filter>
...
<data android:scheme="${schemeName}" />
...
</intent-filter>
More from the official docs

Failed to run Google I/O 2014 Android app

Google has released I/O 2014 android app, since it must be an valuable android app demo, so I decided to download it and tried to debug it. But, unfortunately, while I was trying to run it after compiling, it said "This app won't run unless you update google play services", actually the google play services on my phone(Nexus 5, Kitkat 4.4.4) is already the newest. So, in my perspective, I thought it was related to the server configurations, because the I/O app uses some google services, like google plus, google map, etc. I followed the official instructions, but instantly I stuck at the first step:After I renamed the package name in the manifest file(using Android Studio refactoring feature, it will change the activity names accordingly) and refactored the R class imports in the java classes(refactoring by moving the old generated R.java to the new package, it will rearrange the corresponding “.R” imports in all related classes), the app failed to run and complained as followings:
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.google.samples.apps.iosched/.ui.BrowseSessionsActivity }
Error type 3
Error: Activity class {com.google.samples.apps.iosched/com.google.samples.apps.iosched.ui.BrowseSessionsActivity} does not exist.
My new package name is “com.enlangtech.samples.apps.iosched”. I have tried to build a trial app and I am sure now that the app package name can be different with the package that activity classes belong to. So I can’t understand where is the problem. Any one could help me? Thanks for advance!
I had the same error after renaming/refactoring. What I did was add the applicationId property attribute to my build.gradle file, and set its value to the application package.
Like this:
build.gradle file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.+'
}
}
apply plugin: 'com.android.application'
repositories {
mavenCentral()
}
dependencies {
compile 'com.android.support:support-v4:19.1.+'
compile 'com.google.android.gms:play-services:4.3.23'
}
android {
compileSdkVersion 19
buildToolsVersion "19.1"
defaultConfig {
applicationId "packageName"
minSdkVersion 16
targetSdkVersion 19;
}
buildTypes {
release{
runProguard true
proguardFile file('path_to_proguard_file\\proguard-project.txt')
proguardFile getDefaultProguardFile('proguard-android.txt')
}
debug{
runProguard false
}
}
}
androidmanifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="myfullpackagename"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="#drawable/launcher_icon"
android:label="#string/app_name"
android:name="mypackagename">
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<activity
android:name="package.Activity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="package.SettingsActivity"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
<action android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name=".AboutScreen"/>
<service android:name="package.Service"
android:exported="false"/>
<receiver android:name="package.Alarm"/>
<receiver android:name="package.MyBroadcastReceiver">
<intent-filter>
<action android:name="package.MY_BROADCAST_RECEIVER"/>
</intent-filter>
</receiver>
<receiver android:name="package.MyBroadcastReceiver2">
<intent-filter>
<action android:name="package.MY_BROADCAST_RECEIVER_2"/>
</intent-filter>
</receiver>
</application>
</manifest>

Categories

Resources