如何在 Android 10 (Android Q) 中访问外部存储?
How to get Access to External Storage in Android 10 (Android Q)?
我刚刚将我的源代码迁移到 Androidx,因为我这样做了,所以我共享声音的共享功能不再有效。 Logcat 说:
Failed to save file: /storage/emulated/0/appfolder/testsound.mp3 (Permission denied)
这是保存声音的部分:
final String fileName = soundObject.getItemName() + ".mp3";
File storage = Environment.getExternalStorageDirectory();
File directory = new File(storage.getAbsolutePath() + "/appfolder/");
directory.mkdirs();
final File file = new File(directory, fileName);
InputStream in = view.getContext().getResources().openRawResource(soundObject.getItemID());
try{
Log.i(LOG_TAG, "Saving sound " + soundObject.getItemName());
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer, 0, buffer.length)) != -1){
out.write(buffer, 0 , len);
}
in.close();
out.close();
} catch (IOException e){
Log.e(LOG_TAG, "Failed to save file: " + e.getMessage());
}
这是共享声音的代码:
try{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){
if (ActivityCompat.checkSelfPermission(view.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions((Activity) view.getContext(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}else {
final String AUTHORITY = view.getContext().getPackageName() + ".fileprovider";
Uri contentUri = FileProvider.getUriForFile(view.getContext(), AUTHORITY, file);
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
intent.setType("audio/mp3");
view.getContext().startActivity(Intent.createChooser(intent, "Share sound via..."));
}
}
else {
final Intent intent = new Intent(Intent.ACTION_SEND);
Uri fileUri = Uri.parse(file.getAbsolutePath());
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setType("audio/mp3");
view.getContext().startActivity(Intent.createChooser(intent, "Share sound via..."));
}
} catch (Exception e){
Log.e(LOG_TAG, "Failed to share sound: " + e.getMessage());
}
}
我需要更改什么以及如何实现每个人无论他使用哪个 Android 版本(minSdkVersion 16)都可以下载和共享声音?
可悲的是,我在 atm 上收到很多差评,因为没有人可以分享(即使 Android 9 及以下,他们过去也可以分享)
谢谢
如果您的目标是 Android 10 或更高,请在您应用的清单文件中将 requestLegacyExternalStorage 的值设置为 true:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
访问文件
要加载媒体文件,请从 ContentResolver 调用以下方法之一:
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
cursor.getLong(Integer.parseInt(BaseColumns._ID)));
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(uri, fileOpenMode);
if (parcelFd != null) {
int fd = parcelFd.detachFd();
// Pass the integer value "fd" into your native code. Remember to call
// close(2) on the file descriptor when you're done using it.
}
在设备 运行 Android 10(API 级别 29)及更高版本上,您的应用可以通过使用 IS_PENDING旗帜。
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.IS_PENDING, 1);
ContentResolver resolver = context.getContentResolver();
Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri item = resolver.insert(collection, values);
try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(item, "w", null)) {
// Write data into the pending image.
} catch (IOException e) {
e.printStackTrace();
}
// Now that we're finished, release the "pending" status, and allow other apps
// to view the image.
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(item, values, null, null);
我被困了很长时间,这对我来说很好
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
File = new File(filepath);
并且不要忘记在清单文件中请求旧版存储。
<application android:requestLegacyExternalStorage="true" >
我刚刚将我的源代码迁移到 Androidx,因为我这样做了,所以我共享声音的共享功能不再有效。 Logcat 说:
Failed to save file: /storage/emulated/0/appfolder/testsound.mp3 (Permission denied)
这是保存声音的部分:
final String fileName = soundObject.getItemName() + ".mp3";
File storage = Environment.getExternalStorageDirectory();
File directory = new File(storage.getAbsolutePath() + "/appfolder/");
directory.mkdirs();
final File file = new File(directory, fileName);
InputStream in = view.getContext().getResources().openRawResource(soundObject.getItemID());
try{
Log.i(LOG_TAG, "Saving sound " + soundObject.getItemName());
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer, 0, buffer.length)) != -1){
out.write(buffer, 0 , len);
}
in.close();
out.close();
} catch (IOException e){
Log.e(LOG_TAG, "Failed to save file: " + e.getMessage());
}
这是共享声音的代码:
try{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1){
if (ActivityCompat.checkSelfPermission(view.getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions((Activity) view.getContext(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}else {
final String AUTHORITY = view.getContext().getPackageName() + ".fileprovider";
Uri contentUri = FileProvider.getUriForFile(view.getContext(), AUTHORITY, file);
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
intent.setType("audio/mp3");
view.getContext().startActivity(Intent.createChooser(intent, "Share sound via..."));
}
}
else {
final Intent intent = new Intent(Intent.ACTION_SEND);
Uri fileUri = Uri.parse(file.getAbsolutePath());
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.setType("audio/mp3");
view.getContext().startActivity(Intent.createChooser(intent, "Share sound via..."));
}
} catch (Exception e){
Log.e(LOG_TAG, "Failed to share sound: " + e.getMessage());
}
}
我需要更改什么以及如何实现每个人无论他使用哪个 Android 版本(minSdkVersion 16)都可以下载和共享声音?
可悲的是,我在 atm 上收到很多差评,因为没有人可以分享(即使 Android 9 及以下,他们过去也可以分享) 谢谢
如果您的目标是 Android 10 或更高,请在您应用的清单文件中将 requestLegacyExternalStorage 的值设置为 true:
<manifest ... >
<!-- This attribute is "false" by default on apps targeting
Android 10 or higher. -->
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
访问文件
要加载媒体文件,请从 ContentResolver 调用以下方法之一:
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
cursor.getLong(Integer.parseInt(BaseColumns._ID)));
String fileOpenMode = "r";
ParcelFileDescriptor parcelFd = resolver.openFileDescriptor(uri, fileOpenMode);
if (parcelFd != null) {
int fd = parcelFd.detachFd();
// Pass the integer value "fd" into your native code. Remember to call
// close(2) on the file descriptor when you're done using it.
}
在设备 运行 Android 10(API 级别 29)及更高版本上,您的应用可以通过使用 IS_PENDING旗帜。
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.IS_PENDING, 1);
ContentResolver resolver = context.getContentResolver();
Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri item = resolver.insert(collection, values);
try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(item, "w", null)) {
// Write data into the pending image.
} catch (IOException e) {
e.printStackTrace();
}
// Now that we're finished, release the "pending" status, and allow other apps
// to view the image.
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(item, values, null, null);
我被困了很长时间,这对我来说很好
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
File = new File(filepath);
并且不要忘记在清单文件中请求旧版存储。
<application android:requestLegacyExternalStorage="true" >