1,内容提供器简介
1,内容提供器(ContentProvider) 主要用于在不同的应用程序之间实现数据共享额功能,它提供了一套完整的机制,允许一个程序访问另一个程序的数据,同时保证被访问的数据的安全性。
2,使用内提供器是Android实现跨程序共享数据的标准形式。
2,运行时权限
Android开发团队在6.0系统中加入了运行时权限,用户可以不用在安装软件时一次性授权应用的所有申请的权限,而是在软件的使用过程中再对某一权限进行授权。
Android中的危险权限有9组24个权限
分别是日历、拍照、联系人、位置、麦克风、电话、传感器、短信及存储。
注意 :24个权限每个都属于一个权限组,我们在进行运行时权限的处理时 使用的是权限名
但是用户一旦同意授权了,那么该权限所在的权限组的其他权限也会被授权。
下面我们做一个打电话的Demo
首先在AndroidManifest.xml文件中声明权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.chen.runtimepermissiontest">
//CALL_PHONE是打电话时所需要的权限
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
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(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, "你没权限", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
}
ContextCompat.checkSelfPermission(Context, 权限名).
1,先调用checkSelfPermission方法判断用户是否已经授过权,此方法接受两个参数,第一个是Context,第二个是具体的权限名。
2,将checkSelfPermission方法的返回值与 PackageManager.PERMISSION_GRANTED 比对
若相等则说明用户已经授权,不相等则表示用户没有授权.
3, 若用户没有授权,则调用ActivityCompat.requestPermissions(Activity实例,String数组,请求码)。
将申请的权限名放入String数组中,请求码必须是唯一值。
4,调用了requestPermissions()方法后,系统会弹出一个权限申请的对话框,可以选择同意或者拒绝。
然后把申请权限的结果回调到onRequestPermissionsResult(nt requestCode(请求码),String [] permissions,int [] grantResults))中,授权的结果被封装到grantResults参数中。
3,访问其他程序中的数据
内容提供器的用法有两种
- 使用现有的内容提供器来操作相应程序中的数据
- 创建自己的内容提供器给我们的程序提供外部访问接口
3-1 ContentResolver的基本用法
通过Context的getContentResolver()方法获取该类的实例
- insert() 添加数据
- update() 更新数据
- delete() 删除数据
- query() 查询数据
Uri:
ContentResolver中的增删改查的方法不接受数据库表名的参数,而是使用Uri代替,称为内容URI,内容URI给内容提供器中的数据建立了唯一的标识符。
Uri = authority + path
- authurity是为了区分不同的应用程序,一般为应用程序的包名. 如: com/example.app.provider
- path是为了同一应用程序中的不同表 如:table1
则Uri = com/example.app.provider/table1
为了辨认某个字符串是内容Uri,需要在字符串的头部加上协议声明。
URI的标准写法:
content://com/example.app.provider/table1
再把它解析成Uri对象
Uri uri = Uri.parse(“content://com/example.app.provider/table1”)
查询数据
Cursor cursor = getContentResolver(uri, //指定查询某个应用程序下的某一张表
projection, // 指定查询的列名
selection, // 指定where的约束条件
selectionArgs, // 为where中的占位符提供具体的值
sortOrder // 指定查询结果的排序方式
);
插入数据
ContentValues values = new ContentValues();
values.put("column1","text");
values.put("column2",1);
getContentRresolver().insert(uri,values);
更改数据
ContentValues values = new ContentValues();
values.put("columns1", " ");
getContentResolver().update(uri,values ,"column1 = ? and column2 = ?" ,
new String[] {"text","1"});
删除数据
getContentResolver().delete(uri,"column2 = ?" ,new String[] {"1"} );
读取联系人的demo
public class MainActivity extends AppCompatActivity {
ArrayAdapter<String> adapter;
List<String> contactList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.contacts_id);
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,
contactList);
listView.setAdapter(adapter);
//获取联系人权限
if(ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,new String[]
{Manifest.permission.READ_CONTACTS} ,1 );
} else {
readContact();
}
}
@Override
public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) {
switch (requestCode) {
case 1 :
if (grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readContact();
} else {
Toast.makeText(this, "你没有读取联系人权限", Toast.LENGTH_SHORT).show();
}
default:break;
}
}
private void readContact() {
Cursor cursor = null;
try {
//查询联系人数据
cursor = getContentResolver().query(ContactsContract.CommonDataKinds
.Phone.CONTENT_URI,null ,null ,null );
if(cursor != null) {
while (cursor.moveToNext()) {
//获取联系人姓名
String displayName = cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//获取联系人号码
String displayNumber = cursor.getString(cursor.getColumnIndex
(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactList.add(displayName + "\n" + displayNumber);
}
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(cursor != null) {
cursor.close();
}
}
}
}