Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

Fix ProGuard config #572

Open
Tracked by #525
sk22 opened this issue Jun 13, 2023 · 2 comments
Open
Tracked by #525

Fix ProGuard config #572

sk22 opened this issue Jun 13, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@sk22
Copy link
Owner

sk22 commented Jun 13, 2023

I just temporarily disabled the "minifyEnabled" option in build.gradle to avoid all the crashes regarding #571 and released this as version 95 on the Play Store (the build is otherwise identical to version 94, and I think the build config is now actually equivalent with the config for the GitHub release).

Now ideally, of course, I'd like to re-enable ProGuard, but there appears to be some rules missing. (proguard-rules.pro is located here: https://github.com/sk22/megalodon/blob/main/mastodon/proguard-rules.pro)

Version 93's error message showed this stack trace:

Exception java.lang.ExceptionInInitializerError:
  at org.joinmastodon.android.GlobalUserPreferences.load (GlobalUserPreferences.java:95)
  at org.joinmastodon.android.MastodonApp.onCreate (MastodonApp.java:30)
  at android.app.Instrumentation.callApplicationOnCreate (Instrumentation.java:1211)
  at android.app.ActivityThread.handleBindApplication (ActivityThread.java:7094)
  at android.app.ActivityThread.access$1600 (ActivityThread.java:276)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2131)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:210)
  at android.os.Looper.loop (Looper.java:299)
  at android.app.ActivityThread.main (ActivityThread.java:8293)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:556)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1045)
Caused by java.lang.RuntimeException: Missing type parameter.
  at com.google.gson.reflect.TypeToken.getSuperclassTypeParameter (TypeToken.java:84)
  at com.google.gson.reflect.TypeToken.<init> (TypeToken.java:62)
  at org.joinmastodon.android.GlobalUserPreferences$1.<init> (GlobalUserPreferences.java)
  at org.joinmastodon.android.GlobalUserPreferences.<clinit> (GlobalUserPreferences.java:65)

…which was resolved by adding the missing ProGuard rules for Gson:

# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken

Then, there was this error:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to org.joinmastodon.android.model.HeaderPaginationList
	at org.joinmastodon.android.api.requests.HeaderPaginationRequest.validateAndPostprocessResponse(SourceFile:17)
	at org.joinmastodon.android.api.MastodonAPIController$1.onResponse(SourceFile:177)
	at okhttp3.RealCall$AsyncCall.execute(SourceFile:174)
	at okhttp3.internal.NamedRunnable.run(SourceFile:32)

…which could be resolved by adding this line:

# i don't know how proguard works
-keep public class * extends java.util.ArrayList

But this error is still unresolved:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to org.joinmastodon.android.model.Filter
	at org.joinmastodon.android.api.CacheController$$ExternalSyntheticLambda4.test(SourceFile:0)
	at j$.util.stream.Q1.accept(SourceFile:0)
	at j$.util.U.b(SourceFile:0)
	at j$.util.stream.c.p0(SourceFile:0)
	at j$.util.stream.c.Q0(SourceFile:0)
	at j$.util.stream.v0.H(Unknown Source:4)
	at j$.util.stream.c.T0(SourceFile:0)
	at j$.util.stream.W1.collect(SourceFile:0)
	at org.joinmastodon.android.api.CacheController.lambda$getHomeTimeline$3(SourceFile:61)
	at org.joinmastodon.android.api.CacheController.$r8$lambda$g-uVY2ox275rVKKmEKpWKndW6LA(SourceFile:0)
	at org.joinmastodon.android.api.CacheController$$ExternalSyntheticLambda2.run(SourceFile:0)
	at android.os.Handler.handleCallback(Handler.java:942)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loopOnce(Looper.java:201)
	at android.os.Looper.loop(Looper.java:288)
	at me.grishka.appkit.utils.WorkerThread.run(SourceFile:54)

It seems to occur while it's trying to read the filters list,

List<Filter> filters = AccountSessionManager.getInstance()
    .getAccount(accountID).wordFilters.stream()
    .filter(f->f.context.contains(Filter.FilterContext.HOME)).collect(Collectors.toList());

which is loaded from the respective account.json file on startup (https://github.com/sk22/megalodon/blob/main/mastodon/src/main/java/org/joinmastodon/android/api/session/AccountSessionManager.java#L94, gson is initialized in https://github.com/sk22/megalodon/blob/main/mastodon/src/main/java/org/joinmastodon/android/api/MastodonAPIController.java#L52):

SessionsStorageWrapper w=MastodonAPIController.gson.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), SessionsStorageWrapper.class);
for(AccountSession session:w.accounts){
	domains.add(session.domain.toLowerCase());
	sessions.put(session.getID(), session);
}
@sk22 sk22 added the bug Something isn't working label Jun 13, 2023
@migdol
Copy link

migdol commented Jun 13, 2023

After some tinkering (pulling the right commit for appKit, supply temporary signing credentials), I was able to compile the app. It didn't crash at launch for myself, but I did notice crashes when navigating to other portions of the app such as settings. The errors I witnessed involved instantiating Fragment classes in calls to Nav.go. I added the following to ProGuard to address this crash issue. It works by skipping Fragment classes during the minify and obfuscation step.

-keep class org.joinmastodon.android.**.*Fragment { *; }

For reference, I tested on a Pixel 6 emulator running API 33.

@sk22
Copy link
Owner Author

sk22 commented Jun 15, 2023

@migdol

-keep class org.joinmastodon.android.**.*Fragment { *; }

unfortunately, this didn't really seem to help.. most of the crashes happen after having restarted the app once - throwing this exception when loading (previously loaded and saved) filters:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to org.joinmastodon.android.model.Filter

anyway, seems like @LucasGGamerM's fix works fine (even though it just keeps everything). i think i'll just keep this line until i know what exactly i'd need to app to prevent the errors from happening

-keep class org.joinmastodon.android.** { *; }

sk22 added a commit that referenced this issue Jun 15, 2023
@sk22 sk22 mentioned this issue Aug 22, 2023
2 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants