I'm doing a small Android Application, currently the apk has 382KB, and I'm using OkHttp, looking inside the apk, the Okhttp inserts a file publicsuffixes.gz that has 33Kb (8~9% of total apk size).
If I exclude the file with the follow code the application crashes, so it obviously necessary, my question is, what is the function of that file and is it possible to replace or modify to reduce the size?
The exclude code:
android {
...
packagingOptions {
exclude "publicsuffixes.gz"
}
}
Firstly, this shouldn't fail if you don't configure your client to support cookies. Can you provide a stacktrace of it failing?
If you need cookies but don't care about security (YOLO!) I suspect you could hack something up by modifying https://github.com/square/okhttp/blob/9bfe575960af8e7bb164642f2f513b5ccb39ff4f/okhttp/src/test/java/okhttp3/internal/publicsuffix/PublicSuffixListGenerator.java
To have a basically empty file. It seems like a bad idea, but caveat emptor. You will break security around Cookie handling, which may or may not be acceptable to you.
in case if someone is facing HTTP FAILED: java.lang.IllegalStateException: Unable to load publicsuffixes.gz resource from the classpath issue , below given solution will work for them.
Add the following two lines to proguard-rules.pro
-keep class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
https://programmersought.com/article/25321169177/;jsessionid=A144F66609278A032E652302EB65AA95
Related
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.
All Room dependencies are aligned to version 2.3.0
I've added a Room DB migration and added two more columns to an existing table, it seems to work fine as no error appeared during normal operation.
I wanted to add some tests for the migration and did so following the official docs:
Room DB Migration Testing
However this line:
db = helper.runMigrationsAndValidate(TEST_DB, 2, true, MIGRATION_1_2);
will throw a
java.lang.AbstractMethodError: abstract method "void androidx.room.RoomOpenHelper$Delegate.onPreMigrate(androidx.sqlite.db.SupportSQLiteDatabase)"
I went down the rabbit hole and indeed androidx.room.testing.MigrationTestHelper.MigratingDelegate does not implement onPreMigrate
Does anyone have an actual sample with migration and testing showing off how it should work ?
Am I totally off or are the docs wrong already on the dependency:
testImplementation "androidx.room:room-testing:$room_version"
should probably be androidTestImplementation
since it's a on-device test ? Googling didn't serve any results, so does that mean that nobody actually uses the package ?
I finally found the issue, it was Proguard/minification.
First I tried to disable it for the test-apk all together, by adding testProguardFile 'proguard-test.pro' to my build.gradle, with proguard-test.pro containing
-dontoptimize
-dontobfuscate
-keepclasseswithmembers class ** { *; }
(don't really need any minification for the test-apk) but that didn't do the trick.
Since androidx.room.testing.MigrationTestHelper.MigratingDelegate does not override androidx.room.RoomOpenHelper$Delegate.onPreMigrate the proguard rule has to actually go to the regular proguardFile (for the APK under test). I added
-keepclassmembers class androidx.room.RoomOpenHelper$Delegate { *; }
and it's working now.
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've an Android app using retrofit 2 and okhttp for its json requests. everything was going fine until android studio(AS) oferred me the update from 3.9.6 to 4.1
The update is done easily inside the AS and it also updates the gradle plugin.
Once the update was finished I rebuild and compiled a new aab, then i notice the new file generated was 100kb smaller than the previous one (altough no code or assets changes were made, only the IDE version updated)... then i release on google play and download it in my test device (real phone). It didn't work. The app opens but it is not able to perform any okhttp request
I tried to run inside AS emulator -> it worked fine.
I tried to run in the emulator with minifyEnabled true shrinkResources true -> it worked fine
so i added to the code several debug calls in order to let me know exaclty until what line the app was working.... and i got.
try {
okHttpClient.newCall(new Request.Builder().get().url("https://www.google.com").build()).execute();
return true;
} catch (Exception e) {
return false;
}
this is a little snippet i use to test if user has internet connection.
No exception is thrown, no value is returned, the call simple dive into the okhttp api and never come back...
So i want to let clear: no code was changed, no api was updated, no r8 rules was changed
the only thing changed was the AS updated from 3.9.6 to 4.1 and some mandatory gradle plugin updated as well
after that the signed aab built got 100kb smaller and this very weird behavior started happening...
I've already tried EVERYTHING i can, but still no idea how to solve. does anyone ever face a similar problem or have idea what to do?
there are my imports
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation('com.facebook.android:facebook-login:5.13.0') {
exclude group: 'com.android.support', module: 'appcompat-v7'
}
//retrofit
implementation('com.squareup.retrofit2:retrofit:2.9.0') {
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
implementation "com.squareup.okhttp3:okhttp:4.10.0-RC1"
implementation 'com.squareup.okio:okio:2.9.0'
implementation 'com.google.code.gson:gson:2.8.6'
implementation('com.squareup.retrofit2:converter-gson:2.9.0') {
exclude group: "com.google.code.gson", module: "gson"
}
I've already tried EVERYTHING i can, but still no idea how to solve. does anyone ever face a similar problem or have idea what to do?
Yes, everyone faces these problems. It's part of the learning process of being a developer. Stop focusing on this particular problem with this library for a minute and ask why you are stuck and how to get unstuck. If you reported this to a library maintainer this is what they would need to do, which is why they would ask for a clean reproduction.
Firstly read http://sscce.org/ and understand what it means and why the above question isn't getting answers. It's not a clean reproduction, it's a few random lines of code.
Then ask a a colleague to help you use a debugger, where is it stuck, what are the threads doing or waiting on.
Use the features of the library e.g. add an OkHttp Event Listener https://square.github.io/okhttp/events/.
Going back the SSCCE example, make a small example project reproducing the issue and post it to a temporary github project, then report that as a bug to OkHttp project. They can just check out the project and run it to reproduce then.
For me, I was trying to fetch data using a retrofit. Getting 400 on release build. My model was like the following:
data class ContentIdAddRQ(
#SerializedName("contentId")
val contentId: String? = null,
#SerializedName("contentType")
val contentType: String? = "VOD",
)
Then I tried adding #Keep annotation to my Model file as shown below:
#Keep
data class ContentIdAddRQ(
#SerializedName("contentId")
val contentId: String? = null,
#SerializedName("contentType")
val contentType: String? = "VOD",
)
After setting up the Sentry.io error tracking I get this error when I try to Generate Signed Apk:
Java Compiler
error: An organization slug is required (provide with --org)
Click on this image and open it to see more details:
I cannot understand anything from this one:
Process 'command
'/var/folders/j4/_fzm1rks3tsc2h3j4l2qbq4w0000gn/T/.sentry-cli1369818638611304938.exe'
' finished with non-zero exit value 1
This is the file address that was raised in error:
How can I solve this problem and Generate Signed Apk?
The docs are not a bit clear, though its mentioned but easy to miss it. There are two different sentry.properties required here.
Please note the sentry.properties in your project root that configures sentry-cli is different than the one you include in your application resources to configure the Sentry SDK at runtime (as seen in the configuration documentation).
You need to have another sentry.properties file in the project root with
defaults.project=your-project
defaults.org=your-org
auth.token=YOUR_AUTH_TOKEN
and the runtime sentry.properties with DSN values, etc can be placed in app/src/main/resources directory(create resource directory if required)
Config Docs
You need to upload the Proguard mapping file to the sentry server.
create a file in the root project folder and set name sentry.properties.
defaults.url=https://sentry.io
defaults.org=TEST
defaults.project=TEST_DEV
auth.token=TOKEN
replace TEST, TEST_DEV, and TOKEN.
you can get TOKEN from https://sentry.io/api
if you are use custom sentry server, replace https://sentry.io to your server adddress.
and change file build.gradle
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.2'
classpath 'io.sentry:sentry-android-gradle-plugin:1.7.27'
}
}
and
apply plugin: 'com.android.application'
apply plugin: 'io.sentry.android.gradle'
...
sentry {
autoProguardConfig true
autoUpload true
}
android {
...
}
dependencies {
...
implementation 'io.sentry:sentry-android:1.7.27'
implementation 'org.slf4j:slf4j-nop:1.7.25'
...
}
When you enable Proguard minification, symbols are uploaded to Sentry.
This upload is done via the sentry-cli, which is throwing the error. The error says the CLI doesn't know which project within Sentry to associate your symbols with.
You need to make sure to go through the gradle integration in the docs.
Specifically:
defaults.project=airflow
defaults.org=sentry
auth.token=YOUR_AUTH_TOKEN
Alternatively you can use sentry-cli directly to upload symbols, although the gradle integration is advised.
For ReactNative/iOS, if you have such errors check that you put sentry.properties file in iOS folder
I also stranded here whilst trying to figure what was going wrong with my sentry source map uploads (not on android, but for web with a similar error). To debug my events that weren't matched, I was using the sentry-cli like so;
So I was searching how I could add the organization slug to my source map uploads. But this error wasn't about the event, but for using the explain CLI functionality itself!!! Which confused me.
I had to pass additional parameters to the CLI script to get the actual problem with the event;
Maybe this will help someone else who also skipped over the docs 😅
instead of making
minifyEnabled false
Just add these rules to proguard rules file and keep minifyEnabled true
#sentry
-keepattributes LineNumberTable,SourceFile
-dontwarn org.slf4j.**
-dontwarn javax.**
-keep class io.sentry.event.Event { *; }
That solved my issue without disabling minification
IT IS NOT A REAL ANSWER But it can solve our problem in the short term by setting false value to minifyEnabled.
app/build.gradle:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
but it added 1.3MB to the size my of Apk file.
Please let me know if anyone has a different better solution.