web-dev-qa-db-ja.com

Android 6:もうファイルを共有できませんか?

私は画像を共有していますが、このコードは、Android 6:

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri uri = Uri.fromFile(new File(mFilename));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle));

ただし、Android 6を使用して共有しようとすると、トーストエラー「空のファイルを添付できません」が表示されます。

ファイルが存在し、長さがゼロではないことを確認しました。

誰にもこれに対する解決策がありますか?

30
Daniele B

Android 6.0ランタイムパーミッションシステムの制限の1つは、問題を引き起こすコーナーケースがあることです。発生したのは、外部ストレージ上のファイルを持たないアプリと共有しようとすることです。ランタイムのアクセス許可は、特定のUIパスを確認します。

これは、受信アプリのこのバグがユーザーに影響を与えるため、ユーザーは以前にそのアプリを使用して必要な許可を付与することができなかったため、これが「コーナーケース」だと言います。どちらか:

  • ユーザーは以前にそのアプリを使用したことがないが、まだコンテンツを共有しようとしている、または

  • ユーザーは設定を介して許可を取り消しましたが、この機能の一部が壊れることに気づきませんでした

どちらも低確率イベントです。

送信者として、次の2つの主なオプションがあります。

  1. file://Uri値の使用から切り替えて、ContentProviderのようなファイルサービスFileProviderを優先し、許可が不要になるか、または

  2. コーナーケースと一緒に暮らす

22
CommonsWare

@CommonsWareが示唆するように、FileProviderを実装することで解決しました。

最初にFileProviderを構成する必要があります。

  • まず、<provider>ファイルマニフェストXML

    <provider
        Android:name="Android.support.v4.content.FileProvider"
        Android:authorities="com.myfileprovider"
        Android:exported="false"
        Android:grantUriPermissions="true">
        <meta-data
            Android:name="Android.support.FILE_PROVIDER_PATHS"
            Android:resource="@xml/file_provider_paths" />
    </provider>
    
  • 次に、別のXMLファイルでファイルパスを定義し、「file_provider_paths.xml」と呼びました

    <paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <external-path name="share" path="/" />
    </paths>
    

完全な説明はこちらにあります ドキュメントページ

xMLでファイルプロバイダーを設定した後、これは画像ファイルを共有するコードです。

Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri fileUri = FileProvider.getUriForFile(mContext, "com.myfileprovider", new File(mFilename));
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
mContext.startActivity(Intent.createChooser(shareIntent, mChooserTitle));
38
Daniele B

あるいは、ContentProvider/FileProviderを持つ必要はありません。共有されているURIに読み取りアクセス許可を付与するフラグを追加するだけです。具体的には、share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);がトリックを行う必要があります。

2
yrizk

この問題を回避する別の方法は、ファイルをパブリックディレクトリに書き込んだ直後にMediaScannerConnectionを使用してコンテンツプロバイダースタイルのURIを取得することでした。

        MediaScannerConnection.scanFile(context, new String[] {imageFile.toString()}, yourMimeType, new OnScanCompletedListener() {
            @Override
            public void onScanCompleted(String path, Uri uri) {
                //uri = "content://" style URI that is safe to attach to share intent
            }
        });

これは、ニーズに応じたより短いソリューションかもしれません。

0
AndroidEx