当前位置: 首页 > 面试题库 >

应用程序可以在Eclipse中进行调试/运行,但是.APK在解析包含自定义View的XML布局时会给出.classNotFoundException

史阳晖
2023-03-14
问题内容

当通过Eclipse通过USB安装应用程序时,我的应用程序将在目标设备(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

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

万一这可能是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 <methods>;
}

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

-keepclasseswithmembernames 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 *;
}

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

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <ImageView   
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="top|left"
    android:scaleType="centerCrop"
    android:id="@+id/dashLayoutImage"
    android:src="@drawable/background2" android:drawingCacheQuality="high"/>

    <com.trevp.myAppName.DashboardLayout
    android:clipChildren="false"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/dashLayout"
    android:layout_gravity="top|left" />

    <include
    android:layout_gravity="top|left"
    layout="@layout/status_bar"
    android:id="@+id/statusBar" />

    <TextView
    android:layout_gravity="bottom|left"
    android:id="@+id/pollRate"
     android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    </TextView>

</merge>

在此先感谢您提供任何提示。如果需要其他摘要或配置信息,请大声喊叫。


问题答案:

现在,通过使用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 <methods>;
}

-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.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 <init>(android.content.Context, android.util.AttributeSet);
}

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

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



 类似资料:
  • 我使用Gradle构建了一个jar文件。它在“Gradle Run”中运行得很好,但是当我在Eclipse中运行它时(运行->外部工具->外部工具配置),我在一个Spring类上得到了NoClassDefoundError。 这是大楼。格雷德尔: 我查看了jar文件,它没有依赖的jar,这就是为什么在Eclipse中运行时出现NoClassDefinition错误的原因。我也尝试过在本地包含这些J

  • 我有应用程序上传在玩商店。它在调试模式下运行良好,但当我从play store下载相同的APK(发布模式)时,它就崩溃了。我无法确定堆栈跟踪没有给出准确的错误位置。 java.lang.RuntimeException:在Android.os.AsyncTask$3上完成(asynctask.java:318)在java.util.concurrent.FutureTask.FinishCompl

  • 问题内容: 在Java中,是否可以在应用程序运行时动态创建类定义,然后创建该类的对象? 例如,正在运行的应用程序将读取一个文本文件,该文件包含要包含在新类中的类成员列表。然后,应用程序将基于成员列表定义类定义,然后使其实例化。 问题答案: 是的,这样做是有可能的,从理论上讲,您的类文件是字节代码,而字节代码最后是字节数组!然后可以使用defineClass(String,byte [],int,i

  • 我正在使用flutter和firebase OTP。在运行我的应用程序的调试APK时收到SMS。但是,我在使用命令运行发布APK时收到了此消息。 这是返回的消息: 此应用程序未经授权使用Firebase身份验证。请验证Firebase控制台中是否配置了正确的包名称和SHA-1。[传递了safety_net_token,但没有在Firebase控制台中注册匹配的SHA-256。请确保此应用程序的pa