从内部存储打开图像的意图

5

我想在Nexus 7平板电脑上使用Android默认的图像查看器打开内部文件夹中的图像。 我使用以下代码,但由于某些原因,图像未显示。 我做错了什么? 文件的路径是:

file:///data/data/com.example.denandroidapp/files/Attachments/photoTemp/photo.jpg

(这就是Uri.parse("file://" + file)返回的内容。)
ArticlePhoto photo =  new ArticlePhoto(soapObject);
File f = new File(context.getFilesDir() + "/Attachments/photoTemp");

if(!f.exists())
    f.mkdirs();

if (photo.ArtPhoto != null) {
    Bitmap articlePhoto = BitmapFactory.decodeByteArray(photo.ArtPhoto, 0, photo.ArtPhoto.length);                      
    ByteArrayOutputStream  bytesFile  =  new ByteArrayOutputStream();
    articlePhoto.compress(Bitmap.CompressFormat.JPEG, 100, bytesFile);

    File file = new File(f + "/photo.jpeg");

    try {
        if(!file.exists())
            file.createNewFile();

        FileOutputStream outStream =  new FileOutputStream(file);

        outStream.write(bytesFile.toByteArray());                  
        outStream.close();

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.parse("file://" + file),"image/jpeg"); 
        startActivity(intent);

    } catch(Exception ex) {
        AlertDialog alert =  new  AlertDialog.Builder(context).create();
        alert.setTitle("Warning!");
        alert.setMessage(ex.getMessage());
        alert.show();
    }
}

你是在设备上还是模拟器上进行测试? - Pratik Sharma
8个回答

6

请尝试以下方法:

    Intent intent = new Intent();  
    intent.setAction(android.content.Intent.ACTION_VIEW);
    Uri uri = Uri.parse("file://" + file.getAbsolutePath());                 
    intent.setDataAndType(uri,"image/*");
    startActivity(intent);

感谢您的选择。

2
仍然没有任何东西。只有一个黑屏。 - Roman Marius
我认为问题出在将照片写入平板电脑内部存储的部分,因为如果我浏览平板电脑文件夹,我无法看到附件/照片临时文件夹。 - Roman Marius
很奇怪,如果我在调试模式下运行应用程序,它会显示文件存在,但是如果我从 Windows 浏览平板电脑文件夹,我就看不到文件夹或照片。 - Roman Marius
这个方法不起作用。我使用了Uri.fromFile(file)代替Uri.parse("file://" + file.getAbsolutePath()),然后它就可以工作了。 - Saeid Z

3
问题在于图像是您的应用程序内部的!因此,外部应用程序(图像查看器)无法访问内部应用程序中的数据。
您可能需要创建内容提供程序。请参考链接:http://web.archive.org/web/20111020204554/http://www.marcofaion.it/?p=7 Android Manifest.xml。
<provider android:authorities="com.example.denandroidapp" android:enabled="true" android:exported="true" android:name=<fully classified name of provider class>>
</provider>

创建 Intent

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);

Uri uri = Uri.parse("content://com.example.denandroidapp/" + filename);
intent.setDataAndType(uri, "image/jpeg");

这帮助我让我的代码工作了。另请参阅https://dev59.com/2WEi5IYBdhLWcg3wZ7q8和https://dev59.com/QWct5IYBdhLWcg3wV7-k。 - mc9

3

如果一个文件与您的应用相关联(存储在您应用的内部存储空间中),其他应用程序无法直接访问您的文件,前提是提供了有效的文件路径。相反,您必须创建一个文件提供者并生成内容URI。

首先,在AndroidManifest.xml中添加文件提供程序。

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.mydomain.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

然后你需要创建一个名为file_paths的文件,在xml / file_paths.xml中(默认情况下不创建xml目录,因此请创建它)。

file_paths.xml看起来像

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="myFiles" path="./"/>
</paths>

provider 中添加您想要访问的路径。

最后,您需要创建您的 intent

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
File imagePath = new File(context.getFilesDir(), "fileName");
Uri contentUri = FileProvider.getUriForFile(context, "com.mydomain.fileprovider", imagePath);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri,"image/*");
context.startActivity(intent);

注意:确保 file_paths.xml 文件中指定的文件路径与 new File(context.getFilesDir(),"fileName") 中的路径匹配。getFilesDir() 将为您提供应用程序的根目录。


1
你可以使用扩展ContentProvider的FileProvider。
查看链接 -

https://developer.android.com/reference/android/support/v4/content/FileProvider

为了指定FileProvider组件本身,请在您的应用程序清单中添加一个“provider”元素。
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/file_paths" />
</provider>

你必须为包含想要内容URI的文件的每个目录指定“paths”的子元素。例如,这些XML元素指定了两个目录。

<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <files-path name="my_images" path="images/"/>
  <files-path name="my_docs" path="docs/"/>
</paths>

生成文件的内容URI,然后调用意图。请参考下面的链接。

https://developer.android.com/reference/android/support/v4/content/FileProvider#GetUri


1
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
 intent.setDataAndType(Uri.fromFile(new File(outputFileName)),"image/jpeg");
 startActivity(intent);

同样的结果。一个黑屏 :( - Roman Marius

0

请查看:https://dev59.com/HGgu5IYBdhLWcg3wzKAb#11088980;

File file = new File(filePath);
MimeTypeMap map = MimeTypeMap.getSingleton();
String ext = MimeTypeMap.getFileExtensionFromUrl(file.getName());
String type = map.getMimeTypeFromExtension(ext);
if (type == null)
    type = "*/*";

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri data = Uri.fromFile(file);
intent.setDataAndType(data, type);
startActivity(intent);

PS:如果您尝试打开 .jpg 文件,请尝试使用替换 String ext = MimeTypeMap.getFileExtensionFromUrl(file.getName()); String ext = MimeTypeMap.getFileExtensionFromUrl(".jpg");

祝好运。


0
在我的情况下,画廊启动了,但没有显示任何图像,直接跳转到主页。我的情况与 OP 面临的情况非常不同,但我认为值得在这里提及,因为问题是关于通过隐式意图未显示图像。我的问题来自以下代码。
val intent = context.packageManager.getLaunchIntentForPackage(packageName ?: "")

上面的代码告诉PackageManager启动应用程序的入口点,而不是显示图像的活动。

enter image description here

如果您查看上面的Logcat,您可以发现使用cat=[android.intent.category.Launcher]启动的意图将进入SplashActivity。这是因为我使用getLaunchIntentForPackage()创建了该意图。

另一种选择是像下面的代码一样使用setPackage()来使用Intent

val intent = Intent()
val uri = Uri.fromFile(file) // You should probably replace with ContentProvider's uri
intent.apply {
    flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    action = Intent.ACTION_VIEW
    setPackage(packageName)
    setDataAndType(uri, "image/*")
}
context.startActivity(intent)

0

代码中的小改动对我很有帮助。

val intent = Intent(Intent.ACTION_VIEW)
val contentUri = FileProvider.getUriForFile(mContext, mContext.packageName + ".provider", mediaFile)
intent.setDataAndType(contentUri, mimeType)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK // <-- should be before 'addFlags'
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)  // <--- this line
mContext.startActivity(intent)

以下代码无法正常工作。

 val intent = Intent(Intent.ACTION_VIEW)
 val contentUri = FileProvider.getUriForFile(mContext, mContext.packageName + ".provider", mediaFile)
 intent.setDataAndType(contentUri, mimeType) 
 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) 
 intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK 
             
 mContext.startActivity(intent)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接