下面列出了怎么用android.content.UriPermission的API类实例代码及写法,或者点击链接到github查看源代码。
@TargetApi(Build.VERSION_CODES.KITKAT)
private Uri getRootUri(String docId){
Uri treeUri;
final int splitIndex = docId.indexOf(':', 1);
final String tag = docId.substring(0, splitIndex);
//check in cache
treeUri = secondaryRoots.get(tag);
if(null != treeUri){
return treeUri;
}
//get root dynamically
List<UriPermission> permissions = mContext.getContentResolver().getPersistedUriPermissions();
for (UriPermission permission :
permissions) {
String treeRootId = getRootUri(permission.getUri());
if(docId.startsWith(treeRootId)){
treeUri = permission.getUri();
secondaryRoots.put(tag, treeUri);
return treeUri;
}
}
return treeUri;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private Uri getRootUri(String docId){
Uri treeUri;
final int splitIndex = docId.indexOf(':', 1);
final String tag = docId.substring(0, splitIndex);
//check in cache
treeUri = secondaryRoots.get(tag);
if(null != treeUri){
return treeUri;
}
//get root dynamically
List<UriPermission> permissions = mContext.getContentResolver().getPersistedUriPermissions();
for (UriPermission permission :
permissions) {
String treeRootId = getRootUri(permission.getUri());
if(docId.startsWith(treeRootId)){
treeUri = permission.getUri();
secondaryRoots.put(tag, treeUri);
return treeUri;
}
}
return treeUri;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private Uri getRootUri(String docId){
Uri treeUri;
final int splitIndex = docId.indexOf(':', 1);
final String tag = docId.substring(0, splitIndex);
//check in cache
treeUri = secondaryRoots.get(tag);
if(null != treeUri){
return treeUri;
}
//get root dynamically
List<UriPermission> permissions = mContext.getContentResolver().getPersistedUriPermissions();
for (UriPermission permission :
permissions) {
String treeRootId = getRootUri(permission.getUri());
if(docId.startsWith(treeRootId)){
treeUri = permission.getUri();
secondaryRoots.put(tag, treeUri);
return treeUri;
}
}
return treeUri;
}
/**
* requestCodeに対応するUriへアクセス可能かどうか
* @param context
* @param requestCode
* @return
* @throws UnsupportedOperationException
*/
public static boolean hasPermission(
@NonNull final Context context,
final int requestCode) {
boolean found = false;
if (BuildCheck.isLollipop()) {
final Uri uri = loadUri(context, getKey(requestCode));
if (uri != null) {
// 恒常的に保持しているUriパーミッションの一覧を取得する
final List<UriPermission> list
= context.getContentResolver().getPersistedUriPermissions();
for (final UriPermission item: list) {
if (item.getUri().equals(uri)) {
// requestCodeに対応するUriへのパーミッションを恒常的に保持していた時
found = true;
break;
}
}
}
} else {
throw new UnsupportedOperationException("should be API>=21");
}
return found;
}
/**
* requestCodeに対応するUriへアクセス可能かどうか
* @param context
* @param requestCode
* @return
* @throws UnsupportedOperationException
*/
public static boolean hasPermission(
@NonNull final Context context,
final int requestCode) {
if (BuildCheck.isLollipop()) {
final Uri uri = loadUri(context, getKey(requestCode));
if (uri != null) {
// 恒常的に保持しているUriパーミッションの一覧を取得する
final List<UriPermission> list
= context.getContentResolver().getPersistedUriPermissions();
return hasPermission(list, uri);
}
} else {
throw new UnsupportedOperationException("should be API>=21");
}
return false;
}
private static Uri getDocumentUri(
ContentResolver resolver, String path, List<UriPermission> uriPermissions)
throws RemoteException {
try (ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY)) {
final Bundle in = new Bundle();
in.putParcelableList(
DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY + ".extra.uriPermissions",
uriPermissions);
final Bundle out = client.call("getDocumentId", path, in);
return out.getParcelable(DocumentsContract.EXTRA_URI);
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static boolean isSDCardAccessGranted(Context context) {
if (!isTreeUriSaved(context)) return false;
String sdcardUri = PreferenceUtil.getInstance().getSAFSDCardUri();
List<UriPermission> perms = context.getContentResolver().getPersistedUriPermissions();
for (UriPermission perm : perms) {
if (perm.getUri().toString().equals(sdcardUri) && perm.isWritePermission()) return true;
}
return false;
}
public boolean hasPermissionsAt(Uri uri) {
for (UriPermission perm : _context.getContentResolver().getPersistedUriPermissions()) {
if (perm.getUri().equals(uri)) {
return perm.isReadPermission() && perm.isWritePermission();
}
}
return false;
}
/**
* requestCodeに対応するUriが存在していて恒常的パーミッションがあればそれを返す, なければnullを返す
* @param context
* @param requestCode
* @return
* @throws UnsupportedOperationException
*/
@Nullable
private static Uri getStorageUri(
@NonNull final Context context,
final int requestCode) throws UnsupportedOperationException {
if (BuildCheck.isLollipop()) {
final Uri uri = loadUri(context, getKey(requestCode));
if (uri != null) {
boolean found = false;
// 恒常的に保持しているUriパーミッションの一覧を取得する
final List<UriPermission> list
= context.getContentResolver().getPersistedUriPermissions();
for (final UriPermission item: list) {
if (item.getUri().equals(uri)) {
// requestCodeに対応するUriへのパーミッションを恒常的に保持していた時
found = true;
break;
}
}
if (found) {
return uri;
}
}
} else {
throw new UnsupportedOperationException("should be API>=21");
}
return null;
}
public static boolean hasPermission(
@NonNull final List<UriPermission> persistedUriPermissions,
@NonNull final Uri uri) {
for (final UriPermission item: persistedUriPermissions) {
if (item.getUri().equals(uri)) {
return true;
}
}
return false;
}
/**
* requestCodeに対応するUriが存在していて恒常的パーミッションがあればそれを返す, なければnullを返す
* @param context
* @param requestCode
* @return
* @throws UnsupportedOperationException
*/
@Nullable
private static Uri getStorageUri(
@NonNull final Context context,
final int requestCode) throws UnsupportedOperationException {
if (BuildCheck.isLollipop()) {
final Uri uri = loadUri(context, getKey(requestCode));
if (uri != null) {
boolean found = false;
// 恒常的に保持しているUriパーミッションの一覧を取得する
final List<UriPermission> list
= context.getContentResolver().getPersistedUriPermissions();
for (final UriPermission item: list) {
if (item.getUri().equals(uri)) {
// requestCodeに対応するUriへのパーミッションを恒常的に保持していた時
found = true;
break;
}
}
if (found) {
return uri;
}
}
} else {
throw new UnsupportedOperationException("should be API>=21");
}
return null;
}
public boolean hasUriAccess() {
if( this.uri != null ) {
List<UriPermission> uriPermissions = this.getActivity().getContentResolver().getPersistedUriPermissions();
for (UriPermission uriPermission : uriPermissions) {
if (this.uri.equals(uriPermission.getUri()) && uriPermission.isReadPermission()) {
return true;
}
}
}
return false;
}
public static void revokePreviousPermissions(@NonNull final ContentResolver resolver, @NonNull final Uri newUri) {
// Unfortunately, the content Uri of the selected resource is not exactly the same as the one stored by ContentResolver
// -> solution is to compare their TreeDocumentId instead
String treeUriId = DocumentsContract.getTreeDocumentId(newUri);
for (UriPermission p : resolver.getPersistedUriPermissions())
if (!DocumentsContract.getTreeDocumentId(p.getUri()).equals(treeUriId))
resolver.releasePersistableUriPermission(p.getUri(),
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (resolver.getPersistedUriPermissions().isEmpty()) {
Timber.d("Permissions revoked successfully.");
} else {
Timber.d("Permissions failed to be revoked.");
}
}
@Override @RequiresApi(KITKAT) @NonNull public List<UriPermission> getPersistedUriPermissions() {
return mBase.getPersistedUriPermissions();
}
@Override @RequiresApi(KITKAT) @NonNull public List<UriPermission> getOutgoingPersistedUriPermissions() {
return mBase.getOutgoingPersistedUriPermissions();
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static boolean hasPermission() {
List<UriPermission> uriPermission = Common.getInstance().getContentResolver().getPersistedUriPermissions();
return uriPermission != null && uriPermission.size() > 0;
}
@Override @RequiresApi(KITKAT) @NonNull public List<UriPermission> getPersistedUriPermissions() {
return mBase.getPersistedUriPermissions();
}
@Override @RequiresApi(KITKAT) @NonNull public List<UriPermission> getOutgoingPersistedUriPermissions() {
return mBase.getOutgoingPersistedUriPermissions();
}
@Override @RequiresApi(KITKAT) @NonNull public List<UriPermission> getPersistedUriPermissions() {
return mBase.getPersistedUriPermissions();
}
@Override @RequiresApi(KITKAT) @NonNull public List<UriPermission> getOutgoingPersistedUriPermissions() {
return mBase.getOutgoingPersistedUriPermissions();
}
public void onSelectSAFRootFolder(@NonNull final Uri treeUri) {
boolean isUriPermissionPeristed = false;
ContentResolver contentResolver = getContentResolver();
String treeUriId = DocumentsContract.getTreeDocumentId(treeUri);
for (UriPermission p : contentResolver.getPersistedUriPermissions()) {
if (DocumentsContract.getTreeDocumentId(p.getUri()).equals(treeUriId)) {
isUriPermissionPeristed = true;
Timber.d("Uri permission already persisted for %s", treeUri);
break;
}
}
if (!isUriPermissionPeristed) {
Timber.d("Persisting Uri permission for %s", treeUri);
// Release previous access permissions, if different than the new one
FileHelper.revokePreviousPermissions(contentResolver, treeUri);
// Persist new access permission
contentResolver.takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
DocumentFile selectedFolder = DocumentFile.fromTreeUri(this, treeUri);
if (selectedFolder != null) {
String folderName = selectedFolder.getName();
if (null == folderName) folderName = "";
// Make sure we detect the Hentoid folder if it's a child of the selected folder
if (!ImportHelper.isHentoidFolderName(folderName))
selectedFolder = ImportHelper.getExistingHentoidDirFrom(this, selectedFolder);
}
// If no existing hentoid folder is detected, tell the user to select it again
if (null == selectedFolder || null == selectedFolder.getName() || !ImportHelper.isHentoidFolderName(selectedFolder.getName()))
{
ToastUtil.toast("Please select an existing Hentoid folder. Its location is displayed on screen.");
return;
}
scanLibrary(selectedFolder);
}
public static @Result
int setAndScanFolder(
@NonNull final Context context,
@NonNull final Uri treeUri,
boolean askScanExisting,
@Nullable final ImportOptions options) {
boolean isUriPermissionPeristed = false;
ContentResolver contentResolver = context.getContentResolver();
String treeUriId = DocumentsContract.getTreeDocumentId(treeUri);
for (UriPermission p : contentResolver.getPersistedUriPermissions()) {
if (DocumentsContract.getTreeDocumentId(p.getUri()).equals(treeUriId)) {
isUriPermissionPeristed = true;
Timber.d("Uri permission already persisted for %s", treeUri);
break;
}
}
if (!isUriPermissionPeristed) {
Timber.d("Persisting Uri permission for %s", treeUri);
// Release previous access permissions, if different than the new one
FileHelper.revokePreviousPermissions(contentResolver, treeUri);
// Persist new access permission
contentResolver.takePersistableUriPermission(treeUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
DocumentFile docFile = DocumentFile.fromTreeUri(context, treeUri);
if (null == docFile || !docFile.exists()) {
Timber.e("Could not find the selected file %s", treeUri.toString());
return Result.INVALID_FOLDER;
}
DocumentFile hentoidFolder = addHentoidFolder(context, docFile);
if (null == hentoidFolder) {
Timber.e("Could not create Hentoid folder in root %s", docFile.getUri().toString());
return Result.CREATE_FAIL;
}
if (!FileHelper.checkAndSetRootFolder(context, hentoidFolder, true)) {
Timber.e("Could not set the selected root folder %s", hentoidFolder.getUri().toString());
return Result.INVALID_FOLDER;
}
if (hasBooks(context)) {
if (!askScanExisting) {
runImport(context, options);
return Result.OK_LIBRARY_DETECTED;
} else return Result.OK_LIBRARY_DETECTED_ASK;
} else {
// New library created - drop and recreate db (in case user is re-importing)
new ObjectBoxDAO(context).deleteAllLibraryBooks(true);
return Result.OK_EMPTY_FOLDER;
}
}
public static void updateUsbOtg(final Context context) {
if (Build.VERSION.SDK_INT < 24) {
return;
}
if (swapView == null) {
Utils.debugLog(TAG, "swapView == null");
return;
}
TextView storageVolumeText = swapView.findViewById(R.id.storage_volume_text);
Button requestStorageVolume = swapView.findViewById(R.id.request_storage_volume_button);
storageVolumeText.setVisibility(View.GONE);
requestStorageVolume.setVisibility(View.GONE);
final StorageManager storageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
for (final StorageVolume storageVolume : storageManager.getStorageVolumes()) {
if (storageVolume.isRemovable() && !storageVolume.isPrimary()) {
Log.i(TAG, "StorageVolume: " + storageVolume);
final Intent intent = storageVolume.createAccessIntent(null);
if (intent == null) {
Utils.debugLog(TAG, "Got null Storage Volume access Intent");
return;
}
storageVolumeText.setVisibility(View.VISIBLE);
String text = storageVolume.getDescription(context);
if (!TextUtils.isEmpty(text)) {
requestStorageVolume.setText(text);
UsbDevice usb = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (usb != null) {
text = String.format("%s (%s %s)", text, usb.getManufacturerName(), usb.getProductName());
Toast.makeText(context, text, Toast.LENGTH_LONG).show();
}
}
requestStorageVolume.setVisibility(View.VISIBLE);
requestStorageVolume.setOnClickListener(new View.OnClickListener() {
@Override
@RequiresApi(api = 24)
public void onClick(View v) {
List<UriPermission> list = context.getContentResolver().getPersistedUriPermissions();
if (list != null) for (UriPermission uriPermission : list) {
Uri uri = uriPermission.getUri();
if (uri.getPath().equals(String.format("/tree/%s:", storageVolume.getUuid()))) {
intent.setData(uri);
TreeUriScannerIntentService.onActivityResult(context, intent);
return;
}
}
((Activity) context).startActivityForResult(intent,
MainActivity.REQUEST_STORAGE_ACCESS);
}
});
}
}
}
/**
* Permits an application to get the persistent URI permissions granted to another.
*
* <p>Typically called by Settings.
*
* @param packageName application to look for the granted permissions
* @return list of granted URI permissions
*
* @hide
*/
public ParceledListSlice<UriPermission> getGrantedUriPermissions(String packageName) {
try {
return getService().getGrantedUriPermissions(packageName,
UserHandle.myUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets a URI backed by a {@link DocumentsProvider} that points to the same media
* file as the specified mediaUri. This allows apps who have permissions to access
* media files in Storage Access Framework to perform file operations through that
* on media files.
* <p>
* Note: this method doesn't grant any URI permission. Callers need to obtain
* permission before calling this method. One way to obtain permission is through
* a 3-step process:
* <ol>
* <li>Call {@link android.os.storage.StorageManager#getStorageVolume(File)} to
* obtain the {@link android.os.storage.StorageVolume} of a media file;</li>
*
* <li>Invoke the intent returned by
* {@link android.os.storage.StorageVolume#createAccessIntent(String)} to
* obtain the access of the volume or one of its specific subdirectories;</li>
*
* <li>Check whether permission is granted and take persistent permission.</li>
* </ol>
* @param mediaUri the media URI which document URI is requested
* @return the document URI
*/
public static Uri getDocumentUri(Context context, Uri mediaUri) {
try {
final ContentResolver resolver = context.getContentResolver();
final String path = getFilePath(resolver, mediaUri);
final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
return getDocumentUri(resolver, path, uriPermissions);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}