自定义contentprovider
contentprovider是不同应用程序之间交换数据
自定义contentprovider的步骤:
(1)定义一个contract类,描述数据库中的相关元数据,定义所要用到的常量。
package com.bobo.myprovider; import android.net.Uri; import android.provider.BaseColumns; public class PersonDataBase { public static final String AUTHORITY="com.bobo.myprovider"; public static final String DataBaseName="MyDataBase"; public static final int Version=1; public static final Uri CONTENT_URI=Uri.parse("content://"+AUTHORITY); public static class PersonTable implements BaseColumns{ //表名 public static final String TableName="PersonTable"; //表中的姓名列 public static final String NAME="name"; //表中的年龄列 public static final String AGE="age"; //整体查询的返回类型 public static final String CONTENT_TYPE="vnd.android.cursor.dir/person"; //单条查询的返回类型 public static final String CONTENT_ITEM_TYPE="vnd.android.cursor.item/person"; //默认的排序方式 public static final String DEFAULT_SORT_ORDER = PersonTable.NAME + " ASC"; //访问路径 public static final String CONTENT_DIRECTORY="PersonTable"; //这个表对应的contentUri public static final Uri CONTENT_URI=Uri.withAppendedPath(PersonDataBase.CONTENT_URI,PersonDataBase.PersonTable.TableName); } }
(2)如何使用数据库进行数据存储,定义一个sqlhelper类
(除了数据库之外,还可以采用其他任何的结构化数据存储方式)。如果需要存储诸如图片,音频等二进制文件,可以采用文件结合数据库的形式,此时在下面的contentprovider需要覆写一个getStreamTypes的方法。)
/** * */ package com.bobo.myprovider; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; /** * @author bobo * */ public class MyDataHelper extends SQLiteOpenHelper { public MyDataHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } /* (non-Javadoc) * @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase) */ @Override public void onCreate(SQLiteDatabase db) { String sqlString="CREATE TABLE "+PersonDataBase.PersonTable.TableName+"(" +PersonDataBase.PersonTable._ID+" INTEGER PRIMARY KEY," +PersonDataBase.PersonTable.NAME+" VARCHAR(50) NOT NULL," +PersonDataBase.PersonTable.AGE+" INTEGER NOT NULL)"; db.execSQL(sqlString); } /* (non-Javadoc) * @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int) */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { String sql="DROP TABLE IF EXISTS"+PersonDataBase.PersonTable.TableName; db.execSQL(sql); this.onCreate(db); } }
(3)定义一个类继承contentProvider,覆写其中的各个方法。其中会借助一些辅助类,诸如UriMatcher,contentUris等(下面的示例仅仅完成了插入功能)
package com.bobo.myprovider; import android.annotation.SuppressLint; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; public class MyProvider extends ContentProvider { private static UriMatcher matcher; private static final int GET_LIST = 1; private static final int GET_ITEM = 2; private MyDataHelper helper; static { matcher = new UriMatcher(UriMatcher.NO_MATCH); matcher.addURI(PersonDataBase.AUTHORITY, PersonDataBase.PersonTable.CONTENT_DIRECTORY, GET_LIST); matcher.addURI(PersonDataBase.AUTHORITY, PersonDataBase.PersonTable.TableName + "/#", GET_ITEM); } @Override public boolean onCreate() { this.helper = new MyDataHelper(this.getContext(), PersonDataBase.DataBaseName, null, PersonDataBase.Version); return true; } @SuppressLint("NewApi") @Override public String[] getStreamTypes(Uri uri, String mimeTypeFilter) { // 当返回文件类型的数据时,需要覆写这个方法 return super.getStreamTypes(uri, mimeTypeFilter); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor result; System.out.println("***"+matcher.match(uri)); SQLiteDatabase db = this.helper.getReadableDatabase(); switch (matcher.match(uri)) { case GET_LIST: return db.query(PersonDataBase.PersonTable.TableName, projection, selection, selectionArgs, null, null, sortOrder); case GET_ITEM: selectionArgs=new String[]{ContentUris.parseId(uri)+""}; return db.query(PersonDataBase.PersonTable.TableName, projection, "_id=?", selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("IllegalArgumentException"); } } @Override public String getType(Uri uri) { switch (matcher.match(uri)) { case GET_LIST: return PersonDataBase.PersonTable.CONTENT_TYPE; case GET_ITEM: return PersonDataBase.PersonTable.CONTENT_ITEM_TYPE; default: throw new IllegalArgumentException("IllegalArgumentException"); } } // 返回插入的记录对应的uri @Override public Uri insert(Uri uri, ContentValues values) { System.out.println("***"+matcher.match(uri)); Cursor result; SQLiteDatabase db = this.helper.getWritableDatabase(); long id; switch (matcher.match(uri)) { case GET_LIST: id = db.insert(PersonDataBase.PersonTable.TableName, null, values); return ContentUris.withAppendedId(uri, id); case GET_ITEM: id = db.insert(PersonDataBase.PersonTable.TableName, null, values); String uriPath = uri.toString(); String path = uriPath.subSequence(0, uriPath.lastIndexOf("/")) .toString() + id; return Uri.parse(path); default: throw new IllegalArgumentException("IllegalArgumentException"); } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }
(4)在配置文件中进行contentprovider的配置,还可以配置权限,以及不需要权限通过intent访问contentPovider等功能。(详见api文档)
<provider android:name=".MyProvider" android:authorities="com.bobo.myprovider" > </provider>
(5)具体的使用借助于contentResolver
package com.bobo.myprovider; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.support.v4.widget.SimpleCursorAdapter; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; public class MainActivity extends Activity { private Button insert; private Button query; private Button delete; private Button update; private ContentResolver resolver; private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); resolver = this.getContentResolver(); insert = (Button) this.findViewById(R.id.insert); query = (Button) this.findViewById(R.id.query); delete = (Button) this.findViewById(R.id.delete); update = (Button) this.findViewById(R.id.update); lv = (ListView) this.findViewById(R.id.lv); insert.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ContentValues values = new ContentValues(); values.put("name", "test"); values.put("age", 28); Uri uri = resolver.insert( PersonDataBase.PersonTable.CONTENT_URI, values); Toast.makeText(getApplicationContext(), uri.toString(), Toast.LENGTH_SHORT).show(); } }); query.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // String[] projection=new String{"name","age"}; // 首先查询全部 Cursor cursor = resolver.query( PersonDataBase.PersonTable.CONTENT_URI, null, null, null, PersonDataBase.PersonTable.DEFAULT_SORT_ORDER); //操作cursor结构集合 MainActivity.this.startManagingCursor(cursor); System.out.println(cursor.getColumnName(0)+";"+cursor.getColumnName(1)+cursor.getColumnName(2)); for(cursor.moveToFirst();cursor.isAfterLast();cursor.moveToNext()){ System.out.println(cursor.getString(cursor.getColumnIndex("name"))+";"+cursor.getInt(cursor.getColumnIndex("age"))+";Id="+cursor.getInt(0)); } /* SimpleCursorAdapter adapter = new SimpleCursorAdapter( getApplicationContext(), android.R.layout.simple_list_item_2, cursor, new String[] {"_id", "name"}, new int[] { android.R.id.text1, android.R.id.text2 }); lv.setAdapter(adapter);*/ } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }