web-dev-qa-db-ja.com

FileProviderを使用してギャラリーから画像ファイルを選択する

Android N FileProviderの問題に直面しました。ユーザーがギャラリーから画像を選択したり、カメラで写真を撮ったりして、正方形にトリミングできるようにする必要があります。

カメラで画像を取得するためにFileProviderを実装できましたが、ギャラリーから画像を選択する際に深刻な問題があります。問題は、ギャラリーにさまざまな場所からのファイルがたくさんあり、たとえば次のような例外があることです。

_  Java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/6133-3766/DCIM/100ANDRO/DSC_0035.JPG
_

だから問題は、file_paths.xmlに何を入れて_/storage/_のどこにでもアクセスできるようにすることです。 WhatsAppや同様のアプリからの写真がある可能性があるため、正確なパスに依存することはできません。たとえば、WhatsAppイメージはこのパスを取得します。

_/storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20160821-WA0000.jpg
_

私は空のパスで解決することができました:

_<external-path name="external_storage" path=""/>_

documentation。 によると、これはEnvironment.getExternalStorageDirectory()に似ています

しかし、それでも_/storage/SOME_DIR/_に保存されている画像の処理方法を理解することはできません。助けてください。

19

この質問は誤解に基づいていると思います。

FileProvider の目的は、アプリがすでに制御しているファイルへの grant (外部アプリへの)アクセスを許可することです。

独自のファイルプロバイダーを使用して、外部アプリが所有するファイルにゲインアクセスすることはできません。

必要に応じて、ファイルプロバイダーを使用してそのアクセスを許可するのは外部アプリの責任です。

それが質問が求めているもののようです。私があなたの質問を理解していない場合は私に知らせてください、しかし私がそれを理解している場合、あなたがやろうとしていることはうまくいきません。

5
x-code

@ x-code の回答に同意しましたが、問題についてあまり明確に説明されていませんが、別のアプリの内部データにアクセスしようとする場合は、アクセスするための権限が必要です。

アプリに正当に属し、ユーザーがアプリをアンインストールするときに削除する必要があるファイル。これらのファイルは外部ストレージにあるため、ユーザーや他のアプリから技術的にアクセスできますが、実際にはアプリ外のユーザーに価値を提供しないファイルです。

実際、ドキュメントでSDKバージョン24が多くのスキームで更新され、ファイルの操作に大幅な変更が加えられていることがわかりました。ドキュメントから、file://として記述されています。

パッケージドメインの外部でfile:// URIを渡すと、レシーバーにアクセスできないパスが残る可能性があります。したがって、file:// URIを渡そうとすると、FileUriExposedExceptionがトリガーされます。プライベートファイルのコンテンツを共有するための推奨される方法は、FileProviderを使用することです。

セキュリティ上の理由から、file://の代わりにContent://を使用することを強くお勧めします。したがって、基本的にFileProviderの代わりにContentProviderを使用します。

それを使用する簡単な例を以下に示します。

AndroidMenifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    ...
    <application
        ...
        <provider
            Android:name="Android.support.v4.content.FileProvider"
            Android:authorities="${applicationId}.provider"
            Android:exported="false"
            Android:grantUriPermissions="true">
            <meta-data
                Android:name="Android.support.FILE_PROVIDER_PATHS"
                Android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest> 

次に、resフォルダーの下のxmlフォルダーにprovider_paths.xmlファイルを作成します。フォルダが存在しない場合は、作成する必要があります。

ファイルの内容を以下に示します。ルートフォルダ(path=".")にある外部ストレージへのアクセスをexternal_filesという名前で共有したいと説明しています。

res/xml/provider_paths.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>

今それを使用するには、

Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
        BuildConfig.APPLICATION_ID + ".provider",
        createImageFile());

私はこれを このブログ から取ったので、完全に理解するためにそれを読んでください。それが皆に役立つことを願っています。

4
TapanHP