Android N allowing Permission kills the app - java

I hope you can help. I cannot find any documentation on this anywhere.
I am requesting runtime permission in my Android app WRITE_EXTERNAL_STORAGE.
Under Android M this works as expected. I hit 'Allow' and all is fine.
Under Android N, clicking 'Allow' kills my app. It doesn't crash, it just stops.
In the logcat it shows
Killing 6599:com.myname.myappname/u0a223 (adj 100): permission grant or revoke changed gids
Force removing ActivityRecord{c834991 u0 com.myname.myappname/.MainActivity t1814}: app died, no saved state
Destroying surface Surface(name=Window{bf01619 u0 com.myname.myappname/com.myname.myappname.MainActivity}) called by com.android.server.wm.WindowStateAnimator.destroySurface:-1 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:-1 com.android.server.wm.WindowState.removeLocked:-1 com.android.server.wm.WindowManagerService.removeWindowInnerLocked:-1 com.android.server.wm.WindowManagerService.removeWindowLocked:-1 com.android.server.wm.WindowManagerService.removeWindowLocked:-1 com.android.server.wm.AppWindowToken.removeAllWindows:-1 com.android.server.wm.AppWindowToken.removeAppFromTaskLocked:-1
Looking at the Android Source Code I found 'permission grant or revoke changed gids' in PackageManagerService.java
private static final String KILL_APP_REASON_GIDS_CHANGED = "permission grant or revoke changed gids";
And
final int result = permissionsState.grantRuntimePermission(bp, userId);
switch (result) {
case PermissionsState.PERMISSION_OPERATION_FAILURE: {
return;
}
case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
mHandler.post(new Runnable() {
#Override
public void run() {
killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
}
});
My app code which used to work fine is:
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
And then
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
if (requestCode == 1) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do stuff
}
Can anyone explain to me why the app is being killed? And possibly how to catch it in order to restart the app programmatically?

Related

Java Android - Requesting multiple permissions but one doesn't get requested

