Android Automotive下无需知晓包名,为任意客户端授予FileProvider读取权限
解决方案
方案一:动态捕获访问客户端包名并授权
你可以自定义FileProvider子类,在客户端首次访问时获取其包名并授予临时读取权限。核心思路是利用Binder.getCallingUid()拿到调用方UID,再转换为包名完成授权:
- 自定义FileProvider子类:
public class AutoMediaFileProvider extends FileProvider { @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, @Nullable CancellationSignal cancellationSignal) { handleUriPermission(uri); return super.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); } @Override public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { handleUriPermission(uri); return super.openFile(uri, mode); } private void handleUriPermission(Uri uri) { String callerPackage = getContext().getPackageManager().getNameForUid(Binder.getCallingUid()); if (callerPackage != null) { getContext().grantUriPermission(callerPackage, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); } } }
- 替换Manifest中的FileProvider配置:
<provider android:name=".AutoMediaFileProvider" android:authorities="com.your.package.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
临时权限会在系统重启或应用进程销毁后失效,但足以覆盖媒体播放周期内的访问需求。
方案二:将图片纳入MediaStore实现无权限访问
如果你的媒体封面允许公开访问,可将文件插入系统MediaStore,生成的URI默认对所有合法客户端开放(Android 10+无需额外权限):
- 插入文件到MediaStore的代码示例:
public Uri insertImageToMediaStore(Context context, File imageFile, String displayName, String mimeType) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, displayName); values.put(MediaStore.Images.Media.MIME_TYPE, mimeType); values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/YourMediaFolder"); Uri contentUri = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ? MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) : MediaStore.Images.Media.EXTERNAL_CONTENT_URI; Uri insertedUri = context.getContentResolver().insert(contentUri, values); if (insertedUri == null) return null; try (OutputStream os = context.getContentResolver().openOutputStream(insertedUri); FileInputStream fis = new FileInputStream(imageFile)) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { os.write(buffer, 0, length); } return insertedUri; } catch (IOException e) { context.getContentResolver().delete(insertedUri, null, null); return null; } }
生成的insertedUri可直接放入媒体元数据,无需额外授权,缺点是文件会出现在系统图库中,适合公开的媒体资源。
内容的提问来源于stack exchange,提问作者Oderik
相关产品推荐
相关产品推荐

