Android-Speicherdatei auf externem Speicher

84

Ich habe ein kleines Problem beim Erstellen eines Verzeichnisses und beim Speichern einer Datei in meiner Android-Anwendung. Ich benutze diesen Code, um dies zu tun:

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();

Aber es wirft eine Ausnahme:

java.io.FileNotFoundException: /mnt/sdcard/MyApp/MediaCard/MediaCard-0.png (Keine solche Datei oder kein solches Verzeichnis)

in dieser Zeile: fos = new FileOutputStream(file);

Wenn ich den Dateinamen auf: setze "MyApp/MediaTag-"+objectId+", funktioniert er, aber wenn ich versuche, die Datei zu erstellen und in einem anderen Verzeichnis zu speichern, wird die Ausnahme ausgelöst. Also irgendwelche Ideen, was ich falsch mache?

Und noch eine Frage: Gibt es eine Möglichkeit, meine Dateien im externen Speicher privat zu machen, sodass der Benutzer sie nicht in der Galerie sehen kann, nur wenn er sein Gerät als verbindet Disk Drive?

Android-Droid
quelle

Antworten:

185

Verwenden Sie diese Funktion, um Ihre Bitmap auf einer SD-Karte zu speichern

private void SaveImage(Bitmap finalBitmap) {

    String root = Environment.getExternalStorageDirectory().toString();
    File myDir = new File(root + "/saved_images");    
     if (!myDir.exists()) {
                    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();
    }
}

und füge dies im Manifest hinzu

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

BEARBEITEN: Wenn Sie diese Zeile verwenden, können Sie gespeicherte Bilder in der Galerieansicht anzeigen.

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

Schauen Sie sich diesen Link auch an http://rajareddypolam.wordpress.com/?p=3&preview=true

RajaReddy PolamReddy
quelle
10
Sie sollten immer noch Environment.getExternalStorageDirectory()anstelle von verwenden /sdcard.
Che Jami
1
Es wird nur in Ihrem Ordner
gespeichert.
8
Bitte verwenden Sie finallyund fangen Sie nicht generischException
Mr_and_Mrs_D
2
@LiamGeorgeBetsworth Alle oben beschriebenen Verhaltensweisen arbeiten , wie es ist in pre KitKat .
Muhammad Babar
3
Es ist nicht geeignet zu verwenden Intent.ACTION_MEDIA_MOUNTEDund funktioniert nicht mit KitKat. Die richtige Absicht zu senden istnew Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file) )
Anthony Garcia-Labiad
28

Der von RajaReddy präsentierte Code funktioniert nicht mehr für KitKat

Dieser macht (2 Änderungen):

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);
                }
    });

}
Yar
quelle
2
Ich bekomme uri null?
Mukesh
Informieren Sie den Medienscanner über die neue Datei, damit sie dem Benutzer sofort zur Verfügung steht - das rettet meinen Tag
Saiful Islam Sajib
6

Update 2018, SDK> = 23.

Jetzt sollten Sie auch überprüfen, ob der Benutzer die Berechtigung für externen Speicher erteilt hat, indem Sie Folgendes verwenden:

public boolean isStoragePermissionGranted() {
    String TAG = "Storage Permission";
    if (Build.VERSION.SDK_INT >= 23) {
        if (this.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            Log.v(TAG, "Permission is granted");
            return true;
        } else {
            Log.v(TAG, "Permission is revoked");
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { //permission is automatically granted on sdk<23 upon installation
        Log.v(TAG,"Permission is granted");
        return true;
    }
}

public void saveImageBitmap(Bitmap image_bitmap, String image_name) {
    String root = Environment.getExternalStorageDirectory().toString();
    if (isStoragePermissionGranted()) { // check or ask permission
        File myDir = new File(root, "/saved_images");
        if (!myDir.exists()) {
            myDir.mkdirs();
        }
        String fname = "Image-" + image_name + ".jpg";
        File file = new File(myDir, fname);
        if (file.exists()) {
            file.delete();
        }
        try {
            file.createNewFile(); // if file already exists will do nothing
            FileOutputStream out = new FileOutputStream(file);
            image_bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            out.flush();
            out.close();

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

        MediaScannerConnection.scanFile(this, new String[]{file.toString()}, new String[]{file.getName()}, null);
    }
}

und natürlich hinzufügen in AndroidManifest.xml:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
João Cartucho
quelle
5

Sie benötigen hierfür eine Erlaubnis

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

und Methode:

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
}
Dev Sabby
quelle
4

Versuche dies :

  1. Überprüfen Sie das externe Speichergerät
  2. Datei schreiben
  3. Datei lesen
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");
    }
}
Nirav Ranpara
quelle
2
Dies sieht dem Code von hier sehr ähnlich: stackoverflow.com/a/8330635/19679 . Wenn es von dort gezeichnet wurde, sollten Sie dies wahrscheinlich in Ihrer Antwort zitieren.
Brad Larson
4

