我尝试实现从存储中写入和读取的请求权限。一切都运行良好,但今天 Android 向我展示了 onRequestPermissionsResult(...) 方法已被弃用。 StackOverflow 中有很多关于这个主题的问题,但不幸的是,它们已经过时了。
我在片段中调用了以下方法。
建议只需致电:
requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
StorageKeys.STORAGE_PERMISSION_CODE)
而不是我的方法:
ActivityCompat.requestPermissions(getActivity(),
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
StorageKeys.STORAGE_PERMISSION_CODE))
但是它们都表明 onRequestPermissionsResult(...) 已被弃用。
这是我的 onRequestPermissionsResult(...) 方法:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == StorageKeys.STORAGE_PERMISSION_CODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
exportBibTex.createBibFile();
exportBibTex.writeBibFile(exportBibTex
.getBibDataLibrary(libraryModel, bookDao, noteDao));
Toast.makeText(getContext(),
getString(R.string.exported_file_stored_in) + '\n'
+ File.separator + StorageKeys.DOWNLOAD_FOLDER + File.separator + fileName
+ StorageKeys.BIB_FILE_TYPE, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getContext(), R.string.storage_permission_denied,
Toast.LENGTH_SHORT).show();
}
}
}
这是一个简单的警报对话框,我在其中调用 onRequestPermissionsResult(...):
private void showRequestPermissionDialog() {
AlertDialog.Builder reqAlertDialog = new AlertDialog.Builder(getContext());
reqAlertDialog.setTitle(R.string.storage_permission_needed);
reqAlertDialog.setMessage(R.string.storage_permission_alert_msg);
reqAlertDialog.setPositiveButton(R.string.ok,
(dialog, which) -> ActivityCompat.requestPermissions(getActivity(),
new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
StorageKeys.STORAGE_PERMISSION_CODE));
reqAlertDialog.setNegativeButton(R.string.cancel,
(dialog, which) -> dialog.dismiss());
reqAlertDialog.create().show();
}
我可以使用 onRequestPermissionsResult(...) 的替代方案吗?
onRequestPermissionsResult()
方法在 androidx.fragment.app.Fragment
中已弃用。
所以你可以使用
registerForActivityResult()
方法而不是onRequestPermissionsResult()
。
您可以参考这个网址。
以下是Kotlin代码,大家可以参考一下:
val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted ->
if (isGranted) {
// PERMISSION GRANTED
} else {
// PERMISSION NOT GRANTED
}
}
// Ex. Launching ACCESS_FINE_LOCATION permission.
private fun startLocationPermissionRequest() {
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
我从以下 URL 添加了 java 代码。
如何在新的ActivityResult API(1.3.0-alpha05)中获取权限请求?
private ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
new ActivityResultCallback<Boolean>() {
@Override
public void onActivityResult(Boolean result) {
if (result) {
// PERMISSION GRANTED
} else {
// PERMISSION NOT GRANTED
}
}
}
);
// Ex. Launch the permission window -- this is in onCreateView()
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
requestPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION);
}
});
您还可以请求多个权限:
val requestMultiplePermissions = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
// To log permissions:
permissions.entries.forEach {
Log.d("DEBUG", "${it.key} = ${it.value}")
}
// To check for permissions:
val a: Boolean = permissions[Manifest.permission.READ_CONTACTS] as Boolean
val b: Boolean = permissions[Manifest.permission.ACCESS_FINE_LOCATION] as Boolean
if (a && b) {
Log.d("LOG_TAG", "Has permissions: READ_CONTACTS, ACCESS_FINE_LOCATION.")
}
}
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.READ_CONTACTS,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
Kotlin 中的简单方法
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ActivityCompat
import androidx.fragment.app.Fragment
class MyFragment : Fragment() {
companion object {
val TAG: String = MyFragment::class.java.simpleName
var PERMISSIONS = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
}
private val permReqLauncher =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val granted = permissions.entries.all {
it.value == true
}
if (granted) {
displayCameraFragment()
}
}
private fun takePhoto() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
displayCameraFragment()
return
}
activity?.let {
if (hasPermissions(activity as Context, PERMISSIONS)) {
displayCameraFragment()
} else {
permReqLauncher.launch(
PERMISSIONS
)
}
}
}
// util method
private fun hasPermissions(context: Context, permissions: Array<String>): Boolean = permissions.all {
ActivityCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}
private fun displayCameraFragment() {
// open camera fragment
}
}
使用示例:
private fun permissionSetup() {
val permission = ContextCompat.checkSelfPermission(
requireContext(), Manifest.permission.READ_CONTACTS)
if (permission != PackageManager.PERMISSION_GRANTED) {
permissionsResultCallback.launch(Manifest.permission.READ_CONTACTS)
} else {
println("Permission isGranted")
}
}
private val permissionsResultCallback = registerForActivityResult(
ActivityResultContracts.RequestPermission()){
when (it) {
true -> { println("Permission has been granted by user") }
false -> {
Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show()
dialog.dismiss()
}
}
}
private final ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),
result -> {
if (result) {
//Permission granted
} else {
//permission denied
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, WRITE_EXTERNAL_STORAGE)) {
//show permission snackbar
} else {
//display error dialog
}
}
});
请求权限。注册的ActivityResultCallback获取本次请求的结果。
if (checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PermissionChecker.PERMISSION_GRANTED) {
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
} else {
//Permission already granted
}
private val REQUESTED_PERMISSIONS =
arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
当我们使用多个权限数组启动时,此 registerForActivityResult
会调用。
private val requestMultiplePermissions = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
permissions.entries.forEach {
Log.d("DEBUG", "${it.key} = ${it.value}")
if (!it.value){
return@registerForActivityResult
}
}
init()
}
现在我们创建一个函数来检查是否已授予权限。
private fun checkSelfPermission(): Boolean {
return !(ContextCompat.checkSelfPermission(
requireContext(),
REQUESTED_PERMISSIONS[0]
) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(
requireContext(),
REQUESTED_PERMISSIONS[1]
) != PackageManager.PERMISSION_GRANTED)
}
现在我们通过 onCreate
方法检查是否授予权限。如果未授予权限,则我们调用
requestMultiplePermissions.launch(REQUESTED_PERMISSIONS)
like
super.onCreate(savedInstanceState)
if (!checkSelfPermission()) {
requestMultiplePermissions.launch(REQUESTED_PERMISSIONS)
}
}
private fun checkPermissions() {
if (mContext?.let {
ContextCompat.checkSelfPermission(
it,
READ_EXTERNAL_STORAGE
)
} != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "Request Permissions")
requestMultiplePermissions.launch(
arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE))
} else {
Log.d(TAG, "Permission Already Granted")
}
}
private val requestMultiplePermissions =
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
Log.d(TAG, "${it.key} = ${it.value}")
}
if (permissions[READ_EXTERNAL_STORAGE] == true && permissions[WRITE_EXTERNAL_STORAGE] == true) {
Log.d(TAG, "Permission granted")
} else {
Log.d(TAG, "Permission not granted")
}
}
class ProfileFragment : Fragment(){
private lateinit var permissionRequest : ActivityResultLauncher<Array<String>>
companion object {
val LOCATION_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
}
private fun getGpsLocation() {
if(activity != null){
permissionRequest.launch(LOCATION_PERMISSIONS)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.locBtn.setOnClickListener { getGpsLocation() }
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerPermissionRequest()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_profile, container, false)
return binding.root
}
private fun registerPermissionRequest(){
var permissionCount = 0
permissionRequest = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
if(it.value){
permissionCount++
}
}
if(permissionCount == 2){
getMyLocation()
}
}
}
}
缺少的东西是
A)Fragment 在创建之前必须调用 registerForActivityResult()(即初始化、onAttach() 或 onCreate())。否则它将无法工作并且应用程序会崩溃。
错误:
java.lang.IllegalStateException:片段ProfileFragment {bf12414}(210ad5a1-3286-4586-a48f-deac1d8e3eef id=0x7f09008b) 正在尝试注册ForActivityResult 后 创建的。片段必须在调用之前调用 registerForActivityResult() 被创建(即初始化、onAttach() 或 onCreate())。B) 建议在确实需要时请求许可。 在我的示例中,当用户单击 id 为
Button
的
locBtn
时,将显示权限对话框,而不是显示创建活动/片段的时间。
https://developer.android.com/training/permissions/requesting
查看以下内容,可以在文档中找到。
// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
registerForActivityResult(RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
// Permission is granted. Continue the action or workflow in your
// app.
} else {
// Explain to the user that the feature is unavailable because the
// features requires a permission that the user has denied. At the
// same time, respect the user's decision. Don't link to system
// settings in an effort to convince the user to change their
// decision.
}
}
之后,发起请求
when {
ContextCompat.checkSelfPermission(
CONTEXT,
Manifest.permission.REQUESTED_PERMISSION
) == PackageManager.PERMISSION_GRANTED -> {
// You can use the API that requires the permission.
}
//Is not needed for it to work, but is a good practice as it plays a role
//in letting user know why the permission is needed.
shouldShowRequestPermissionRationale(...) -> {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...)
}
else -> {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
requestPermissionLauncher.launch(
Manifest.permission.REQUESTED_PERMISSION)
}
}
Dexter 库。如果您使用 RxJava2,Rx Permissions 也是不错的选择。
plugin:
androidPackage: com.ly.permission
pluginClass: PermissionPlugin
它对我有用。