如何解决Android - onRequestPermissionsResult() 已弃用有没有其他选择?
我尝试实现写入和读取存储的请求权限。一切正常,但今天 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(),StorageKeys.STORAGE_PERMISSION_CODE));
reqAlertDialog.setNegativeButton(R.string.cancel,which) -> dialog.dismiss());
reqAlertDialog.create().show();
}
我可以使用 onRequestPermissionsResult(...) 的替代方法吗?
解决方法
onRequestPermissionsResult()
方法在 androidx.fragment.app.Fragment
中已弃用。
因此您使用 registerForActivityResult()
方法代替 onRequestPermissionsResult()
。
你可以参考这个URL。
以下是 kotlin 代码。但你可以参考它。
val permReqLuncher = registerForActivityResult(ActivityResultContracts.RequestPermission()){
if (it) {
// Good pass
} else {
// Failed pass
}
}
我从以下 URL 添加了 java 代码。
How to get a permission request in new ActivityResult API (1.3.0-alpha05)?
private ActivityResultLauncher<String> mPermissionResult = registerForActivityResult(
new ActivityResultContracts.RequestPermission(),new ActivityResultCallback<Boolean>() {
@Override
public void onActivityResult(Boolean result) {
if(result) {
Log.e(TAG,"onActivityResult: PERMISSION GRANTED");
} else {
Log.e(TAG,"onActivityResult: PERMISSION DENIED");
}
}
});
// Launch the permission window -- this is in onCreateView()
floatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPermissionResult.launch(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
}
});
您可以请求多个权限。
val requestMultiplePermissions = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
permissions.entries.forEach {
Log.e("DEBUG","${it.key} = ${it.value}")
}
}
requestMultiplePermissions.launch(
arrayOf(
Manifest.permission.READ_CONTACTS,Manifest.permission.ACCESS_FINE_LOCATION
)
)
,
这对我有用 - (kotlin):
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")
}
}
,
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()
}
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
}
}
,
替代 registerForActivityResult
示例使用:
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()
}
}
}
,
大多数答案都针对 OP 要求。但是我发现缺少的东西很少,所以我想提供一个完整的例子(在 Koltin 中)
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 onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View {
binding = DataBindingUtil.inflate(inflater,R.layout.fragment_profile,container,false)
registerPermissionRequest()
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)片段在创建之前必须调用 registerForActivityResult()(即初始化、onAttach() 或 onCreate())。否则它将无法工作,应用程序会崩溃。 错误
java.lang.IllegalStateException: Fragment ProfileFragment{bf12414} (210ad5a1-3286-4586-a48f-deac1d8e3eef id=0x7f09008b) is attempting to registerForActivityResult after being created. Fragments must call registerForActivityResult() before they are created (i.e. initialization,onAttach(),or onCreate()).
B) 建议在确实需要时请求许可。在我的示例中,当用户点击 ID 为 locBtn
的按钮时,会显示权限对话框,而不是在创建活动/片段时显示。
您可以使用一些外部库进行权限处理以减少一些样板代码。我使用Dexter library。如果您使用的是 RxJava2,Rx Permissions 也是不错的选择。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。