使用反射技术封装一个请求应用运行时所需权限的工具类,这里只实现请求一个权限的封装,反射调用的业务方法是无参数列表的。
参考示例:https://github.com/googlesamples/android-RuntimePermissionsBasic/ 这个链接展示了如何请求一个运行时的权限,它里面请求的是一个使用摄像头的权限。
我封装的工具类代码如下:
1.GetPermissionUtils.java
package com.aaa.aContacts; import android.app.Activity; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; import android.widget.Toast; import androidx.core.app.ActivityCompat; import java.lang.reflect.Method; /** * 作者:kevin on 2019/8/9 15:56 * 通过反射封装工具类 请求运行时权限 针对android 6.0以上版本的系统 * 反射默认调用Main.java这个类中的无参数列表的业务方法 */ public class GetPermissionUtils implements ActivityCompat.OnRequestPermissionsResultCallback { private Context context; private Activity activity; Class clazz ; // class对象,通过用户传入的path得到 String path; // 调用者传入的类路径 如 com.aaa.aContacts.Main String[] permissions = {}; // 需要申请的权限列表 int index = 0; // 权限在permissions 数组中的索引值 String methodName; // Activity中得到运行所需权限后,准备要执行的业务方法名称 Method method ; // Method对象,一旦拿到实例就是执行Activity中的那个业务方法 private ContentResolver resolver; private static final int MY_CODE = 0; /** * 有参构造器 * @param context 应用上下文对象 * @param activity 当前的Activity * @param path 当前的Activity的全名 com.aaa.aContacts.Main * @param permissions 需要申请的权限数组 * @param index 某个权限在数组中的索引位置 * @param methodName ctivity中得到运行所需权限后,准备要执行的业务方法名称 */ public GetPermissionUtils(Context context, Activity activity, String path, String[] permissions, int index,String methodName) { this.context = context; this.activity = activity; this.path = path; this.permissions = permissions; this.index = index; this.methodName = methodName; try { resolver = context.getContentResolver(); this.clazz = Class.forName(path); method = clazz.getMethod(methodName,new Class[]{}); } catch (Exception e) { e.printStackTrace(); } } // 请求权限 :先检测当前Activity是否具有运行时所需权限,如果有直接调用业务方法,如果没有就去申请 public void checkPermission() { int code = ActivityCompat.checkSelfPermission(context, permissions[index]); // 检测应用是否具备该权限 if(code == PackageManager.PERMISSION_GRANTED ){ // 已经具有运行时所需权限 try { method.invoke(activity,new Object[]{}); } catch (Exception e) { e.printStackTrace(); } }else { // 没有运行时所需权限 requestRuntimePermission(); // 请求运行时所需权限 } } /** * 如果用户授予权限就提示一下,否则就请求权限 */ public void requestRuntimePermission(){ // 2019年8月9日16:04:09 请求运行时所需权限 if (ActivityCompat.shouldShowRequestPermissionRationale(activity,permissions[index])) { Toast.makeText(context.getApplicationContext(),"恭喜你,成功授予权限",Toast.LENGTH_LONG).show(); }else{ ActivityCompat.requestPermissions(activity,permissions, MY_CODE); } } @Override // 2019年8月9日16:01:48 请求权限回调方法 public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) { if (requestCode == MY_CODE ) { if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(context,"恭喜你,成功授予权限",Toast.LENGTH_LONG).show(); try { method.invoke(activity,new Object[]{}); } catch (Exception e) { e.printStackTrace(); } } else { Toast.makeText(context,"很遗憾,你不同意授权",Toast.LENGTH_LONG).show(); } } } }
2.通过Main.java 这个Activity测试,请求READ_CONTACTS这个权限,确实可以用。需要在模拟器中添加一位联系人,不然Logcat中没有想要的日志信息。
package com.aaa.aContacts; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import android.Manifest; import android.app.Activity; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; public class Main extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { private Context appContext; private ContentResolver resolver; private static final String TAG = "Main"; private static final int MY_CODE=0; private GetPermissionUtils getPermissionUtils; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); appContext = Main.this.getApplicationContext(); resolver = appContext.getContentResolver(); } public void ReadContacts(View view){ String path = "com.aaa.aContacts.Main"; String[] permisssions = {Manifest.permission.READ_CONTACTS}; getPermissionUtils = new GetPermissionUtils(appContext,Main.this,path,permisssions,0,"read"); getPermissionUtils.checkPermission(); // getPermission(); } @Override // 2019年8月9日16:01:48 请求权限回调方法 public void onRequestPermissionsResult(int requestCode,String[] permissions,int[] grantResults) { getPermissionUtils.onRequestPermissionsResult(requestCode,permissions,grantResults); } public void read(){ Uri uri = Uri.parse("content://com.android.contacts/contacts"); Cursor cursor = resolver.query(uri, new String[]{"_id"}, null, null, null); while (cursor.moveToNext()){ int contactsId = cursor.getInt(0); // 获取到联系人的id值 StringBuilder sb = new StringBuilder("contactId"); sb.append(contactsId); uri = Uri.parse("content://com.android.contacts/contacts/"+contactsId+"/data"); Cursor dataCursor = resolver.query(uri,new String[]{"mimetype","data1","data2"},null,null,null); while (dataCursor.moveToNext()){ String data = dataCursor.getString(dataCursor.getColumnIndex("data1")); // String type = dataCursor.getString(dataCursor.getColumnIndex("data2")); String type = dataCursor.getString(dataCursor.getColumnIndex("mimetype")); if("vnd.android.cursor.item/name".equals(type)){ // 姓名 sb.append("name="+data); }else if("vnd.android.cursor.item/phone_v2".equals(type)){ // 电话 sb.append("phone="+data); }else if("vnd.android.cursor.item/email_v2".equals(type)){ // email sb.append("email="+data); } } Log.i(TAG,sb.toString()); } } }
3.通过反射封装一个能执行带参数列表方法的请求权限的工具类