简体   繁体   中英

Unable to get provider : ClassNotFoundException

I have MyContentProvider in my app which works fine when I develop and run in debug mode.

<provider android:name=".MyContentProvider"
        android:authorities="com.contactcities"
        android:exported="false">
</provider>

But when I export the app, download it and run it, it crashes instantly :

10-10 18:24:37.682 E/AndroidRuntime(10428): FATAL EXCEPTION: main
10-10 18:24:37.682 E/AndroidRuntime(10428): java.lang.RuntimeException: Unable to get provider com.contactcities.MyContentProvider: java.lang.ClassNotFoundException: com.contactcities.MyContentProvider in loader dalvik.system.PathClassLoader[/system/framework/com.google.android.maps.jar:/data/app/com.contactcities-1.apk]
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.app.ActivityThread.installProvider(ActivityThread.java:4509)
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.app.ActivityThread.installContentProviders(ActivityThread.java:4281)
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4237)
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.app.ActivityThread.access$3000(ActivityThread.java:125)
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2071)
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.os.Handler.dispatchMessage(Handler.java:99)
10-10 18:24:37.682 E/AndroidRuntime(10428): at android.os.Looper.loop(Looper.java:123)

I can reproduce it on all my devices, 2.2, 4.0, 4.1

I have read through numerous threads today. Some of them blaming ProGuard for this. I have tried adding

-keep public class com.contactcities.MyContentProvider

but with no luck.

When I disable proguard, by not putting proguard.config=proguard.cfg in my project.properties . It still gives the same error in release version. Debug is again fine. Maybe its not enough to disable proguard like that?

Maybe the hint is that it refers to maps.jar in this crash. Im not sure why it does that

in loader dalvik.system.PathClassLoader[/system/framework/com.google.android.maps.jar

Any clues will be much appreciated

Argh, thought I tried that, but seems like I didnt.

Project -> clean made it work

face palm

I was getting the same error, turns out I had the wrong android:name attribute value for my provider tag in AndroidManifest.xml :

<provider
    android:authorities="com.example.ProviderClass"
    android:name=".ProviderClass"
    android:exported="false" >
</provider>

So double check this value is as above .ProviderClass or whatever your class name is (prefixed with a dot). Then do Project > Clean and it will work.

The authorities attribute needs to match the content authority while the name attribute needs to match the class name of your Custom Provider class.

For eg:

      <provider
         android:authorities="com.richa.myapp"
         android:name=".data.CustomProvider"/>

Maybe my inexperience will help someone else with this bug. It was utterly cryptic to me, but like everything in computers obvious once you know.

I was following this tutorial, which is overall very good: http://www.vogella.com/tutorials/AndroidSQLite/article.html

Early on, he says to create a package called "contentprovider" and then a class within it "MyTodoContentProvider". Now anyone familiar with Java-style naming conventions would have seen this was supposed to be relative to the main package. But I was new to this all, so I created it over on the side somewhere.

All through building the code, things worked fine. Eclipse found and included this package, and showed no errors. Then the crash and the cryptic "Unable to get provider" message. The path in the error message, which I now understand was the non-existent path where the code was looking for the class, was so long and contained so many iterations of "contentprovider" it was hard to see what it was referring to or what was wrong with it.

I suspected the problem was in the manifest file, but I was sure it was in "android:authority". That was a bit non-intuitive. The string in this element in the manifest corresponds to a public member you expose in your provider class. That member is named "CONTENT_URI". But the two do not exactly match. For example:

private static final String AUTHORITY = "com.vegnab.provider";
private static final String BASE_PATH = "todos";
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/" + BASE_PATH);

This ends up with:

CONTENT_URI = "content://com.vegnab.provider/todos"

(Note that AUTHORITY itself is a private member, not externally available.)

The corresponding manifest line would be:

android:authorities="com.vegnab.provider"

This is the middle part between the scheme "content://" and the base path.

The problem was actually in the manifest line:

android:name=".contentprovider.MyTodoContentProvider"

I had an error-free class named "MyTodoContentProvider" in a package named "contentprovider", so what was the problem? The problem was that the package was in the wrong place. It was supposed to be relative to the main package. That's what the dot, first in the name, means. It should follow the same syntax as the "android:name" lines of the activities, in their sections of the manifest.

If you find this useful, please one-up. Once you solve this problem, it's easy to forget how cryptic it was.

You might have passed your class limit on older OS versions—before Android 5.0 (API level 21) replaced the DEX runtime with ART. If you're right on the edge of the limit, you can pass compilation but get this error during startup.

Try enabling multi-dex as described in the Android Enable Multidex for Apps with Over 64K Methods documentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM