The debug build of my APK always successfully registers with GCM. I've just built the first release version of my APK. I can install and run the release version, via Android Studio, on my USB-connected device. However GCM registration always fails for the release version.
private static final String TAG = "GcmRegIntentService";
MyRegistrationEpt backendRegService = getRegistrationService();
try {
synchronized (TAG) {
InstanceID instanceID = InstanceID.getInstance(appContext);
String token = instanceID.getToken(GCM_SENDER_ID, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Log.i(TAG, "before register, token: " + token);
backendRegService.register(token).execute();
}
} catch (Exception ex) {
Log.i(TAG, "Error: " + ex.getMessage());
}
private MyRegistrationEpt getRegistrationService() {
MyRegistrationEpt.Builder builder = new MyRegistrationEpt.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl("https://some_valid_app.appspot.com/_ah/api/")
.setApplicationName(getResources().getString(R.string.app_name));
return builder.build();
}
When this code runs this is the log:
08-21 12:52:54.225 4145-13398/technology.grandma.margriver I/GcmRegIntentService﹕ before register, token: <some_long_string>
08-21 12:52:55.430 4145-13398/technology.grandma.margriver I/GcmRegIntentService﹕ Error: 404 Not Found
I have narrowed down the problem to be related to proguard stripping required GCM classes from my build. If I set "minifyEnabled false" in build.gradle the problem disappears. I'm using Google Play services API level 7.8.0. Page https://developers.google.com/android/guides/setup says:
"ProGuard directives are included in the Play services client libraries to preserve the required classes. The Android Plugin for Gradle automatically appends ProGuard configuration files in an AAR (Android ARchive) package and appends that package to your ProGuard configuration. During project creation, Android Studio automatically creates the ProGuard configuration files and build.gradle properties for ProGuard use. To use ProGuard with Android Studio, you must enable the ProGuard setting in your build.gradle buildTypes. For more information, see the ProGuard guide."
I interpret this to mean that I do not need to manually need to add any proguard rules for GCM. Can anyone explain the cause of this error and suggest how I fix it?
I fixed this problem. The problem was not caused by proguard stripping GCM classes but by proguard stripping types and annotations needed to connect to by Google App Engine API client. To fix this I added these lines to my proguard rules:
# Needed by google-api-client to keep generic types and #Key annotations accessed via reflection
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
-keepclassmembers class * {
#com.google.api.client.util.Key <fields>;
}
See https://developers.google.com/api-client-library/java/google-http-java-client/setup#proguard.
SHA1 Certificate might be needed to be added in the API console . For Both debug and release
Related
I am using the amplify libraries for flutter to connect to my aws backend. After a successful call to Amplify.Auth.signIn() I use Amplify.Auth.fetchAuthSession() to access the current credentials. Like that:
final result = await Amplify.Auth.fetchAuthSession(
options: CognitoSessionOptions(getAWSCredentials: true),
);
if (!result.isSignedIn) return const None();
if (result is CognitoAuthSession) {
return Some(result.userPoolTokens.idToken);
}
But when I build an apk with flutter using the following command my code breaks.
flutter build apk
Because result.userPoolTokens is suddenly null and I get a NoSuchMethodError. The getter 'idToken' was called on null. But if I disable shrinking and build the apk with the following command everything works again.
flutter build apk --no-shrink
So I think it has something to do with the shrinking and I would prefer to shrink my app because the shrinked apk is significantly smaller.
Would appreciate any help.
This is likely due to inadequate rules being applied for the R8 shrinker.
The Amplify Android library did not vend any consumer-rules.pro until version 1.6.10 (see release notes), which was just released January 22nd, 2021.
The latest version of Amplify Flutter is 0.0.2-dev.1, and it consumes version 1.6.8 of the Android library. I've raised an issue on their GitHub repository, to update to 1.6.10.
In the meantime, you could try to apply these rules in your top-level application project.
-keep class com.amazon.** { *; }
-keep class com.amazonaws.** { *; }
-keep class com.amplifyframework.** { *; }
I just started using timber for logging on android, we are trying to add filenames/class-names to log message. I was able to add filenames in debug build using debug tree, but I'm not finding a way to add filenames in the release tree. Is there a possibility to add the filename in the release tree with R8 enabled?
Okay use it like this:
Define a TAG variable with your class name in your whole classes as:
private static final String TAG = "Your class name";
then pass your TAG:
Timber.tag(TAG).d("Error %s!", error);
As described here there are several ways to go about this.
For release builds
When you generate an actual release build of the app that you intend to publish on the Play Store you also get a mapping.txt for every release artifact. Upload this file (be careful - every build generates a new file, so you must use the exact file that was generated with your artifact) and Google will deobfuscate crash logs in the Google Play Console for you.
You also have the option to use the retrace command line tool to translate logs you receive from this build yourself using mapping.txt.
For non-release builds/internal testing
Since you will not be releasing this artifact to the world it is possibly acceptable to break your own code obfuscation. You can use rules in the proguard-rules.pro file to keep relevant information during R8 shrinking.
Check the docs for all relevant parameters. Especially useful are
-dontobfuscate, -keeppackagenames and -keepattributes (with params like SourceFile and LineNumberTable).
Remember that changes in shrinking and obfuscating code can break thinks like reflection and resource lookup when you do these manually. So make sure your obfuscated release build works as expected after fiddling with these parameters.
I am using retrofit for my application. it is able to read all API data in development mode and even with Build APK. but same version of code not working in signed APK. it just move to onFailRequest. Connectivity check flag shows true that network is connected. I am unsure that it's Android 9 or higher problem. My API server have http://domainname.com only. it doesn't have https. can it be problem?
It was solved by set minify as false. (Build/Edit Buildtype) I read that "if you set this option when code release, some part is removed" so tried with false and it worked.
one other comment was there which tells add -keep class Responseclass { *; } rule in proguard rules fixed it for me.
but in mycase minify false worked.
I face issue with get token from firebase (push notification)
Default FirebaseApp is not initialized in this process com.ready_apps.Nebka.Business. Make sure to call FirebaseApp.initializeApp(Context) first.
even I called FirebaseApp.InitializeApp(this); in many places
MyApplication (that extend Application) , in onCreate of Activity where I call FirebaseInstanceId.Instance?.Token;
Edit: This bug has been fixed in Xamarin.Firebase version 57.1104.0-beta1.
This error seems to be present in the newer versions of Firebase for Xamarin. I am also experiencing this error as of today, using the latest stable version 42.1021.1. (The error is also present in the latest beta build).
I found that a bug report has been filed for the issue here.
As mentioned in the bug report, deleting both the /obj and /bin folders in your Android project, and/or cleaning the project in Visual Studio should fix the problem temporarily until you update any resource that would change the Resource.Designer.cs file.
Downgrading to an older version of Firebase and Google Play Services is also possible before a permanent solution is available. I did not experience this error on Firebase and Google Play Services version 32.961.0, for example.
Just Clean the solution once and run the app again.
This bug is already reported to Xamarin.
https://bugzilla.xamarin.com/show_bug.cgi?id=56108
This solution is provided in their comment thread, it might get fixed in the newer release of xamarin NuGet package.
I didnt fix it but I find walkaround this issue in debug mode only
I called this method onCreate() in activit I need to request the token
FirebaseInstanceId.Instance?.Token
here is the method
private void ConfigureFireBase()
{
#if DEBUG
try
{
Task.Run(() =>
{
var instanceId = FirebaseInstanceId.Instance;
instanceId?.DeleteInstanceId();
//Log.Debug("TAG", "{0} {1}", instanceId?.Token?.ToString(), instanceId.GetToken(GetString(Resource.String.gcm_defaultSenderId), Firebase.Messaging.FirebaseMessaging.InstanceIdScope));
});
// For debug mode only - will accept the HTTPS certificate of Test/Dev server, as the HTTPS certificate is invalid /not trusted
ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
}catch (Exception e)
{
Log.Debug("TAG", e.Message);
}
#endif
}
I'm trying to use Google's App Invites API with my Android app and according to their guide, I need to put a config file that is generated from the developer console in the app/ directory of the project. My app has multiple build flavors, one for production, qa, and debug. I don't know how this works (since it is a pluging) with multiple build flavors and am hoping that someone can shed some light on this issue.
I investigated a bit regarding the google-services plugin and json and found the sources to this plugin.
First things first:
The gradle-plugin google-services that is referenced by classpath and with apply is a build-time plugin only! So it only influences the build-process of your app, but not the runtime-process!
This plugin is only meant as a quickstart-helper to integrating Google-services quickly in your app. Obviously, the process is somewhat convoluted and not documented, so Google should have made it clear what this process does.
In fact, I found the source code for the plugin version com.google.gms:google-services:1.4.0-beta3 and didnt find any specific reference in it regarding appinvites nor did I find any Google API for App Invites! (But maybe it just uses a generic API project with its project id, I didnt try this)
What it does:
The google-services gradle-plugin looks for the mentioned google-services.json file in your app-module. Then it looks for configured settings like project-id's and tracking-id's and such, generated by the Google API developer console into the google-services.json file.
From the settings it found, Android resource values are generated into the following path:
$project.buildDir/generated/res/google-services/$variant.dirName/values/values.xml
For example for a debug-build of your app:
app/generated/res/google-services/debug/values/values.xml
E.g. if you followed the GCM tutorial, the JSON file would include the API project's id as the following android-resource:
<string name="gcm_defaultSenderId">project-id</string>
So this plugin and JSON file are not essential to running or publishing your app, it is just a quickstart helper to generate some basic android-resource files for easier integration of specific Google API features.
Notice in the source code referenced below that the google-services plugin always generates those android-resources for every app-variant that is defined in your app/build.gradle.
If you don't want that, you should use those generated resources in the app-variants you want, and delete the others. Don't forget to remove the google-services plugin apply from app/build.gradle, or else it will be regenerated for all app-variants.
What it does not:
This plugin and JSON-file do NOT directly influence the inner workings of said Google-features for your app!
If you already have followed older tutorials on developer.android.com on how to integrate e.g. GCM or Google Analytics, then you don't even need to integrate either the gradle-plugin google-services or the google-services.json file!
Notice about where I found the sources:
After you integrated the google-services gradle-plugin and when sync your project, Gradle automatically downloads the google-services dependency to a path similar to this (on Windows, you might need to look into your home/.gradle for Linux):
C:\Users\user\.gradle\caches\modules-2\files-2.1\com.google.gms\google-services\1.4.0-beta3\f1580f62e3be313eba041ce19b64fd3f44cf8951\google-services-1.4.0-beta3-sources.jar
If you extract this jar-file, you will find two files:
GoogleServicesPlugin.groovy
GoogleServicesTask.java
which contain the plain source code of the gradle-plugin.
GoogleServicesPlugin.groovy
contains the handling of the app-variants and basic definitions of paths etc.
GoogleServicesTask.java
contains the actual task-definition, look for the following method to see what it really does:
#TaskAction
public void action() throws IOException {
checkVersionConflict();
// google-services.json
if (!quickstartFile.isFile()) {
getLogger().warn("File " + quickstartFile.getName() + " is missing from module root folder." +
" The Google Services Plugin cannot function without it.");
// Skip the rest of the actions because it would not make sense if `quickstartFile` is missing.
return;
}
// delete content of outputdir.
deleteFolder(intermediateDir);
if (!intermediateDir.mkdirs()) {
throw new GradleException("Failed to create folder: " + intermediateDir);
}
JsonElement root = new JsonParser().parse(Files.newReader(quickstartFile, Charsets.UTF_8));
if (!root.isJsonObject()) {
throw new GradleException("Malformed root json");
}
JsonObject rootObject = root.getAsJsonObject();
Map<String, String> resValues = new TreeMap<String, String>();
handleProjectNumber(rootObject, resValues);
JsonObject clientObject = getClientForPackageName(rootObject);
if (clientObject != null) {
handleAnalytics(clientObject, resValues);
handleAdsService(clientObject, resValues);
handleGoogleAppId(clientObject, resValues);
} else {
getLogger().warn("No matching client found for package name '" + packageName + "'");
}
// write the values file.
File values = new File(intermediateDir, "values");
if (!values.exists() && !values.mkdirs()) {
throw new GradleException("Failed to create folder: " + values);
}
Files.write(getValuesContent(resValues), new File(values, "values.xml"), Charsets.UTF_8);
}
So if the Google-docs don’t say which resources are needed for specific Google-features, I would suggest to generate the JSON-file for each relevant buildtype/flavor, see what resources get generated by the plugin and then put those resources manually into their respective src/buildtypeORflavor/res directories.
Delete the references to google-services plugin and the JSON-file after that, and you are done.
According to the Google services gradle plugin documentation, the plugin supports different google-services.json per buildType, but not per flavor
[...] as of version 2.0.0-alpha3 of the plugin support was added for
build types, which would make the following directory structure valid:
app/src/
main/google-services.json
dogfood/google-services.json
mytype1/google-services.json
However, it's not working for me. I'm using 2.0.0-alpha9 and Gradle still complains that it can't find a google-services.json file in root folder
Error:Execution failed for task
':app:processProdReleaseGoogleServices'.
File google-services.json is missing from module root folder. The Google Services Plugin cannot function without it.
I've filed a bug: https://code.google.com/p/android/issues/detail?id=200116