这对我来说是一个谜。我不知道如何调试这种情况:
我遇到的问题是在“PreferenceFragment”类中。我开发了一个带有首选项标题的经典“设置”界面:
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<header
android:fragment="debut.telebox.Config$PrefSystemeFragment"
android:icon="@drawable/ic_action_prefsysteme"
android:title="Paramètres Système"
android:summary="Paramètres système"
/>
<header
android:fragment="debut.telebox.Config$PrefChainesFragment"
android:icon="@drawable/ic_action_preffavoris"
android:title="Paramètres pour les chaînes"
android:summary="Favoris"
/>
<header
android:fragment="debut.telebox.Config$PrefAproposFragment"
android:icon="@drawable/icon"
android:title="A propos"
android:summary="A propos de TeleBox"
/>
PreferenceActivity是:
public class Config extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}
@Override
public void onDestroy() {
super.onDestroy();
...
}
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.layout.prefentete, target);
}
public static class PrefSystemeFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
当我使用Eclipse直接在测试设备(Android 4.0.4下的Xoom和Nexus S)上运行此应用程序时,我没有问题:我能够读取和写入参数。
但是当我导出应用程序然后在设备上运行它时,我收到运行时错误:
05-17 17:30:12.680: E/AndroidRuntime(6391): at dalvik.system.NativeStart.main(Native Method)
05-17 17:30:12.680: E/AndroidRuntime(6391): Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment debut.telebox.Config$PrefSystemeFragment: make sure class name exists, is public, and has an empty constructor that is public
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.app.Fragment.instantiate(Fragment.java:581)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.preference.PreferenceActivity.switchToHeaderInner(PreferenceActivity.java:1117)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.preference.PreferenceActivity.switchToHeader(PreferenceActivity.java:1150)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.preference.PreferenceActivity.onCreate(PreferenceActivity.java:551)
05-17 17:30:12.680: E/AndroidRuntime(6391): at debut.telebox.Config.onCreate(Unknown Source)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.app.Activity.performCreate(Activity.java:4465)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
05-17 17:30:12.680: E/AndroidRuntime(6391): ... 11 more
05-17 17:30:12.680: E/AndroidRuntime(6391): Caused by: java.lang.ClassNotFoundException: debut.telebox.Config$PrefSystemeFragment
05-17 17:30:12.680: E/AndroidRuntime(6391): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
05-17 17:30:12.680: E/AndroidRuntime(6391): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
05-17 17:30:12.680: E/AndroidRuntime(6391): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
05-17 17:30:12.680: E/AndroidRuntime(6391): at android.app.Fragment.instantiate(Fragment.java:571)
05-17 17:30:12.680: E/AndroidRuntime(6391): ... 18 more
05-17 17:30:12.680: W/ActivityManager(161): Force finishing activity debut.telebox/.Config
05-17 17:30:12.690: W/ActivityManager(161): Force finishing activity debut.telebox/.TeleBox
不幸的是,我在Google Play上传了自己的应用,却没有发现它无效......
答案 0 :(得分:5)
如果它在调试模式下工作而不是在导出时,ProGuard可能已经做了一些事情来破坏你的类名。将以下行添加到项目中的proguard-project.txt
文件中:
-keep class debut.telebox.** { *; }
看看是否有帮助。
如果没有,只需将PreferenceFragment
类移动到单独的公共Java类中,而不是使用静态内部类,并查看是否有帮助。
答案 1 :(得分:0)
我用-keep class android.support.v4.** { *; }
答案 2 :(得分:0)
由于我无法添加注释,我想添加到CommonsWare的答案中,我注意到在java文件上没有引用类时会发生这种情况,因为Proguard的默认行为是删除未引用的类以进行空间优化。
我遇到与OP原始问题完全相同的问题 - 使用头文件将PreferenceActivity与PreferenceFragment的自定义扩展接口,在Signed build上调试和ClassNotFoundException时使用。显然,ADT生成的源代码不会在帐户中使用android:fragment引用(但话说再说一次,自2013年8月以来我没有更新ADT)
有效的解决方案正是CommonsWare所建议的:
-keep problematicpackage.** { *; }
“problematicpackage”是我声明自定义片段的包。 ** {*; } expression包含-keep“指令”的所有内容。
有一点需要注意:您可能无法使用此“指令”获取,压缩或优化此包。我并不太关心元包装或超级版权,以至于因为应该是防故障的东西而失眠,但如果你需要这些功能,我建议你仔细阅读Proguard手册。