Ich habe eine AsyncTask zum Speichern von Bitmaps erstellt.

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)
            {
            }
        }
    }
}
AndroidGeek
quelle
Wie kann ich GIF-Bild speichern?
Vishal Senjaliya
1
Das GIF-Bild enthält mehrere Bilder. Sie müssen zuerst diese Frames trennen, dann können Sie diese Methode verwenden. Es ist meine Meinung.
AndroidGeek
1
Ich habe es von stackoverflow.com/questions/39826400/…
Vishal Senjaliya
3

Wahrscheinlich wird eine Ausnahme ausgelöst, da kein MediaCardUnterverzeichnis vorhanden ist. Sie sollten überprüfen, ob alle Verzeichnisse im Pfad vorhanden sind.

Informationen zur Sichtbarkeit Ihrer Dateien: Wenn Sie eine Datei mit dem Namen .nomediain Ihr Verzeichnis einfügen, teilen Sie Android mit, dass sie nicht nach Mediendateien durchsucht werden soll und diese nicht in der Galerie angezeigt werden.

Ognyan
quelle
2

seit android 4.4 dateispeicherung wurde geändert. es gibt

ContextCompat.getExternalFilesDirs(context, name);

Es wird ein Array neu abgestimmt.

wenn der Name null ist

Der erste Wert lautet /storage/emulated/0/Android/com.my.package/files

Der zweite Wert lautet /storage/extSdCard/Android/com.my.package/files

Android 4.3 und weniger werden ein einzelnes Elementarray neu abgestimmt

Teile von wenig chaotischem Code, aber es zeigt, wie es funktioniert:

    /** 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;
        }
Shimon Doodkin
quelle
1

Dieser Code funktioniert hervorragend und funktioniert auch mit KitKat. Schätzen Sie @RajaReddy PolamReddy Hier wurden
einige weitere Schritte hinzugefügt und auch in der Galerie sichtbar.

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();
    }

}

Dies ist der Medienscanner, der in der Galerie sichtbar ist.

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);
}
Crishnan Iyengar
quelle
1

Für API-Level 23 (Marshmallow) und höher sollte zusätzlich zu den Verwendungsberechtigungen im Manifest auch eine Popup-Berechtigung implementiert werden, die der Benutzer während der Verwendung der App zur Laufzeit erteilen muss.

Unten finden Sie ein Beispiel zum Speichern hello world!als myFile.txtDateiinhalt im TestVerzeichnis im Bildverzeichnis.

Im Manifest:

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

Wo möchten Sie die Datei erstellen:

int permission = ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE};

if (permission != PackageManager.PERMISSION_GRANTED)
{
     ActivityCompat.requestPermissions(MainActivity.this,PERMISSIONS_STORAGE, 1);
}

File myDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Test");

myDir.mkdirs();

try 
{
    String FILENAME = "myFile.txt";
    File file = new File (myDir, FILENAME);
    String string = "hello world!";
    FileOutputStream fos = new FileOutputStream(file);
    fos.write(string.getBytes());
    fos.close();
 }
 catch (IOException e) {
    e.printStackTrace();
 }
Arischer Firouzian
quelle
0

Klicken Sie hier für eine vollständige Beschreibung und einen Quellcode

public void saveImage(Context mContext, Bitmap bitmapImage) {

  File sampleDir = new File(Environment.getExternalStorageDirectory() + "/" + "ApplicationName");

  TextView tvImageLocation = (TextView) findViewById(R.id.tvImageLocation);
  tvImageLocation.setText("Image Store At : " + sampleDir);

  if (!sampleDir.exists()) {
      createpathForImage(mContext, bitmapImage, sampleDir);
  } else {
      createpathForImage(mContext, bitmapImage, sampleDir);
  }
}
Hitesh Tarbundiya
quelle
1
Fügen Sie hier eine Beschreibung hinzu
Mathews Sunny