Android cannot create file in dir getExternalStoragePublicDirectory () directory

I am trying to copy my own alarms to the Android system, following these explanations and this code .

The problem is that I cannot copy the file from my source resources to external memory. I looked at other questions here, but no answer seems to work for me.

This is my AndroidManifest (I put the external application tag WRITE_EXTERNAL_STORAGE, as indicated here ):

... <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application... 

And this is my code. It starts in a new thread, starting onCreate of my main action. The void onFirstTime () method is called from this new thread, and this method repeatedly calls void copyRawRingtone (File dstPath, int resId):

 void copyRawRingtone(File dstPath, int resId) { final String fileName = getResources().getResourceEntryName(resId) + ".mp3"; File dstFile = new File(dstPath, fileName); if (!dstFile.exists()) { InputStream srcStream = getResources().openRawResource(resId); FileOutputStream dstStream = null; try { dstFile.createNewFile(); // THIS THROWS THE EXCEPTION dstStream = new FileOutputStream(dstFile); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = srcStream.read(buffer)) > 0) { dstStream.write(buffer, 0, bytesRead); } // Set the file metadata final String mimeType = "audio/mpeg"; final String dstAbsPath = dstFile.getAbsolutePath(); ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.MediaColumns.DATA, dstAbsPath); contentValues.put(MediaStore.MediaColumns.TITLE, fileName); contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType); contentValues.put(MediaStore.Audio.Media.IS_ALARM, true); contentValues.put(MediaStore.Audio.Media.IS_NOTIFICATION, false); contentValues.put(MediaStore.Audio.Media.IS_RINGTONE, false); contentValues.put(MediaStore.Audio.Media.IS_MUSIC, false); // Add the metadata to the file in the database Uri contentUri = MediaStore.Audio.Media.getContentUriForPath(dstAbsPath); Uri newUri = getContentResolver().insert(contentUri, contentValues); // Tell the media scanner about the new ringtone MediaScannerConnection.scanFile( this, new String[]{newUri.toString()}, new String[]{mimeType}, null ); } catch (Exception e) { e.printStackTrace(); } finally { if (dstStream != null) { try { dstStream.close(); } catch (IOException e) { e.printStackTrace(); } } } try { srcStream.close(); } catch (IOException e) { e.printStackTrace(); } } } // First time initialization (called in a new thread from onCreate) void onFirstTime() { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File dstPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS); // This returns false but since I run it on an emulator, I don't know how to check if it actually exists: dstPath.mkdirs(); Field[] rawResources = R.raw.class.getFields(); final ProgressBar installProgress = (ProgressBar) findViewById(R.id.progressBar); final int length = rawResources.length; runOnUiThread(new Runnable() { @Override public void run() { installProgress.setMax(length); } }); for (int i = 0; i < length; ++i) { try { int resId = rawResources[i].getInt(rawResources[i]); copyRawRingtone(dstPath, resId); // Call the method above } catch (IllegalAccessException e) { e.printStackTrace(); } final int progress = i + 1; runOnUiThread(new Runnable() { @Override public void run() { installProgress.setProgress(progress); } }); } } } 

String: dstFile.createNewFile (); throws an exception:

 java.io.IOException: open failed: ENOENT (No such file or directory) 

I do not understand what the problem is. I run this on an emulator: Nexus_S_API_21_armeabi-v7a.

I don’t see the emulator repository under my PC, so I think that the phone emulator repository is not mounted on my PC, so I don’t think it could be a problem .

At the time of the exception, these are some of the values ​​of the variables:

 dstPath="/storage/sdcard/Alarms" fileName="whistle_alarm.mp3" dstFile="/storage/sdcard/Alarms/whistle_alarm.mp3" 

Since this returns true:

 Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 

It seems that the media is mounted and writable (not MEDIA_MOUNTED_READ_ONLY). So I don’t know what the problem is! Somebody knows?

EDIT

I added these two lines (I also put one line before and once to see it in context:

 File dstPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS); final boolean exists = dstPath.exists(); // Added. exists=true final boolean canWrite = dstPath.canWrite(); // Added. canWrite=true dstPath.mkdirs(); 

I also deleted:

 dstFile.createNewFile(); // THIS THROWS THE EXCEPTION 

And now it works!

But I tested many times without this line createNewFile (), and that didn't work. Indeed, I added this line to find out if I can work with it. So I tried this line again, and it works too!

I suspect the actual solution was to restart the emulator.

+5
source share

Source: https://habr.com/ru/post/1214586/


All Articles