我遇到运行时权限问题,我试图为Marshmallow及以上版本管理它们,但我的应用程序仍然在运行时崩溃(当我重新启动应用程序时) 这是活动代码:
在清单中:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
这里是活动代码(不是所有,但我认为必须理解)
public class HomeActivityNew extends AppCompatActivity implements AdapterView.OnItemClickListener, View.OnClickListener, SeekBar.OnSeekBarChangeListener {
// here all variables ...
private boolean permissionToRecordAccepted = false;
private boolean permissionToWriteAccepted = false;
private String[] permissions = {"android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE"}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_new);
int requestCode = 200;
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(permissions, requestCode);
}
init();
myHandler = new Handler();
slidingUpPanelLayout.setPanelState(SlidingUpPanelLayout.PanelState.HIDDEN);
SetupToolbar();
SetupPager();
SetupDrawer();
iv_playpause.setTag("pause");
MobileAds.initialize(getApplicationContext(), getResources().getString(R.string.admov_id));
AdView mAdView = (AdView) findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
/* SharedPreferences pref = getSharedPreferences("logincheck", Context.MODE_PRIVATE);
SharedPreferences.Editor edit1 = pref.edit();
edit1.putString("login","true");
edit1.apply();*/
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 200:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
permissionToRecordAccepted=true;
}
if(grantResults.length > 0 && grantResults[1] == PackageManager.PERMISSION_GRANTED){
permissionToWriteAccepted=true;
}
break;
}
if (!permissionToRecordAccepted) HomeActivityNew.super.finish();
if (!permissionToWriteAccepted) HomeActivityNew.super.finish();
}
这就是错误:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=200, result=0, data=null} to activity {com.mypackage.HomeActivityNew}: java.lang.
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
变量grantResults
为空!
运行时的app会同时显示权限和崩溃的对话窗口,但是当我重新启动应用程序时,它会等待权限
答案 0 :(得分:0)
this.requestPermissions
中调用{p> onCreate
。 documentation on requestPermission
州:
此方法可以启动一项活动,允许用户选择授予哪些权限以及拒绝哪些权限。因此,您应该准备好您的活动可以暂停和恢复。此外,授予某些权限可能需要重新启动您的应用程序。在这种情况下,系统将在将结果传递给onRequestPermissionsResult(int,String [],int [])之前重新创建活动堆栈。
检查您是否拥有权限时,应使用checkSelfPermission(String)。
调用此API以获取已授予您应用的权限,系统会向用户显示UI,以确定该应用是否仍能保留这些权限。如果您的应用使用受权限保护的数据的方式发生重大变化,这将非常有用。
这些陈述中隐含的是requestPermissions
依赖于活动生命周期。因此,您的活动需要能够处理暂停和恢复,甚至在请求权限时触发重新启动。因此,请等待您的活动完全设置(稍后在onCreate或稍后的回调中调用requestPermissions)。
更好的是,你正在接近这个错误。根据{{3}}
注意:从Android 6.0(API级别23)开始,用户可以随时撤消任何应用的权限,即使该应用针对较低的API级别也是如此。 无论您的应用针对哪种API级别,您都应该测试自己的应用,以验证其在错过所需权限时的行为是否正常。
(强调我的)。
如果您因为缺少权限而终止了您的活动,那么您将创建糟糕的用户体验。即时应用程序关闭,没有给出任何理由令人困惑,至少可以说。并且,即使它确实授予了许可,用户也可以随时撤销它们。
您应该致电AppCompat.requestPermissions(thisActivity, permissions, requestCode)
并且 应该在onCreate
(活动未完全初始化)中调用它。
此外,如果您的应用程序尚未授予权限,则应该只调用它。因此,您应该在App需要权限的时候致电ActivityCompat.checkSelfPermission
。
如果不这样做,它应该要求获得所需的许可。在这样做时,它应该检查是否应该显示基本原理(当用户在过去拒绝了许可或在某个时候撤销了许可时)。以下是Android Documentation - Requesting Permissions
的摘录private void requestCameraPermission() {
Log.i(TAG, "CAMERA permission has NOT been granted. Requesting permission.");
// BEGIN_INCLUDE(camera_permission_request)
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example if the user has previously denied the permission.
Log.i(TAG,
"Displaying camera permission rationale to provide additional context.");
Snackbar.make(mLayout, R.string.permission_camera_rationale,
Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.ok, new View.OnClickListener() {
@Override
public void onClick(View view) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA);
}
})
.show();
} else {
// Camera permission has not been granted yet. Request it directly.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA);
}
// END_INCLUDE(camera_permission_request)
}
请参阅示例的其余部分(上面一行),了解通常如何完成请求权限。还有其他方法可以编写代码来获取其他行为,但是您应该先从一个经过验证的工作示例开始,然后了解每个调用的原因,然后再向新的方向发展。
(googlesamples/android-runtime-permissions是上面示例的v7重新实现。我建议您查看两者以了解权限如何工作。但是,请注意,不要进行不兼容的v4和v7调用,这可能导致令人沮丧的错误)
让我再强调一下:即使平台/ sdk小于api 23,用户也可以随时撤销权限。因此,只要需要权限,就必须检查权限。
答案 1 :(得分:0)
像这样写
private String[] permissions = {Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}
投入
private String[] permissions = {"android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE"}
答案 2 :(得分:0)
在您的代码中使用了
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(permissions, requestCode);//Call require API level 23 and above
}
因此您没有提到其他情况,您应该已经请求API级别23或更低的权限。所以更正后的代码:
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.M){
//Call this method for API level 21 and above
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},200);
}else{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECORD_AUDIO},200);
}