位于内部存储中的裁剪图像

Crop Image Located in Internal Storage

我在 Android 中使用裁剪意图时遇到问题。

我将图像存储在我的应用程序的内部存储分配中,我希望能够裁剪它们然后将它们设置为墙纸。

我可以使用存储在外部存储器中的图像并使用此代码:

cropIntent.setDataAndType(Uri.fromFile(new File(uri)), "image/*");

当我执行下面的代码时,intent 无法启动裁剪 intent 并返回 0 结果代码。

Intent cropIntent = new Intent("com.android.camera.action.CROP");

cropIntent.setDataAndType(FileProvider.getUriForFile(activity, "com.example.test.fileprovider", new File(uri)), "image/*");

cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 9);
cropIntent.putExtra("aspectY", 16);
cropIntent.putExtra("return-data", true);
cropIntent.putExtra("scale", true);

activity.startActivityForResult(cropIntent, PIC_CROP);

来自Storage Options | Android Developers

By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user).

ACTION_CROP 启动一个支持裁剪的 "other application",并将要裁剪的文件的 URI 传递给它。如果该文件在内部存储中,则裁剪应用程序无法直接访问它。

使用 FileProvider to provide an internal file to other apps requires some configuration. From Setting Up File Sharing | Android Developers:

Specify the FileProvider

Defining a FileProvider for your app requires an entry in your manifest. This entry specifies the authority to use in generating content URIs, as well as the name of an XML file that specifies the directories your app can share.

<snip>

Specify Sharable Directories

Once you have added the FileProvider to your app manifest, you need to specify the directories that contain the files you want to share. To specify the directories, start by creating the file filepaths.xml in the res/xml/ subdirectory of your project.

以下 FileProvider 示例集成了您的代码并成功地在内部存储中的图像上打开裁剪 activity(在 Nexus 5 stock Android 5.1.1 上测试):

AndroidManifest.xml

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

res/xml/filepaths.xml

<paths>
    <files-path path="images/" name="images" />
</paths>

MainActivity.java

            // Manually stored image for testing
            final File imagePath = new File(getFilesDir(), "images");
            final File imageFile = new File(imagePath, "sample.jpg");

            // Provider authority string must match the one declared in AndroidManifest.xml
            final Uri providedUri = FileProvider.getUriForFile(
                    MainActivity.this, "com.example.test.fileprovider", imageFile);

            Intent cropIntent = new Intent("com.android.camera.action.CROP");

            cropIntent.setDataAndType(providedUri, "image/*");

            cropIntent.putExtra("crop", "true");
            cropIntent.putExtra("aspectX", 9);
            cropIntent.putExtra("aspectY", 16);
            cropIntent.putExtra("return-data", true);
            cropIntent.putExtra("scale", true);

            // Exception will be thrown if read permission isn't granted
            cropIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

            startActivityForResult(cropIntent, PIC_CROP);