记录(AndroidContentProvider的使用)

赋料扬雄敌,诗看子建亲。这篇文章主要讲述记录:AndroidContentProvider的使用相关的知识,希望能为你提供帮助。

摘要: contentprivoder好像自己没有遇到过, 不过通常使用 联系人, 日历等等之类系统自身提供的。简略的摘抄一下网上各位的资料以作为自己记录。对 其中 getType(Uri uri)方法还是不知道具体使用方法, 暂且留在这里。等后面看能不能搜集到具体使用
概述
??ContentProvider的主要用途我认为是对一些数据进行管理, 而对于数据的实现也有非常多。因此, 实际的应用中要自行取舍。在每一个应用中数据库都允许创建它的应用自己来读写, 那其它应用要访问这个数据库就需要使用 ContentProvider对数据共享。
??在学习使用ContentProvider的时候, 里面面涉及了SQLite、Uri等等系列的操作等等, 前面通过摘抄了一下记录: Android SQLite的使用 和 记录: URI、URL和Uri 的使用。还有很零碎的点边在这里记录一下。

??UriMatcher
??UriMatcher是一个工具类, 主要是用于 ContentProvider中匹配 URI。实际上相当于一棵树, 实例化的UriMatcher对象, 相对于树的根节点。
【记录(AndroidContentProvider的使用)】??使用方法如下:
??首先第一步, 初始化:
//UriMatcher.NO_MATCH, 是一个常量, 如果不匹配就返回 -1 UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);

??第二步注册需要的Uri
/** *authority: 就是 contentprivoder 的authority参数, 这参数必须与 androidmanifest.xml中对应privoder的authorities值一样 *path: 就是完整uri中, authority后的一长串 *code: 对应码 */ //addURI 添加一个 uri, 如果这个 uri匹配成功则返回匹配吗, 不匹配则返回 -1 public void addURI(String authority, String path, int code)

??第三部, 与已经注册的Uri进行匹配
//从以创建的uri树中去匹配传进来的uri, 如果匹配成功, 则返回匹配码, 否则-1 public int match(Uri uri)


?? ContentUris ??ContentUris是一个工具类, 主要是用来处理“Content”约束的 Uri 对象。 ??contentUris对象的语法格式是: “content://authority/path/id“ ??常用方法介绍:
public static long parseId(Uri contentUri)

??这个方法是将 uri 的id解析出来, 此方法返回的是一个 long型的 id。
public static Uri withAppendedId(Uri contentUri, long id)

