运行时权限
点击查看完整权限列表
例子:CALL_PHONE
AndroidManifest.xml
package="com.example.runtimepermissiontest">
<uses-permission android:name="android.permission.CALL_PHONE"/>
<application
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/make_call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Make Call"
android:textAllCaps="false"/>
</LinearLayout>
MainActivity.java
-
第一步就是要先判断用户是不是已经给过我们授权了,借助的是
ContextCompat.checkSelfPermission()
方法。checkSelfPermission()方法接收两个参数,- 第一个参数是
Context
, - 第二个参数是具体的权限名,比如打电话的权限名就是
Manifest.permission.CALL_PHONE
,然后我们使用方法的返回值和PackageManager.PERMISSION_GRANTED
做比较,相等就说明用户已经授权,不等就表示用户没有授权。
- 第一个参数是
-
如果已经授权的话就简单了,直接去执行拨打电话的逻辑操作就可以了,这里我们把拨打电话的逻辑封装到了call()方法当中。如果没有授权的话,则需要调用
ActivityCompat.requestPermissions()
方法来向用户申请授权,requestPermissions()方法接收3个参数:- 第一个参数要求是Activity的实例,
- 第二个参数是一个String数组,我们把要申请的权限名放在数组中即可,
- 第三个参数是请求码,只要是唯一值就可以了,这里传人了1。
-
调用完了requestPermissions()方法之后,系统会弹出一个权限申请的对话框,然后用户可以选择同意或拒绝我们的权限申请,不论是哪种结果,最终都会回调到
onRequest-PermissionsResult()
方法中,而授权的结果则会封装在grantResults
参数当中。这里我们只需要判断一下最后的授权结果,如果用户同意的话就调用call()方法来拨打电话,如果用户拒绝的话我们只能放弃操作,并且弹出一条失败提示。
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 view) {
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.re questPermissions(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 (Exception 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;
}
}
}
访问其他程序中数据
读取系统联系人
MainActivity.java
package com.example.contactstest;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
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 = (ListView) 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()){
@SuppressLint("Range") String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
@SuppressLint("Range") 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, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode){
case 1:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
readContacts();
}else{
Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
}
AndroidManifest.xml
package="com.example.contactstest">
<uses-permission android:name="android.permission.READ_CONTACTS"/>
创建自己的内容提供器
onCreate()
初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化。query ()
从内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。insert()
向内容提供器中添加一条数据。使用uri参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。update()
更新内容提供器中已有的数据。使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和 selectionArgs 参数用于约束更新哪些行,受影响的行数将作为返回值返回。delete()
从内容提供器中删除数据。使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。getType()
根据传入的内容URI来返回相应的MIME类型。
创建内容提供器步骤
- *:表示匹配任意长度的任意字符。
- #:表示匹配任意长度的数字。
MyProvider.java
public class MyProvider extends ContentProvider {
//访问表1中所有的数据
public static final int TABLE1_DIR = 0;
//访问表1中单个数据
public static final int TABLE1_ITEM = 1;
public static final int TABLE2_DIR = 2;
public static final int TABLE2_ITEM = 3;
private static UriMatcher uriMatcher;
static{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI("com.example.app.provider","table1",TABLE1_DIR);
uriMatcher.addURI("com.example.app.provider","table1/#",TABLE1_ITEM);
uriMatcher.addURI("com.example.app.provider","table2",TABLE1_DIR);
uriMatcher.addURI("com.example.app.provider","table2/#",TABLE1_ITEM);
}
@Override
public boolean onCreate() {
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
switch (uriMatcher.match(uri)){
case TABLE1_DIR:
//查询表1中所有的数据
break;
case TABLE1_ITEM:
//查询表1中单条数据
break;
case TABLE2_DIR:
//查询表2中所有的数据
break;
case TABLE2_ITEM:
//查询表2中单条数据
break;
default:
break;
}
return null;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
switch (uriMatcher.match(uri)){
case TABLE1_DIR:
return "vnd.android.cursor.dir.com.example.app.provider.table1";
case TABLE1_ITEM:
return "vnd.android.cursor.item.com.example.app.provider.table1";
case TABLE2_DIR:
return "vnd.android.cursor.dir.com.example.app.provider.table2";
case TABLE2_ITEM:
return "vnd.android.cursor.item.com.example.app.provider.table2";
}
return null;
}
实现跨程序数据共享
需要删除所有的Toast,因为跨程序访问不能直接使用Toast
package com.example.databasetest;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
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;
private static UriMatcher uriMatcher;
private static final String AUTHORITY = "com.example.datatbasetest.provider";
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 deletedRows = 0;
switch(uriMatcher.match(uri)){
case BOOK_DIR:
deletedRows = db.delete("Book",selection,selectionArgs);
break;
case BOOK_ITEM:
String bookId = uri.getPathSegments().get(1);
deletedRows = db.delete("Book","id = ?",new String[]{bookId});
break;
case CATEGORY_DIR:
deletedRows = db.delete("Category",selection,selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId = uri.getPathSegments().get(1);
deletedRows = db.delete("Category","id = ?",new String[]{categoryId});
break;
default:
break;
}
return deletedRows;
}
@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.android.cursor.dir.com.example.app.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item.com.example.app.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir.com.example.app.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item.com.example.app.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;
}
}
MainActivity.java
package com.example.databasetest;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.sql.SQLClientInfoException;
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper databaseHelper;
private String newId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
databaseHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Uri uri = Uri.parse("content://com.example.datatbasetest.provider/book");
ContentValues values = new ContentValues();
values.put("name","A Clash of Kings");
values.put("author","jinyifei");
values.put("pages",454);
values.put("price",16);
Uri newUri = getContentResolver().insert(uri,values);
newId = newUri.getPathSegments().get(1);
}
});
Button deleteData = (Button)findViewById(R.id.delete_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Uri uri = Uri.parse("content://com.example.datatbasetest.provider/book");
getContentResolver().delete(uri,null,null);
}
});
Button queryButton = (Button) findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Uri uri = Uri.parse("content://com.example.datatbasetest.provider/book");
Cursor cursor = getContentResolver().query(uri,null,null,null,null);
if(cursor != null){
do{
@SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex("name"));
@SuppressLint("Range") String author = cursor.getString(cursor.getColumnIndex("author"));
@SuppressLint("Range") int pages = cursor.getInt(cursor.getColumnIndex("pages"));
@SuppressLint("Range") double price = cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity","book name is "+ name);
Log.d("MainActivity","book author is "+ author);
Log.d("MainActivity","book pages is "+ pages);
Log.d("MainActivity","book price is "+ price);
}while(cursor.moveToNext());
}
cursor.close();
}
});
Button updateData = findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Uri uri = Uri.parse("content://com.example.datatbasetest.provider/book"+newId);
ContentValues values = new ContentValues();
values.put("name","A Storm od Swords");
values.put("pages",1216);
values.put("price",24.05);
getContentResolver().update(uri,values,null,null);
}
});
}
}