我遇到Proguard
混淆问题。我的(内联)java方法只从JNI调用一次,尽管它是从循环中调用的。
循环的第一次迭代运行良好,但在第二次迭代(textureCount
> 1)上,应用程序似乎没有输入getTexture
方法 - 这导致我的应用程序崩溃{{ 1}}因为Texture::create(env, textureObject)
为NULL。
要说清楚 - 未启用textureObject
- 一切正常。
在我的JNI代码中
ProGuard
proguard.cfg
JNIEXPORT void JNICALL
Java_com_example_MyApp_initApplicationNative(JNIEnv* env, jobject obj) {
// Handle to the activity class:
jclass activityClass = env->GetObjectClass(obj);
jmethodID getTextureCountMethodID = env->GetMethodID(activityClass, "getTextureCount", "()I");
if (getTextureCountMethodID == 0) {
LOG("Function getTextureCount() not found.");
return;
}
textureCount = env->CallIntMethod(obj, getTextureCountMethodID);
if (!textureCount) {
LOG("getTextureCount() returned zero.");
return;
}
textures = new Texture*[textureCount];
jmethodID getTextureMethodID = env->GetMethodID(activityClass, "getTexture",
"(I)Lcom/example/MyApp/Texture;");
if (getTextureMethodID == 0) {
LOG("Function getTexture() not found.");
return;
}
// Register the textures
for (int i = 0; i < textureCount; ++i)
{
jobject textureObject = env->CallObjectMethod(obj, getTextureMethodID, i);
if (textureObject == NULL) {
LOG("GetTexture() returned zero pointer");
return;
}
textures[i] = Texture::create(env, textureObject);
}
}
MyApp.java
-optimizationpasses 5
-dontusemixedcaseclassnames
-useuniqueclassmembernames
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# will keep line numbers and file name obfuscation
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
########## default settings #########
-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 class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.billing.IInAppBillingService
-keep public class com.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);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.content.Context {
public void *(android.view.View);
public void *(android.view.MenuItem);
}
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class **.MyApp {
native <methods>;
int getTextureCount();
com.example.MyApp.Texture getTexture(int);
}
编辑 - 解决方案
解决这个问题的原因可能是我没有通过Proguard保存Texture类名 起初我用这种方式,只保留相关的班级成员:
/**
* Returns the texture object at the specified index.
*/
public Texture getTexture(int i) {
return mTextures.elementAt(i);
}
但当我把它改为:
-keepclassmembers class **.Texture {
native <methods>;
byte[] getData();
int mWidth;
int mHeight;
....
}
这一切都成功了。
我必须说,我不确定我能解释得多,我只知道来自-keep class **.Texture { *; }
和getTexture()
命令的返回值现在正在完美运行,没有例外。
我尽量不尽可能地使用jclass textureClass = env->GetObjectClass(textureObject);
,但在这里我不确定我有更好的解决方案。