我们都知道ContentProvider为四大组件之一,平时也很少使用它,也就访问通讯录的时候对它进行操作,最近出了一个需求,就是要自定义ContentProvider,我们写的一个sdk1要供sdk2调用它的一些信息,这个时候咋整呢?sdk存储信息在本地,然后sdk2用ContentProvider去访问就好:
第一步:在AndroidManifest里面吧你的继承ContentProvider的类注册一下,如下:
第二步:AutonomicContentProvider extends ContentProvider,吧这个类写好,如下:
package com.robot.zhangyun.myapplication;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
/**
* Created by Tumbler on 2016/9/22.
*/
public class AutonomicContentProvider extends ContentProvider {
private static final String AUTONMIC_CONTENTPROVIDER_NAME="com.efrobot.provider.autonomic";
//你在其他地方用provider的时候要传uri,就是这个,content://是固定的,AUTONMIC_CONTENTPROVIDER_NAME随便写,一般写包名,"/scene"是表名
static final Uri CONTENT_URI=Uri.parse("content://"+AUTONMIC_CONTENTPROVIDER_NAME+"/scene");
static final String _ID="_id";//表字段主键id
private SQLiteDatabase sqLiteDatabase;
private final String DATEBASE_NAME="autonomic"; //数据库的名字
private final int DATEBASE_VERSION=1; //数据库版本
static final int Scene = 1; //匹配用的,看gettype()方法
static final int Scene_ID = 2;
private static final UriMatcher uriMatcher;
static{ //这个是用来匹配uri的,当我们用provider增删改查的时候,会传个uri,好像就是匹配这里的,scene是表名,随便写会报错
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTONMIC_CONTENTPROVIDER_NAME, "scene", Scene);//多个场景的url
uriMatcher.addURI(AUTONMIC_CONTENTPROVIDER_NAME, "scene/#", Scene_ID);//某个场景
}
// 当provider启动的时候被调用,就是拿到SQLiteDatabase的对象的
@Override
public boolean onCreate() {
sqLiteDatabase = DBHelper.getInstance(getContext(),DATEBASE_NAME,null,DATEBASE_VERSION).getWritableDatabase();
return (sqLiteDatabase == null)? false:true;
}
//查询,用provider的时候,不是常常用个uri就得到一个Cursor,这里重写方法是为了提供给外部查询的方法的
@Nullable
@Override
public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
SQLiteQueryBuilder sqlBuilder = new SQLiteQueryBuilder();
sqlBuilder.setTables(getType(uri));
if (uriMatcher.match(uri) == Scene_ID)//如果
sqlBuilder.appendWhere(_ID + " = " + uri.getPathSegments().get(1));
Cursor c = sqlBuilder.query(sqLiteDatabase, strings, s, strings1, null, null, s1);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
//这里的getType返回的也是表名,这个AutonomicContentProvider里面不一定只有一张表
@Nullable
@Override
public String getType(Uri uri) {
//返回给定的URI数据的MIME类型
switch (uriMatcher.match(uri)){
case Scene: //多个场景
return "scene";
case Scene_ID://某个场景
return "scene";
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
}
//利用ContentValues插入时应该就是掉的这个方法,固定的写法,getType(uri)返回的是表名,插入基本都是一样的
// 估计是因为我们的表名都不一样,所以把ContentProvider弄成一个抽象类让我们去继承,灵活应用的
@Nullable
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
//---add a new scene---
Log.e("插入",getType(uri));
long rowID = sqLiteDatabase.insert(getType(uri), "", contentValues);
if (rowID>0) {
Uri _uri = ContentUris.withAppendedId(uri, rowID);
getContext().getContentResolver().notifyChange(_uri, null);
return _uri;
}
throw new SQLException("Failed to insert row into " + uri);
}
//删除的方法
@Override
public int delete(Uri uri, String s, String[] strings) {
int count=0;
switch (uriMatcher.match(uri)){
case Scene:
count = sqLiteDatabase.delete(getType(uri), s, strings);
break;
case Scene_ID:
String id = uri.getPathSegments().get(1);
count = sqLiteDatabase.delete(getType(uri), _ID + " = " + id + (!TextUtils.isEmpty(s) ? " AND (" + s + ')' : ""), strings);
break;
default: throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
//修改数据的方法
@Override
public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
int count = 0;
switch (uriMatcher.match(uri)){
case Scene:
count = sqLiteDatabase.update(getType(uri), contentValues, s, strings);
break;
case Scene_ID:
count = sqLiteDatabase.update(getType(uri), contentValues, _ID + " = " + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(s) ? " AND (" + s + ')' : ""), strings);
break;
default: throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
}
第三步,在其他app里面应用,如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*插入数据*/
ContentValues values = new ContentValues();
values.put("outputname", "输出我要吃饭");//outputname,inputname为字段名
values.put("inputname", "输入为我饿了");
getContentResolver().insert(AutonomicContentProvider.CONTENT_URI, values);
values.clear();
values.put("outputname", "输出111");
values.put("inputname", "输入2222");
getContentResolver().insert(AutonomicContentProvider.CONTENT_URI, values);
/*查询数据测试一下*/
displayNote();
}
private void displayNote(){
Uri myUri = AutonomicContentProvider.CONTENT_URI;
Cursor cur = getContentResolver().query(myUri, null, null, null, null);
if (cur.moveToFirst()) {
String id = null;
String inputname = null;
String outputname = null;
do {
id = cur.getString(cur.getColumnIndex(AutonomicContentProvider._ID));
inputname = cur.getString(cur.getColumnIndex( "inputname"));
outputname = cur.getString(cur.getColumnIndex("outputname"));
Toast toast = Toast.makeText(this, "TITILE:"+id + "\t" + "NOTE:" + inputname+"\t" +outputname, Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP|Gravity.CENTER, 0, 40);
toast.show();
} while (cur.moveToNext());
}
}
}