棉花糖及以上Permissions:Runtime Crash

时间:2017-11-24 11:47:49

标签: android indexoutofboundsexception android-permissions

我遇到运行时权限问题,我试图为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会同时显示权限和崩溃的对话窗口,但是当我重新启动应用程序时,它会等待权限

3 个答案:

答案 0 :(得分:0)

不应在this.requestPermissions中调用{p> onCreatedocumentation 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);
     }