目录
一、内容提供器简介
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能
二、运行时权限
1.Android权限机制详解
权限分成两类:
普通权限:这部分权限申请系统会自动帮我们授权,无需手动操作
危险权限:必须由用户手动点击授权
2.在程序运行时申请权限
-
借助ContextCompat.checkSelfPermission()方法判断用户是不是已经给过我们授权,第一个参数是Context,第二个参数是具体的权限名,使用方法的返回值和PackageManager.PERMISSION_GRANTED作比较,相等说明用户已经授权,不等表示用户没有授权
-
申请授权需要调用ActivityCompat.requestPermissions()方法,第一个参数是Activity的实例,第二个参数是一个String数组,要申请的权限名放在数据中,第三个参数是请求码,传入唯一值即可
-
选择同意或拒绝授权申请后,结果会回调到onRequestPermissionsResult()方法中
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button makeCall = 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:10010"));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull 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:
}
}
}
三、访问其他程序中的数据
1.ContentResolver的基本用法
-
可通过Context的getContentResolver()获取该类的实例
-
ContentResolver提供了一系列的方法用于对数据进行CRUD操作:insert(),update(),delete(),query()
-
ContentResolver中的增删改查方法不接受表名参数,而是使用Uri参数代替,称为内容URI
2.实践---读取系统联系人
public class MainActivity extends AppCompatActivity {
ArrayAdapter<String> adapter;
List<String> contactsList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView contactsView = findViewById(R.id.contacts_view);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contactsList);
contactsView.setAdapter(adapter);
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS},1);
}else{
readContacts();
}
}
private void readContacts(){
Cursor cursor = null;
try {
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
if(cursor!=null){
while(cursor.moveToNext()){
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName+"\n"+number);
}
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(cursor!=null){
cursor.close();
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch(requestCode){
case 1:
if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
readContacts();
}else {
Toast.makeText(this, "您拒绝了读取联系人权限", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
}
四、创建自己的内容提供器
1.创建内容提供器的步骤
通过新建一个类继承ContentProvider的方式来创建一个自己的内容提供器
ContentProvider类中由6个抽象方法:
-
onCreate()
-
query()
-
insert()
-
update()
-
delete()
-
getType()
2.实现跨程序数据共享
public class DatabaseProvider extends ContentProvider {
public static final int BOOK_DIR = 0;
public static final int BOOK_ITEM = 1;
public static final int CATEGORY_DIR = 2;
public static final int CATEGORY_ITEM = 3;
public static final String AUTHORITY = "com.jack.databasetest.provider";
public 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);
}
public DatabaseProvider() {
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// Implement this to handle requests to delete one or more rows.
SQLiteDatabase db = dbHelper.getWritableDatabase();
int deleteRows = 0;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
deleteRows = db.delete("Book",selection,selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deleteRows = db.delete("Book", "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
deleteRows = db.delete("Category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deleteRows = db.delete("Category", "id = ?", new String[]{categoryId});
break;
default:
break;
}
return deleteRows;
}
@Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
switch(uriMatcher.match(uri)){
case BOOK_DIR:
return "vnd.cursor.android.dir/vnd.com.jack.database.provider.book";
case BOOK_ITEM:
return "vnd.cursor.android.item/vnd.com.jack.database.provider.book";
case CATEGORY_DIR:
return "vnd.cursor.android.dir/vnd.com.jack.database.provider.category";
case CATEGORY_ITEM:
return "vnd.cursor.android.item/vnd.com.jack.database.provider.category";
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO: Implement this to handle requests to insert a new row.
SQLiteDatabase db = dbHelper.getWritableDatabase();
Uri uriReturn = null;
switch(uriMatcher.match(uri)){
case BOOK_DIR:
case BOOK_ITEM:
long newBookId = db.insert("Book", null, values);
uriReturn = Uri.parse("content://"+AUTHORITY+"/book/"+newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId = db.insert("Category", null, values);
uriReturn = Uri.parse("content://"+AUTHORITY+"/category/"+newCategoryId);
break;
default:
break;
}
return uriReturn;
}
@Override
public boolean onCreate() {
// TODO: Implement this to initialize your content provider on startup.
dbHelper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO: Implement this to handle query requests from clients.
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
cursor = db.query("Book", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
cursor = db.query("Book", projection, "id = ?", new String[]{bookId}, null, null, sortOrder);
break;
case CATEGORY_DIR:
cursor = db.query("Category", projection, selection, selectionArgs, null, null, sortOrder);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
cursor = db.query("Category", projection, "id = ?", new String[]{categoryId}, null, null, sortOrder);
break;
default:
break;
}
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO: Implement this to handle requests to update one or more rows.
SQLiteDatabase db = dbHelper.getWritableDatabase();
int updateRows = 0;
switch (uriMatcher.match(uri)){
case BOOK_DIR:
updateRows = db.update("Book", values, selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
updateRows = db.update("Book", values, "id = ?", new String[]{bookId});
break;
case CATEGORY_DIR:
updateRows = db.update("Category", values, selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
updateRows = db.update("Category", values, "id = ?", new String[]{categoryId});
break;
default:
break;
}
return updateRows;
}
}
完!