java lang RuntimeException: Failure delivering result on Activity - android

As you can see this is my code, I built several applications in which I used several permission methods without any problem. In this case, I only have just one activity but it gives me an error while it wants to return the request permission result.
Code:
public class ActivityStartUp extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback {
private static final String[] PERMISSIONS = { "android.permission.CAMERA",
"android.hardware.camera", "android.hardware.camera.autofocus",
"android.hardware.camera.flash",
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE" ,
"android.permission.READ_PHONE_STATE"};
private static final int PERMISSION_CODE = 0xBAB0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_startup);
if (Utilities.hasMarshmallowApi()) {
requestPermissions(PERMISSIONS, PERMISSION_CODE);
}else{
//Open an activity
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_CODE: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
G.permissionGrantStatus = true;
Log.i("Log", "Permission Status:" + true);
if(Utilities.hasMarshmallowApi()){
// Do something
}
// Do task
} else {
G.permissionGrantStatus = false;
Log.i("Log", "Permission Status:" + false);
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
}
Error:
java.lang.RuntimeException: Failure delivering result
ResultInfo{who=#android:requestPermissions:, request=47792, result=-1,
data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }}
to activity {com.bvapp.sh.uni.watermanagement/com.bvapp.sh.uni.watermanagement.ActivityStartUp}:
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
As you can see in error "grantResults" has 0 length. I tried to find a good solution but unfortunately I couldn't fine a right one. why it's happening and how should I solve it?
Thanks in advance.

Maybe this is you'r problem (from: OnRequestPermissionsResultCallback() - Android Developer)
Note: It is possible that the permissions request interaction with the user is interrupted. In this case you will receive empty
permissions and results arrays which should be treated as a
cancellation.

Related

Android Studio: Automatically allow permissions to use camera to take photo and capture video

I created a system that has a camera function. This camera is to take the photo and save it to database. If I want to use the camera function, it will popup a message either to allow the apps to use camera or not. If I press "Allow", I can take the photo from the camera. But when I press "Deny", then if I press back the camera button, the app will stop working.
Thus, I want to make the permission camera is automatically allowed, which means, if the user press camera button, there's no popup message to choose allow or deny. Can any want know how to solve?
Below is my current code for camera
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_task_update_before);
EnableRuntimePermission();
btnCameraBefore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 7);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 7 && resultCode == RESULT_OK) {
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
imgAttachBefore.setImageBitmap(bitmap);
photoBefore();
}
}
public void EnableRuntimePermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(TaskUpdateBefore.this,
Manifest.permission.CAMERA))
{
Toast.makeText(TaskUpdateBefore.this,"CAMERA permission allows us to Access CAMERA app", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(TaskUpdateBefore.this,new String[]{
Manifest.permission.CAMERA}, RequestPermissionCode);
}
}
#Override
public void onRequestPermissionsResult(int RC, String per[], int[] PResult) {
switch (RC) {
case RequestPermissionCode:
if (PResult.length > 0 && PResult[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(TaskUpdateBefore.this,"Permission Granted, Now your application can access CAMERA.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(TaskUpdateBefore.this,"Permission Canceled, Now your application cannot access CAMERA.", Toast.LENGTH_LONG).show();
}
break;
}
}
it is not possible,it is android security purpose imbedded upon using itshardware services. best way you can do is , prompt the camera permission on startup (you can trigger app that if it doesn't access the permission, you can close the app so that will not work) but if you configure allowing the permission then you should run the application. (by the way,the allowing permission is once, will not popup again)
Typically you will want your user to have access to the rest of your features even when they dont accept all the permissions, and then give them the option to accept the permisison later on.
My suggestion:
Close your camera activity when the permission is not allowed. If you want, you can pass a message through your intent to get displayed on the previous screen. Adding finishActivity() should do the trick however without passing through a message.
#Override
public void onRequestPermissionsResult(int RC, String per[], int[] PResult) {
switch (RC) {
case RequestPermissionCode:
if (PResult.length > 0 && PResult[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(TaskUpdateBefore.this,"Permission Granted, Now your application can access CAMERA.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(TaskUpdateBefore.this,"Permission Canceled, Now your application cannot access CAMERA.", Toast.LENGTH_LONG).show();
finishActivity();
}
break;
}
}

Android API 26 SecurityException issue

In my app I have a fragment and an imageButton inside of this fragment. When I run the app in my device (Android 8 - API 26) and click imageButton, the app crashes and throws a runtime error which I didn't see before.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mustafa.diyetisyenadmin, PID: 26366
java.lang.SecurityException: Permission Denial: null asks to run as user 1 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS
at android.os.Parcel.readException(Parcel.java:1945)
at android.os.Parcel.readException(Parcel.java:1891)
at android.view.autofill.IAutoFillManager$Stub$Proxy.addClient(IAutoFillManager.java:326)
at android.view.autofill.AutofillManager.ensureServiceClientAddedIfNeededLocked(AutofillManager.java:903)
at android.view.autofill.AutofillManager.notifyViewExited(AutofillManager.java:487)
at android.view.View.notifyEnterOrExitForAutoFillIfNeeded(View.java:6983)
at android.view.View.dispatchAttachedToWindow(View.java:17594)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3332)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3339)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3339)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3339)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3339)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3339)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3339)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1792)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1515)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7266)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:981)
at android.view.Choreographer.doCallbacks(Choreographer.java:790)
at android.view.Choreographer.doFrame(Choreographer.java:721)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:967)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
So I added the required permissions in Manifest.xml and also tried every codes in the topic Android permission.INTERACT_ACROSS_USERS_FULL but I get the same error. I have solved Autofill problem with this topic but in that fragment error occurs just only I clicked ImageButton. What should I do to solve this problem?
Finally I found out the solution. Problem occurs since I had a method in my activity named getUserId() that returns String user_id and send data to fragments. I changed it's name and now everything works fine.
You have to add runtime permission. To do that follow
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkIfAlreadyhavePermission()) {
requestForSpecificPermission();
}
}
Module checkIfAlreadyhavePermission() is implemented as :
private boolean checkIfAlreadyhavePermission() {
int result = ContextCompat.checkSelfPermission(this, Manifest.permission.INTERACT_ACROSS_USERS_FULL);
return result == PackageManager.PERMISSION_GRANTED;
}
Module requestForSpecificPermission() is implemented as :
private void requestForSpecificPermission() {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERACT_ACROSS_USERS_FULL}, 101);
}
and Override in Activity :
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 101:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//DO WHATEVER YOU WANTED TO DO
} else {
//not granted
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}

