安卓开发:无法复制MP3到外部存储,遇FileNotFoundException求解决方案
Hey there! Let's break down your two Android MP3-related issues step by step—since you're new to coding, I'll keep things clear and actionable.
第一步:完善权限回调逻辑
You mentioned a snippet of the onRequestPermissionsResult method, so let's fill it out properly to ensure permissions are handled before you try copying files:
private static final int MY_PERMISSIONS_REQUEST_STORAGE = 1; @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case MY_PERMISSIONS_REQUEST_STORAGE: { // Check if permission was granted if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission approved—run your file copy logic here copyMp3FromRawToExternal(); } else { // Permission denied, let the user know it's required Toast.makeText(this, "Storage permission is needed to copy the MP3", Toast.LENGTH_SHORT).show(); } return; } // Handle other permission requests if you have them } }
Note: For Android 10 (API 29)+, you'll either need to add android:requestLegacyExternalStorage="true" to your AndroidManifest.xml (for backward compatibility) or use the MediaStore API. For Android 13+, you'll also need to request the READ_MEDIA_AUDIO permission.
第二步: Fix the Core File Copy Issues
Problem 1: Can't copy MP3 from Raw to external storage
Problem 2: java.io.FileNotFoundException: /storage/emulated/0/Music/Arno lacht. (Is a directory)
This error is the key clue: you're pointing to a folder instead of a specific file. The path /storage/emulated/0/Music/Arno lacht. tells Android you're targeting a directory, not an MP3 file. You need to add the .mp3 extension to specify it's a file.
Here's a complete method to handle the copy correctly:
private void copyMp3FromRawToExternal() { // Replace with your actual Raw resource ID (e.g., R.raw.arno_lacht) int rawMp3Id = R.raw.arno_lacht; // Target path: make sure it's a full file path, not just a folder String targetPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + "/Arno lacht.mp3"; File targetFile = new File(targetPath); // Create the parent folder if it doesn't exist File parentFolder = targetFile.getParentFile(); if (!parentFolder.exists()) { parentFolder.mkdirs(); // Creates nested folders if needed } InputStream inputStream = null; OutputStream outputStream = null; try { // Open input stream from Raw directory inputStream = getResources().openRawResource(rawMp3Id); // Open output stream to the target file outputStream = new FileOutputStream(targetFile); // Copy data in chunks (more efficient than byte-by-byte) byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } Toast.makeText(this, "MP3 copied successfully!", Toast.LENGTH_SHORT).show(); // Call share function once copy is done shareMp3ViaApps(targetFile); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "Copy failed: " + e.getMessage(), Toast.LENGTH_LONG).show(); } finally { // Always close streams to avoid resource leaks try { if (inputStream != null) inputStream.close(); if (outputStream != null) outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
Bonus: Share the MP3 to WhatsApp & Other Apps
Once the file is copied, use this method to share it:
private void shareMp3ViaApps(File mp3File) { if (!mp3File.exists()) { Toast.makeText(this, "File not found—can't share", Toast.LENGTH_SHORT).show(); return; } // Get file URI (use FileProvider for Android 7.0+) Uri fileUri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { fileUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", mp3File); } else { fileUri = Uri.fromFile(mp3File); } Intent shareIntent = new Intent(Intent.ACTION_SEND); shareIntent.setType("audio/mpeg"); shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri); shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // Give apps access to the file startActivity(Intent.createChooser(shareIntent, "Share MP3 via")); }
If using FileProvider, you'll need to add a provider entry to your AndroidManifest.xml and create a res/xml/file_paths.xml file to define accessible directories.
Key Takeaways for Beginners
- Always target a specific file: Don't stop at the folder—include the full filename with
.mp3 - Check permissions first: Never run file operations without confirming permissions are granted
- Close streams: Failing to close input/output streams can cause memory leaks
- Version compatibility: Android changes how storage works across versions, so keep an eye on API levels
内容的提问来源于stack exchange,提问作者Herophes Spartano

