京東商城Android權限申請流程分析

京東動態申請定位權限分析

京東權限申請流程.png

1、安裝完成后,權限狀態為詢問狀態,此時,進入應用提示

首次進入App提示信息.png
1.1點擊取消,對話框消失,Toast提示信息如下

需在手機設置中打開京東的位置信息權限。

Screenshot_20170901-161650.png
1.2在1中點擊"去打開",對話框消失,系統對話框提示
Screenshot_20170901-161947.png
1.2.1未選中"禁止后不再詢問",點擊拒絕,提示信息如下
未選中''禁止后不再詢問',點擊拒絕提示信息.png

1.2.1.1點擊取消,Toast提示信息和1.1一致
1.2.1.2點擊"去允許",系統提示信息和1.2一致

1.2.2選中"禁止后不再詢問",點擊拒絕
選中''禁止后不再詢問',點擊拒絕提示信息.png

此時點擊取消顯示Toast信息
點擊去打開跳轉到應用信息頁面,在下面這個頁面中打開定位權限即可


應用信息頁面.png

高仿京東動態申請定位權限

第一、在配置文件中聲明定位權限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

第二、檢查是否獲取權限(關鍵方法)

/**
     * 第一步調用檢查定位權限
     */
    public void checkLocationPermission() {
        Context activity = getActivity();
        //未獲取權限
        if (ContextCompat.checkSelfPermission(activity,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            //詢問狀態
            if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
                /*在Fragment中不能使用以下方式申請權限,否則,會接收不到結果
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        REQUEST_PERMISSION_LOCATION);*/
                new AlertDialog.Builder(getActivity())
                        .setMessage("為保證您正常地使用此功能,需要獲取您的位置使用權限,請允許")//  禁止狀態
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                showMessage("需在手機設置中打開應用的拍照權限.");
                                dialog.dismiss();
                            }
                        })
                        .setPositiveButton("去允許", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //在Fragment中申請權限
                                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATION);
                                dialog.dismiss();
                            }
                        })
                        .show();

            } else {
                /*
                * 禁止狀態
                * 注意:禁止狀態調用申請權限的方法requestPermissions沒反應,此時提示用戶為什么要這個權限且跳轉至應用信息頁面,讓用戶開啟權限
                * */
                new AlertDialog.Builder(getActivity())
                        .setMessage("未取得您的位置信息使用權限,此功能無法使用。請前往應用權限設置打開權限")//  禁止狀態
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getActivity(), mCancelTip, Toast.LENGTH_SHORT);
                                dialog.dismiss();
                            }
                        })
                        .setPositiveButton("去打開", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //去應用信息頁面
                                goToAppDetailSettingIntent(getActivity());
                                dialog.dismiss();
                            }
                        })
                        .show();
            }

        } else {
            //已經允許
            startLocation();
        }
    }

第三、提供用戶點擊始終允許后回調的方法

    public abstract void startLocation();

BaseLocationFragment.java基類完整代碼如下

/**
 * 類描述:請求定位權限Fragment有需要定位權限功能的應用,在Actvity的布局中使用fragment標簽,name設置為該
 * 來的實現類即可,在回調方法中調用定位API即可
 * 作者:xues
 * 時間:2017年09月02日
 */

public abstract class BaseLocationFragment extends BaseFragment {
    private static final int REQUEST_PERMISSION_LOCATION = 111;//定位權限請求碼
    private static final String mCancelTip = "需在手機設置中打開京東的位置信息權限。";//取消提示信息

    /**
     * 第一步調用檢查定位權限
     */
    public void checkLocationPermission() {
        Context activity = getActivity();
        //未獲取權限
        if (ContextCompat.checkSelfPermission(activity,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            //詢問狀態
            if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
                /*在Fragment中不能使用以下方式申請權限,否則,會接收不到結果
                ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        REQUEST_PERMISSION_LOCATION);*/
                new AlertDialog.Builder(getActivity())
                        .setMessage("為保證您正常地使用此功能,需要獲取您的位置使用權限,請允許")//  禁止狀態
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getActivity(), mCancelTip, Toast.LENGTH_SHORT).show();
                                dialog.dismiss();
                            }
                        })
                        .setPositiveButton("去允許", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //在Fragment中申請權限
                                requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATION);
                                dialog.dismiss();
                            }
                        })
                        .show();

            } else {
                /*
                * 禁止狀態
                * 注意:禁止狀態調用申請權限的方法requestPermissions沒反應,此時提示用戶為什么要這個權限且跳轉至應用信息頁面,讓用戶開啟權限
                * */
                new AlertDialog.Builder(getActivity())
                        .setMessage("未取得您的位置信息使用權限,此功能無法使用。請前往應用權限設置打開權限")//  禁止狀態
                        .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getActivity(), mCancelTip, Toast.LENGTH_SHORT);
                                dialog.dismiss();
                            }
                        })
                        .setPositiveButton("去打開", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                //去應用信息頁面
                                goToAppDetailSettingIntent(getActivity());
                                dialog.dismiss();
                            }
                        })
                        .show();
            }

        } else {
            //已經允許
            startLocation();
        }
    }


    /**
     * 跳轉到應用信息頁面
     *
     * @param context
     */
    public static void goToAppDetailSettingIntent(Context context) {
        Intent localIntent = new Intent();
        localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= 9) {
            localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
            localIntent.setData(Uri.fromParts("package", context.getPackageName(), null));
        } else if (Build.VERSION.SDK_INT <= 8) {
            localIntent.setAction(Intent.ACTION_VIEW);
            localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
            localIntent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
        }
        context.startActivity(localIntent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case REQUEST_PERMISSION_LOCATION: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    startLocation();
                }
            }
        }
    }

    /**
     * 在該方法中調用定位服務
     */
    public abstract void startLocation();
}

BaseLocationFragment的使用

1、繼承BaseLocationFragment,讓BaseLocationFragment繼承你自己的BaseFragment,如果你想要在Activity中使用,建議在Activity中使用Fragment即可
2、定位前先調用checkLocationPermission檢查定位服務,用戶允許后會回調startLocation方法
3、在startLocation方法中,啟動定位服務即可

動態申請權限時,主要有以下幾點需要開發者注意的地方

1、用戶選中“禁止后不再詢問”再點擊“拒絕” 后,代碼就不做處理了,這樣的結果會導致下次調用申請權限的方法時,沒有任何反應(BaseLocationFragment已經處理)
2、在Fragment中申請權限時,不能使用以下方法進行申請,這樣的做法會導致Fragment中的方法onRequestPermissionsResult不執行

ActivityCompat.requestPermissions(getActivity(),
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        REQUEST_PERMISSION_LOCATION);

正確的做法是使用fragment中的方法,而不是ActivityCompat的方法

requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATION);

3、shouldShowRequestPermissionRationale,這個方法,個人的理解是:返回false表示當前權限的狀態為禁止狀態,即選中“禁止后不再詢問”,點擊拒絕后的狀態
到這里,使用原生API動態申請權限的分析就結束了,有什么不正確的地方,請指示,共同進步!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容