Androidサポートライブラリを使用して、内部ファイルを外部アプリケーションと正しく共有(開くのではなく)する方法を探しています。ファイルプロバイダー。
ドキュメントの例に従って、
<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)
FLAG_GRANT_READ_URI_PERMISSION は、インテントの で指定された URI に対する権限のみを付与し、 ( によって設定された)エクストラdata
の値に対する権限は付与しないため、機能しません。EXTRA_STREAM
setStream
プロバイダーに を設定することでセキュリティを侵害しようとしましたが、android:exported
内部的にそれ自体がエクスポートされているかどうかがチェックされ、エクスポートされている場合は例外がスローされます。true
FileProvider
ベストアンサー1
サポートライブラリを使用する場合FileProvider
、他のアプリが特定のURIを読み取るための権限を手動で付与および取り消す必要があります(実行時)。コンテキスト.grantUriPermissionそしてコンテキスト.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 つのアクティビティに付与された権限は、そのアプリの
他のコンポーネントに自動的に拡張されます。
ところで、必要であればコピーすることができますFileProvider のソースattachInfo
プロバイダーがエクスポートされているかどうかをチェックしないようにメソッドを変更します。