赞
踩
关于Android中关于文件权限的具体解释
drwxrwx-x
第一位:-表示文件,d表示文件夹,l表示连接
二三四:所有者权限,即程序本身访问文件或目录的权限
五六七:所在群组的权限
八九十:其他用户权限
r表示读权限,w表示写权限,x表示可执行权限,-表示没有权限,用数字表示法:r=4,w=2,x=1,-=0
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LAkutBXO-1623813168455)(009 Android之ContentProvider.assets/1623330084594.png)]
ContentProvider 内容提供者是安卓中的四大组件之一,为什么需要ContentProvider?
ContentProvider提供了应用之间共享数据的方法,应用程序通过ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保护了数据
Android系统中附带的ContentProvider包括:
关于ContentProvider数据集
ContentProvider数据集类似于数据库的数据表,每行是一条记录,每列具有相同的数据类型,如下所示
应用程序使用ContentResolver对象,利用URI,才能访问ContentProvider提供的数据集
URI:通用资源标志符(Uniform Resource Identifer),用来定位远程或本地的可用资源;URI的基本格式如下
content://<authority>/<data_path>/<id>
content://contacts/people/ 表示全部联系人信息的URI
content://contacts/people/1 表示ID=1的联系人信息的URI
原生写法
content://com.android.contacts/contacts/
常量写法
ContactsContract.Contacts.CONTENT_URI
由于URI比较长,而且容易写错,所以在Android中定义了一些辅助类和常量来代替这些字符串
在Android中广泛应用URI,而不是URL。URL是标识资源的物理位置,相当于文件的路径,例如:
http://www.163.com/logo.png
URI则是标识资源的逻辑位置,并不提供资源的具体位置。
比如说电话本中的数据,如果用URL来标识的话,可能会是一个很复杂的文件结构,而一旦文件的存储路径改变,URL也必须改动。
但如果是URI,则可以用诸如content://contacts/people/
这样容易记录的逻辑地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也不需要做变化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UYxXHIJS-1623813168464)(009 Android之ContentProvider.assets/1623412259686.png)]
首先创建一个ContentProvider
指定URI的路径
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO: Implement this to handle query requests from clients.
Log.d("GuiShou","ContentProvider::query");
return null;
}
然后在query方法中输出一条日志
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn1"
android:text="访问ContentProvider"
android:onClick="btnOnclick"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
然后编写页面文件,新增一个按钮,用于访问ContentProvider
public void btnOnclick(View view) {
//获取内容解析者
ContentResolver resolver=getContentResolver();
//创建URI对象
Uri uri= Uri.parse("content://myContentProvider");
//查询
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
Cursor cursor= resolver.query(uri,null,null,null,null,null);
Log.d("GuiShou","Cursor::"+cursor);
}
}
编写onClick方法,利用ContentResolver调用ContentProvider的resolver方法
按钮点击之后,ContentResolver会检测URI所指向的ContentProvider是否存在;如果存在,则调用该ContentProvider的query方法。所以URI的路径至关重要,如果不存在,则后面的代码无法执行成功
基于上个实例的代码,在自己的ContentProvider中访问数据库。首先需要准备数据
首先新建一个类名为DBHelper,继承自SQLiteOpenHelper
public class DBHelper extends SQLiteOpenHelper { public DBHelper(@Nullable Context context) { super(context, "mydata.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { //创建表 db.execSQL("create table person(_id integer primary key autoincrement,name varchar(20))"); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } }
重写三个函数,在onCreate函数中创建一个数据库文件
private DBHelper mDBHelper;
private SQLiteDatabase mDatabase;
@Override
public boolean onCreate() {
mDBHelper=new DBHelper(getContext());
return true;
}
在MyContentProvider类内创建DBHelper对象,并在onCreate方法中进行初始化
public static UriMatcher sUriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
private static final String authority = "myContentProvider";
private static final int PERSONS =0x111 ;
private static final int PERSONS_ID = 0x222;
static {
//content://myContentProvider/person
sUriMatcher.addURI(authority,"person",PERSONS);
//content://myContentProvider/person/id
sUriMatcher.addURI(authority,"person/#",PERSONS_ID);
}
接着创建一个UriMatcher,并新增两个URI路径
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO: Implement this to handle requests to insert a new row.
//获取数据库对象
mDatabase=mDBHelper.getReadableDatabase();
//插入values数据
long id= mDatabase.insert("person",null,values);
//返回组合好的URI对象://content://myContentProvider/person/
return ContentUris.withAppendedId(uri,id);
}
完成MyContentProvider的insert方法
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO: Implement this to handle query requests from clients. Log.d("GuiShou","ContentProvider::query"); //获取数据库对象 mDatabase=mDBHelper.getReadableDatabase(); //match方法返回的是addURI的第三个参数code int code=sUriMatcher.match(uri); if (code==PERSONS) { return mDatabase.query("person",new String[]{"_id","name"},null,null,null,null,null); }else if (code==PERSONS_ID) { long id= ContentUris.parseId(uri); return mDatabase.query("person",new String[]{"_id","name"},"_id=?",new String[]{""+id},null,null,null); } return null; }
完成MyContentProvider的query方法。现在在MyContentProvider中还没有数据,我们需要在里面新增数据,查询的时候才能显示出来
<Button
android:id="@+id/btn2"
android:text="插入数据"
android:onClick="btnOnclick2"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
xml中新增一个按钮,用于插入数据
//插入数据按钮 public void btnOnclick2(View view) { //获取内容解析者 ContentResolver resolver=getContentResolver(); //创建URI对象 Uri uri= Uri.parse("content://myContentProvider"); //创建数据 for (int i = 0; i <100 ; i++) { ContentValues values=new ContentValues(); values.put("_id",""+i); values.put("name","王大锤"+i); resolver.insert(uri,values); } Log.d("GuiShou","插入数据完成"); }
实现插入数据的onClick代码
public void btnOnclick(View view) { //获取内容解析者 ContentResolver resolver=getContentResolver(); //查询 Uri uri1= Uri.parse("content://myContentProvider/person"); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { Cursor cursor= resolver.query(uri1,null,null,null,null,null); Log.d("GuiShou","Cursor::"+cursor); while (cursor.moveToNext()){ int id= cursor.getInt(0); String name=cursor.getString(1); Log.d("GuiShou","id:"+id+"name:"+name); } } }
接着完成查询数据的按钮,到此所有代码编写完成。点击插入数据按钮,效果如图:
执行流程首先会通过ContentResolver找到对应的uri,并执行ContentProvider里的insert方法,insert则调用DBHelper的onCreate创建数据库
点击查询按钮,可以看到刚刚被插入的数据
同样是通过ContentResolver找到对应的uri,调用了ContentProvider的query方法查询了所有person数据
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。