Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Unable to get provider (ClassNotFoundException)

progrAMMaRprogrAMMaR USMember ✭✭
edited July 2017 in Xamarin.Android

I am working on a Solution in Xamarin which contains at least 4 different Android Applications.

My Goal is to create a shared content provider for all of these four apps so that I can have the Master data in one place (If an application updates that data, I can get that updated version in another app).

In Visual Studio, I have create a PCL project where I have defined the Content provider (which I can reference in all applications and do the CRUD operations).

My Content Provider is as follows:

namespace com.cybertron.android.Provider
{
    public class SectionProvider : ContentProvider
    {
        SectionDatabase sectDb;
        public const string AUTHORITY = "com.cybertron.android.Provider.SectionProvider";
        public const string SECTIONS_MIME_TYPE = ContentResolver.CursorDirBaseType + "/vnd.com.cybertron.android.sections";
        public const string SECTION_MIME_TYPE = ContentResolver.CursorItemBaseType + "/vnd.com.cybertron.android.section";
        static string BASE_PATH = "sections";
        static UriMatcher uriMatcher = BuildUriMatcher();
        public static readonly Android.Net.Uri CONTENT_URI = Android.Net.Uri.Parse("content://" + AUTHORITY + "/" + BASE_PATH);
        const int GET_ALL = 0;
        const int GET_ONE = 1;
        public static class SectionConsts
        {
            public const string SectNo = "SectNo";
            public const string KeyPos = "Key";
            public const string Date = "Date";
            public const string UnitID = "UnitID";
        }

        static UriMatcher BuildUriMatcher()
        {
            var matcher = new UriMatcher(UriMatcher.NoMatch);

            matcher.AddURI(AUTHORITY, BASE_PATH, GET_ALL); 
            matcher.AddURI(AUTHORITY, BASE_PATH + "/#", GET_ONE);
            return matcher;
        }
        public override bool OnCreate()
        {
            sectDb = new SectionDatabase(Context);
            return true;
        }        

        public override string GetType(Android.Net.Uri uri)
        {
            switch (uriMatcher.Match(uri))
            {
                case GET_ALL:
                    return SECTIONS_MIME_TYPE; // list
                case GET_ONE:
                    return SECTION_MIME_TYPE; // single item
                default:
                    throw new Java.Lang.IllegalArgumentException("Unknown Uri: " + uri);
            }
        }        
    }
}

I have referenced my project in my Xamarin Application project. I did not put the ContentProvider attribute because I learned that gives out INSALL_FAILED_CONFLICT error if two applications use the same one. Instead I put that in the manifest file as follows:

        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                        package="com.cybertron.android.bluecork"
                        android:versionCode="1" android:versionName="1.0">
          <uses-sdk android:minSdkVersion="16" />
          <application android:label="com.cybertron.android.bluecork.blueapp">
            <provider
                  android:name="com.cybertron.android.Provider.SectionProvider"
                  android:authorities="com.cybertron.android.Provider.SectionProvider"
                  android:exported="true" />
          </application>          
        </manifest>

When I try to debug this application I get an error up front (when the app starts in the emulator)

java.lang.RuntimeException: Unable to get provider com.cybertron.android.Provider.SectionProvider:
java.lang.ClassNotFoundException: Didn't find class com.cybertron.android.Provider.SectionProvider on path: DexPathList......

Can anyone tell me why I am getting this error. Secondly, I would like to know if it is possible for multiple applications to share one database on Android Systems?

Answers

  • AKythorAKythor USMember
    edited July 2017

    Hello there,

    I recently had this issue, and found that there's a slightly obscure reference that can cause this.

    If you're using a SyncAdapter (I hope you are otherwise this won't help you), then you must make sure that the Content Authority matches between this and the ContentProvider.

    Make sure that the android:contentAuthority matches between SyncAdapter settings (in syncadapter.xml) and the ContentProvider settings (in AndroidManifest.xml).

    An important second point, as I'm sure you've seen in other searches related to this issue, make sure you do a clean before building your updated solution.

    [EDIT}

    I just found a second issue.

    If you read the Xamarin docs for SimpleContentProvider you'll see there's a note near the top which mentions that you need to add an attribute to your ContentProvider class. In short, you need to add the following to the class:

        [ContentProvider(new string[] {  Namespace.for.MyContentProvider.AUTHORITY })]
    
        public class MyContentProvider : ContentProvider
        {
            public const string AUTHORITY = "com.example.android.provider";
            ...
    

    Once you've done that, you can remove the declaration from AndroidManifest.xml, as Xamarin will add it for you.

  • AKythorAKythor USMember

    Ensure that (if you have one), your SyncAdapter uses the same provider as your ContentProvider.

    Also, from SimpleContentProvider you'll see that you need an attribute to be added to your ContentProvider class

        [ContentProvider(new string[] { Namespace.MyContentProvider.AUTHORITY })]
            public class MyContentProvider : ContentProvider
            {
                public const string AUTHORITY = "com.example.android.provider";
            ...
    

    So far I've been able to remove the section from AndroidManifest.xml as Xamarin adds it for me. That might change as I customise the ContentProvider, though.

    Hope that helps.

Sign In or Register to comment.