FileProviderを使ってファイルを共有する

5830 ワード

起因
私達のスクリーンショットはAndroid Oでシェア機能を使う時にcrashしました.エラーキーワード:FileUriExposedException.Googleはこの問題を発見しました.Android Nから現れたのです.file://Uriを使ってファイルを共有する時にこの異常を投げます.しかし、不思議なことに、私たちはAndroid Nでシェア機能を使う時は問題がなく、とにかく問題があったら解決します.一言で言えば、私たちがやるべきことはfileの代わりにcontent:/Uriを使うことです.
解決プロセス
エラーコード:
    public void shareScreenshot() {
        final File imageFile = new File(mScreenshotPath);
        // Create a shareScreenshot intent
        Intent sharingIntent = new Intent(Intent.ACTION_SEND);
        sharingIntent.setType("image/png");
        sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
        startActivity(Intent.createChooser(sharingIntent, getResources().getText(R.string.share)));
    }
私たちはUri.from Fileを使ってfile://Uriを獲得しました.このfile://Uriを使っています.次に私達は何歩かに分けてfile://Uriをcontent:/Uriに変えます.
  • FileProviderがAndroid Manifest.xmlにFileProviderを定義することを指定します.二つの値に注目してください.android:authoritiesとandroid:resource、前者はパッケージ名とfileproviderで、後者は訪問したいディレクトリを定義するファイルです.以下で詳しく説明します.
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.example.myapp">
       <application
           ...>
           <provider
               android:name="android.support.v4.content.FileProvider"
               android:authorities="com.ckt.screenshot.provider"
               android:grantUriPermissions="true"
               android:exported="false">
               <meta-data
                   android:name="android.support.FILE_PROVIDER_PATHS"
                   android:resource="@xml/provider_paths"/>
           provider>
           ...
       application>
    manifest>
  • 共有できるディレクトリを指定します.res/xml/作成と上記android:resourceに対応するファイルのprovider_paths.xmlです
    <paths>
       <files-path path="images/" name="myimages" /> 
       <external-path name="external_files" path="Pictures/Screenshots/"/>
    paths>
    この例では、files-pathラベルは、アプリケーション内部にfiles/サブディレクトリを格納するファイルを表し、external-pathタグは、外部記憶ルートディレクトリを表している.他のラベルはFileProviderを見て紹介してください.
  • pathはサブディレクトリを表しています.ラベルが表すディレクトリのサブディレクトリです.例えば、上記の2つのディレクトリのうち、最初はアプリケーション内部にfiles/下のimags/サブディレクトリが格納され、もう一つはルートディレクトリ下のPictures/Sreenshot/サブディレクトリが格納されている.指定されたファイル名で特定のファイルを共有することはできません.ワイルドカードでファイルを指定することもできません.
  • nameはcontent Uriの一節であり、pathの別名であり、安全性を強化するために、実際のpath経路に代えてnameの値をcontent Uriに追加する.
  • Javaコードを修正し、FileProvider.getsUriForFileを使ってcontent Uriを取得する.
    +        Uri imageUri = FileProvider.getUriForFile(mContext,
    +                BuildConfig.APPLICATION_ID + ".provider",
    +                imageFile);
            // Create a shareScreenshot intent
            Intent sharingIntent = new Intent(Intent.ACTION_SEND);
            sharingIntent.setType("image/png");
    -        sharingIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(imageFile));
    +        sharingIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
    実際のファイルパスイメージファイ/storge/emaulated/0/Pictures/Sreenshot2014024-104038 pgでイマジリを獲得しました.content://com.ckt.screenshot.provider/external_files/Screnshot_2014024-104038 pg provider_を結合する.paths.xmlコントラストは、Pictures/Screnshots(path実際の経路)がexternal_に置き換えられていることがわかります.files(nameの別名)
  • Uri.from Fileを使わないいくつかの理由
  • Does not allow file shring acros profiles.
  • ファイル共有を要求するアプリケーションにWRITE_があります.EXTERNAL_STORAGEの権限(Android 4.4及び以下)
  • 受信ファイルのアプリケーションにREAD_があることを要求する.EXTERNAL_STORAGEの権限は、ファイルを共有する権限がないアプリケーションに失敗します.例えばGmailにはこの権限がありません.最も重要な点は、Android Nと以上にCrashが現れます.
  • 参照接続
  • FileUriExposedException
  • FileProvider
  • セットアップUp File Sharing
  • android.os.FileUriExposedException:file:///storage/emulated/0/test.txt exposed beyond ap through Intent.getData()
  • Android N 7.0のエラーを解決します.android.os.FileUriExposedException