- 上节学过的数据持久化方式:文件存储,
SharedPreferences
存储,都只提供了MODE_PRIVATE
一种访问模式,即只能在本程序中访问。 - 在夸程序数据共享方面,安卓官方推荐使用内容提供器技术
7.1内容提供器简介
内容提供器主要用于在不同程序间共享数据,并且提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同事还能保证被访数据的安全性
7.2 运行时权限
安卓将权限分为了两类:普通权限和危险权限
如果是普通权限,在权限清单中声明一下就可以,如果是危险权限Android6.0
之后引进了**“运行时权限”**的概念
- 在低于
Android 6.0
中的系统上运行的话,直接就可以运行 - 高于
Android 6.0
的系统,需要用户授予**“运行时权限”**
运行时权限的处理代码如下:
Button makeCall = (Button)findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CALL_PHONE)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1);
}else{
call();
}
}
});
private void call(){
try{
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData("tel:10086");
startActivity(intent);
}catch(SecurityException e){
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults){
switch(requestCode){
case 1:
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
call();
}else{
Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
代码分析:
- 第一步:判断用户是否已经授权了该运行时权限,利用
ContextCompat.checkSelfPermission()
方法,该方法接收两个参数,第一个是Context
,第二个是权限名,如打电话是Manifest.permission.CALL_PHONE;
然后将返回值与PackageManager.PERMISSION_GRANTED
作比较,如果相等,表示已授权;否则表示没有授权; - 第二步:如果用户已经进行了授权,可以直接调用call()方法打电话;
否则,向用户申请授权。申请授权需要调用ActivityCompat.requestPermissions()
方法,接收三个参数:- 第一个参数是活动的实例,例如
MainActivity.this
- 第二个参数是一个
String
数组,将需要申请的权限名放进其中即可 - 第三个参数是请求码,
int
类型,标识是哪个地方进行的权限申请。
- 第一个参数是活动的实例,例如
- 请求权限之后,会回调
onRequestPermissionsResult()
方法,接收三个参数:- 请求码
- 请求的权限列表
String[] permissions
- 请求结果数组
int[] requestResults
,如果和PackageManager.PERMISSION_GRANTED
相同,证明授予了权限。
#访问其他程序中的数据 ContentResolver
- 通过
Context
类中的getContentResolver()
方法得到ContentResolver
对象 - 对数据的增删改查方法:
public Uri insert(Uri uri,ContentValues values)
public Cursor query(Uri uri,String[] projection,String selection,Stirng[] selectionArgs,String sortOrder)
public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs)
public int delete(Uri uri,String selection,String[] selectionArgs)
#创建自己的内容提供器ContentProvider
-
新建一个内容提供器类继承自
ContentProvider
,重写:Contentprovider
中的增删改查方法public String getType(Uri uri)
方法public boolean onCreate()
方法
-
public boolean onCreate()
:初始化内容提供器的时候调用,完成数据库多的创建和升级操作;- 返回值true表示创建成功;false表示创建失败
- 只有在
ContentResolver
尝试访问程序中的数据时,onCreate()
方法才会被调用
-
insert()
:返回值是一个Uri
对象,指向新插入的记录 -
delete()
:返回值是一个int
,受影响的行数 -
update()
:返回值是一个int
,受影响的行数 -
query()
:返回值是一个Cursor
,查出来的内容,配合Cursor.moveToNext()
方法使用。查询具体cursor
中的内容需配合getString()
等方法使用,getString()
的参数是ColumnIndex
对象,通过getColumnIndex()
方法获得。 -
public String getType(Uri uri)
方法返回Uri
对象对应的MIME
类型:MIME
类型的规定:- 以
.vnd
开头 - 第二部分:如果URI以路径结尾,则第二部分为
android.cursor.dir/
;如果以id
结尾,则第二部分为android.cursor.item/
- 最后是vnd..
- 以
- 例如:对于
content://com.example.app.provider/table1
,MIME
为:vnd.android.cursor.dir/vnd.com.example.app.provider.table1
; - 对于
content://com.example.app.provider/table1/1
,MIME为:vnd.android.cursor.item/vnd.com.example.app.provider.table1
具体的创建自己的内容提供器的代码:
public class DatabaseProvider extends ContentProvider{
public static final BOOK_DIR = 0;
public static final BOOK_ITEM = 1;
public static final CATEGORY_DIR = 2;
public static final CATEGORY_ITEM = 3;
public static final String AUTHORITY = "com.example.databasetest.provider";
private static UriMatcher uriMatcher;
private MyDatabaseHelper dbHelper;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY,"book",BOOK_DIR);
uriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM);
uriMatcher.addURI(AUTHORITY,"category",CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY,"category/#",CATEGORY_ITEM);
}
@Override
public boolean onCreate(){
dbHelper = new MyDatabaseHelper(getContext(),"BookStore.db",null,2);
return true;
**此时只是创建出数据库的实例,并没有具体的新建数据库**
}
注册内容提供器
要在AndroidManifest.xml
中进行注册
<application>
<provider
android:name=".DatabaseProvider"
android:authority="com.example.databasetest.provider"
android:enable="true"
android:exported="true">
</provider>
</application>
属性 | 意义 |
---|---|
android:name | 类名 |
android:authority | provider的路径 |
android:enable | 是否启用 |
android:exported | 是否可以被其他应用程序访问 |