Android-拾取图像时无法两次使用同一URI

Android-拾取图像时无法两次使用同一URI,android,uri,android-contentprovider,android-permissions,Android,Uri,Android Contentprovider,Android Permissions,我正在使用照片裁剪库(此处为2.7版:)来使用图库应用程序(如三星图库、谷歌照片、文件等)挑选和裁剪图像。 该库通过使用intent.ACTION\u GET\u内容启动picker intent来工作,用户选择图像后,Uri将传递到裁剪视图,从而打开位图。 在某些情况下,我需要通过自动使用用户上次选择的照片的Uri来重置裁剪。因此,在用户选择图像后,我记住Uri,然后使用相同的Uri开始裁剪步骤(解码位图) 这对三星Gallery有效,但我对Google Photos有一个问题,当uri被重新

我正在使用照片裁剪库(此处为2.7版:)来使用图库应用程序(如三星图库、谷歌照片、文件等)挑选和裁剪图像。 该库通过使用intent.ACTION\u GET\u内容启动picker intent来工作,用户选择图像后,Uri将传递到裁剪视图,从而打开位图。
在某些情况下,我需要通过自动使用用户上次选择的照片的Uri来重置裁剪。因此,在用户选择图像后,我记住Uri,然后使用相同的Uri开始裁剪步骤(解码位图)

这对三星Gallery有效,但我对Google Photos有一个问题,当uri被重新打开时,它会抛出一个SecurityException。因此,当用户第一次仅选择图像时,谷歌照片的图像拾取功能就可以正常工作。当我尝试传递相同的Uri时(当我重置裁剪时),我得到以下异常(这也发生在“文件”中-我在emulator和motorola one上进行了测试):

用于向用户显示要使用哪个应用程序选择照片的代码为:

List<Intent> allIntents = new ArrayList<>();
PackageManager packageManager = this.getPackageManager();

boolean includeCamera = useCamera;
// collect all camera intents if Camera permission is available
if (!CropImage.isExplicitCameraPermissionRequired(this) && includeCamera) {
    allIntents.addAll(CropImage.getCameraIntents(this, packageManager));
}

boolean includeDocuments = false;
if (useGallery) {
    List<Intent> galleryIntents =
            CropImage.getGalleryIntents(packageManager, Intent.ACTION_GET_CONTENT, includeDocuments);
    if (galleryIntents.size() == 0) {
        // if no intents found for get-content try pick intent action (Huawei P9).
        galleryIntents = CropImage.getGalleryIntents(packageManager, Intent.ACTION_PICK, includeDocuments);
    }
    allIntents.addAll(galleryIntents);
}

Intent target;
if (allIntents.isEmpty()) {
    target = new Intent();
} else {
    target = allIntents.get(allIntents.size() - 1);
    allIntents.remove(allIntents.size() - 1);
}

// Create a chooser from the main  intent
Intent chooserIntent = Intent.createChooser(target, "Choose");

// Add all other intents
chooserIntent.putExtra(
        Intent.EXTRA_INITIAL_INTENTS, allIntents.toArray(new Parcelable[allIntents.size()]));

this.startActivityForResult(
        chooserIntent
        , CropImage.PICK_IMAGE_CHOOSER_REQUEST_CODE);
