Reputation: 21
I want to ask the user for Camera, Location, Write Storage, CallPhone
permissions and show an alert dialog when user denies any of the permissions.
But my code throws this exception :
E/AndroidRuntime: FATAL EXCEPTION: main Process: fwt_android.mpermissions, PID: 4850 java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=1, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {fwt_android.mpermissions/fwt_android.mpermissions.activities.Splash}: android.content.res.Resources$NotFoundException: Resource ID #0x0 at android.app.ActivityThread.deliverResults(ActivityThread.java:3699) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) at android.app.ActivityThread.-wrap16(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x0 at android.content.res.Resources.getValue(Resources.java:1351) at android.content.res.Resources.loadXmlResourceParser(Resources.java:2774) at android.content.res.Resources.getLayout(Resources.java:1165) at android.view.LayoutInflater.inflate(LayoutInflater.java:421) at android.view.LayoutInflater.inflate(LayoutInflater.java:374) at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:287) at android.support.v7.app.AppCompatDialog.setContentView(AppCompatDialog.java:83) at android.support.v7.app.AlertController.installContent(AlertController.java:226) at android.support.v7.app.AlertDialog.onCreate(AlertDialog.java:260) at android.app.Dialog.dispatchOnCreate(Dialog.java:394) at android.app.Dialog.show(Dialog.java:295) at fwt_android.mpermissions.activities.Splash.onRequestPermissionsResult(Splash.java:215) at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6553) at android.app.Activity.dispatchActivityResult(Activity.java:6432) at android.app.ActivityThread.deliverResults(ActivityThread.java:3695) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742) at android.app.ActivityThread.-wrap16(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Here are the constants for checking permissions -
private final int PERMISSION_CALLBACK_CONSTANT = 1;
private final int REQUEST_PERMISSION_SETTING = 1;
String[] permissionsRequired = new String[]{Manifest.permission.CAMERA, Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CALL_PHONE};
Here is my code for checking permisions -
public void checkPermission() {
if (ActivityCompat.checkSelfPermission(context, permissionsRequired[0]) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, permissionsRequired[1]) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, permissionsRequired[2]) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, permissionsRequired[3]) != PackageManager.PERMISSION_GRANTED
) {
if (ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissionsRequired[0])
|| ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissionsRequired[1])
|| ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissionsRequired[2])
|| ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissionsRequired[3])) {
//Show Information about why you need the permission
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Need Multiple Permissions");
builder.setMessage("This app needs Camera Location, Storage and Phone permissions.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ActivityCompat.requestPermissions(Splash.this, permissionsRequired, PERMISSION_CALLBACK_CONSTANT);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
}).create().show();
} else if (permissionStatus.getBoolean(permissionsRequired[0], false)
|| permissionStatus.getBoolean(permissionsRequired[1], false)
|| permissionStatus.getBoolean(permissionsRequired[2], false)
|| permissionStatus.getBoolean(permissionsRequired[3], false)
) {
//Previously Permission Request was cancelled with 'Dont Ask Again',
// Redirect to Settings after showing Information about why you need the permission
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Need Multiple Permissions");
builder.setMessage("This app needs Camera, Location, Storage and Phone permissions.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
sentToSettings = true;
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
// Toast.makeText(getApplicationContext(), "Go to Permissions to Grant Camera and Location", Toast.LENGTH_LONG).show();
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
finish();
}
}).create().show();
} else {
//just request the permission
ActivityCompat.requestPermissions(Splash.this, permissionsRequired, PERMISSION_CALLBACK_CONSTANT);
}
SharedPreferences.Editor editor = permissionStatus.edit();
editor.putBoolean(permissionsRequired[0], false);
editor.putBoolean(permissionsRequired[1], false);
editor.putBoolean(permissionsRequired[2], false);
editor.putBoolean(permissionsRequired[3], false);
editor.apply();
} else {
//You already have the permission, just go ahead.
splashTread.start();
}
}
And Here is the callback function -
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PERMISSION_CALLBACK_CONSTANT) {
//check if all permissions are granted
boolean allgranted = false;
for (int grantResult : grantResults) {
if (grantResult == PackageManager.PERMISSION_GRANTED) {
allgranted = true;
} else {
allgranted = false;
break;
}
}
if (allgranted) {
splashTread.start();
} else if (ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissions[0])
|| ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissions[1])
|| ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissions[2])
|| ActivityCompat.shouldShowRequestPermissionRationale(Splash.this, permissions[3])) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Need Multiple Permissions");
builder.setMessage("This app needs Camera, Location, Storage and Phone permissions.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
ActivityCompat.requestPermissions(Splash.this, permissionsRequired, PERMISSION_CALLBACK_CONSTANT);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
finish();
}
}).create().show();
} else {
Toast.makeText(getBaseContext(), "Unable to get Permission", Toast.LENGTH_LONG).show();
}
}
}
And the splashThread()
functions is the function for waiting when all permissions are granted which is working correct but when I deny any permission and proceed so that a new alert dialog should be displayed to send the user to settings but the app crashes at the time of builder.show();
I don't know why I am getting this error even when I have debugged the whole class. Can you please help me finding out the error and its solution ?
Upvotes: 1
Views: 103
Reputation: 21
Got solution for my answer by rechecking the guidelines of Google for runtime permissions. As its stated there that the
ActivityCompat.shouldShowRequestPermissionRationale()
should not block the thread for user response it should just show the user an explanation for permission requirement.
So, I did it by replacing
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Need Multiple Permissions");
builder.setMessage("This app needs Camera, Location, Storage and Phone permissions.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
ActivityCompat.requestPermissions(Splash.this, permissionsRequired, PERMISSION_CALLBACK_CONSTANT);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
finish();
}
}).create().show();
with checkPermission()
call
Upvotes: 1