简介
内容提供其主要用于在不同应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。
不同于文件存储和SharedPreferences存储中的两种可全局读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。
不过在正式开始学习内容提供器之前,我们需要先掌握另一个非常重要的知识——Android运行时权限。
运行时权限
权限机制详解
我们在学习广播时用到了权限声明。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<ses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
</manifest>
因为访问系统网络以及监听开机广播涉及了用户设备的安全性,因此必须在AndroidManifest.xml
中加入权限声明,否则我们的程序就会崩溃。
运行时申请权限
我们用CALL_PHONE
这个权限来做个实践。
给按钮注册事件:
Button makeCall = (Button) findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try{
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
} catch (SecurityException e){
e.printStackTrace();
}
}
});
在注册表中加入:
<uses-permission
android:name="android.permission.CALL_PHONE"/>
这样的程序在Android版本6.0之前都可以正常运行,但是在更高的版本需要修正一下,因为触及了危险权限。
public class RuntimePermissionTest extends BaseActivity {
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.runtime_permission);
Button makeCall = (Button) findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(ContextCompat.checkSelfPermission(RuntimePermissionTest.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(RuntimePermissionTest.this, new String[]{ Manifest.permission.CALL_PHONE }, 1);
} else {
call();
}
}
});
}
private void call(){
try{
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("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_LONG).show();
}
break;
default:
}
}
}
上面代码将运行是权限的完整流程都覆盖了。
运行时权限的核心就是在程序运行时由用户授权我们去执行一些危险操作。因此,第一步是要先判断用户是不是已经给过授权,借助的是ContextCompat.checkSelfPermission
方法,这个方法接收两个参数,第一个参数是Context
,第二个是具体的权限名,然后我们使用方法的返回值和PackageManager.PERMISSION_GRANTED
作比较,相等就是已授权,否则未授权。
如果已经授权就直接执行拨打电话,如果没有,就需要调用ActivityCompat.requsetPermissions
方法来向用户申请授权,这个方法接收三个参数,第一个参数要求Activity
的实例,第二个是一个String
数组,第三个是请求码,只要是唯一值即可,我们传入1。
调用完成之后,系统会弹出一个权限申请的对话框,不管用户选择了什么,都会回调到onRequestPermissionResult
方法中,授权的结果则会封装在grantResults
参数中。这里我们只需要判断一下最后的授权结果,如果用户同意就调用call
方法,如果不同意,我们只能放弃操作,弹出一条失败提示。
网友评论