Android Xamarin - 无法找到'提供商'的提供商信息

时间:2016-11-08 12:40:05

标签: c# android xamarin.android runtime-error android-contentprovider

我被困在这一段时间,我不知道如何继续前进。我已经尝试了Stack和其他来源中列出的所有解决方案,但问题仍然没有解决。我正在开发一个必须从另一个应用程序访问的内容提供程序。 APP1有内容提供程序,其中包含SQLite数据和工作正常,因为我使用查询运行它。问题是当我尝试从App2访问此内容提供程序时,我收到以下错误

Failed to find provider info for 'Provider'
Unhandled Exception:

System.NullReferenceException: Object reference not set to an instance of an object

以下是我的APP1代码

NamesProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.Database;
using Android.Net;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Database.Sqlite;

namespace CustomContentProvider
{
    [ContentProvider(new[] { "customcontentprovider.customcontentprovider.NamesProvider" }, Name = "customcontentprovider.customcontentprovider.NamesProvider")]
    class NamesProvider : ContentProvider
    {
        public static string PROVIDER_NAME = "customcontentprovider.customcontentprovider.NamesProvider";
        public static Android.Net.Uri CONTENT_URI = Android.Net.Uri.Parse("content://" + PROVIDER_NAME + "/locations");
        private MyProviderDBHelper dbHelper;

       // "content://customcontentprovider.customcontentprovider.NamesProvider/locations"

        public const string _ID = "_id";
        public const string NAME = "name";
        private const string DEFAULT_SORT_ORDER = "name DESC";

        //private const int uriCode = 1;
        private static UriMatcher uriMatcher;
        private static Dictionary<String, String> values;

        private const string DATABASE_NAME = "Locations";
        private const string DATABASE_TABLE_NAME = "Location";

        private const int LOCATIONS = 1;
        private const string LOCATION_TYPE = "vnd.android.cursor.dir/vnd.customcontentprovider.location";


        private const int DATABASE_VERSION = 1;
        static NamesProvider()
        {
            values = new Dictionary<string, string>();
            values.Add(_ID, _ID);
            values.Add(NAME, NAME);

            uriMatcher = new UriMatcher(UriMatcher.NoMatch);
            uriMatcher.AddURI(PROVIDER_NAME, "locations", LOCATIONS);
        }

        public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
        {
            if (uriMatcher.Match(uri) != LOCATIONS)
            {
                throw new ArgumentException("Unknown URI " + uri);
            }
            SQLiteDatabase db = dbHelper.WritableDatabase;
            long rowID = db.Insert(DATABASE_TABLE_NAME, NAME, values);
            if (rowID >= 0)
            {
                Android.Net.Uri _uri = ContentUris.WithAppendedId(CONTENT_URI, rowID);
                Context.ContentResolver.NotifyChange(_uri, null);
                return _uri;
            }
            throw new SQLException("Failed to add a record into " + uri);
        }
        public override ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
        {
            SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
            qb.Tables = DATABASE_TABLE_NAME;

            switch (uriMatcher.Match(uri))
            {
                case LOCATIONS:
                    qb.SetProjectionMap(values);
                    break;
                default:
                    throw new ArgumentException("Unknown URI " + uri);
            }

            string orderBy;
            if (sortOrder.Length < 1)
            {
                orderBy = DEFAULT_SORT_ORDER;
            }
            else
            {
                orderBy = sortOrder;
            }

            SQLiteDatabase db = dbHelper.WritableDatabase;
            ICursor c = qb.Query(db, projection, selection, selectionArgs, null,
              null, orderBy);
            c.SetNotificationUri(Context.ContentResolver, uri);
            return c;
        }

        public override bool OnCreate()
        {
            dbHelper = new MyProviderDBHelper(Context);
            return true;
        }
        public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
        {
            SQLiteDatabase db = dbHelper.WritableDatabase;
            int count = 0;
            switch (uriMatcher.Match(uri))
            {
                case LOCATIONS:
                    count = db.Update(DATABASE_TABLE_NAME, values, selection, selectionArgs);
                    break;
                default:
                    throw new ArgumentException("Unknown URI " + uri);
            }
            Context.ContentResolver.NotifyChange(uri, null);
            return count;
        }
        public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)
        {
            SQLiteDatabase db = dbHelper.WritableDatabase;
            int count = 0;
            switch (uriMatcher.Match(uri))
            {
                case LOCATIONS:
                    count = db.Delete(DATABASE_TABLE_NAME, selection, selectionArgs);
                    break;
                default:
                    throw new ArgumentException("Unknown URI " + uri);
            }
            Context.ContentResolver.NotifyChange(uri, null);
            return count;
        }