??在指定的 uri后面添加一条 id 为指定的记录 ??一个摘抄的demo
private static finalString AUTHORITY= " com.smaple.hu" ; private static final int PEOPLE = 1; private static final int PEOPLE_ID = 2; private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { sURIMatcher.addURI(AUTHORITY," people" ,PEOPLE); //这里的#代表匹配任意数字, 另外还可以用*来匹配任意文本 sURIMatcher.addURI(AUTHORITY," people/#" ,PEOPLE_ID); }private void testUriMatcher() { Uri uriExact = Uri.parse(" content://" + AUTHORITY+ " /people" ); Log.i(" info" ," uriExact: = " + uriExact) ; Log.i(" info" ," match excat = " + getType(uriExact)); Uri uriNumber = Uri.parse(" content://" + AUTHORITY+ " /people" + " /2" ); Log.i(" info" ," uriNumber: = " + uriNumber) ; Log.i(" info" ," match number = " + getType(uriNumber)); //拼接Uri Uri newUri = ContentUris.withAppendedId(uriExact,15); Log.i(" info" ," newUri: = " + newUri) ; //获取 ID long id = ContentUris.parseId(newUri) ; Log.i(" info" ," ID = " + id); Log.i(" info" ," getPathSegments = " + newUri.getPathSegments()); } private String getType(Uri uri){ int match = sURIMatcher.match(uri); switch (match){ casePEOPLE:return " vnd.android.cursor.dir/person" ; casePEOPLE_ID:return " vnd.android.cursor.item/person" ; default:return null; } }

??打印出来的 log信息为:
I/info: uriExact: = content://com.smaple.hu/people I/info: match excat = vnd.android.cursor.dir/person I/info: uriNumber: = content://com.smaple.hu/people/2 I/info: match number = vnd.android.cursor.item/person I/info: newUri: = content://com.smaple.hu/people/15 I/info: ID = 15 I/info: getPathSegments = [people, 15]

??在UriMatcher的 math( )方法中有一个 uri.getPathSegments( ), 大致的意思就是按“/”进行切分。和下面的参考资料有所差异 ??想要实现自己的 contentprovider, 需要继承 “android.content.ContentProvider“ 抽象类, 在继承之后必须覆写以下几个方法。
  • oncreate( ): 构造方法, 运行在 UI线程中, 因此不能做一些耗时操作, 一般用作属性初始化( 比如数据库初始化)
  • getType(Uri uri): 返回 uri对应的资源 MIME类型
  • insert(): 插入一条数据, 返回插入数据的资源定位符
  • delete(): 使用给定的条件删除数据库信息, 返回收受影响的记录数
  • update(): 使用给定的条件更新数据库信息, 返回受影响的记录数
  • query(): 使用条件查询, 最基本的也是最常用的方法, 其实返回一个数据库游标
??毕竟是四组件, 要求在 Androidmanifest.xml中进行注册声明
< provider android:authorities= " com.hu.smaple.provider" android:name= " .hu.provider.TestProvider" android:exported= " true" />

??这里有两个地方需要注意:
  1. authorities: 的值为 provider 对外暴露的 Uri地址, 其必须保证全系统唯一性。即无论你的应用内部还是 android系统中都不能出现两个 authorities 值相同的 privoder声明
  2. name: 的属性则是真正 privoder类的位置。(恩, 自己看着戳它)
contentprivoder的使用示例
??可以看见contentprivoder的基本操作方法都需要传入一个 Uri才能够使用。通过下面的摘抄的 demo, 阅读起来可以更好的理解具体使用方法步骤:
??首先创建一个数据库, (为了方便把 记录: Android SQLite的使用 里面的直接copy使用。在这里还遇到了一个问题, 初始的时候, 两个不同的 activity去分别创建一张在 test.db下的表。这样会只有一个能够正常使用, 后面修改成不通的数据库, 两者才可以同时使用。由于是小白, 希望知道的朋友些能帮忙一下, 是因为一个SQLiteOpenHelper创建 数据库之后, 同一应用中再次创建相同名称数据库的时候, 不是在其后面追加表。而是, 抛出异常)
public class TestSQLite extends SQLiteOpenHelper {private static final String DB_NAME = " provider.db" ; private static final int DB_VERSION = 1; private final String TABLE_NAME= " providertable" ; private final String COL_ID = " _id" ; private final String COL_NAME = " name" ; private final String COL_AGE = " age" ; private final String COL_INFO = " info" ; public TestSQLite(Context context) { super(context, DB_NAME, null, DB_VERSION); }@ Override public void onCreate(SQLiteDatabase db) {String sql = " create table if not exists [" + TABLE_NAME+ " ] " + " (" + COL_ID+ " integer primary key autoincrement, " + COL_NAME+ " varchar, " + COL_AGE+ " integer, " + COL_INFO+ " text)" ; Log.i(" info" ," create table = " + sql) ; db.execSQL(sql); }@ Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(" ALTER TABLE person ADD COLUMN other STRING" ); } }

