文章目录
Android文件权限简述
关于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?
- Android中的应用程序运行在不同的进程空间中,因此不同应用程序中的数据是不能够直接访问的
- 为了增强程序之前的数据共享能力,Android系统虽然提供了像SharedPrefences这类简单的跨程序边界的访问方法,但这些方法都存在一定的局限性
ContentProvider提供了应用之间共享数据的方法,应用程序通过ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保护了数据
Android系统中附带的ContentProvider包括:
- Browser:存储如浏览器的信息
- CallLog:存储通话记录等信息
- Contacts:存储联系人等信息
- MediaStore:存储媒体文件的信息
- Settings:存储设备的设置和首选项信息
关于ContentProvider数据集
ContentProvider数据集类似于数据库的数据表,每行是一条记录,每列具有相同的数据类型,如下所示
ContentResolver
应用程序使用ContentResolver对象,利用URI,才能访问ContentProvider提供的数据集
URI
什么是URI
URI:通用资源标志符(Uniform Resource Identifer),用来定位远程或本地的可用资源;URI的基本格式如下
content://<authority>/<data_path>/<id>
- content 固定前缀
- authority 授权者名称,用来确定具体由哪一个ContentProvider提供资源
- data_path 数据路径,用来确定请求的是哪个数据集
- id 数据编号,用来匹配数据集中_ID字段的值,如果请求的数据不止一条则可以省略
URI示例
content://contacts/people/ 表示全部联系人信息的URI
content://contacts/people/1 表示ID=1的联系人信息的URI
原生写法
content://com.android.contacts/contacts/
常量写法
ContactsContract.Contacts.CONTENT_URI
由于URI比较长,而且容易写错,所以在Android中定义了一些辅助类和常量来代替这些字符串
URI和URL
在Android中广泛应用URI,而不是URL。URL是标识资源的物理位置,相当于文件的路径,例如:
http://www.163.com/logo.png
URI则是标识资源的逻辑位置,并不提供资源的具体位置。
比如说电话本中的数据,如果用URL来标识的话,可能会是一个很复杂的文件结构,而一旦文件的存储路径改变,URL也必须改动。
但如果是URI,则可以用诸如content://contacts/people/
这样容易记录的逻辑地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也不需要做变化
ContentProvider实例
ContentProvider实例1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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实例2
基于上个实例的代码,在自己的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数据