Android 12启动时未弹出位置权限对话框问题求助
问题:Android 12真机启动APP未弹出位置权限对话框,直接显示前往设置的Snackbar
按照教程实现APP启动时请求位置权限,但在Android 12真机测试时,未弹出权限对话框,而是显示提示用户前往设置手动授权的Snackbar。预期是APP启动时弹出权限对话框。
Manifest文件
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <!-- TODO: Step 1 add in permissions for fine location and background--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".HuntMainActivity" android:label="@string/title_activity_hunt" android:launchMode="singleInstance" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".GeofenceBroadcastReceiver"/> </application> </manifest>
代码实现
class HuntMainActivity : AppCompatActivity() { private lateinit var binding: ActivityHuntMainBinding private lateinit var geofencingClient: GeofencingClient private lateinit var viewModel: GeofenceViewModel private val runningQOrLater = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q // A PendingIntent for the Broadcast Receiver that handles geofence transitions. // TODO: Step 8 add in a pending intent override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = DataBindingUtil.setContentView(this, R.layout.activity_hunt_main) viewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(GeofenceViewModel::class.java) binding.viewmodel = viewModel binding.lifecycleOwner = this // TODO: Step 9 instantiate the geofencing client // Create channel for notifications createChannel(this ) } override fun onStart() { super.onStart() checkPermissionsAndStartGeofencing() } /* * When we get the result from asking the user to turn on device location, we call * checkDeviceLocationSettingsAndStartGeofence again to make sure it's actually on, but * we don't resolve the check to keep the user from seeing an endless loop. */ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // TODO: Step 7 add code to check that the user turned on their device location and ask // again if they did not } /* * When the user clicks on the notification, this method will be called, letting us know that * the geofence has been triggered, and it's time to move to the next one in the treasure * hunt. */ override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) val extras = intent?.extras if(extras != null){ if(extras.containsKey(GeofencingConstants.EXTRA_GEOFENCE_INDEX)){ viewModel.updateHint(extras.getInt(GeofencingConstants.EXTRA_GEOFENCE_INDEX)) checkPermissionsAndStartGeofencing() } } } /* * In all cases, we need to have the location permission. On Android 10+ (Q) we need to have * the background permission as well. */ @SuppressLint("MissingSuperCall") override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { Log.d(TAG, "onRequestPermissionResult") if ( grantResults.isEmpty() || grantResults[LOCATION_PERMISSION_INDEX] == PackageManager.PERMISSION_DENIED || (requestCode == REQUEST_FOREGROUND_AND_BACKGROUND_PERMISSION_RESULT_CODE && grantResults[BACKGROUND_LOCATION_PERMISSION_INDEX] == PackageManager.PERMISSION_DENIED)) { Snackbar.make( binding.activityMapsMain, R.string.permission_denied_explanation, Snackbar.LENGTH_INDEFINITE ) .setAction(R.string.settings) { startActivity(Intent().apply { action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS data = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null) flags = Intent.FLAG_ACTIVITY_NEW_TASK }) }.show() } else { checkDeviceLocationSettingsAndStartGeofence() } } /** * This will also destroy any saved state in the associated ViewModel, so we remove the * geofences here. */ override fun onDestroy() { super.onDestroy() removeGeofences() } /** * Starts the permission check and Geofence process only if the Geofence associated with the * current hint isn't yet active. */ private fun checkPermissionsAndStartGeofencing() { if (viewModel.geofenceIsActive()) return if (foregroundAndBackgroundLocationPermissionApproved()) { checkDeviceLocationSettingsAndStartGeofence() } else { requestForegroundAndBackgroundLocationPermissions() } } /* * Uses the Location Client to check the current state of location settings, and gives the user * the opportunity to turn on location services within our app. */ private fun checkDeviceLocationSettingsAndStartGeofence(resolve:Boolean = true) { val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_LOW_POWER } val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest) val settingsClient = LocationServices.getSettingsClient(this) val locationSettingsResponseTask = settingsClient.checkLocationSettings(builder.build()) locationSettingsResponseTask.addOnFailureListener { exception -> if (exception is ResolvableApiException && resolve){ try { exception.startResolutionForResult(this@HuntMainActivity, REQUEST_TURN_DEVICE_LOCATION_ON) } catch (sendEx: IntentSender.SendIntentException) { Log.d(TAG, "Error getting location settings resolution: " + sendEx.message) } } else { Snackbar.make( binding.activityMapsMain, R.string.location_required_error, Snackbar.LENGTH_INDEFINITE ).setAction(android.R.string.ok) { checkDeviceLocationSettingsAndStartGeofence() }.show() } } locationSettingsResponseTask.addOnCompleteListener { if ( it.isSuccessful ) { addGeofenceForClue() } } } /* * Determines whether the app has the appropriate permissions across Android 10+ and all other * Android versions. */ @TargetApi(29) private fun foregroundAndBackgroundLocationPermissionApproved(): Boolean { val foregroundLocationApproved = ( PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)) val backgroundPermissionApproved = if (runningQOrLater) { PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_BACKGROUND_LOCATION ) } else { true } return foregroundLocationApproved && backgroundPermissionApproved } /* * Requests ACCESS_FINE_LOCATION and (on Android 10+ (Q) ACCESS_BACKGROUND_LOCATION. */ @TargetApi(29 ) private fun requestForegroundAndBackgroundLocationPermissions() { if (foregroundAndBackgroundLocationPermissionApproved()) return var permissionsArray = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) val resultCode = when { runningQOrLater -> { permissionsArray += Manifest.permission.ACCESS_BACKGROUND_LOCATION REQUEST_FOREGROUND_AND_BACKGROUND_PERMISSION_RESULT_CODE } else -> { REQUEST_FOREGROUND_ONLY_PERMISSIONS_REQUEST_CODE } } Log.d(TAG, "Request foreground only location permission") ActivityCompat.requestPermissions( this@HuntMainActivity, permissionsArray, resultCode ) } /* * Adds a Geofence for the current clue if needed, and removes any existing Geofence. This * method should be called after the user has granted the location permission. If there are * no more geofences, we remove the geofence and let the viewmodel know that the ending hint * is now "active." */ private fun addGeofenceForClue() { // TODO: Step 10 add in code to add the geofence } /** * Removes geofences. This method should be called after the user has granted the location * permission. */ private fun removeGeofences() { // TODO: Step 12 add in code to remove the geofences } companion object { internal const val ACTION_GEOFENCE_EVENT = "HuntMainActivity.treasureHunt.action.ACTION_GEOFENCE_EVENT" } } private const val REQUEST_FOREGROUND_AND_BACKGROUND_PERMISSION_RESULT_CODE = 33 private const val REQUEST_FOREGROUND_ONLY_PERMISSIONS_REQUEST_CODE = 34 private const val REQUEST_TURN_DEVICE_LOCATION_ON = 29 private const val TAG = "HuntMainActivity" private const val LOCATION_PERMISSION_INDEX = 0 private const val BACKGROUND_LOCATION_PERMISSION_INDEX = 1
截图

内容的提问来源于stack exchange,提问作者Krista
相关产品推荐
相关产品推荐