OnRequestPermissionsResult is not called in PageRenderer (Xamarin.Android)

I have a VideoCallPageRenderer like below
VideoCallPageRenderer : PageRenderer, Android.Support.V4.App.ActivityCompat.IOnRequestPermissionsResultCallback
{
public const int REQUEST_MIC = 0;
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
// Other codes
RequestMicPermission();
}
public void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
if (requestCode == REQUEST_MIC)
{
if (grantResults.Length == 1 && grantResults[0] == Permission.Granted)
{
}
}
}
private void RequestMicPermission()
{
Android.Support.V4.App.ActivityCompat.RequestPermissions((Activity)Xamarin.Forms.Forms.Context, new string[] { Android.Manifest.Permission.RecordAudio }, REQUEST_MIC);
}
}
Here RequestMicPermission works fine because I can see the pop up coming on screen asking for permission. But after I allow or deny OnRequestPermissionsResult is not called.
Any help? It would be very hard to try to override it in the Activity.
For anyone else having an issue here, I was not seeing the OnRequestPermissionsResult being called either. But I had the debugger attached, the handler wasn't doing anything, and even though the breakpoint was valid, it was never hit.
I finally did a clean and rebuild and voila, the breakpoint was hit.
Just in case someone else was tearing their hair out like myself :).
For future readers that encountered this problem too, a good approach is abstract the permissions features in a service and register it with Xamarin FormĀ“s Dependencyservice.
You can resolve this service in your renderer, or any non-activity class, to use it. Also resolve it in MainActivity, override OnRequestPermissionsResult, and call yourService.OnPermissionResult to communicate the result.
As Koushik says ActivityCompat.IOnRequestPermissionsResultCallback doesnt work because we call RequestPermissions with reference to MainActivity, so the result is obtained in this activity.
You can see an implementation example in my Github:
GpsService
MainActivity

Does the Android 6.0 runtime permission check callback have to be handled in the Activity?

