0

i have a problem with Run time permissions, i tried to manage them for Marshmallow and above but my application still crashes on runtime (not when i restart app) this is the code of activity:

in the Manifest:

<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" />

Here the activity code ( not all but necessary to understand i think)

 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();
        }

and this the error :

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

variable grantResults empty! app on runtime shows the dialog window for permission and crashes at same time but when i restart the app it waits for permissions

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
SBCODE
  • 1
  • 1
  • Possible duplicate of [How to check the multiple permission at single request in Android M?](https://stackoverflow.com/questions/34040355/how-to-check-the-multiple-permission-at-single-request-in-android-m) – Goku Nov 24 '17 at 11:49
  • check the length before accessing.. `grantResults[1]`. – SRB Bans Nov 24 '17 at 11:50
  • You should verify you are using the right `requestPermissions` - see [Android M Permissions onRequestPermissionsResult not being called](https://stackoverflow.com/questions/32714787/android-m-permissions-onrequestpermissionsresult-not-being-called) – Les Nov 24 '17 at 12:19
  • i follow all your suggestions but i still have error " permission windows disapear in 1 seconde – SBCODE Nov 24 '17 at 21:50

3 Answers3

0

this.requestPermissions should not be called in onCreate. The documentation on requestPermission states:

This method may start an activity allowing the user to choose which permissions to grant and which to reject. Hence, you should be prepared that your activity may be paused and resumed. Further, granting some permissions may require a restart of you application. In such a case, the system will recreate the activity stack before delivering the result to onRequestPermissionsResult(int, String[], int[]).

When checking whether you have a permission you should use checkSelfPermission(String).

Calling this API for permissions already granted to your app would show UI to the user to decide whether the app can still hold these permissions. This can be useful if the way your app uses data guarded by the permissions changes significantly.

Implicit in these statements is that requestPermissions relies upon the Activity Life Cycle. So, your activity needs to be able to handle Pause and Resume and even Re-Start being triggered while requesting permissions. So, wait until your activity is fully set up (call requestPermissions later in onCreate, or in a later callback).

Better yet, you are approaching this wrong. According to Android Documentation - Requesting Permissions

Note: Beginning with Android 6.0 (API level 23), users can revoke permissions from any app at any time, even if the app targets a lower API level. You should test your app to verify that it behaves properly when it's missing a needed permission, regardless of what API level your app targets.

(emphasis mine).

If you kill your activity because it is missing a permission, you are creating an awful user experience. Instant app closure and no reason given is confusing to say the least. And, even if it did grant permission, the user can revoke them at any time.

You should be calling AppCompat.requestPermissions(thisActivity, permissions, requestCode) and you should not be calling it in onCreate (where the activity is not fully initialized).

Furthermore, you should only be calling it if your App does not have permissions granted already. So you should be calling ActivityCompat.checkSelfPermission at the point your App needs the permission.

Failing that, it should ask for the permission it needs. In doing so, it should check if rationale should be displayed (for when the user has denied the permission in the past or revoked permission at some point). Here is an excerpt from googlesamples/android-runtime-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)
}

See the rest of the sample (line above) to see how requesting permissions is typically done. There are other ways to write the code to get other behaviors, but you should first start with a proven and working example, and understand the reasons for each call, before going off in a new direction.

(Developer Samples - Runtime Permissions is is the v7 re-implementation of the sample above. I recommend you review both to understand how permissions work. Be careful, though, not to make incompatible v4 and v7 calls, which can lead to frustrating bugs)

Let me re-emphasize: the user can revoke permissions at anytime, even when the platform/sdk is less than api 23. So, you must check permissions whenever the permission is needed.

Community
  • 1
  • 1
Les
  • 10,335
  • 4
  • 40
  • 60
  • i did that but grantResults stay empty and app close the window of permissions fast , its like i didnt ask for permissions if i remove the lines :
    `//if (!permissionToRecordAccepted) HomeActivityNew.super.finish(); //if (!permissionToWriteAccepted) HomeActivityNew.super.finish();` the app stay open but its not Legal to continue without thoses permissions
    – SBCODE Nov 24 '17 at 13:33
  • Totally re-wrote my answer. See if this new answer helps. – Les Nov 25 '17 at 12:04
0

Write like this

private String[] permissions = {Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}

insted of

private String[] permissions = {"android.permission.RECORD_AUDIO", "android.permission.WRITE_EXTERNAL_STORAGE"}
SahdevRajput74
  • 754
  • 7
  • 18
  • thank you @SahdevRajput but i tried it , and i got same result, the strange is that crash on first launch but after close i reopen the app and it show the the dialog for permissions and wait !! – SBCODE Nov 24 '17 at 13:20
  • The error is that the : grantResults that contains permissions result is empty so it close the app as i mentionned that in the code : `if (!permissionToRecordAccepted) HomeActivityNew.super.finish(); if (!permissionToWriteAccepted) HomeActivityNew.super.finish();` – SBCODE Nov 24 '17 at 13:26
  • i dont have error its only app does not check permissions , i got error only ( the error that i wrote above) when i try to log the grantResults[0] for test because `grantResults` is empty and i dont know why phone does not get permissions and close the dialog in 1 ms : `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` – SBCODE Nov 24 '17 at 14:17
0

In your code you have used

if (Build.VERSION.SDK_INT >= 23) {
  requestPermissions(permissions, requestCode);//Call require API level 23 and above          
} 

so you have not mentioned else case where you should have requested the permission for API level 23 or low.So corrected code:

 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);
     }
taranjeetsapra
  • 524
  • 7
  • 19
  • I thought it was logical to do the case ' >= 23' because the else is already in Manifest ( and user accept before installing the app from the playstore) , not right? – SBCODE Nov 24 '17 at 13:23
  • In that case if you want to filter out your app for API level 23 and above the set android:minSdkVersion=23. Please read this post [link](https://stackoverflow.com/questions/4568267/android-min-sdk-version-vs-target-sdk-version) – taranjeetsapra Nov 24 '17 at 13:35
  • its not the probleme right now but i added it too , as i test with Samsung S7 (API 24) i should be in the case `SDK_INT >Build.VERSION_CODE.M ` I really dont understand why : dialogs of permissions does not stay until pemissions granted or denied. and after restart they stays . very strange – SBCODE Nov 24 '17 at 14:35