Запись файла во внешнее хранилище в 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
7 ответов:
вы можете сделать это с помощью этого кода также.
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+ нам нужно:
добавьте в манифест следующее разрешение:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
запрос утверждения от пользователя:
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! } }
обрабатывать ответ пользователя внутри действия:
@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, Integer, String> { 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