21

この Google チュートリアルに従って、 で画像をキャプチャするインテントを開始しましたnew Intent(MediaStore.ACTION_IMAGE_CAPTURE)。このチュートリアルgetExternalStoragePublicDirectoryでは、私のアプリに最適な public ディレクトリを使用することをお勧めします。しかし、彼らの例では代わりに を使用していgetExternalFilesDirます。次に、ファイルの URI をインテントに渡すにはMediaStore.EXTRA_OUTPUTコンテンツ URI を取得する必要があります。なぜなら、Android N をターゲットにしたいからです。現在、NI は、あまり好ましくないFileUriExposedExceptionように思われる を取得し始めました。

このようなファイルがあるとすれば...

private File createImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyAppFolder");
    if (!storageDir.exists() && !storageDir.mkdir())
        Log.w(TAG, "Couldn't create photo folder: " + storageDir.getAbsolutePath());
    File image = new File(storageDir, timeStamp + ".jpg");
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

...パブリック ピクチャ ディレクトリの組み込みプロバイダを使用して、コンテンツ URI を取得できますか? もしそうなら、どのように?

私は次のようなものを試しました

takePictureIntent.putExtra(
    MediaStore.EXTRA_OUTPUT, 
    FileProvider.getUriForFile(this, MediaStore.AUTHORITY, createImageFile()));

しかし、それはただ投げます

IllegalArgumentException: android.support.FILE_PROVIDER_PATHS メタデータがありません

その権限は正しいですか?公開ファイルを共有するために独自のプロバイダーを使用する必要がある場合、FILE_PROVIDER_PATHS メタデータでどのパスを指定できますか? 私が見つけることができるすべてのオプションは、プライベートディレクトリ用です。

4

2 に答える 2

16

TL:DR<external-path name="MyAppFolder" path="." />は動作しますが、安全ですか?

自分で作成する必要がありますFileProvider。そのドキュメントを読む価値はありますが、ここで簡単に要約します。

@CommonsWare が述べたように、MediaStore.AUTHORITY例をに置き換える必要があります。"com.example.fileprovider"これは、マニフェストで次のように定義する権限です...

<application>AndroidManifestの タグ内に、次のように入力します。

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

あなたが取得している例外は、触れることが許可されて<meta-data>いるすべてのパスを含むxmlファイルにリンクするタグがないためです。FileProviderしかし、私が苦労してきたのは、このファイルに入っているものです。

リンクしたチュートリアルの終わりに向かって、「フルサイズの写真を保存する」セクションの最後で、Google がこれに対して提供する例file_paths.xmlは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>

"my_images"あなたの例では に置き換えられ"MyAppFolder"ます。そのチュートリアルで、Googleは主張しています

パス コンポーネントは、Environment.DIRECTORY_PICTURES で呼び出されたときに getExternalFilesDir() によって返されるパスに対応します。com.example.package.name をアプリの実際のパッケージ名に置き換えてください。

...そしてそれを入力すると、それはあなたと私が探している公開の写真ディレクトリを参照していないことに気付きました。そのパスを使用するとこの例外が発生する理由を説明します。

java.lang.IllegalArgumentException: /storage/emulated/0/Pictures/MyAppFolder/{filename}.jpg を含む構成済みのルートが見つかりませんでした

今後の参考のためにここに残しておき、大きな質問への回答に移ります。API レベル 24 以降を対象とするアプリによって作成されたパブリック Pictures ディレクトリ内のファイルを他のアプリが操作できるようにするには、どのパスを指定できますか?

@CommonsWare が言ったように、「目的のサブディレクトリの詳細はデバイスによって異なる」ため、パブリック Pictures ディレクトリへのパスを宣言することはできませんが、機能する方法を見つけました。

<external-path name="MyAppFolder" path="." />を使用すると、他のアプリ (カメラなど) にコンテンツ URI を渡すことができます。FileProviderこのアプリは、解決先のファイルの読み取りと書き込みを行うことができます。

これに危険性や欠点がある場合は、ぜひ聞きたいです。

于 2016-12-21T02:03:49.470 に答える