1. ホーム
  2. android

[解決済み] 他のアプリとコンテンツを共有するためにサポートFileProviderを使用するにはどうすればよいですか?

2022-04-25 04:47:35

質問

Android Support ライブラリを使用して、内部ファイルを外部アプリケーションと正しく共有(OPENではない)する方法を探しています。 ファイルプロバイダ .

ドキュメントにある例に従う。

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

で、ShareCompatを使って、以下のように他のアプリにファイルを共有することができます。

ShareCompat.IntentBuilder.from(activity)
.setStream(uri) // uri from FileProvider
.setType("text/html")
.getIntent()
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

で指定された Uri に対してのみ許可を与えるので、FLAG_GRANT_READ_URI_PERMISSION は機能しません。 data の値ではなく、インテントの EXTRA_STREAM によって設定された)余分な setStream ).

を設定することでセキュリティを妥協してみました。 android:exported から true はプロバイダ用ですが FileProvider は、それ自身がエクスポートされているかどうかを内部でチェックし、エクスポートされている場合は例外をスローします。

解決方法は?

使用方法 FileProvider サポートライブラリから、他のアプリが特定のURIを読み取るためのパーミッションを(実行時に)手動で付与したり取り消したりする必要があります。使用方法 Context.grantUriPermission Context.revokeUriPermission メソッドを使用します。

例えば

//grant permision for app with package "packegeName", eg. before starting other app via intent
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

//revoke permisions
context.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);

最後の手段として、パッケージ名を提供できない場合、特定のインテントを処理できるすべてのアプリに権限を付与することができます。

//grant permisions for all apps that can handle given intent
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
...
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
    String packageName = resolveInfo.activityInfo.packageName;
    context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

による代替方法 ドキュメント :

  • setData()を呼び出して、コンテンツURIをIntentに入れる。
  • 次に、FLAG_GRANT_READ_URI_PERMISSION または FLAG_GRANT_WRITE_URI_PERMISSION のいずれかを指定して Intent.setFlags() メソッドを呼び出します。 またはその両方。
  • 最後に、Intentを他のアプリに送信します。多くの場合、setResult()を呼び出すことでこれを行います。

    インテントで付与されたパーミッションは、スタックにある間、有効です。 を受信するアクティビティが有効です。スタックが終了すると

    のパーミッションは自動的に削除されます。1つのパーミッションに付与された

    クライアントアプリのアクティビティは、自動的に他の

    のコンポーネントを使用します。

Btw.必要なら、コピーしてください。 FileProviderのソース を変更し attachInfo メソッドを使用して、プロバイダがエクスポートされているかどうかをチェックしないようにします。