2011-10-25 80 views
68

我在創建目錄並在我的android應用程序上保存文件時遇到了一些問題。我使用這段代碼做到這一點:Android將文件保存到外部存儲

String filename = "MyApp/MediaTag/MediaTag-"+objectId+".png"; 
File file = new File(Environment.getExternalStorageDirectory(), filename); 
FileOutputStream fos; 

fos = new FileOutputStream(file); 
fos.write(mediaTagBuffer); 
fos.flush(); 
fos.close(); 

但它拋出一個異常:

java.io.FileNotFoundException:到/ mnt/SD卡/ MyApp的/ MediaCard/MediaCard-0。 PNG(沒有這樣的文件或目錄)

在該行:fos = new FileOutputStream(file);

如果我設置文件名:"MyApp/MediaTag-"+objectId+"它的工作,但如果我嘗試創建文件並將其保存到另一個引發異常的目錄中。所以,有什麼想法我做錯了?

而另一個問題:有沒有什麼辦法讓我的文件在外部存儲空間保密,所以用戶無法在圖庫中看到它們,只要他將他的設備連接爲Disk Drive

回答

164

使用此功能,以節省您的位圖SD卡

private void SaveImage(Bitmap finalBitmap) { 

    String root = Environment.getExternalStorageDirectory().toString(); 
    File myDir = new File(root + "/saved_images");  
    myDir.mkdirs(); 
    Random generator = new Random(); 
    int n = 10000; 
    n = generator.nextInt(n); 
    String fname = "Image-"+ n +".jpg"; 
    File file = new File (myDir, fname); 
    if (file.exists()) 
     file.delete(); 
    try { 
     FileOutputStream out = new FileOutputStream(file); 
     finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); 
     out.flush(); 
     out.close(); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

和清單

添加此
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

編輯:通過使用此行,您將能夠在圖庫視圖中看到保存的圖像。

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
         Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 

看看這個鏈接也http://rajareddypolam.wordpress.com/?p=3&preview=true

+9

你應該仍然使用'Environment.getExternalStorageDirectory()'而不是'/ sdcard'。 –

+0

code working good.but images are shown in the gallery in gallery and my folder too.how我可以這樣做。 –

+1

它只保存在您的文件夾中,它顯示在相機中意味着您通過相機自動拍攝圖像並將其存儲在相機中。 –

3

可能會拋出異常,因爲沒有MediaCard子目錄。你應該檢查路徑中的所有目錄是否存在。

關於文件的可見性:如果您將名爲.nomedia的文件放在您的目錄中,則表明您不希望它掃描媒體文件,並且它們不會出現在圖庫中。

4

試試這個:

  1. 檢查外部存儲設備
  2. 寫文件
  3. 讀取文件
public class WriteSDCard extends Activity { 

    private static final String TAG = "MEDIA"; 
    private TextView tv; 

    @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"); 
    } 
} 
+2

這看起來非常相似的代碼從這裏:http://stackoverflow.com/a/8330635/19679 。如果它是從那裏抽取的,那麼你應該在你的答案中引用它。 –

20

通過RajaReddy給出的代碼不再適用於奇巧

這個人做(2種變化):

private void saveImageToExternalStorage(Bitmap finalBitmap) { 
    String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString(); 
    File myDir = new File(root + "/saved_images"); 
    myDir.mkdirs(); 
    Random generator = new Random(); 
    int n = 10000; 
    n = generator.nextInt(n); 
    String fname = "Image-" + n + ".jpg"; 
    File file = new File(myDir, fname); 
    if (file.exists()) 
     file.delete(); 
    try { 
     FileOutputStream out = new FileOutputStream(file); 
     finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); 
     out.flush(); 
     out.close(); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 


    // Tell the media scanner about the new file so that it is 
    // immediately available to the user. 
    MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null, 
      new MediaScannerConnection.OnScanCompletedListener() { 
       public void onScanCompleted(String path, Uri uri) { 
        Log.i("ExternalStorage", "Scanned " + path + ":"); 
        Log.i("ExternalStorage", "-> uri=" + uri); 
       } 
    }); 

} 
+1

我得到uri null? –

0

此代碼是偉大的工作&從事過奇巧爲好。欣賞@RajaReddy PolamReddy
在這裏增加了更多的步驟,也可以在Gallery上看到。