Basically, I want to create a wrapper for my application to handle the runtime permission checks using my own callback. I want to do some equivalent of adding a new callback to the requestPermissions method or Overriding the Activity method onRequestPermissionsResult in this function so I don't have to worry about application states. Is this possible?
I know that there are other ways to manage this using the requestCode and Fragments but I'm just curious about this as a possibility.
See example:
interface IPermissionResponse {
void permissionGranted();
void providePermissionRationale();
void permissionDenied();
}
private final static int REQUEST_INTERNET = 1;
#SuppressLint("NewApi")
public static void checkInternetPermission(Activity activity, boolean giveRationale, IPermissionResponse callback) {
if(!platformVersionCheck()){
// not android M, proceed with permission granted
callback.permissionGranted();
return;
}
Context nContext = activity.getApplicationContext();
// android M things...
if(nContext.checkSelfPermission(Manifest.permission.INTERNET) == PackageManager.PERMISSION_GRANTED){
// permission granted
callback.permissionGranted();
} else {
// permission not granted
// provide additional rationale to the user if the permission was not granted
// and the user would benefit from additional information about the use of the permission
if(giveRationale && activity.shouldShowRequestPermissionRationale(Manifest.permission.INTERNET)){
callback.providePermissionRationale();
}
// request the permission
activity.requestPermissions(new String[] {Manifest.permission.INTERNET}, REQUEST_INTERNET
/*, new IRequestPermissionCallback(){
// create new callback here
// if accepted, callback.permissionGranted
// if denied, callback.permissionDenied
}*/);
// OR SOMETHING LIKE
// handle the result callback ?????
// activity.onRequestPermissionsResult(........){
// // create new callback here
// // if accepted, callback.permissionGranted
// // if denied, callback.permissionDenied
// };
}
}
private static boolean platformVersionCheck() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
The RxPermission maybe helpful.
RxPermissions.getInstance(activity)
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.subscribe(new Action1<Boolean>() {
#Override
public void call(Boolean grant) {
if (grant) {
save(); // granted
} else {
Snackbar.make(mContainer, getString(R.string.no_permission),
Snackbar.LENGTH_LONG).show();
}
}
});
No, there isn't any callback. To have an automatic management you can look here: Permission library

Duplicate permission request after orientation change

Because the Android SDK 23 gives users the possibility to deny apps access to certain functionalities I wanted to update one of my apps to request permissions as it is described in here: https://developer.android.com/preview/features/runtime-permissions.html.
In one of the activities I embed a SupportMapFragment. To make it work you need to have the WRITE_EXTERNAL_STORAGE permission, so I request it when I start the activity which results in a creation of a permission request dialog.
Now the problem is that when the dialog is still open and I rotate the device the activity will be restarted and open a new permission request dialog while the old one is still there. The result is two of those dialogs on top of each other and only one of it being useful.
Is there a way to get rid of the dialog that was started first?
As CommonsWare said in his comment the best solution is to put a boolean into the savedInstanceState-Bundle to know if the dialog is still open.
Example:
// true if dialog already open
private boolean alreadyAskedForStoragePermission = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
alreadyAskedForStoragePermission = savedInstanceState.getBoolean(STORAGE_PERMISSION_DIALOG_OPEN_KEY, false);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY, alreadyAskedForStoragePermission);
}
private void checkStoragePermission(){
if(alreadyAskedForStoragePermission){
// don't check again because the dialog is still open
return;
}
if(ActivityCompat.checkSelfPermission(this, STORAGE_PERMISSIONS[0]) != PackageManager.PERMISSION_GRANTED){
// the dialog will be opened so we have to keep that in memory
alreadyAskedForStoragePermission = true;
ActivityCompat.requestPermissions(this, STORAGE_PERMISSIONS, STORAGE_PERMISSION_REQUEST_CODE);
} else {
onStoragePermissionGranted();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode){
case STORAGE_PERMISSION_REQUEST_CODE:
// the request returned a result so the dialog is closed
alreadyAskedForStoragePermission = false;
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
onStoragePermissionGranted();
}
break;
}
}
As #user1991776 mentioned there is actually an undocumented extra that contains whether or not there is a permission dialog open at the moment, in Activity:
private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY =
"android:hasCurrentPermissionsRequest";
However there is a better way. When you request a permission dialog the second time (due to a rotation), Activity automatically cancels the old dialog by calling your onRequestPermissionResult() with empty arrays:
public final void requestPermissions(#NonNull String[] permissions, int requestCode) {
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can reqeust only one set of permissions at a time");
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, new String[0], new int[0]);
return;
}
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
mHasCurrentPermissionsRequest = true;
}
Or course this behaviour isn't documented because this is Android, and who wants to document complex behaviour?
Anyway you can just always request permissions in onCreate() and then ignore calls to onRequestPermissionsResult() with zero-length permissions arrays.
I guess as this is a system dialog you cannot control it. You could instead prevent that your activity gets reloaded if you turn your device.

Categories

Resources