user312684
user312684

Reputation:

Obfuscate Android app with Proguard results in fatal exception when starting app on device with official download and licensing libraries

I tried to obfuscate a finished app which is written totally in C++ only the download and licensing is written in java. It works without using proguard very well, but once it is obfuscated I get following error when starting the application on the phone.

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fantasyhaze.rememory/com.fantasyhaze.rememory.Main}: android.database.sqlite.SQLiteException: no such table: MetadataColumns: , while compiling: SELECT APKVERSION,_id,DOWNLOADSTATUS,DOWNLOADFLAGS FROM MetadataColumns LIMIT 1
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1840)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1861)
    at android.app.ActivityThread.access$1500(ActivityThread.java:132)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1038)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:150)
    at android.app.ActivityThread.main(ActivityThread.java:4310)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:507)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    at dalvik.system.NativeStart.main(Native Method)
    Caused by: android.database.sqlite.SQLiteException: no such table: MetadataColumns: , while compiling: SELECT APKVERSION,_id,DOWNLOADSTATUS,DOWNLOADFLAGS FROM MetadataColumns LIMIT 1
    at android.database.sqlite.SQLiteCompiledSql.native_compile(Native Method)
    at android.database.sqlite.SQLiteCompiledSql.compile(SQLiteCompiledSql.java:92)
    at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:65)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:83)
    at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:49)
    at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1438)
    at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1406)
    at N.<init>(Unknown Source)
    at N.a(Unknown Source)
    at com.google.android.vending.expansion.downloader.impl.DownloaderService.a(Unknown Source)
    at com.fantasyhaze.rememory.GameActivity.onCreate(Unknown Source)
    at com.fantasyhaze.rememory.Main.onCreate(Unknown Source)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1804)
    ... 11 more

I used following configs in the proguard.cfg

-dontpreverify
-repackageclasses ''
-allowaccessmodification
-optimizations !code/simplification/arithmetic


-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public interface com.google.android.vending.licensing.ILicensingService

-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * implements android.os.Parcelable {
    static android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

-keepclassmembers public class com.google.android.vending.expansion.downloader.impl.DownloadsDB { 
    public static final java.lang.String * ; 
} 

When building the app it gives a few warnings, which I don't know how to resolve when using the play_licensing and play_apk_expansion stuff.

-obfuscate:
    [mkdir] Created dir: D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\bin\proguard
      [jar] Building jar: D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\bin\proguard\original.jar
 [proguard] ProGuard, version 4.7
 [proguard] Reading program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\bin\proguard\original.jar]
 [proguard] Reading program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\lib\play_apk_expansion\downloader_library\bin\classes.jar]
 [proguard] Reading program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\lib\play_licensing\library\bin\classes.jar]
 [proguard] Reading program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\lib\play_apk_expansion\zip_file\bin\classes.jar]
 [proguard] Reading program jar [C:\Android\android-sdk\tools\support\annotations.jar]
 [proguard] Reading library jar [C:\Android\android-sdk\platforms\android-15\android.jar]
 [proguard] Preparing output jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\bin\proguard\obfuscated.jar]
 [proguard]   Copying resources from program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\bin\proguard\original.jar]
 [proguard]   Copying resources from program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\lib\play_apk_expansion\downloader_library\bin\classes.jar]
 [proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [classes.jar:META-INF/MANIFEST.MF])
 [proguard]   Copying resources from program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\lib\play_licensing\library\bin\classes.jar]
 [proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [classes.jar:META-INF/MANIFEST.MF])
 [proguard]   Copying resources from program jar [D:\SlidersEdgeUniverse\FloWars\CPE\trunk\Rememory\Source\PRO_Android\lib\play_apk_expansion\zip_file\bin\classes.jar]
 [proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [classes.jar:META-INF/MANIFEST.MF])
 [proguard]   Copying resources from program jar [C:\Android\android-sdk\tools\support\annotations.jar]
 [proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate zip entry [annotations.jar:META-INF/MANIFEST.MF])

Upvotes: 0

Views: 3467

Answers (2)

MichalisB
MichalisB

Reputation: 568

I recently came upon this error, it seems that after obfuscating the code, reflection stops working on DownloadsDB class. The problem stems on the issue that inside the DownloadsContentDBHelper.onCreate method it retrieves the nested classes declared through reflection and at least on my case no classes were returned.

So I replaced the line

Class<?>[] arrayOfClass = DownloadsDB.class.getDeclaredClasses();

with

 Class<?>[] arrayOfClass = new Class[] {MetadataColumns.class, DownloadColumns.class};

manually specifying the classes required. Class fields are also accessed by name and so I instructed proguard to completely keep the class and all members:

-keep class com.google.android.vending.expansion.downloader.impl.DownloadsDB* {*;}

that seems to do the trick for me.

Upvotes: 1

Christoph Purrer
Christoph Purrer

Reputation: 31

The error message in the first posting

Unable to start activity ComponentInfo{com.fantasyhaze.rememory/com.fantasyhaze.rememory.Main}: android.database.sqlite.SQLiteException: no such table: MetadataColumns: , while compiling: SELECT APKVERSION,_id,DOWNLOADSTATUS,DOWNLOADFLAGS FROM MetadataColumns LIMIT 1

indicates that there is a problem with the SQLite database, since a required table is missing.

I would suggest to decompile the APK file with dex2jar for example and then look into the Java class files with JD-GUI to find out which Java class files a missings or have been obfuscated in a way, resulting an application crash ..

For my personal experience most problems with Proguard are related to classes where certain necessary properties have been obfuscated in a bad way or the classes have just been removed during the obfuscation process.

Statements like

-keep public class * extends android.app.Activity

in your proguard.pro file allow you to exclude classes from Proguard's obfuscation process

Upvotes: 3

Related Questions