        public override string GetType(Android.Net.Uri uri)
        {
            switch (uriMatcher.Match(uri))
            {
                case LOCATIONS:
                    return LOCATION_TYPE;

                default:
                    throw new ArgumentException("Unsupported URI: " + uri);
            }
        }
        private class MyProviderDBHelper : SQLiteOpenHelper
        {
            public MyProviderDBHelper(Context context)
                : base(context, DATABASE_NAME, null, DATABASE_VERSION)
            {

            }
            public override void OnCreate(SQLiteDatabase db)
            {
                db.ExecSQL(@"
                    CREATE TABLE " + DATABASE_TABLE_NAME + " ("
                                   + _ID + " INTEGER PRIMARY KEY NOT NULL,"
                                   + NAME + " TEXT NOT NULL)"
                                   );
            }

            public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
            {
                db.ExecSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_NAME);
                OnCreate(db);
            }
        }
    }
}

MainActivity.cs

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace CustomContentProvider
{
    [Activity(Label = "CustomContentProvider", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            SetContentView(Resource.Layout.Main); 
            QueryValues();


            // Get our button from the layout resource,
            // and attach an event to it
            Button btn = FindViewById<Button>(Resource.Id.btnAdd);
            btn.Click += delegate
            {
                EditText nameEditText = FindViewById<EditText>(Resource.Id.txtName);
                if (nameEditText.Text.Length < 0)
                {
                    Toast.MakeText(this, "Name cannot be empty.", ToastLength.Long).Show();
                    return;
                }

                ContentValues values = new ContentValues();
                values.Put(NamesProvider.NAME, (FindViewById<EditText>(Resource.Id.txtName).Text));
                Android.Net.Uri uri = ContentResolver.Insert(NamesProvider.CONTENT_URI, values);
                if (uri != null)
                {
                    nameEditText.Text = "";
                    Toast.MakeText(this, "record added !!! ", ToastLength.Long).Show();
                    QueryValues();
                }
                else
                {
                    Toast.MakeText(this, "record add failed!!! ", ToastLength.Long).Show();
                }
            };
        }

        private void QueryValues()
        {
            Android.Net.Uri allLocations = NamesProvider.CONTENT_URI;    

            Android.Database.ICursor c = ManagedQuery(allLocations, null, null, null, "_id");
            if (c.MoveToFirst())
            {
                System.Diagnostics.Debug.WriteLine("\n****************************\n");
                do
                {
                    // This will show in the output window of Visual Studio // MonoDevelop when you run it in debug mode
                    System.Diagnostics.Debug.WriteLine("NameProvider:\n"
                        + "ID: " + c.GetString(c.GetColumnIndex(NamesProvider._ID)) + "\n"
                        + "Name: " + c.GetString(c.GetColumnIndex(NamesProvider.NAME))
                        );
                } while (c.MoveToNext());
            }              
        }
     }
}

的Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="CustomContentProvider.CustomContentProvider" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="16" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
    <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
    <application android:label="CustomContentProvider">
        <provider android:name="customcontentprovider.customcontentprovider.NamesProvider" 
              android:authorities="customcontentprovider.customcontentprovider.NamesProvider" 
              android:exported="true" 
              android:enabled="true" 
              android:syncable="true"
              android:grantUriPermissions="true"
              android:multiprocess="true"></provider>
    </application>
</manifest>

APP2代码:

MainActivity.cs

using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Database;
using Android.Content.PM;
using System.Collections.Generic;
using Java.Util;

namespace ContentProviderConsumer
{
    [Activity(Label = "ContentProviderConsumer", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {

        ListView listview;
        Android.Database.ICursor cursor;



        public static string PROVIDER_NAME = "customcontentprovider.customcontentprovider.NamesProvider";
        public static Android.Net.Uri CONTENT_URI = Android.Net.Uri.Parse("content://" + PROVIDER_NAME + "/locations");

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            Android.Net.Uri allLocations = CONTENT_URI;


            ContentResolver cr = ContentResolver;
            cursor = cr.Query(allLocations , null, null, null, null);
            StartManagingCursor(cursor);

             if (cursor.MoveToFirst())
             {
                 do
     {
 System.Diagnostics.Debug.WriteLine("NamesProvider:\n"
                             + "ID: " + cursor.GetString(cursor.GetColumnIndex("_id")) + "\n"
                             + "Name: " + cursor.GetString(cursor.GetColumnIndex("name"))
                             );                            
      } while (cursor.MoveToNext());
             }
        }
    }
}

Manifes.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ContentProviderConsumer.ContentProviderConsumer" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="16" />
    <uses-permission android:name="CustomContentProvider.READ_DATABASE" />
    <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.READ_USER_DICTIONARY" />
  <uses-permission android:name="android.permission.WRITE_USER_DICTIONARY" />
    <application android:label="ContentProviderConsumer"></application>
</manifest>

我的猜测是,我应该将包名称与权限和提供者名称混淆。也许我在我的清单中缺少一些权限。我还是放了代码。请仔细研究并建议我如何做对。提前谢谢。

0 个答案:

没有答案