SQLiteの使い方がわかったら次はContentProviderですよね。 ということで、SQLの部分はさくっと実装。
using Android.Content; using Android.Database.Sqlite; namespace ContentProviderSample { public class PeopleDatabase : SQLiteOpenHelper { private const string DbName = "people.db"; private const string TableName = "People"; private const string CreateTable = @" create table People ( _id integer primary key autoincrement, name varchar(150) );"; private const int DatabaseVersion = 2; public PeopleDatabase(Context context) : base(context, DbName, new PeopleCursorFactory(), DatabaseVersion) { } public override void OnCreate(SQLiteDatabase db) { db.ExecSQL(CreateTable); for (int i = 0; i < 100; i++) { var c = new ContentValues(); c.Put("name", "tanaka" + i); db.Insert(TableName, null, c); } } public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public PeopleCursor GetAll() { return (PeopleCursor) this.ReadableDatabase.Query(TableName, new[] { "_id", "name" }, null, null, null, null, "_id"); } public PeopleCursor GetOne(long id) { return (PeopleCursor) this.ReadableDatabase.Query(TableName, new[] { "_id", "name" }, "_id = ?", new[] { id.ToString() }, null, null, null); } } public class PeopleCursor : SQLiteCursor { public PeopleCursor(ISQLiteCursorDriver driver, string editTable, SQLiteQuery query) : base(driver, editTable, query) { } public long Id { get { return this.GetLong(this.GetColumnIndex("_id")); } } public string Name { get { return this.GetString(this.GetColumnIndex("name")); } } } public class PeopleCursorFactory : Java.Lang.Object, SQLiteDatabase.ICursorFactory { public Android.Database.ICursor NewCursor(SQLiteDatabase db, ISQLiteCursorDriver masterQuery, string editTable, SQLiteQuery query) { return new PeopleCursor(masterQuery, editTable, query); } } }
ContentProvider
コンテンツプロバイダーを作っておくと、いろいろ便利らしいので、作っておきます。
using Android.Content; using System; namespace ContentProviderSample { // Authorityを属性で設定する [ContentProvider(new[] { Authority })] public class PeopleContentProvider : ContentProvider { // URI組立に必要な人たち private const string Authority = "com.example.PeopleProvider"; private const string BasePath = "people"; public static readonly Android.Net.Uri ContentUri = Android.Net.Uri.Parse("content://" + Authority + "/" + BasePath); // Mime private const string MimeType = "/vnd.com.example.People"; // UriMatcherのマッチ結果 private const int GetAll = 0; private const int GetOne = 1; private static readonly UriMatcher UriMatcher = CreateUriMatcher(); // UriMatcherを生成する private static UriMatcher CreateUriMatcher() { var r = new UriMatcher(UriMatcher.NoMatch); r.AddURI(Authority, BasePath, GetAll); r.AddURI(Authority, BasePath + "/#", GetOne); return r; } private PeopleDatabase db; // 列名の定数 public static class PeopleColumns { public const string Id = "_id"; public const string Name = "name"; } // 削除。とりあえず未実装 public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs) { throw new NotImplementedException(); } // Uriに応じてMimeを返す。今回は同じもの返す public override string GetType(Android.Net.Uri uri) { switch (UriMatcher.Match(uri)) { case GetAll: case GetOne: return MimeType; default: throw new Java.Lang.IllegalArgumentException(); } } // 挿入。とりあえず未実装 public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values) { throw new NotImplementedException(); } // 作成時の処理。とりあえずDB作る public override bool OnCreate() { this.db = new PeopleDatabase(this.Context); return true; } // Uriを判別して全件返すか一件返すか処理をわける public override Android.Database.ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder) { switch (UriMatcher.Match(uri)) { case GetAll: return this.db.GetAll(); case GetOne: return this.db.GetOne(long.Parse(uri.LastPathSegment)); default: throw new Java.Lang.IllegalArgumentException(); } } // 更新。とりあえず未実装 public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs) { throw new NotImplementedException(); } } }
なんか定型でめんどくさい感じがしますね。
使う
ListViewにとりあえず表示してみようと思います。
using Android.App; using Android.Content; using Android.Database; using Android.OS; using Android.Widget; namespace ContentProviderSample { [Activity(Label = "ContentProviderSample", MainLauncher = true, Icon = "@drawable/icon")] public class MainActivity : Activity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // Set our view from the "main" layout resource this.SetContentView(Resource.Layout.Main); // ListViewを取得して var listView = this.FindViewById<ListView>(Resource.Id.Main_ListViewPeople); // 取得する列名を指定して string[] projection = new[] { PeopleContentProvider.PeopleColumns.Id, PeopleContentProvider.PeopleColumns.Name }; // 表示列を指定 string[] fromColumns = new[] { PeopleContentProvider.PeopleColumns.Name }; // 表示先コントロールのIDを指定 int[] toControlIds = new[] { Android.Resource.Id.Text1 }; // コンテンツプロバイダーからデータを読み込む var loader = new CursorLoader(this, PeopleContentProvider.ContentUri, projection, null, null, null); var cursor = loader.LoadInBackground() as ICursor; // カーソルを使うアダプタを作って、ListViewに設定 var adapter = new SimpleCursorAdapter(this, Android.Resource.Layout.SimpleListItem1, cursor, fromColumns, toControlIds); listView.Adapter = adapter; } } }
見事表示できた。