開發app在android6.0執行直接退出解決(二)
阿新 • • 發佈:2019-02-09
許可權的適配主要就是兩步,一是請求許可權,二是系統應答,主要在這兩個地方進行封裝。主要使用第三方庫PermissionsDispatcher
(1)專案build.gradle 中新增
classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’
(2)app的 build.gradle 中新增
apply plugin:’android-apt’
apt ‘com.github.hotchemi:permissionsdispatcher-processor:2.1.3’
1.定義PermissionHandler用於許可權回撥,許可權通過、許可權拒絕、許可權不再詢問三種情況
public abstract class PermissionHandle{
//許可權通過
public abstract void onGranted();
//許可權拒絕
public abstract void onDenied();
//許可權不在詢問
public boolean onNeverAsk(){
return false;
}
}
2、請求許可權
private PermissionHandle mHandle;
/**
* 請求許可權
* @param permissions 許可權列表
* @param handle 回撥
*/
protected void requestPermission(String[] permissions,PermissionHandle handle){
if (PermissionUtil.hasSelfPermissions(this,permissions)){
handle.onGranted();
}else {
mHandle=handle;
ActivityCompat.requestPermissions(this,permissions,001);
}
}
注:PermissionUtil是PermissionsDispatcher中使用的工具類
public final class PermissionUtil {
private static SimpleArrayMap<String,Integer> MIN_SDK_PERMISSIONS;
static {
MIN_SDK_PERMISSIONS=new SimpleArrayMap<>(8);
MIN_SDK_PERMISSIONS.put("com.android.voicemail.permission.ADD_VOICEMAIL",14);
MIN_SDK_PERMISSIONS.put("android.permission.BODY_SENSORS",20);
MIN_SDK_PERMISSIONS.put("android.permission.READ_CALL_LOG",16);
MIN_SDK_PERMISSIONS.put("android.permission.READ_EXTERNAL_STORAGE",16);
MIN_SDK_PERMISSIONS.put("android.permission.USE_SIP",9);
MIN_SDK_PERMISSIONS.put("android.permission.WRITE_CALL_LOG",16);
MIN_SDK_PERMISSIONS.put("android.permission.SYSTEM_ALERT_WINDOW", 23);
MIN_SDK_PERMISSIONS.put("android.permission.WRITE_SETTINGS", 23);
}
private static volatile int targetSdkVersion=-1;
public PermissionUtil() {
}
//檢查所有的許可權是否被授權
public static boolean verifyPermissions(int... grantResults){
if (grantResults.length==0){
return false;
}
for (int result : grantResults) {
if (result!= PackageManager.PERMISSION_GRANTED){
return false;
}
}
return true;
}
//如果活動或片段可以訪問所有給定的許可權,則返回true
public static boolean hasSelfPermissions(Context context,String... permissions){
for (String permission : permissions) {
if (permissionExists(permission)&&hasSelfPermissions(context,permission)){
return false;
}
}
return true;
}
//如果在這個SDK版本存在的許可權,則返回true
private static boolean permissionExists(String permission) {
Integer minVersion = MIN_SDK_PERMISSIONS.get(permission);
return minVersion == null || Build.VERSION.SDK_INT >= minVersion;
}
//確定上下文訪問給定的許可權。
private static boolean hasSelfPermission(Context context, String permission) {
try {
return PermissionChecker.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
} catch (RuntimeException t) {
return false;
}
}
//檢查需要給予的許可權,顯示理由
public static boolean shouldShowRequestPermissionRationale(Activity activity, String... permissions) {
for (String permission : permissions) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
return true;
}
}
return false;
}
//獲取sdk 版本
@TargetApi(Build.VERSION_CODES.DONUT)
public static int getTargetSdkVersion(Context context) {
try {
if (targetSdkVersion != -1) {
return targetSdkVersion;
}
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
targetSdkVersion = packageInfo.applicationInfo.targetSdkVersion;
} catch (PackageManager.NameNotFoundException ignored) {
}
return targetSdkVersion;
}
}
3.許可權結果處理
/**
* 許可權請求結果
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (mHandle==null){
return;
}
if (PermissionUtil.shouldShowRequestPermissionRationale(this,permissions)){
if (!mHandle.onNeverAsk()){
Toast.makeText(this, "許可權已被拒絕,請在設定-應用-許可權中開啟", Toast.LENGTH_SHORT).show();
}
}else{
mHandle.onDenied();
}
}
4、呼叫
public class PermissionActivity extends XPermissionActivity implements View.OnClickListener {
private Context mContext;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_permission);
mContext=PermissionActivity.this;
findViewById(R.id.btn_camera).setOnClickListener(this);
findViewById(R.id.btn_call).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_camera:
requestPermission(new String[]{Manifest.permission.CAMERA}, new PermissionHandle() {
@Override
public void onGranted() {
Intent intent = new Intent(); //呼叫照相機
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
}
@Override
public void onDenied() {
Toast.makeText(PermissionActivity.this, "拒絕", Toast.LENGTH_SHORT).show();
}
});
break;
case R.id.btn_call:
requestPermission(new String[]{Manifest.permission.CALL_PHONE}, new PermissionHandle() {
@Override
public void onGranted() {
/*Intent i=new Intent(Intent.ACTION_CALL,Uri.parse("tel:10086"));
startActivity(i);*/
Uri uri = Uri.parse("tel:10086");
Intent intent = new Intent(Intent.ACTION_DIAL, uri);
startActivity(intent);
}
@Override
public void onDenied() {
Toast.makeText(PermissionActivity.this, "拒絕", Toast.LENGTH_SHORT).show();
}
@Override
public boolean onNeverAsk() {
new AlertDialog.Builder(mContext)
.setTitle("許可權申請")
.setMessage("在設定-應用-許可權中開始電話許可權,以保證功能的正常使用")
.setPositiveButton("去開啟",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
Intent i=new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri=Uri.fromParts("package",getPackageName(),null);
i.setData(uri);
startActivity(i);
dialog.dismiss();
}
})
.setNegativeButton("取消",null)
.setCancelable(false)
.show();
return true;
}
});
break;
}
}
}