应用程序在Eclipse的调试/运行中工作,但.APK在解析包含自定义视图的XML布局时给出.classNotFoundException

当应用程序通过USB从Eclipse安装时,我的应用程序将在我的目标设备(HTC Desire HD)上进行完全调试和运行。

但是,当我导出到.APK然后在我的Desire HD上安装此.APK(首先手动卸载我之前安装的应用程序)时,它崩溃了。

检查过Logcat中的错误后,我可以看到我的自定义扩展View ,它在布局XML文件中使用其完全限定名称引用,显然无法找到并导致.classNotFoundException

Logcat错误跟踪中的两条关注线是:

04-09 21:29:01.101: E/AndroidRuntime(2157): Caused by: android.view.InflateException: Binary XML file line #12: Error inflating class com.trevp.myAppName.DashboardLayout

以下进一步说明:

04-09 21:29:01.101: E/AndroidRuntime(2157): Caused by: java.lang.ClassNotFoundException: com.trevp.myAppName.DashboardLayout in loader dalvik.system.PathClassLoader[/data/app/com.trevp.myAppName-1.apk

只有从导出的.APK安装应用程序时,才会从Eclipse安装此应用程序时发生此崩溃。

如果这可能是Proguard问题,这是我的Proguard配置文件。 我没有真正触及默认设置,因为我刚开始使用Proguard。 我的Proguard版本是4.7。

 -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -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.licensing.ILicensingService -keepclasseswithmembernames class * { native ; } -keepclasseswithmembernames class * { public (android.content.Context, android.util.AttributeSet); } -keepclasseswithmembernames class * { public (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 *; } 

正在膨胀的XML文件。 (使用Merge标记,因为其中的元素作为子元素添加到父FrameLayout 。)

         

提前感谢您提供此任何提示。 如果需要任何其他摘录或配置信息,请大声说出来。

现在通过使用从新创建的测试项目中获取的完全标准和默认的proguard.cfg文件来修复此问题。

我之前使用的配置文件,正如我原来的问题所引用的那样,我不得不在短时间内手动添加到项目中,因为它丢失了。 我不确定文件来自何处 – 我最有可能使用Google搜索并找到了一个示例默认文件并使用它。

这是Eclipse为我提供的新项目,它启用了一个有效的.APK。

 -optimizationpasses 5 -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* -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.licensing.ILicensingService -keepclasseswithmembernames class * { native ; } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } 

我可以看到差异在-keepclass*类型指令中。

我现在将更加努力地了解如何配置Proguard!

为了感兴趣,请看以下几行:

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

这些看起来像是保存View构造函数(或保留包含它们的类),只有在从XML引用类时才会调用它们。

在使用merge进行视图膨胀时,不要将attachToRoot设置为true可能是InflateException的原因。

或者你可以用$ {sdk.dir} /tools/proguard/proguard-android.txt中的默认值替换项目中的那个。