How to Persist Permission in Android API 19 (Kitkat)

How to persist permission in android API 19 (KitKat)?

I believe I've solved it. The request intent:

Intent intent;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
}else{
intent = new Intent(Intent.ACTION_GET_CONTENT);
}
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.form_pick_photos)), REQUEST_PICK_PHOTO);

and onActivityResult

...
// kitkat fixed (broke) content access; to keep the URIs valid over restarts need to persist access permission
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
final int takeFlags = data.getFlags() & Intent.FLAG_GRANT_READ_URI_PERMISSION;
ContentResolver resolver = getActivity().getContentResolver();
for (Uri uri : images) {
resolver.takePersistableUriPermission(uri, takeFlags);
}
}
...

I haven't tested this pre-kitkat, my phone is running 5.1, can anyone verify this on older phones?

Android KitKat (API 19) - How to write messages in SMS Content Provider, without sending them, from Non-Default App?

The SmsWriteOpUtils class uses reflection to access methods of the AppOpsManager Service in order to enable/disable a non-default SMS app's write access to the SMS Provider in API Level 19 (KitKat). Once set, an app's access mode will be retained until it is reset, or the app is uninstalled.

Enabling an app's write access allows that app all of the standard methods of interaction with the SMS Provider, including insert() and delete().

Please note that this class does no API Level check, and that the WRITE_SMS permission is still required.

import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public final class SmsWriteOpUtils {
private static final int WRITE_OP_CODE = 15;

public static boolean isWriteEnabled(Context context) {
int result = checkOp(context);
return result == AppOpsManager.MODE_ALLOWED;
}

public static boolean setWriteEnabled(Context context, boolean enabled) {
int mode = enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
return setMode(context, mode);
}

private static int checkOp(Context context) {
try {
Method checkOpMethod = AppOpsManager.class.getMethod("checkOp",
Integer.TYPE,
Integer.TYPE,
String.class);

AppOpsManager appOpsManager =
(AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int uid = context.getApplicationInfo().uid;
String packageName = context.getPackageName();

return checkOpMethod.invoke(appOpsManager, WRITE_OP_CODE, uid, packageName);
}
catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return -1;
}

private static boolean setMode(Context context, int mode) {
try {
Method setModeMethod = AppOpsManager.class.getMethod("setMode",
Integer.TYPE,
Integer.TYPE,
String.class,
Integer.TYPE);

AppOpsManager appOpsManager =
(AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int uid = context.getApplicationInfo().uid;
String packageName = context.getPackageName();

setModeMethod.invoke(appOpsManager, WRITE_OP_CODE, uid, packageName, mode);

return true;
}
catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
}

Example usage:

boolean canWriteSms;

if(!SmsWriteOpUtils.isWriteEnabled(getApplicationContext())) {
canWriteSms = SmsWriteOpUtils.setWriteEnabled(getApplicationContext(), true);
}
...

NB: For regular user apps, this works only on API Level 19 (KitKat). The hole was patched in later versions.

Ask Permission not shown on kitkat

You can not ask runtime permission below Android 6.0

Below Android 6.0 all permisson are granted while user install the app

FYI

Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app

Read about runtime permission

Android KitKat securityException when trying to read from MediaStore

Had the same problem for the last couple of days. Tried a few solutions, but for some reason I was getting permission denial on Uri content provider for some images even when I had the android.permission.MANAGE_DOCUMENTS permission added to my manifest.

Here's a workaround, for the time being:

i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, CHOOSE_IMAGE);

This forces the older image gallery to open instead of the new Kitkat documents view.

Now, you can get the Uri by calling the following in your onActivityResult:

Uri selectedImageURI = data.getData();

Hope this helps.

Storage access framework in android kitkat

My app needs to write to external secondary storage

It is unclear what you mean by "external secondary storage".

Now with kitkat I cannot write to external storage apart from app specific files

Your app can request the WRITE_EXTERNAL_STORAGE permission, in which case you can write to arbitrary locations on the device's designated external storage, such as Environment.getExternalStoragePublicDirectory(). This has not changed in years.

Can I write to secondary external storage using this framework not in app specfic directory but other directory

Not really. Storage Access Framework does not give you control over where things are read from; it gives the user control. It is designed for cloud-based storage providers, like Google Drive, DropBox, etc.

IllegalArgumentException in grantUriPermission on API level 19

I believe this is caused by a change added in KitKat which should have fixed content access but they broke it.

You would need to run a check using Build.VERSION.SDK_INT < 19 (ie. pre-KitKat)

if(Build.VERSION.SDK_INT < 19) {
context.getApplicationContext().grantUriPermission(packageName, uri, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
} else {
takePersistableUriPermission(packageName, uri);
}

http://developer.android.com/reference/android/content/ContentResolver.html#takePersistableUriPermission

Uri permissions after the device reboot on pre-KitKat devices?

There is no mechanism for persistent access to a URI across reboots prior to API 19 and the introduction of ACTION_OPEN_DOCUMENT - that was the exact reason the API was introduced.

You'll have to make a copy in your own storage space if you want to allow multiple editing sessions on the same item.

Android storage access framework persistable permission not granted during asyntask

I solved my own problem. If you look at my code you can see that I used intent.getData(). Then I persisted the permission with that uri. When I saved the uri for later use I decoded it. Uri.decode(uri.toString().

Encoded Uri: content://com.android.providers.media.documents/document/image%3A32
Decoded: content://com.android.providers.media.documents/document/image:32

So, I instead used intent.getDataString(), then used Uri.parse() to create a Uri for the takePersistableUriPermission() method. Then I saved the initial data string from the intent in the database which keeps the encoded components.



Related Topics



Leave a reply



Submit