List allint=new ArrayList();
PackageManager PackageManager=this.getPackageManager();
布尔includeCamera=useCamera;
//收集所有摄像机意图(如果摄像机许可可用)
如果(!CropImage.isExplicitCameraPermissionRequired(此)&&includeCamera){
allIntents.addAll(CropImage.getCameraIntents(这个,packageManager));
}
布尔值includeDocuments=false;
如果(使用图库){
列出厨房内容=
CropImage.GetGalleryContent(packageManager、Intent.ACTION和GET内容,包括文档);
如果(GalleryContents.size()==0){
//如果找不到获取内容的意图,请尝试选择意图操作(华为P9)。
GalleryContents=CropImage.getGalleryContents(packageManager,Intent.ACTION\u PICK,包括文档);
}
allIntents.addAll(厨房内容);
}
意向目标;
if(allIntents.isEmpty()){
目标=新意图();
}否则{
target=allIntents.get(allIntents.size()-1);
allIntents.remove(allIntents.size()-1);
}
//从主意图创建选择器
Intent-chooserint=Intent.createChooser(目标,“选择”);
//添加所有其他意图
选择内容(
Intent.EXTRA_INITIAL_INTENTS,allIntents.toArray(新的可包裹[allIntents.size()]);
这是startActivityForResult(
选择内容
,CropImage.PICK\u IMAGE\u CHOOSER\u REQUEST\u CODE);
以及CropImage.GetGalleryContents方法:

  public static List<Intent> getGalleryIntents(
      @NonNull PackageManager packageManager, String action, boolean includeDocuments) {
    List<Intent> intents = new ArrayList<>();
    Intent galleryIntent =
        action == Intent.ACTION_GET_CONTENT
            ? new Intent(action)
            : new Intent(action, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    galleryIntent.setType("image/*");
    List<ResolveInfo> listGallery = packageManager.queryIntentActivities(galleryIntent, 0);
    for (ResolveInfo res : listGallery) {
      Intent intent = new Intent(galleryIntent);
      intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
      intent.setPackage(res.activityInfo.packageName);
      intents.add(intent);
    }

    // remove documents intent
    if (!includeDocuments) {
      for (Intent intent : intents) {
        if (intent
            .getComponent()
            .getClassName()
            .equals("com.android.documentsui.DocumentsActivity")) {
          intents.remove(intent);
          break;
        }
      }
    }
    return intents;
  }
公共静态列表GetGalleryContents(
@非空PackageManager PackageManager,字符串操作,布尔值包含文档){
列表意图=新建ArrayList();
意向书内容=
action==Intent.action\u获取内容
?新意图(行动)
:新意图(操作、MediaStore.Image.Media.EXTERNAL\u内容\u URI);
GalleryContent.setType(“image/*”);
List listGallery=packageManager.QueryInputActivities(GalleryContent,0);
用于(ResolveInfo res:listGallery){
意向意向=新意向(GalleryContent);
setComponent(新组件名(res.activityInfo.packageName,res.activityInfo.name));
intent.setPackage(res.activityInfo.packageName);
意图。添加(意图);
}
//删除文件的意图
如果(!包括文件){
for(意图:意图){
如果(意图)
.getComponent()
.getClassName()
.equals(“com.android.documentsui.DocumentsActivity”)){
意图。移除(意图);
打破
}
}
}
返回意图;
}

我是否有正确的解决方案或解决方法?谢谢。

对于您的
GalleryContent
,请使用
ACTION\u OPEN\u文档

但是要注意,即使是
操作\u打开\u文档
在几个小时后仍然会失效


对图像进行无限制访问的唯一方法是将其保存到应用程序自己的存储中,并在那里访问以供以后使用。

“我记住Uri,然后使用相同的Uri开始裁剪步骤”-“记住”是什么意思?如果在组件之间(例如,在活动之间)传递
Uri
,是否正确(将其放在
Intent
的“数据”方面,并将
标志\u GRANT\u READ\u Uri\u PERMISSION
添加到
Intent
)?我尝试了操作\u OPEN\u文档,它可以工作,但在选择带有chich的应用程序来选择图像时,它不会显示谷歌照片。有什么想法吗?这是因为谷歌照片不处理
动作\u打开\u文档
意图。你可以尝试我给你的第二个选项,将图像保存在你的应用程序中。我设法将正确旋转的位图存储到一个临时文件中,现在我存储了该文件的Uri,因此它可以工作。非常感谢。
  public static List<Intent> getGalleryIntents(
      @NonNull PackageManager packageManager, String action, boolean includeDocuments) {
    List<Intent> intents = new ArrayList<>();
    Intent galleryIntent =
        action == Intent.ACTION_GET_CONTENT
            ? new Intent(action)
            : new Intent(action, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    galleryIntent.setType("image/*");
    List<ResolveInfo> listGallery = packageManager.queryIntentActivities(galleryIntent, 0);
    for (ResolveInfo res : listGallery) {
      Intent intent = new Intent(galleryIntent);
      intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
      intent.setPackage(res.activityInfo.packageName);
      intents.add(intent);
    }

    // remove documents intent
    if (!includeDocuments) {
      for (Intent intent : intents) {
        if (intent
            .getComponent()
            .getClassName()
            .equals("com.android.documentsui.DocumentsActivity")) {
          intents.remove(intent);
          break;
        }
      }
    }
    return intents;
  }