1. 程式人生 > >Android 6.0 動態許可權申請簡單簡潔優雅的處理方式

Android 6.0 動態許可權申請簡單簡潔優雅的處理方式

Android M 或以上的裝置,在使用涉及隱私的安全許可權時,需要動態申請,雖然不難,但寫下來程式碼工作量也不少,而且幾乎每個應用都需要用到。所以一直在探索一個要足夠簡單簡潔優雅的處理方式,強迫症的精神指導我要拒絕一切繁瑣。至於完不完美那就仁者見仁了。

一、思路:

如果在每個用到許可權的地方去申請,有點繁瑣,所以做法是直接在每個Activity介面顯示前就把該介面所需的許可權全部申請允許了,再進入正常的流程。如果有許可權未被允許,開發者可以在介面中自己處理,可以直接提示並退出,或者提示許可權的作用後重新發起許可權申請。

二、危險許可權列表:Dangerous Permissions

在Android M 或以上,以下許可權需要動態申請的意思。

group:android.permission-group.CONTACTS
  permission:android.permission.WRITE_CONTACTS
  permission:android.permission.GET_ACCOUNTS
  permission:android.permission.READ_CONTACTS

group:android.permission-group.PHONE
  permission:android.permission.READ_CALL_LOG
  permission:android.permission.READ_PHONE_STATE
  permission:android.permission.CALL_PHONE
  permission:android.permission.WRITE_CALL_LOG
  permission:android.permission.USE_SIP
  permission:android.permission.PROCESS_OUTGOING_CALLS
  permission:com.android.voicemail.permission.ADD_VOICEMAIL

group:android.permission-group.CALENDAR
  permission:android.permission.READ_CALENDAR
  permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA
  permission:android.permission.CAMERA

group:android.permission-group.SENSORS
  permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION
  permission:android.permission.ACCESS_FINE_LOCATION
  permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE
  permission:android.permission.READ_EXTERNAL_STORAGE
  permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE
  permission:android.permission.RECORD_AUDIO

group:android.permission-group.SMS
  permission:android.permission.READ_SMS
  permission:android.permission.RECEIVE_WAP_PUSH
  permission:android.permission.RECEIVE_MMS
  permission:android.permission.RECEIVE_SMS
  permission:android.permission.SEND_SMS
  permission:android.permission.READ_CELL_BROADCASTS
三、使用方式:

先從Activity的使用開始。

public class MainActivity extends AppCompatActivity implements PermissionInterface {

    private PermissionHelper mPermissionHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

		//初始化併發起許可權申請
        mPermissionHelper = new PermissionHelper(this, this);
        mPermissionHelper.requestPermissions();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(mPermissionHelper.requestPermissionsResult(requestCode, permissions, grantResults)){
			//許可權請求結果,並已經處理了該回調
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    public int getPermissionsRequestCode() {
		//設定許可權請求requestCode,只有不跟onRequestPermissionsResult方法中的其他請求碼衝突即可。
        return 10000;
    }

    @Override
    public String[] getPermissions() {
		//設定該介面所需的全部許可權
        return new String[]{
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_PHONE_STATE
        };
    }

    @Override
    public void requestPermissionsSuccess() {
		//許可權請求使用者已經全部允許
        initViews();
    }

    @Override
    public void requestPermissionsFail() {
        //許可權請求不被使用者允許。可以提示並退出或者提示許可權的用途並重新發起許可權申請。
        finish();
    }
    
    private void initViews(){
        //已經擁有所需許可權,可以放心操作任何東西了
		
    }

}
四、其中使用到的兩個類和一個介面實現:

1、Activity需要實現的介面PermissionInterface.java

/**
 * 許可權請求介面
 * Created by dway on 2018/1/10.
 */
public interface PermissionInterface {

    /**
     * 可設定請求許可權請求碼
     */
    int getPermissionsRequestCode();

    /**
     * 設定需要請求的許可權
     */
    String[] getPermissions();

    /**
     * 請求許可權成功回撥
     */
    void requestPermissionsSuccess();

    /**
     * 請求許可權失敗回撥
     */
    void requestPermissionsFail();

}
2、工具類PermissionUtil.java
/**
 * 動態許可權工具類
 * Created by dway on 2017/1/13.
 */
public class PermissionUtil {

    /**
     * 判斷是否有某個許可權
     * @param context
     * @param permission
     * @return
     */
    public static boolean hasPermission(Context context, String permission){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if(context.checkSelfPermission(permission)  != PackageManager.PERMISSION_GRANTED){
                return false;
            }
        }
        return true;
    }

    /**
     * 彈出對話方塊請求許可權
     * @param activity
     * @param permissions
     * @param requestCode
     */
    public static void requestPermissions(Activity activity, String[] permissions, int requestCode){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            activity.requestPermissions(permissions, requestCode);
        }
    }

    /**
     * 返回缺失的許可權
     * @param context
     * @param permissions
     * @return 返回缺少的許可權,null 意味著沒有缺少許可權
     */
    public static String[] getDeniedPermissions(Context context, String[] permissions){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ArrayList<String> deniedPermissionList = new ArrayList<>();
            for(String permission : permissions){
                if(context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED){
                    deniedPermissionList.add(permission);
                }
            }
            int size = deniedPermissionList.size();
            if(size > 0){
                return deniedPermissionList.toArray(new String[deniedPermissionList.size()]);
            }
        }
        return null;
    }

}
3、許可權操作幫助類PermissionHelper.java
package com.dway.permission;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.annotation.NonNull;

/**
 * 動態許可權幫助類
 * Created by dway on 2018/1/10.
 */
public class PermissionHelper {

    private Activity mActivity;
    private PermissionInterface mPermissionInterface;

    public PermissionHelper(@NonNull Activity activity, @NonNull PermissionInterface permissionInterface) {
        mActivity = activity;
        mPermissionInterface = permissionInterface;
    }

    /**
     * 開始請求許可權。
     * 方法內部已經對Android M 或以上版本進行了判斷,外部使用不再需要重複判斷。
     * 如果裝置還不是M或以上版本,則也會回撥到requestPermissionsSuccess方法。
     */
    public void requestPermissions(){
        String[] deniedPermissions = PermissionUtil.getDeniedPermissions(mActivity, mPermissionInterface.getPermissions());
        if(deniedPermissions != null && deniedPermissions.length > 0){
            PermissionUtil.requestPermissions(mActivity, deniedPermissions, mPermissionInterface.getPermissionsRequestCode());
        }else{
            mPermissionInterface.requestPermissionsSuccess();
        }
    }

    /**
     * 在Activity中的onRequestPermissionsResult中呼叫
     * @param requestCode
     * @param permissions
     * @param grantResults
     * @return true 代表對該requestCode感興趣,並已經處理掉了。false 對該requestCode不感興趣,不處理。
     */
    public boolean requestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){
        if(requestCode == mPermissionInterface.getPermissionsRequestCode()){
            boolean isAllGranted = true;//是否全部許可權已授權
            for(int result : grantResults){
                if(result == PackageManager.PERMISSION_DENIED){
                    isAllGranted = false;
                    break;
                }
            }
            if(isAllGranted){
                //已全部授權
                mPermissionInterface.requestPermissionsSuccess();
            }else{
                //許可權有缺失
                mPermissionInterface.requestPermissionsFail();
            }
            return true;
        }
        return false;
    }
    
}

OK,完成。哪個Activity需要許可權就實現介面,其他用幫助類就全部搞定。

轉載請註明來源:http://blog.csdn.net/lin_dianwei/article/details/79025324