在Android11设备上,比如u盘的挂载路径/storage/A804-B928下有一个db.apk,如何实现在接受到ACTION_MEDIA_MOUNTED广播后把这个apk复制到DCIM目录下
时间: 2024-02-23 16:58:55 浏览: 241
Android开发实现读取assets目录下db文件的方法示例
在 Android 11 设备上,应用程序无法直接访问外部存储设备的根目录,因此在应用程序中直接访问 u 盘可能会出现卸载 u 盘失败的问题。为了避免这个问题,可以使用 Storage Access Framework(SAF)来访问 u 盘中的文件并将其复制到应用程序可以访问的目录中。具体实现步骤如下:
1. 在 `ACTION_MEDIA_MOUNTED` 广播处理程序中启动一个服务,用于将 u 盘中的 db.apk 复制到 DCIM 目录中。
2. 在服务中使用 SAF 访问 u 盘中的 db.apk 文件,具体可以使用 `Intent.ACTION_OPEN_DOCUMENT` 操作打开 SAF 选择器,并让用户选择 u 盘中的 db.apk 文件。
3. 选择 db.apk 文件后,可以使用 `DocumentFile` 类来访问该文件并将其复制到 DCIM 目录中,具体可以使用 `ContentResolver` 和 `DocumentFile.createFile` 方法来创建文件并将 u 盘中的 db.apk 内容写入到该文件中。
4. 复制完成后,可以发送一个广播通知系统图库进行扫描,以便能够在相册中看到该文件。
具体实现代码如下:
```
public class MyMediaReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_MEDIA_MOUNTED.equals(action)) {
Uri uri = intent.getData();
if (uri != null) {
String path = uri.getPath();
if (path != null) {
Intent copyIntent = new Intent(context, CopyService.class);
copyIntent.putExtra("source", path + "/db.apk");
context.startService(copyIntent);
}
}
}
}
}
public class CopyService extends Service {
private static final String TAG = "CopyService";
private static final String DESTINATION_DIR = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String source = intent.getStringExtra("source");
if (source != null) {
copyFile(source);
}
return super.onStartCommand(intent, flags, startId);
}
private void copyFile(String source) {
try {
ContentResolver resolver = getContentResolver();
Uri sourceUri = Uri.parse("content://com.android.externalstorage.documents/tree/" + source.split("/")[1] + "/document/" + source.replaceFirst(".*?/", ""));
DocumentFile sourceFile = DocumentFile.fromSingleUri(this, sourceUri);
InputStream inputStream = resolver.openInputStream(sourceFile.getUri());
String destPath = DESTINATION_DIR + "/db.apk";
OutputStream outputStream = new FileOutputStream(destPath);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + destPath)));
} catch (Exception e) {
Log.e(TAG, "Error copying file", e);
}
stopSelf();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
```
在广播处理程序中启动了一个服务 `CopyService`,并将 `ACTION_MEDIA_MOUNTED` 广播中的 u 盘路径传递给该服务。在服务中使用 SAF 访问 u 盘中的 db.apk 文件,并将其复制到 DCIM 目录中。复制完成后,发送一个广播通知系统图库进行扫描。
需要注意的是,Android 11 以后需要在应用程序的 `AndroidManifest.xml` 文件中添加以下权限:
```
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
```
同时还需要在 `AndroidManifest.xml` 文件中声明 `MyMediaReceiver` 和 `CopyService` 类:
```
<receiver android:name=".MyMediaReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
<service android:name=".CopyService" />
```
最后需要注意的是,将文件复制到 DCIM 目录中可能会影响到用户的相册体验,因此应该根据实际需求选择合适的目录进行文件复制。
阅读全文