如果一个应用程序通过内容提供器对其数据提供了外部访问接口,那么任何其他的应用程序就都可以对这部分数据进行访问。Android系统中自带的电话簿、短信、媒体库等程序都提供了类似的访问接口,这就使得第三方应用程序可以充分地利用这部分数据来实现更好的功能。
Resolver的基本用法
对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助Content-Resolver类,可以通过Context中的 getContentResolver() 方法获取到该类的实例。
Content-Resolver中提供了一系列的方法用于对数据进行CRUD操作,
其中
insert()方法用于添加数据,
update()方法用于更新数据,
delete()方法用于删除数据,
query()方法用于查询数据。
内容URI
不同于SQLiteDatabase,ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI。内容URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path。
authority
authority是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。比如某个程序的包名是com-example.app,那么该程序对应的authority就可以命名com.example.app.provider。
path
path则是用于对同一应用程序中不同的表做区分的,通常都会添加到authority的后面。比如某个程序的数据库里存在两张表:tablel和table2,这时就可以将path分别命名为/tablel和/tabIe2。
组合成内容URI
然后把authority和path进行组合,内容URI就变成了com.example.app.provider/table1和com-example.app.provider/table2。
不过,目前还很难辨认出这两个字符串就是两个内容URI,我们还需要在字符串的头部加上协议声明。因此,内容URI最标准的格式写法如下:
content://com.example.app.provider/table1
内容URI可以非常清楚地表达出我们想要访问哪个程序中哪张表里的数据。
Uri.parse()解析URI字符串
在得到了内容URI字符串之后,我们还需要将它解析成Uri对象才可以作为参数传入。解析的方法也相当简单,代码如下所示:
resolver是用来插入数据的,resolver 的 mainactivity代码具体如下:
// An highlighted block
package com.example.resolver;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
//private ContentResolver resolver;
//private static final String AUTHORITY = "ZJC.Provider1";//由请求方提供,请求方先写
//private static final Uri NOTIFY_URI = Uri.parse("content://"+AUTHORITY+"/person");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
ContentResolver resolver = getContentResolver();//获得了一个系统的resolver
Uri uri = Uri.parse("content://zjc.provider/student"); //student是表名
//要注意这里的大小写
ContentValues values = new ContentValues();
values.put("name","zjc");
values.put("age",20);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//在button点击时insert
resolver.insert(uri,values);
}
});
}
}
再写provider
新建一个provider项目,provider里面有MyDAO,contentprovider,MyDBhelper,mainactivity四个文件
DAO层一般有接口和该接口的实现类! 接口用于规范实现类! 实现类一般用于用于操作数据库! 一般操作修改,添加,删除数据库操作的步骤很相似,就写了一个公共类DAO类 ,修改,添加,删除数据库操作时 直接调用公共类DAO类!
MyDao的代码如下
// An highlighted block
package com.example.myprovider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class MyDAO {
//操作数据库的方法,因为不想暴露出去,因此提供一种接口方式
SQLiteDatabase database;
Context context ;
public MyDAO(Context context){
this.context = context;
MyDBhelper dBhelper = new MyDBhelper(context,"zjcDB",null,1);
SQLiteDatabase database = dBhelper.getWritableDatabase();
}
public Uri zjcInsert(ContentValues contentValues){
ContentValues values1 = new ContentValues();
values1.put("name","张三");
values1.put("age",20);
long rowid = database.insert("student",null,values1);
//这里的insert会有一个long型的返回值
Uri uri = Uri.parse("content://zjc.provider/student");
Uri inserturi = ContentUris.withAppendedId(uri,rowid);
context.getContentResolver().notifyChange(inserturi,null);
return inserturi;
}
}
content provider是new-other-content provider,此时会有一个
这里的内容需要和resolver中的uri一致,如下//后面的内容所示
contentprovider代码如下
// An highlighted block
package com.example.myprovider;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
public class MyContentProvider extends ContentProvider {
private MyDAO myDAO;
public MyContentProvider() {
}
@Override
public boolean onCreate() {
// TODO: Implement this to initialize your content provider on startup.
Context context = getContext();
myDAO = new MyDAO(context);
//不能在构造函数里面写,在构造函数里写没有反应
return false;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO: Implement this to handle requests to insert a new row.
//throw new UnsupportedOperationException("Not yet implemented");
//getContext().getContentResolver().insert(uri,values);
return myDAO.zjcInsert(values);
//return uri;
}
因为resolver中只写了insert,因此这里也只写了insert,两边要保持一致。
MyDBhelper
// An highlighted block
package com.example.myprovider;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
public class MyDBhelper extends SQLiteOpenHelper {
public MyDBhelper( Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context,name,null, version);
//name 是数据库的名字
//factory 是游标
}
@Override
public void onOpen(SQLiteDatabase db) {
super.onOpen(db);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("create table student " +
"(id integer primary key autoincrement," + //autoincrement是可以自己标号
"name varchar(20),age integer)");//括号中是之前学到sql语句
//sqLiteDatabase.就会出现所有db中的方法
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
其中Sqliteopenhelper是用于打开数据库的,这里很重要
main中没有新增别的代码
源码地址: https://gitee.com/chenrrr/contentprovider.git