I'm facing a weird issue trying to provide a file in Android 10. My code works fine in Android 9 and 11 but in Android 10 only works 50% of the times. There are no difference on the system status when it works and when it doesn't.
The intent:
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(file, UpdateHelper.APK_TYPE)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
If I grant the permission explicitly, it always work. So my question is not how to fix it, but if there are any explanation for it that I'm missing. In my understanding granting the permission in the intent is the preferred way of doing it.
context?.grantUriPermission(packageName, file, Intent.FLAG_GRANT_READ_URI_PERMISSION)
Reviewing the documentation, it seems to be a race condition.
Permissions granted in an Intent remain in effect while the stack of the receiving Activity is active. When the stack finishes, the permissions are automatically removed.
For some reason this does not affect Android 9 and 11. But in Android 10 does.
The reason for my app to be finished is that I'm using this to pass a new apk to the packageInstaller in order to update the app.
Related
Here is my code:-
public void onClick(View v) {
try {
startActivity(new Intent(
"android.intent.action.SHOW_ALARMS"));
} catch (ActivityNotFoundException ignore) {
Toast.makeText(ac, "ActivityNotFoundException",
Toast.LENGTH_LONG).show();
}
}
This works on the Android emulator running Android 12 API 31: it shows the system clock application with the alarms page. On my Samsung Galaxy S21, also running Android 12 API 31, I get this error:-
Process: uk.co.yahoo.p1rpp.secondsclock, PID: 27629
java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.SHOW_ALARMS cmp=com.sec.android.app.clockpackage/.alarm.activity.AlarmCTSHandleActivity } from ProcessRecord{769a91e 27629:uk.co.yahoo.p1rpp.secondsclock/u0a362} (pid=27629, uid=10362) requires com.android.alarm.permission.SET_ALARM
at android.os.Parcel.createExceptionOrNull(Parcel.java:2437)
at android.os.Parcel.createException(Parcel.java:2421)
at android.os.Parcel.readException(Parcel.java:2404)
at android.os.Parcel.readException(Parcel.java:2346)
at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:2878)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1743)
at android.app.Activity.startActivityForResult(Activity.java:5465)
at android.app.Activity.startActivityForResult(Activity.java:5423)
at android.app.Activity.startActivity(Activity.java:5809)
at android.app.Activity.startActivity(Activity.java:5762)
at uk.co.yahoo.p1rpp.secondsclock.SettingsActivity$25.onClick(SettingsActivity.java:538)
...
Here is the first bit of my AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uk.co.yahoo.p1rpp.secondsclock">
<uses-permission android:name="android.permission.SET_ALARM" />
...
I'm actually asking for the permission even though I shouldn't need it since I'm asking to look at the alarms, not to set one. Without the permission request in the manifest, it still works on the emulator and fails in the same way on the phone.
I see the same behaviour (on both the emulator and the phone) with both debug and release builds.
In case someone asks why I'm doing this, I've written a home screen seconds clock widget, which will be published on github when I have it fully working. I want clicking on the widget to go to the system's clock app, which doesn't work because of this problem. The code shown is test code to check why the code in the widget fails, because the widget code executes in the context of the home screen launcher and is harder to debug.
I can go to the system clock app by using an Intent with its ComponentName (and this works without an error on the phone), but different Android phone models have different clock apps with different Componentnames, so it will only work on one type of phone. I did have code to search the PackageManager for the ComponentName of a clock, but Google's latest security upgrade in API 31 doesn't allow me to do that any more.
Why is the SecurityException happening and what if anything can I do to prevent it?
Why is the SecurityException happening
Samsung apparently has an android:permission attribute for that <activity> requiring that callers need to hold that permission to be able to start that activity.
what if anything can I do to prevent it?
You cannot prevent it. Samsung requires that permission, either intentionally or due to some screwup. You either need to hold the permission or you need to wrap the startActivity() call in a try/catch and "gracefully degrade" if you get that exception.
It does not required the permission that you have mentioned above rather it requires a different permission.
Replace this
<uses-permission android:name="android.permission.SET_ALARM" />
With
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
I'm developing a program that delete the cache of all programs. This has been asked many times before but the solutions were either removed in newer versions of Android or didn't clear all caches or they needed to root the device.
I found a solution in Android docs that added in api 30 and should be launched using Activity#startActivityForResult(Intent, int) so that the user knows which app is requesting to clear cache.
this action requires Manifest.permission.MANAGE_EXTERNAL_STORAGE in manifests.
I have this permission in my manifest and I using following code in my OnClick method:
Intent clearCache = new Intent();
clearCache.setAction(ACTION_CLEAR_APP_CACHE);
startActivity(clearCache);
But it doesn't work in my Android 11 device. Does anyone know code problem?
Thanks.
This intent should be launched using
Activity#startActivityForResult(Intent, int) so that the user knows
which app is requesting to clear cache.
Check the documentation.
Use "startActivityForResult" instead of "startActivity":
//Get cache dialog
int requestCode = 999;
Intent intent = new Intent(StorageManager.ACTION_CLEAR_APP_CACHE);
activity.startActivityForResult(intent, requestCode);
This worked in the past but does not work on my android pie device anymore (worked until the recent pie update):
fun uninstallApp(packageName: String) {
val packageURI = Uri.parse("package:$packageName")
val intent = Intent(Intent.ACTION_DELETE, packageURI)
intent .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent )
}
I could not find any documentation that indicates that this intent is not working anymore.
Does anyone know if there is an alternative way to open the uninstall dialog on android pie?
The code will still work, supposedly the app is not requesting the permission to execute it.
Since Android Pie (Android 9), apps are required to declare that they request apps to be deleted. This can be done by adding this permission to the AndroidManifest.xml:
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
* Note that it is not needed to request this permission at runtime. Declaring this in the Manifest is enough for it to work.
Also, we could use the ACTION_UNINSTALL_PACKAGE action instead for the request of removing packages. For this action, the documentation is mentioning that the permission stated above is required for it to work since Android Pie.
While I try to get new Android 8 (or P) Application Standby Bucket using UsageStatsManager.getAppStandbyBucket, I receive this error, gave every permission possible to app, but still crashes :
java.lang.SecurityException: MATCH_ANY_USER flag requires
INTERACT_ACROSS_USERS permission at
com.android.server.pm.PackageManagerService.getPackageUid:4959
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.getPackageUid:25142
com.android.server.usage.UsageStatsService$BinderService.getAppStandbyBucket:932
android.app.usage.IUsageStatsManager$Stub.onTransact:274
android.os.Binder.execTransact:731 : Neither user 10228 nor current
process has android.permission.INTERACT_ACROSS_USERS.
I posted the same question some days ago, like chrispher said, it's a bug, two issues has been filled in :
https://issuetracker.google.com/issues/111102580
https://issuetracker.google.com/issues/111857669
I know that on the first developer preview, the function was working, so maybe you can download the factory image, put it on an emulator or a device and make your test, a bit of a trick but at least we can test this way...
Edit: Good news ! https://issuetracker.google.com/issues/111102580
We are good to test, the release is here !
I have the following problem:
My app is distributed over an MDM system and runs in Android for Work.
In certain situation, the app must temporarily terminate the DnD mode. To achieve this, the user must grant the DnD permission when the app is started.
So far so good. If I install the app in the unmanaged area, the app shows up in the list and the permission can be granted without any problems.
As soon as the app is distributed via an MDM system, the app no longer appears in the list and the permission cannot be granted. All authorizations have been granted in the MDM system. As an example, I have distributed the Google App over the MDM system. This app appears in the list.
In the Manifest I have set the following permission:
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
When the app is started, the following code is executed:
NotificationManager nm = (NotificationManager).getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M && !nm.isNotificationPolicyAccessGranted()) {
Intent intent = new
Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivity(intent);
}
The problem only occurs with DnD permission. All other permissions such as overlay permission, are displayed without problems.
I hope anyone can help me.
According to Android documentation: NOT POSSIBLE
Users can grant and deny access to Do Not Disturb configuration from here. Managed profiles cannot grant Do Not Disturb access.
I haven't found a proper solution for the problem yet but I found a workaround to display the app in the work area. It seems that the app is only displayed in the dialog if the same app is also installed in the private area.
If the app is not installed in the private area, it will also not appear in the work area.
My workaround was to install the app in the private and work area. After the permission in the work area was granted, I removed the app from the private area. Like I said, it's not a solution to the problem itself, but it worked.
To me this looks like a bug in Android, because for all other permissions the app appears in the list
Apparently there is issure reported regarding this on Google Issue Tracker
https://issuetracker.google.com/issues/77939714
This is the reply from Google:
Status: Won't Fix (Intended Behavior) 11:41AM You can not change DND
settings from a managed profile app. We will be updating the
documentation to clarify this.
There is also a reply stating:
Microsoft Intune has released their fully managed Android Enterprise
profile setup for Android Devices. ... and it can now access and
grant the DnD permission. Not sure if its the fact that we have gone
to fully managed devices or if something else has changed.
And I would believe this is actually because the device is fully managed.
So according to my understadning there are two options:
Fully managed device (will require a factory reset on the phone)
Install it on the personal profile
We have the same issue with the app SignOnSite. Can't get access to the DnD function for emergency evacuations unless we also install the app in the Personal space as well. Makes it to risky doing it this way, so ended up just installing the app in the Personal space.
Using Intune for our MDM.
Try this -
Intent intent = new Intent("android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS");
startActivity(intent);