ClipData.Item.getUriを介してアプリの外に公開


99

Androidファイルシステムに追加された新機能の後に問題を修正しようとしていますが、次のエラーが発生します。

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

だから私は誰かがこれを修正するのを手伝ってくれることを願っています:)

ありがとう

private Uri getTempUri() {
    // Create an image file name
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    String dt = sdf.format(new Date());
    imageFile = null;
    imageFile = new File(Environment.getExternalStorageDirectory()
            + "/MyApp/", "Camera_" + dt + ".jpg");
    AppLog.Log(
            TAG,
            "New Camera Image Path:- "
                    + Environment.getExternalStorageDirectory()
                    + "/MyApp/" + "Camera_" + dt + ".jpg");
    File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
    if (!file.exists()) {
        file.mkdir();
    }
    imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
            + "Camera_" + dt + ".jpg";
    imageUri = Uri.fromFile(imageFile);
    return imageUri;
}

回答:


166

SDK 24以降では、アプリストレージ外のファイルのURIを取得する必要がある場合、このエラーが発生します。
@ eranda.delソリューションでは、これを許可するようにポリシーを変更でき、問題なく機能します。

ただし、アプリのAPIポリシーを変更せずにGoogleガイドラインに従う場合は、FileProviderを使用する必要があります。

最初にファイルのURIを取得するには、FileProvider.getUriForFile()メソッドを使用する必要があります。

Uri imageUri = FileProvider.getUriForFile(
            MainActivity.this,
            "com.example.homefolder.example.provider", //(use your app signature + ".provider" )
            imageFile);

次に、Androidマニフェストでプロバイダーを設定する必要があります。

<application>
  ...
     <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.homefolder.example.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <!-- ressource file to create -->
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">  
        </meta-data>
    </provider>
</application>

( "authorities"では、getUriForFile()メソッドの2番目の引数と同じ値を使用します(アプリの署名+ ".provider"))

最後に、リソースファイル「file_paths」を作成する必要があります。このファイルはres / xmlディレクトリの下に作成する必要があります(おそらく、このディレクトリも作成する必要があります)。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="." />
</paths>

78
「開発者の生活を楽にする」-これは、すべての新しいAPI、Googleのキャッチフレーズです。
Kirill Karmazin

12
Brendonが提供するソリューションは正しいものですが、コピーと貼り付けの準備ができていません。たとえば、ニーズに合っているかどうかを確認する必要があります。<external-path ...Environment.getExternalStorageDirectory()が必要な場合に使用されます。<files-path ...Context.getFilesDir()が必要な場合に使用します。あなたは、より良い最初の公式ドキュメントを確認してください。developer.android.com/reference/android/support/v4/content/...
キリルのKarmazin

9
androidx(新しいサポート名前空間)を使用している場合は、ここ(developer.android.com/reference/androidx/core/content/…)で適切なドキュメントを確認できます。
Rodrirokr

19
次の点に注意してくださいandroidxandroid:name="androidx.core.content.FileProvider"
smörkex19年

150

カメラまたはファイルの参照を開始する前に、次のコードブロックを追加します

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

紹介リンクの厳格モードとその説明されているすべての使用法と技術的な詳細を参照してください。


24
これを解決する正しい方法ではありません。これにより、基本的にstrictmodeポリシーが削除されます。セキュリティ警告を無視します
Ahsan Zaheer 2018

これにはいくつかの長所と短所があります。より多くの情報を取得するには、以下を参照してください stackoverflow.com/questions/18100161/...を
eranda.del

それは機能します、引き戻しがある場合は教えてください:)
Hanan

コードは私のために例外を解決しました。ただし、ここの一番上のコメントは、コードがこれを解決する正しい方法ではないことを述べています。誰が適切な方法がどうなるか知っていますか?
Shn_Android_Dev

Googleはプログラマを嫌っています。
ジュベールバスコンセロス

0

AndroidManifestへの必要なプロバイダー構成はありません。カメラとストレージの権限のみを許可する必要があります。次のコードを使用してカメラを起動します。

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
                new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

画像をキャプチャした後、次の場所でキャプチャした画像を見つけることができます。

"your_file_name_with_dir"

他のコードを与えるよりも、AndroidManifestでプロバイダーの設定を説明する方が良いです。
fury.slay
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.