Запись файла на внешнем накопителе в Android

Я хочу создать файл во внешнем хранилище sdCard и написать ему. Я искал через Интернет и пытаюсь, но не получаю результат, я добавил разрешение в файле манифеста Android также, я делаю это на эмуляторе, я пытаюсь следующий код и получение ERRR “,” Не удалось создать файл “.

btnWriteSDFile = (Button) findViewById(R.id.btnWriteSDFile); btnWriteSDFile.setOnClickListener(new OnClickListener() { //private Throwable e; @Override public void onClick(View v) { // write on SD card file data from the text box try { File myFile = new File("/sdcard/mysdfile.txt"); myFile.createNewFile(); FileOutputStream fOut = new FileOutputStream(myFile); OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut); myOutWriter.append(txtData.getText()); myOutWriter.close(); fOut.close(); } catch (Exception e) { Log.e("ERRR", "Could not create file",e); } }// onClick }); // btnWriteSDFile 

Вы также можете сделать это с помощью этого кода.

  public class WriteSDCard extends Activity { private static final String TAG = "MEDIA"; private TextView tv; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView) findViewById(R.id.TextView01); checkExternalMedia(); writeToSDFile(); readRaw(); } /** Method to check whether external media available and writable. This is adapted from http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */ private void checkExternalMedia(){ boolean mExternalStorageAvailable = false; boolean mExternalStorageWriteable = false; String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // Can read and write the media mExternalStorageAvailable = mExternalStorageWriteable = true; } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { // Can only read the media mExternalStorageAvailable = true; mExternalStorageWriteable = false; } else { // Can't read or write mExternalStorageAvailable = mExternalStorageWriteable = false; } tv.append("\n\nExternal Media: readable=" +mExternalStorageAvailable+" writable="+mExternalStorageWriteable); } /** Method to write ascii text characters to file on SD card. Note that you must add a WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw a FileNotFound Exception because you won't have write permission. */ private void writeToSDFile(){ // Find the root of the external storage. // See http://developer.android.com/guide/topics/data/data- storage.html#filesExternal File root = android.os.Environment.getExternalStorageDirectory(); tv.append("\nExternal file system root: "+root); // See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder File dir = new File (root.getAbsolutePath() + "/download"); dir.mkdirs(); File file = new File(dir, "myData.txt"); try { FileOutputStream f = new FileOutputStream(file); PrintWriter pw = new PrintWriter(f); pw.println("Hi , How are you"); pw.println("Hello"); pw.flush(); pw.close(); f.close(); } catch (FileNotFoundException e) { e.printStackTrace(); Log.i(TAG, "******* File not found. Did you" + " add a WRITE_EXTERNAL_STORAGE permission to the manifest?"); } catch (IOException e) { e.printStackTrace(); } tv.append("\n\nFile written to "+file); } /** Method to read in a text file placed in the res/raw directory of the application. The method reads in all lines of the file sequentially. */ private void readRaw(){ tv.append("\nData read from res/raw/textfile.txt:"); InputStream is = this.getResources().openRawResource(R.raw.textfile); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr, 8192); // 2nd arg is buffer size // More efficient (less readable) implementation of above is the composite expression /*BufferedReader br = new BufferedReader(new InputStreamReader( this.getResources().openRawResource(R.raw.textfile)), 8192);*/ try { String test; while (true){ test = br.readLine(); // readLine() returns null if no more lines in the file if(test == null) break; tv.append("\n"+" "+test); } isr.close(); is.close(); br.close(); } catch (IOException e) { e.printStackTrace(); } tv.append("\n\nThat is all"); } } 

Для записи во внешнее хранилище на устройствах Lollipop + нам необходимо:

  1. Добавьте в Manifest следующее разрешение:

       
  2. Запросить разрешение от пользователя:

      public static final int REQUEST_WRITE_STORAGE = 112; private requestPermission(Activity context) { boolean hasPermission = (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); if (!hasPermission) { ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE); } else { // You are allowed to write external storage: String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/new_folder"; File storageDir = new File(path); if (!storageDir.exists() && !storageDir.mkdirs()) { // This should never happen - log handled exception! } } 
  3. Управлять ответом пользователя внутри Действия:

     @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case Preferences.REQUEST_WRITE_STORAGE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "The app was allowed to write to your storage!", Toast.LENGTH_LONG).show(); // Reload the activity with permission granted or use the features what required the permission } else { Toast.makeText(this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show(); } } } 

Вы должны прочитать документацию по хранению материалов снаружи на Android . Существует множество проблем, которые могут возникнуть с вашим текущим кодом, и я думаю, что рассмотрение документации может помочь вам их убрать.

Я знаю, что это немного поздно, но я надеваю это так, он создает каталог документов, а затем подкаталог для приложения и сохраняет файлы на нем.

  public class loadDataTooDisk extends AsyncTask { String sdCardFileTxt; @Override protected String doInBackground(String... params) { //check to see if external storage is avalibel checkState(); if(canW == canR == true) { //get the path to sdcard File pathToExternalStorage = Environment.getExternalStorageDirectory(); //to this path add a new directory path and create new App dir (InstroList) in /documents Dir File appDirectory = new File(pathToExternalStorage.getAbsolutePath() + "/documents/InstroList"); // have the object build the directory structure, if needed. appDirectory.mkdirs(); //test to see if it is a Text file if ( myNewFileName.endsWith(".txt") ) { //Create a File for the output file data File saveFilePath = new File (appDirectory, myNewFileName); //Adds the textbox data to the file try{ String newline = "\r\n"; FileOutputStream fos = new FileOutputStream (saveFilePath); OutputStreamWriter OutDataWriter = new OutputStreamWriter(fos); OutDataWriter.write(equipNo.getText() + newline); // OutDataWriter.append(equipNo.getText() + newline); OutDataWriter.append(equip_Type.getText() + newline); OutDataWriter.append(equip_Make.getText()+ newline); OutDataWriter.append(equipModel_No.getText()+ newline); OutDataWriter.append(equip_Password.getText()+ newline); OutDataWriter.append(equipWeb_Site.getText()+ newline); //OutDataWriter.append(equipNotes.getText()); OutDataWriter.close(); fos.flush(); fos.close(); }catch(Exception e){ e.printStackTrace(); } } } return null; } } 

Это создает имя файла

  private String BuildNewFileName() { // creates a new filr name Time today = new Time(Time.getCurrentTimezone()); today.setToNow(); StringBuilder sb = new StringBuilder(); sb.append(today.year + ""); // Year) sb.append("_"); sb.append(today.monthDay + ""); // Day of the month (1-31) sb.append("_"); sb.append(today.month + ""); // Month (0-11)) sb.append("_"); sb.append(today.format("%k:%M:%S")); // Current time sb.append(".txt"); //Completed file name myNewFileName = sb.toString(); //Replace (:) with (_) myNewFileName = myNewFileName.replaceAll(":", "_"); return myNewFileName; } 

Хоп это помогает кому-то у меня долгое время, чтобы разобраться и заставить его работать.

  ContextWrapper contextWrapper = new ContextWrapper(getApplicationContext()); //getappcontext for just this activity context get File file = contextWrapper.getDir(file_path, Context.MODE_PRIVATE); if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) { saveToExternalStorage.setEnabled(false); } else { External_File = new File(getExternalFilesDir(file_path), file_name);//if ready then create a file for external } } try { FileInputStream fis = new FileInputStream(External_File); DataInputStream in = new DataInputStream(fis); BufferedReader br =new BufferedReader(new InputStreamReader(in)); String strLine; while ((strLine = br.readLine()) != null) { myData = myData + strLine; } in.close(); } catch (IOException e) { e.printStackTrace(); } InputText.setText("Save data of External file:::: "+myData); private static boolean isExternalStorageReadOnly() { String extStorageState = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) { return true; } return false; } private static boolean isExternalStorageAvailable() { String extStorageState = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(extStorageState)) { return true; } return false; } 

Дополнительный ответ

После записи на внешнее хранилище некоторые файловые менеджеры сразу не видят файл. Это может сбивать с толку, если пользователь думает, что он что-то скопировал на SD-карту, но тогда не может найти его там. Поэтому после копирования файла запустите следующий код, чтобы уведомить файловые менеджеры о его присутствии.

 MediaScannerConnection.scanFile( context, new String[]{myFile.getAbsolutePath()}, null, null); 

Дополнительную информацию см. В документации и этом ответе .

Несмотря на то, что выше ответы правильные, но я хочу добавить уведомление, чтобы различать типы хранилищ:

  • Внутреннее хранилище : он должен сказать «личное хранилище», потому что он принадлежит к приложению и не может использоваться совместно. Где он сохранен, зависит от того, где установлено приложение. Если приложение было установлено на SD-карте (я имею в виду внешнюю карту памяти, которую вы кладете больше на сотовый телефон для большего количества места для хранения изображений, видеороликов …), ваш файл будет принадлежать приложению, так как ваш файл будет находиться в SD-карту. И если приложение было установлено на внутренней карте (я имею в виду карту встроенного хранилища, идущую со своим мобильным телефоном), ваш файл будет на внутренней карте.
  • Внешнее хранилище : он должен сказать «общедоступное хранилище», потому что он может быть общим. И этот режим делит на 2 группы: частное внешнее хранилище и публичное внешнее хранилище. В основном, они почти одинаковы, вы можете проконсультироваться больше с этого сайта: https://developer.android.com/training/data-storage/files
  • Настоящая SD-карта (я имею в виду внешнюю карту памяти, которую вы кладете больше на сотовый телефон для большего количества места для хранения изображений, видео и т. Д.): Это не было четко указано на Android-документах, поэтому многие люди могут быть смущены тем, как сохранить файлы на этой карте.

Вот ссылка на исходный код для случаев, упомянутых выше: https://github.com/mttdat/FileUtils

  • Кнопка пользовательской формы Android
  • Android: использует setContentView несколько раз плохо при изменении раскладок?
  • Как сделать новый эффект параллакса PlayStore
  • Изменение положения диалогового windows на экране Android
  • Одна активность и все остальные fragmentы
  • Android: нарисуйте круг с текстом внутри
  • Как изменить значки меню навигации и переполнения панели инструментов (appcompat v7)?
  • Android - увеличение / уменьшение изображения RelativeLayout с распространением / пинчем
  • Как настроить макет Android для поддержки всех размеров экрана?
  • Android Как настроить макет в полноэкранном режиме, когда видна клавиатура
  • ОШИБКА: проблемы с рендерингом Не удалось найти следующие classы: android.support.v7.internal.widget.ActionBarOverlayLayout
  • Давайте будем гением компьютера.