【问题标题】:ClassNotFoundException for a ContentProviderContentProvider 的 ClassNotFoundException
【发布时间】:2011-06-10 07:31:51
【问题描述】:

我有一个 ContentProvider 类,在 AndroidMenifest.xml 中声明如下:

<provider android:name=".MediaSearchProvider"
    android:authorities="org.iii.romulus.meridian.mediasearch">
    <path-permission android:path="/search_suggest_query"
        android:readPermission="android.permission.GLOBAL_SEARCH" />
</provider>

它在大多数设备上运行良好,但市场告诉我一些用户在使用它时遇到了错误。堆栈跟踪是:

java.lang.RuntimeException: Unable to get provider org.iii.romulus.meridian.MediaSearchProvider: java.lang.ClassNotFoundException: org.iii.romulus.meridian.MediaSearchProvider in loader dalvik.system.PathClassLoader[/mnt/asec/org.iii.romulus.meridian-1/pkg.apk]
at android.app.ActivityThread.installProvider(ActivityThread.java:4509)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:4281)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4237)
at android.app.ActivityThread.access$3000(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2071)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: org.iii.romulus.meridian.MediaSearchProvider in loader dalvik.system.PathClassLoader[/mnt/asec/org.iii.romulus.meridian-1/pkg.apk]
at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
at android.app.ActivityThread.installProvider(ActivityThread.java:4494)
... 12 more

我完全不知道发生了什么,我无法在我的任何手机上重现它。我也尝试过清理和构建,但报告仍然出现。 任何人都可以帮忙吗?谢谢!

【问题讨论】:

  • 您在发布版本时是否在运行 proguard 混淆?这有时会导致这种问题,因为它会更改类名,然后在运行时无法解决。在清单中声明或使用反射引用的任何内容都必须从 proguard 混淆中排除。
  • 是的,我正在运行 Proguard。我会检查一下,非常感谢。

标签: android


【解决方案1】:

关于 proguard 的答案不正确。这将导致每部手机每次都出现容易重现的错误,因为 ContentProvider 类将完全丢失。开发人员明确表示他们无法重现该错误,这意味着 ContentProvider 类存在,但由于某种原因在其用户的一部手机上找不到。

我的应用在市场上报告了同样的崩溃。堆栈跟踪看起来相同,并且错误发生在 installProvider。我的办公室里有大约 15 部测试手机,但没有一部可以重现此问题。任何其他想法将不胜感激。

仅当您的 java 包名称与您的 android 包名称不同时,才需要清单中的完全限定名称。如果未指定完全限定名,操作系统会自动将 android 包名添加到清单中指定的类名。

【讨论】:

  • 我看到了一篇有趣的文章。此错误在页面底部讨论:ContentProvider Class Not Found
  • 我也在市场上看到过这个报道,并同意它与 Proguard 无关。如果是这样,它总是可以重现的。它通常在升级时突然出现。
  • 可以很容易地检查它是否是proguard问题 - 在调试模式下工作/在发布模式下不工作=它的proguard问题
  • 我刚刚在我自己的应用程序中修复了它:1) 属性 -> Java 构建路径 -> 删除所有列出的 jar(“Android 依赖项”和“Android 私有库”除外)。 2)将我的项目中的“lib”文件夹重命名为“libs” 3)清理并重建所有。部署到我的调试设备上,效果很好! (在执行上述 3 个步骤之前,我反复看到 ClassNotFoundException)。
  • 我有 name 属性的完全限定包路径。但是,我仍然在 android KitKat 4.4.4 上遇到错误。这是错误堆栈git.io/fNXhm。请检查它。
【解决方案2】:

确保您在 AndroidManifest.xml 中指定了正确的限定类名称,它必须是这样的:

<provider
    android:authorities="org.iii.romulus.meridian.mediasearch"
    android:name="org.iii.romulus.meridian.MediaSearchProvider">
</provider>

注意@name 是完全限定的。

【讨论】:

  • 为什么需要全称?某些设备存在无法识别非完全限定名称的错误?
  • 这是我的问题。我以为我已经指定了所有内容,但是“名称”属性是“.BlahMyProvider”,并且它没有恰好位于应用程序的顶级包中,从而产生了 ClassNotFound
  • 我有 name 属性的完全限定包路径。但是,我仍然在 android KitKat 4.4.4 上遇到错误。这是错误堆栈git.io/fNXhm。请检查它。
【解决方案3】:

这听起来类似于我遇到的由 ClassLoader 问题引起的问题,请参见此处:Bizarre behaviour when using Apache Commons lib in Android

This bug 讨论了与类加载器有时失败有关的错误。我的解决方法是添加这一行:

Thread.currentThread().setContextClassLoader(this.getClassLoader());

在调用失败代码的类的构造函数中。

【讨论】:

    【解决方案4】:

    Proguard 默认使用此行排除所有继承的内容提供程序(确保它在您的 cfg 中):

    -keep public class * extends android.content.ContentProvider
    

    如果您有任何其他继承,您也应该排除它或排除您的特定 Content Provider 类,例如:

    -keep public class org.iii.romulus.meridian.MediaSearchProvider
    

    【讨论】:

      【解决方案5】:

      这是一个旧线程,OP 没有与我相同的 ContentProvider 声明,但我有同样的错误,所以我想分享我的发现,以防它帮助任何人。

      对我来说,导致问题的原因是 AndroidManifest.xml 中的 ContentProvider 声明将 exported 属性设置为 true

      android:exported="true"

      删除它为我解决了问题。 (我真的不需要它)

      【讨论】:

        【解决方案6】:

        如果您的应用程序已经变得足够大,需要进行 Multidexing,并且您的应用程序未正确设置为 Multidex 应用程序,您将收到此错误。要将您的应用设置为 multidex 应用,请按照以下说明操作:

        Setup multidex app

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-24
          • 2013-08-04
          相关资源
          最近更新 更多