封裝了一個關於權限相關和開關的申請Demo,先貼出來視頻效果,最開始的時候GPS開關沒打開,沒有位置權限,沒開啓藍牙功能,點擊按鈕之後先後打開GPS開關,動態申請位置權限,打開GPS開關和藍牙功能。
貼出核心代碼:
1. 首先先封裝了一個動態權限請求的工具類,藍牙功能的申請也寫在其中:
class PermissionsUtils {
companion object {
fun checkGPS(context: Context): Boolean {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
}
@RequiresApi(Build.VERSION_CODES.M)
fun checkLocationPermission(activity: Activity): Boolean {
return ContextCompat.checkSelfPermission(
activity,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
}
@RequiresApi(Build.VERSION_CODES.M)
fun requestLocationPermissions(activity: Activity) {
if (!checkLocationPermission(activity)) {
activity.requestPermissions(
arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
), POSITION_PERMISSION_REQUEST_CODE
)
}
}
fun toggleLocationSetting(activity: Activity) {
val intent = Intent()
try {
val packageURI = Uri.parse("package:" + activity.packageName)
activity.startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI))
} catch (e: Exception) {
e.printStackTrace()
intent.action = Settings.ACTION_APPLICATION_SETTINGS
intent.putExtra("package", activity.packageName)
activity.startActivity(intent)
}
}
/**
* 檢查藍牙狀態
*/
fun checkBluetooth(): Boolean {
val adapter = BluetoothAdapter.getDefaultAdapter()
return adapter.isEnabled
}
/**
* 調用系統API去打開藍牙
*/
fun requestBluetooth(activity: Activity) {
//會以Dialog的樣式來顯示系統級別的請求開啓藍牙Activity , 我們可以在onActivityResult()方法去處理返回值
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
activity.startActivityForResult(enableBtIntent, BLUETOOTH_REQUEST_CODE)
}
}
}
2. 用一個map記錄對哪些權限/開關發起過申請:
//用來記錄對哪些權限/開關發起過申請
private var requestMaps: MutableMap<String, Boolean> = mutableMapOf()
3. 動態權限申請都是以彈窗的形式讓用戶選擇允許還是拒絕,不管用戶是選擇哪一項, 在點擊完成(如果同時申請多個權限,則需要所有權限全部點擊完)後,必會觸發onRequestPermissionsResult這個回調方法。在權限響應回調的地方 onRequestPermissionsResult、以及響應startActivityForResult打開系統級別對話框的回調onActivityResult中對map進行處理:
/**
*
* 動態權限申請都是以彈窗的形式讓用戶選擇允許還是拒絕;不管用戶是選擇哪一項,
* 在點擊完成(如果同時申請多個權限,則需要所有權限全部點擊完)後,必會觸發onRequestPermissionsResult這個回調方法
*
* **/
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
AppConstants.POSITION_PERMISSION_REQUEST_CODE -> {
isPermissionChecking = false
requestMaps[AppConstants.TAG_LOCATION] = true
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED) {
if (!ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
) {
isPermissionChecking = true
requestMaps[AppConstants.TAG_LOCATION] = true
} else {
checkHardWareState()
}
} else {
checkHardWareState()
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
AppConstants.GPS_REQUEST_CODE -> {
//gps set dialog dismiss callback
resetScreenState()
requestMaps[AppConstants.TAG_GPS] = true
checkHardWareState()
}
AppConstants.BLUETOOTH_REQUEST_CODE -> {
requestMaps[AppConstants.TAG_BLUETOOTH] = true
resetScreenState()
}
}
}
Demo地址:https://download.csdn.net/download/crystal_xing/11958667,做這個功能需求的時候發現,GoogleApiClient的寫法已經被Google棄用,故用新寫法也寫了一份批量申請權限的Demo,一併打包。GPS開關的打開是因爲使用了gms:play-services-location,Google定位。不用這個的話做不到用代碼強行打開手機上的GPS開關。
官網文檔:https://developer.android.google.cn/training/location/change-location-settings (中文鏡像)
https://developer.android.com/training/location