public void SaveOnClick(View v){ 
File mainfile; 
String fpath; 


    try { 
//i.e v2:My view to save on own folder  
     v2.setDrawingCacheEnabled(true); 
//Your final bitmap according to my code. 
     bitmap_tmp = v2.getDrawingCache(); 

File(getExternalFilesDir(Environment.DIRECTORY_PICTURES)+File.separator+"/MyFolder"); 

      Random random=new Random(); 
      int ii=100000; 
      ii=random.nextInt(ii); 
      String fname="MyPic_"+ ii + ".jpg"; 
      File direct = new File(Environment.getExternalStorageDirectory() + "/MyFolder"); 

      if (!direct.exists()) { 
       File wallpaperDirectory = new File("/sdcard/MyFolder/"); 
       wallpaperDirectory.mkdirs(); 
      } 

      mainfile = new File(new File("/sdcard/MyFolder/"), fname); 
      if (mainfile.exists()) { 
       mainfile.delete(); 
      } 

       FileOutputStream fileOutputStream; 
     fileOutputStream = new FileOutputStream(mainfile); 

     bitmap_tmp.compress(CompressFormat.JPEG, 100, fileOutputStream); 
     Toast.makeText(MyActivity.this.getApplicationContext(), "Saved in Gallery..", Toast.LENGTH_LONG).show(); 
     fileOutputStream.flush(); 
     fileOutputStream.close(); 
     fpath=mainfile.toString(); 
     galleryAddPic(fpath); 
    } catch(FileNotFoundException e){ 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

這是媒體掃描儀可以在圖庫中看到。

private void galleryAddPic(String fpath) { 
    Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE"); 
    File f = new File(fpath); 
    Uri contentUri = Uri.fromFile(f); 
    mediaScanIntent.setData(contentUri); 
    this.sendBroadcast(mediaScanIntent); 
} 
2

因爲安卓4.4文件保存已被更改。有

ContextCompat.getExternalFilesDirs(context, name); 

它回調一個數組。

當名稱爲空

第一值是像/storage/emulated/0/Android/com.my.package/files

第二值是像 /存儲/ extSdCard/Android設備/ com.my.package /文件

Android 4.3以上且小於它retuns單個項目陣列

部分有點混亂代碼,但它說明了它是如何工作的:

/** Create a File for saving an image or video 
    * @throws Exception */ 
    private File getOutputMediaFile(int type) throws Exception{ 

     // Check that the SDCard is mounted 
     File mediaStorageDir; 
     if(internalstorage.isChecked()) 
     { 
      mediaStorageDir = new File(getFilesDir().getAbsolutePath()); 
     } 
     else 
     { 
      File[] dirs=ContextCompat.getExternalFilesDirs(this, null); 
      mediaStorageDir = new File(dirs[dirs.length>1?1:0].getAbsolutePath()); 
     } 


     // Create the storage directory(MyCameraVideo) if it does not exist 
     if (! mediaStorageDir.exists()){ 

      if (! mediaStorageDir.mkdirs()){ 

       output.setText("Failed to create directory."); 

       Toast.makeText(this, "Failed to create directory.", Toast.LENGTH_LONG).show(); 

       Log.d("myapp", "Failed to create directory"); 
       return null; 
      } 
     } 


     // Create a media file name 

     // For unique file name appending current timeStamp with file name 
     java.util.Date date= new java.util.Date(); 
     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",Locale.ENGLISH) .format(date.getTime()); 

     File mediaFile; 

     if(type == MEDIA_TYPE_VIDEO) { 

      // For unique video file name appending current timeStamp with file name 
      mediaFile = new File(mediaStorageDir.getPath() + File.separator + slpid + "_" + pwsid + "_" + timeStamp + ".mp4"); 

     } 
     else if(type == MEDIA_TYPE_AUDIO) { 

      // For unique video file name appending current timeStamp with file name 
      mediaFile = new File(mediaStorageDir.getPath() + File.separator + slpid + "_" + pwsid + "_" + timeStamp + ".3gp"); 

     } else { 
      return null; 
     } 

     return mediaFile; 
    } 



    /** Create a file Uri for saving an image or video 
    * @throws Exception */ 
    private Uri getOutputMediaFileUri(int type) throws Exception{ 

      return Uri.fromFile(getOutputMediaFile(type)); 
    } 

//usage: 
     try { 
      file=getOutputMediaFileUri(MEDIA_TYPE_AUDIO).getPath(); 
     } catch (Exception e1) { 
      e1.printStackTrace(); 
      return; 
     } 
3

我已經創建了一個AsyncTask來保存位圖。

public class BitmapSaver extends AsyncTask<Void, Void, Void> 
{ 
    public static final String TAG ="BitmapSaver"; 

    private Bitmap bmp; 

    private Context ctx; 

    private File pictureFile; 

    public BitmapSaver(Context paramContext , Bitmap paramBitmap) 
    { 
     ctx = paramContext; 

     bmp = paramBitmap; 
    } 

    /** Create a File for saving an image or video */ 
    private File getOutputMediaFile() 
    { 
     // To be safe, you should check that the SDCard is mounted 
     // using Environment.getExternalStorageState() before doing this. 
     File mediaStorageDir = new File(Environment.getExternalStorageDirectory() 
       + "/Android/data/" 
       + ctx.getPackageName() 
       + "/Files"); 

     // This location works best if you want the created images to be shared 
     // between applications and persist after your app has been uninstalled. 

     // Create the storage directory if it does not exist 
     if (! mediaStorageDir.exists()){ 
      if (! mediaStorageDir.mkdirs()){ 
       return null; 
      } 
     } 
     // Create a media file name 
     String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date()); 
     File mediaFile; 
      String mImageName="MI_"+ timeStamp +".jpg"; 
      mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName); 
     return mediaFile; 

    } 
    protected Void doInBackground(Void... paramVarArgs) 
    { 
     this.pictureFile = getOutputMediaFile(); 

     if (this.pictureFile == null) { return null; } 

     try 
     { 
      FileOutputStream localFileOutputStream = new FileOutputStream(this.pictureFile); 
      this.bmp.compress(Bitmap.CompressFormat.PNG, 90, localFileOutputStream); 
      localFileOutputStream.close(); 
     } 
     catch (FileNotFoundException localFileNotFoundException) 
     { 
      return null; 
     } 
     catch (IOException localIOException) 
     { 
     } 
     return null; 
    } 

    protected void onPostExecute(Void paramVoid) 
    { 
     super.onPostExecute(paramVoid); 

     try 
     { 
      //it will help you broadcast and view the saved bitmap in Gallery 
      this.ctx.sendBroadcast(new Intent("android.intent.action.MEDIA_MOUNTED", Uri 
        .parse("file://" + Environment.getExternalStorageDirectory()))); 

      Toast.makeText(this.ctx, "File saved", 0).show(); 

      return; 
     } 
     catch (Exception localException1) 
     { 
      try 
      { 
       Context localContext = this.ctx; 
       String[] arrayOfString = new String[1]; 
       arrayOfString[0] = this.pictureFile.toString(); 
       MediaScannerConnection.scanFile(localContext, arrayOfString, null, 
         new MediaScannerConnection.OnScanCompletedListener() 
         { 
          public void onScanCompleted(String paramAnonymousString , 
            Uri paramAnonymousUri) 
          { 
          } 
         }); 
       return; 
      } 
      catch (Exception localException2) 
      { 
      } 
     } 
    } 
} 
+0

我如何保存gif圖像? –

+1

Gif圖像包含多個圖像。你必須首先分離這些幀,然後你可以使用這種方法。這是我的意見。 – Nepster

+1

我是從http://stackoverflow.com/questions/39826400/how-to-save-gif-image-in-sdcard –

5

需要在此

< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

public boolean saveImageOnExternalData(String filePath, byte[] fileData) { 

    boolean isFileSaved = false; 
    try { 
     File f = new File(filePath); 
     if (f.exists()) 
      f.delete(); 
     f.createNewFile(); 
     FileOutputStream fos = new FileOutputStream(f); 
     fos.write(fileData); 
     fos.flush(); 
     fos.close(); 
     isFileSaved = true; 
     // File Saved 
    } catch (FileNotFoundException e) { 
     System.out.println("FileNotFoundException"); 
     e.printStackTrace(); 
    } catch (IOException e) { 
     System.out.println("IOException"); 
     e.printStackTrace(); 
    } 
    return isFileSaved; 
    // File Not Saved 
} 
相關問題