??第二步, 利用 contentPrivoder提供数据库的操作接口
public class TestProvider extends ContentProvider { private static final UriMatcher sUriMatcher ; private static final int MATCHER_TABLE = 1; private static final String AUTHORITY = " com.hu.smaple.provider" ; private static final StringTABLE_NAME = " providertable" ; private static finalUriCONTENT_URI_PROVIDERTABLE = Uri.parse(" content://" + AUTHORITY+ " /" + TABLE_NAME); private TestSQLite testSQLite ; private static final String CONTENT_PROVIDER_TABLE = " com.hu.smaple.provider.type" ; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(AUTHORITY,TABLE_NAME,MATCHER_TABLE); }@ Override public boolean onCreate() {testSQLite = new TestSQLite(getContext()); return false; }@ Nullable @ Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {Log.i(" info" ," query uri = " + uri); SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); switch (sUriMatcher.match(uri)){ case MATCHER_TABLE: //设置查询的表 queryBuilder.setTables(TABLE_NAME); break; default: thrownew IllegalArgumentException(" Unknow URI: " + uri); }SQLiteDatabase db = testSQLite.getWritableDatabase(); Cursor c = queryBuilder.query(db,projection,selection,selectionArgs,null,null,sortOrder); return c; }@ Nullable @ Override public String getType(Uri uri) { Log.i(" info" ," getType uri = " + uri); return null; }@ Nullable @ Override public Uri insert(Uri uri, ContentValues values) { Log.i(" info" ," insert uri = " + uri); String tableName = null ; switch (sUriMatcher.match(uri)){ case MATCHER_TABLE:tableName = TABLE_NAME ; break; default: thrownew IllegalArgumentException(" Unknown URI: " + uri); }SQLiteDatabase db = testSQLite.getWritableDatabase(); long rowId = db.insert(tableName,null,values); Uri result = ContentUris.withAppendedId(uri,rowId); notifyChange(result); return result; }@ Override public int delete(Uri uri, String selection, String[] selectionArgs) { Log.i(" info" ," delete uri = " + uri); String tableName = null ; ; switch (sUriMatcher.match(uri)){ case MATCHER_TABLE: tableName = TABLE_NAME ; break; default: throw new IllegalArgumentException(" Unknown URI " + uri); } SQLiteDatabase db = testSQLite.getWritableDatabase() ; int count = db.delete(tableName,selection,selectionArgs); // 更新数据时, 通知其他ContentObserver if(count > 0){ notifyChange(uri); } return count; }@ Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { Log.i(" info" ," update uri = " + uri); String tableName = null; switch (sUriMatcher.match(uri)){ case MATCHER_TABLE: tableName = TABLE_NAME ; break; default: throw new IllegalArgumentException(" Unknown URI " + uri); }SQLiteDatabase db = testSQLite.getWritableDatabase(); int count = db.update(tableName,values,selection,selectionArgs); if(count > 0 ){ notifyChange(uri); } return count; }private void notifyChange(Uri uri){ Context context = getContext() ; if(context = = null) return; ContentResolver resolver = context.getContentResolver(); if(resolver = = null) return; resolver.notifyChange(uri,null); } }

??注意: 在其中 通过 UriMatcher、ContentUris进行对 Uri的匹配和在返回时进行对Uri拼装。
??第三步, 在其它 app中通过context.getContentResolver( )使用这个共享的数据
public class MainActivity extends AppCompatActivity {private ListView listView ; private static final String AUTHORITY = " com.hu.smaple.provider" ; private static final String TABLENAME = " providertable" ; private static final Uri CONTENT_URI_TABLE = Uri.parse( " content://" + AUTHORITY+ " /" + TABLENAME ); @ Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listView); }public void add(View view){ ArrayList< Person> persons = new ArrayList< Person> (); Person person = new Person(" Ella" + System.currentTimeMillis(), 22, " lively girl insert other app" ); ContentValues cv = new ContentValues(); cv.put(" name" ,person.name); cv.put(" age" ,person.age); cv.put(" info" ,person.info); Uri uri = this.getContentResolver().insert(CONTENT_URI_TABLE,cv); Log.i(" info " , " inserturi = " + uri); }public void update(View view){ Person person = new Person() ; person.name = " Jane" ; person.age = 30 ; person.info= " updata form other app" ; ContentValues cv= new ContentValues() ; cv.put(" name" ,person.name); cv.put(" age" ,person.age); cv.put(" info" ,person.info); int count= this.getContentResolver().update(CONTENT_URI_TABLE,cv," name = ?" ,new String[]{" Jane" }); Log.i(" info " , " update count= " + count); }public void delete(View view) {int count = this.getContentResolver().delete(CONTENT_URI_TABLE," name = ?" ,new String[]{" Jane" }); Log.i(" info " , " delete count= " + count); }public void query(View view){ List< Person> persons = new ArrayList< > (); Cursor c = getContentResolver().query(CONTENT_URI_TABLE,null,null,null,null); if(c.getCount() > 0 & & null != c){while(c.moveToNext()){ Person person = new Person() ; person._id = c.getInt(c.getColumnIndex(" _id" )); person.name = c.getString(c.getColumnIndex(" name" )); person.age = c.getInt(c.getColumnIndex(" age" )); person.info = c.getString(c.getColumnIndex(" info" )); persons.add(person); } }ArrayList< Map< String,String> > list = new ArrayList< > () ; for (Person person : persons) { HashMap< String,String> map = new HashMap< > () ; map.put(" name" ,person.name); map.put(" info" , person.age + " years old, " + person.info); list.add(map); }SimpleAdapter adapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2, new String[]{" name" , " info" }, new int[]{android.R.id.text1, android.R.id.text2}); listView.setAdapter(adapter); }}

??我在 contentprivoder的提供共享数据的界面也添加了一个 添加和查询的按钮, 便于查看是否真的共享了。添加的数据为
Person person1 = new Person(" Ella" , 22, " lively girl" ); Person person2 = new Person(" Jenny" , 22, " beautiful girl" ); Person person3 = new Person(" Jessica" , 23, " sexy girl" ); Person person4 = new Person(" Kelly" , 23, " hot baby" ); Person person5 = new Person(" Jane" , 25, " a pretty woman" );

记录(AndroidContentProvider的使用)

文章图片

    推荐阅读