Removing uses of TestFlight SDK with ProGuard - android

How can I automatically remove all uses of TestFlight SDK from my app? For example, all passCheckpoint calls:
TestFlight.passCheckpoint("FreemiumDialog opened");
My (ProGuard-obfuscated) release builds should not even attempt to send any info to TestFlight, yet I do not want to manually toggle between having TestFlight jar & its uses in my codebase.

This ProGuard configuration removes all calls to TestFlight SDK:
# Remove all TestFlight SDK calls, e.g. TestFlight.takeOff( ... );
# and TestFlight.passCheckpoint( ... );
-assumenosideeffects class com.testflightapp.lib.TestFlight { *; }
-dontwarn org.msgpack.**
Note: without the last line, ProGuard fails with a bunch of warnings like:
Warning: org.msgpack.template.builder.BeansBuildContext: can't find
referenced class javassist.CtClass
Warning: org.msgpack.util.json.JSONUnpacker: can't find referenced class > org.json.simple.parser.JSONParser
This is because the TestFlightLib jar (at least version 1.3) contains and uses a library called MessagePack. We need to either -keep it or mute the warnings. Above I'm muting warnings, since the whole point here is not to use TestFlight in release builds.

Related

Proguard rules for Jetpack GameActivity

I'm trying to use Jetpack GameActivity in my project, but I encounter a strange issue with Proguard. My project has 2 modules, app and my-lib:
my-lib module has MyActivity which extends GameActivity:
api 'androidx.games:games-activity:1.2.1'
app module has MainActivity which extends MyActivity from my-lib module
implementation project(":my-lib")
When I built my project in Release build and had Proguard enabled, I got a native crash:
Abort message: 'Unable to find method setWindowFlags'
=> I tried inspecting GameActivity class from my APK, setWindowFlags method didn't exist at all, which means Proguard has removed it, that's why the native part of the GameActivity library couldn't find the method and it threw an error.
Then, I tried to fix it, by adding Proguard rule like this:
-keep, includedescriptorclasses class com.google.androidgamesdk.GameActivity { *; }
But unfortunately, I got another native crash:
Abort message: 'Unable to find field left'
=> Why does this happen? I tried inspecting the APK again, but have no idea why
Anyway, how can I deal with this situation? Does Jetpack GameActivty need to add Proguard rules to keep methods that will be used by the native part?
There is a know issue in version 1.2.1 and before: the java functions called by native code only were stripped out by proguard for the release build. Version 1.2.2-alpha01 has fixed that and a few other important potential issues, including the static library release in the AAR. To use the 1.2.2-alpha01+:
Add the latest version to the dependency: 1.2.2-alpha01+
Use C/C++ static lib release in the AAR.
add the following or something similar to your project's existing CMakeLists.txt
find_package(game-activity REQUIRED CONFIG)
add_library(${PROJECT_NAME} SHARED sth.cpp) #<=== this is your own.
target_link_libraries(${PROJECT_NAME} game-activity::game-activity_static
# optional: does not hurt to add it; refer to the official doc for update.
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -u \
Java_com_google_androidgamesdk_GameActivity_initializeNativeCode")
If want to use the source code directly(not recommended), do something similar to this:
# Find GameActivity sources to build.
find_package(game-activity REQUIRED CONFIG)
get_target_property(GAME_ACTIVITY_INCLUDE_PATH
game-activity::game-activity
INTERFACE_INCLUDE_DIRECTORIES)
string(REPLACE "include" "" GAME_ACTIVITY_SRCS ${GAME_ACTIVITY_INCLUDE_PATH})
file(GLOB_RECURSE GAME_ACTIVITY_SRCS
${GAME_ACTIVITY_INCLUDE_PATH}/*.c*)
add_library(${PROJECT_NAME} SHARED
sth.cpp. #<== this is your own file
${GAME_ACTIVITY_SRCS})
target_link_libraries(${PROJECT_NAME} PUBLIC
android log
game-activity::game-activity
# other libs
)
Note: it is still just 3 source files now, and you can unzip the latest AAR and list them explicitly like:
add_library(${PROJECT_NAME} SHARED
sth.cpp. #<== this is your own file
${GAME_ACTIVITY_INCLUDE_PATH}/game-activity/GameActivity.cpp
${GAME_ACTIVITY_INCLUDE_PATH}/game-activity/native_app_glue/android_native_app_glue.c
${GAME_ACTIVITY_INCLUDE_PATH}/game-text-input/gametextinput.cpp)
The glob way might be better for future compatibility reasons; but it is not cmake recommended way to do things.
Handle the the "back" button press to exit app either from Kotlin/Java side(handle KEYCODE_BACK in onKeyDown()) or native code (AKEYCODE_BACK in input key event processing).
Referring to the documentation page and probably the list above, you should be able to get your project going. The simple fact is this: all of the C/C++ things are inside AAR, under the prefab sub-directory, you even can copy it out and directly put into your own source tree. This Pull Request might help (but not totally sure).
If you see something or like some new things, please create a bug.
I had the same issues as you and I solved this by adding the following line to my proguard-rules.pro file:
-keep class com.google.androidgamesdk.** { *; }
Of course then I had other proguard related errors so I had to add these
additional lines:
-keep class androidx.core.graphics.Insets { *; }
-keep class androidx.core.view.** { *; }
-keep class org.fmod.** { *; }
Of course you will have different errors in your build, but hopefully this will help you.

Amplify.Auth.fetchAuthSession() userPoolTokens is null when shrinking the apk

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.** { *; }

Android R8 obfuscation with flexJson duplicate key issue

While obfuscating the android app using R8 and minifyEnabled true in build.gradle it adds duplicate key like below in one of webservice response.
Response: {"key1":"value1", ......., "key1":"value1"} it adds "key1" multiple time and flexJson throws exception and crashes the app
Caused by: flexjson.JSONException: Duplicate key "key1"
at flexjson.JSONTokener.putOnce(JSONTokener.java:498)
at flexjson.JSONTokener.parseObject(JSONTokener.java:471)
at flexjson.JSONTokener.nextValue(JSONTokener.java:357)
at flexjson.JSONTokener.parseObject(JSONTokener.java:471)
at flexjson.JSONTokener.nextValue(JSONTokener.java:357)
at flexjson.JSONDeserializer.deserialize(JSONDeserializer.java:197)
Everything works fine without obfuscation(minifyEnabled false).
Gradle Plugin Version used: 3.4.2, Also flexJson is used by one of the library included in the project.
In general you should ensure that all fields which are used for generating JSON through reflection are covered by a keep rule. Otherwise the name in the JSON can change from build to build. Also R8 use the property that the JVM and Android runtimes allow fields of different types to have the same name, you can end up in the situation described here.
One option could be to annotate all classes which are serialized, and use a keep rule like this:
-keep class #MyAnnotation ** {
<fields>;
}
or if all these classes are in a separate package:
-keep class com.example.mypackage.serialized_classes.** {
<fields>;
}

Finotes not reporting issues

I am using Automated bug reporting SDK finotes in android.
I had integrated the sdk and it was reporting issues during development
but I created a release build for testing. Looks like it is not reporting issues anymore.
Any help will be appreciated.
As per their documentation make sure that you add the following in your pro-guard configuration
-keep class com.finotes.android.finotescore.* { *; }
-keepclassmembers class * {
#com.finotes.android.finotescore.annotation.Observe *;
}
Also make sure that, in init() function doesn’t have their dry run turned ON
dryRun flag will prevent the issues from syncing to their dashboard.
For release build, change init() in Application class to,
Fn.init(this);

Android app size increased after adding admob ads using google-play-services_lib

I'm gonna publishing my app in two versions, both paid and free (with AdMob ads).
The two versions are exactly identical except for the google-play-service_lib that i use in the free version for AdMob services.
The final apk sizes after using proguard are:
1.301.435 bytes for paid version
1.946.634 bytes for ads version
In free version i show interstitial ads only.
Here's my proguard settings relative to the google-play-service_lib
-keep class * extends java.util.ListResourceBundle {
protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
public static final *** NULL;
}
-keepnames #com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
#com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
Is there something i can do to reduce file size like removing some -keep flags or what?
EDIT
Using apktool i discovered that none of the classes from the Google Play Service package has been shrinked (including com.google.android.gms.maps.*, com.google.android.gms.games.* and many others that i think are not needed for Ads management).
How to force shrink a class or a class group?
EDIT (again)
It looks like Eclipse doesn't keep Proguard output, at least i couldn't see it anywhere. I then configured my projects and libs to be build using Ant to see some output, but it's almost unsubstantial, these are two cases:
-whyareyoukeeping class com.google.android.gms.maps.GoogleMap
[proguard] Explaining why classes and class members are being kept...
[proguard] Printing usage to [...../bin/proguard/usage.txt]...
[proguard] com.google.android.gms.maps.GoogleMap
[proguard] is not being kept.
(at least i read that class is not been kept, although i can see it using apktool!) and
-whyareyoukeeping class com.google.android.gms.games.Games
[proguard] Explaining why classes and class members are being kept...
[proguard] Printing usage to [...../bin/proguard/usage.txt]...
here nothing is said about given class.
I'm giving up, for a single interstitial my app increases his size by 50%, although Google about GPS states:
The client library has a light footprint if you use ProGuard as part
of your build process, so it won't have an adverse impact on your
app's file size.
and no-where i could find a guide for it!
it is nothing to do with proguard.
as you know, google play service is close source. proguard can't handle it without source
code. but you can shrink it manually.
1, remove unused class from jar file
in the folder of google play service, typically sdk\extras\google\google_play_services
\libproject\google-play-services_lib\libs\,
open google-play-services.jar with zip file manager such as 7zip, you can find many
folder such as maps, games and so on witch is no use for you if you only use ads. so just
delete them. be careful to keep ads, common, dynamic, internal and location folder otherwise you will get fc of NoClassDefFoundError when show ads.
2, remove unused resource from res folder if you only use ads.
many resource in google-play-services_lib\res folder is no use for you, you can remove it. such as values-af, values-am, .... what you need to keep is color, drawable, drawable-hdpi and values folder.
3, now refresh and build the google-play-services_lib project in your eclipse, then refresh
and build your project again. now you shold find the apk size get smaller. the size of my
apk go down from 902kb to 480kb before proguard, and 330kb after proguard.
did u use this line in your build.gradle file?
compile 'com.google.android.gms:play-services:6.+'
if yes then supplement it with this line
compile 'com.google.android.gms:play-services-ads:6.+'
It reduces the app size by around 600kb.
Some other part of your proguard config is causing the GPS classes to be retained.
Have a look at Proguard Usage especially the option
-whyareyoukeeping class_specification
You can use that to tell uyou why particualr classes are being kept if you can't spot it yourself.

Categories

Resources