So i'm trying to request both Location and Camera permissions from the user, and my app all works apart from the part where it has to request Location permissions from the user. The user never gets a request to access location. Is it even possible to request 2 different permissions and have onRequestPermissionsResults to handle them both in the same class?
#Override
public void onClick(View v) {
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
HomePageActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_LOCATION_PERMISSION
);
} else {
getCurrentLocation();
}
askCameraPermissions();
}
this is how it starts, then I think it goes here
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE_LOCATION_PERMISSION:
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getCurrentLocation();
} else {
Toast.makeText(this, "Permission denied", Toast.LENGTH_LONG).show();
}
}
break;
case CAMERA_PERM_CODE:
//if both are true then user has granted requests
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
dispatchTakePictureIntent();
} else {
Toast.makeText(this, "Camera permission is required to Use camera.", Toast.LENGTH_SHORT).show();
}
break;
}
}
'''
except I believe this is where the application is doing something wrong. The camera request and permission works perfectly and I am able to continue and have my camera methods work. However when it comes to Location permissions, as i said, the user is never prompted to allow permissions, so I think something is going wrong here. Any help is appreciated, this is my first post so maybe formatting will be strewn with errors.
I have tried to post only relevant code. I will post more if requested
Rather then asking permission two times which is causing the problem you can actually ask it in a single time like
....
ActivityCompat.requestPermissions(
HomePageActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CAMERA},
REQUEST_CODE_MULTIPLE_PERMISSION
);
....
if you still want to ask separate permission then you should ask after the first one result has arrived.
EDIT
while asking for access fine location you should also ask for coarse location

How to handle setResult in phone settings?

I cannot make this work, I have an application with a webview that requires permissions to access storage when downloading, I am trying that, when the user rejects permissions, my application tells them how to activate the permission by accessing the application settings.
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", getActivity().getPackageName(), null));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(intent, MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
s
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Permission is granted
myWebView.loadUrl(urlDownload);
} else {
}
return;
}
case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openImageChooserActivity();
} else {
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
myWebView.loadUrl(urlDownload); this code snippet runs without problem when permission is granted from android alert but I can't control it if the user grants the permission from the settings.
Finally, a newbie question, I have seen several examples of similar codes that seem to work, but I do not understand how setResult is handled in the configurations because I do not have access to it, if for example MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101 how is it that android configurations know to put setResult (101) when user activates storage?

Cannot Dial Phone Number Automatically After Timer Ends

I've been fiddling with an emergency-esque contact app for a while now and I'm close to being done. After a timer runs out, the app should call a number that the user has saved previously.
I've come awful close to making it dial the number automatically, however I can only seem to make it take the number and put it in the dialer without calling the number.
I really want this to be automatic, how do I make the number get called automatically?
(timer finishes)
String myCallNumber ="tel:" + myPref.getString("phoneINT", "");
startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(myCallNumber)));
Nothing says that I need any additional permissions. Actually, I took this from a webpage tutorial that said no permissions were required.
I tried this code, from linked duplicate. However, it says that Call_Action isn't a real thing.
Intent intent = new Intent(Intent.CALL_ACTION);
intent.setData(Uri.parse(myCallNumber));
startActivity(intent);
This question is not a duplicate of Can I implement automatic call to someone in Android? !
Intent.CALL_ACTION does not work for me, Android studios doesn't recognize it as a command.
Image
Hi please check if you already granted permission. Also, it should be "ACTION_CALL", not "CALL_ACTION"
add into AndroidManifest.xml:
uses-permission android:name="android.permission.CALL_PHONE"
Check permission before calling:
int permissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.CALL_PHONE);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CALL_PHONE},
999);
} else {
startActivity(new Intent(Intent.ACTION_CALL).setData(Uri.parse("tel: your_phone_number")));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 999:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
startActivity(new Intent(Intent.ACTION_CALL).setData(Uri.parse("tel:your_phone_number")));
}
break;
default:
break;
}
}

Android granted runtime permissions to my app without asking

I'm trying to test the Runtime Permissions specifically for Android sdk > 23. But my app is being granted permissions automatically without asking.
Note : I'm using sdk version 24. Here's a snippet of code I'm using:
public void onCalendarClick(View view) {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CALENDAR) == PackageManager
.PERMISSION_DENIED) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.WRITE_CALENDAR)) {
//Display Explanation to the user
//For granting permissions to the app.
}
else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CALENDAR}, CALLBACK_CALENDAR);
}
}
}
#Override
public void onRequestPermissionsResult(int resultCode, String permission[], int grantResults[]) {
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast toast;
switch (resultCode) {
case CALLBACK_CALENDAR : toast = Toast.makeText(this,"Calendar Permission Granted!!",Toast.LENGTH_LONG);
toast.show(); break;
//Other Cases
}
}
}
When I click on Calendar Button, the onCalendarClick() method run, but without asking for any permission, the App directly displays Calendar Permission Granted!! toast. In the App's settings, there are though No Permissions Granted/Requested being displayed.
Am I missing something or doing it the wrong way? Thanks for any help.
So here it is. I found out that for android sdk > 22, though Runtime permissions are added programatically for your application but you still need to declare your app's permission in the AndroidManifest.xml file. So, after adding the code:
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
in the AndroidManifest.xml, the app asks for the permission and it's finally working.
For more information : Android M permission dialog not showing
.Thanks to all for helping me out )
You are missing the order of the code. Check this:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case CALLBACK_CALENDAR: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// calendar-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
There is a little difference, you are asking if the permission is granted even before you know you are talking about CALENDAR permissions. So, you should first check if the current permission response is the one you want, and then check if the permission is granted.
Source: https://developer.android.com/training/permissions/requesting.html

Can't click Allow External Write Access Permissions in Android

I'm not able to allow the app to write to external storage when other background app like twilight (dims screen) runs in the background. In this case, I can only deny it and it says screen overlay detected. But can't allow.
My code:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
boolean hasPermission = (ContextCompat.checkSelfPermission(Timetable.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
ActivityCompat.requestPermissions(Timetable.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
}
Override code:
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//Intent i=new Intent(this,Timetable.class);
//startActivity(i);
//reload my activity with permission granted or use the features what required the permission
} else
{
Toast.makeText(Timetable.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
I want it running even if some background apps like twilight are running.
Downloading a certain file using Android's built in Download Manager provides integrity and a more User Friendly approach. Also the requestPermission method should be called before doing that if the devices having Marshmallow and above are to be supported as well.
And about the allow button not working, that issue is because of apps or activities who capture the screen overlay. Like for instance Facebook messenger or any screen dimming apps. Hence to make it robust you need to check the permission everytime you download something.
public void downloadFile(String uRl) {
File direct = new File(Environment.getExternalStorageDirectory()
+ "/" + "MyFolder");
if (!direct.exists()) {
direct.mkdirs();
}
DownloadManager mgr = (DownloadManager) getSystemService(this.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(uRl);
DownloadManager.Request request = new DownloadManager.Request(downloadUri);
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle("AppNameAsTitle")
.setDescription("Downloaded using My app")
.setDestinationInExternalPublicDir("/MyFolder", "filename.jpg")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
mgr.enqueue(request);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadFile(url);
} else {
Toast.makeText(this, "Permission not granted", Toast.LENGTH_SHORT).show();
}
}

Categories