Android 11 引入了新的应用开发模式——Scoped Storage。Scoped Storage 是一种更加安全的文件管理方式,可以限制应用的文件共享和访问权限,防止了恶意应用窃取用户的隐私信息。不过,有时候 Scoped Storage 可能会对应用造成不必要的麻烦,比如一些旧版应用可能无法正常工作。如果你想关闭 Scoped Storage,可以按照以下步骤进行操作。
Scoped Storage 的原理
在 Android 11 中,应用的所有外部存储访问都必须使用 Scoped Storage,也就是说,应用无法直接访问外部存储的根目录和其他应用的文件。相反,Android 11 引入了一组新的 API,允许应用通过 MediaStore、Storage Access Framework(SAF)和应用专属目录来访问外部存储。这些 API 具有更加严格的权限管理机制,并且可以保护用户的隐私信息。
关闭 Scoped Storage
如果你想关闭 Scoped Storage,可以按照以下步骤进行操作:
Step 1:申请权限
首先,你需要在 AndroidManifest.xml 文件中申请 WRITE_EXTERNAL_STORAGE 权限。因为 Android 11 中的 Scoped Storage 只允许应用访问自己专属的目录,如果你想访问外部存储的其他文件,需要申请这个权限。
```
```
Step 2:配置应用专属目录
在 Android 11 中,所有应用都有一个专属的目录,可以访问这个目录下的文件,无需使用 Scoped Storage。你可以通过 Context.getExternalFilesDir() 方法获取这个目录的路径,并在其中创建自己的文件。
```
val file = File(getExternalFilesDir(null), "test.txt")
file.writeText("Hello, World!")
```
注意,这里的 getExternalFilesDir() 方法中传入的参数只是为了获取不同类型文件的目录,如果你只需要一个通用的目录,可以传入 null。
Step 3:标记文件共享
在 Android 11 中,所有应用的文件默认都是私有的,而且无法与其他应用共享。如果你想让自己的文件被其他应用访问,需要使用 MediaStore API 或 SAF(Storage Access Framework)将文件标记为共享。
使用 MediaStore API 将文件标记为共享:
```
val values = ContentValues().apply {
put(MediaStore.Audio.Media.DISPLAY_NAME, "test.mp3")
put(MediaStore.Audio.Media.MIME_TYPE, "audio/mpeg")
put(MediaStore.Audio.Media.IS_PENDING, 1)
}
val item = contentResolver.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values)
item?.let { uri ->
try {
contentResolver.openFileDescriptor(uri, "w", null).use { parcelFileDescriptor ->
if (parcelFileDescriptor != null) {
FileOutputStream(parcelFileDescriptor.fileDescriptor).use { output ->
output.write(byteArrayOf(0x00))
output.flush()
}
}
}
values.clear()
values.put(MediaStore.Audio.Media.IS_PENDING, 0)
contentResolver.update(uri, values, null, null)
} catch (e: Exception) {
e.printStackTrace()
contentResolver.delete(uri, null, null)
}
}
```
使用 SAF 将文件标记为共享:
```
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
type = "image/*"
addCategory(Intent.CATEGORY_OPENABLE)
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
putExtra(Intent.EXTRA_TITLE, "test.jpg")
}
startActivityForResult(intent, 1001)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == 1001) {
data?.data?.also { uri ->
try {
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
```
通过上述操作,你可以关闭 Android 11 的 Scoped Storage,让应用在外部存储中自由存储和读取文件。不过,需要注意的是,关闭 Scoped Storage 会带来一些安全风险,因此谨慎操作,确保应用的数据不会被泄露。