京東動態申請定位權限分析
京東權限申請流程.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動態申請權限的分析就結束了,有什么不正確的地方,請指示,共同進步!