Android - 将图片保存到特定文件夹

22

我需要将我的应用程序拍摄的照片保存到特定文件夹中。我阅读了许多解决此问题的方案,但我无法使它们中的任何一个起作用,因此我请求帮助。

MainActivity.java

public void onClick(View v) {

    Intent camera = new Intent(
            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

    //Folder is already created
    String dirName = Environment.getExternalStorageDirectory().getPath()
            + "/MyAppFolder/MyApp" + n + ".png";

    Uri uriSavedImage = Uri.fromFile(new File(dirName));
    camera.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
    startActivityForResult(camera, 1);

    n++;
}

AndroidManifest.xml

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

1
请在此处检查此问题的答案:https://dev59.com/qmnWa4cB1Zd3GeqP490V - Razgriz
你检查过文件夹是否真的被创建了吗? - meborda
请查看以下链接:https://dev59.com/_Gsz5IYBdhLWcg3wcndb#7887114 - Hariharan
我已经检查了两个,但都没有对我起作用。 - Goblinch
可能是如何将Android相机中的图像保存到特定文件夹?的重复问题。 - Robert Columbia
5个回答

57

请查看以下代码,它对我来说可以正常工作。

private void createDirectoryAndSaveFile(Bitmap imageToSave, String fileName) {

    File direct = new File(Environment.getExternalStorageDirectory() + "/DirName");

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

    File file = new File("/sdcard/DirName/", fileName);
    if (file.exists()) {
        file.delete();
    }
    try {
        FileOutputStream out = new FileOutputStream(file);
        imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, out);
        out.flush();
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我该如何获取一个包含我的图片的位图对象? - Goblinch
1
从相机中获取图像并在活动结果中写入Bitmap photo =(Bitmap)data.getExtras()。get(“data”);。 - mdDroid
我刚刚发现这是我的操作系统(Ubuntu)的问题。它没有显示图片,但它们确实在正确的文件夹中。 - Goblinch
2
嗨,我正在收到异常:java.io.FileNotFoundException: /Znapo/5/1838: open failed: ENOENT(没有这个文件或目录) - Shajeel Afzal
1
使用压缩会破坏图像并使其模糊,如何获得原始质量。 - Panache
显示剩余2条评论

12

我已经像这样使用了mdDroid的代码:

public void startCamera() {
    // Create photo
    newPhoto = new Photo();
    newPhoto.setName(App.getPhotoName());

    //Create folder !exist
    String folderPath = Environment.getExternalStorageDirectory() + "/PestControl";
    File folder = new File(folderPath);
    if (!folder.exists()) {
        File wallpaperDirectory = new File(folderPath);
        wallpaperDirectory.mkdirs();
    }
    //create a new file
    newFile = new File(folderPath, newPhoto.getName());

    if (newFile != null) {
        // save image here
        Uri relativePath = Uri.fromFile(newFile);
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, relativePath);
        startActivityForResult(intent, CAMERA_REQUEST);
    }
}

完美,为什么这不在顶部? - Ajay
太棒了!在尝试了很多修改已捕获的文件名的“解决方案”后,这是一个简短而美好的解决方案。 - mihai71

9

使用方法如下。这对你有用。

public void onClick(View v) {
  Intent camera = new Intent(
  android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
  startActivityForResult(camera, 1);
}

protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
  super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

  switch(requestCode) {
    case 1:
      if(resultCode == RESULT_OK) {
      Uri selectedImage = imageReturnedIntent.getData();
      String[] filePathColumn = {MediaStore.Images.Media.DATA};

      Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
      cursor.moveToFirst();

      int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
      //file path of captured image
      filePath = cursor.getString(columnIndex);
      //file path of captured image
      File f = new File(filePath);
      filename= f.getName();

      Toast.makeText(getApplicationContext(), "Your Path:"+filePath, 2000).show();
      Toast.makeText(getApplicationContext(), "Your Filename:"+filename, 2000).show();
      cursor.close();

      //Convert file path into bitmap image using below line.
      // yourSelectedImage = BitmapFactory.decodeFile(filePath);
      Toast.makeText(getApplicationContext(), "Your image"+yourSelectedImage, 2000).show();

      //put bitmapimage in your imageview
      //yourimgView.setImageBitmap(yourSelectedImage);  

      Savefile(filename,filePath);
    }
  }
}

public void Savefile(String name, String path) {
  File direct = new File(Environment.getExternalStorageDirectory() + "/MyAppFolder/MyApp/");
  File file = new File(Environment.getExternalStorageDirectory() + "/MyAppFolder/MyApp/"+n+".png");

  if(!direct.exists()) {
    direct.mkdir();
  }

  if (!file.exists()) {
    try {
      file.createNewFile();
      FileChannel src = new FileInputStream(path).getChannel();
      FileChannel dst = new FileOutputStream(file).getChannel();
      dst.transferFrom(src, 0, src.size());
      src.close();
      dst.close();

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

希望这可以帮助到你。参考相机意图的使用。


1
imageReturnedIntent.getData() 返回 null。 - Pranita Patil
@amy 你在清单文件中声明了这个<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>权限吗? - Nirmal
这个解决方案对我很有效,因为自从Android 4.4文件保存方式改变后,就有了ContextCompat.getExternalFilesDirs(context, name)这个方法。参考链接:https://dev59.com/_Gsz5IYBdhLWcg3wcndb - Pranita Patil
即使拥有所有权限,我仍然无法在意图中获取值, 请建议该怎么办。 - Panache

3

这是您需要的内容。我尝试了上述解决方案,它们将图片保存到图库,但图片不可见,显示了404错误,我找到了解决方法。

public void addToFav(String dirName, Bitmap bitmap) {

    String resultPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES)+
            dirName + System.currentTimeMillis() + ".jpg";
    Log.e("resultpath",resultPath);
    new File(resultPath).getParentFile().mkdir();




    if (Build.VERSION.SDK_INT < 29){
        
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "Photo");
        values.put(MediaStore.Images.Media.DESCRIPTION, "Edited");
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());
        values.put("_data", resultPath);

        ContentResolver cr = getContentResolver();
        cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        try {
            OutputStream fileOutputStream = new FileOutputStream(resultPath);
            bitmap.compress(CompressFormat.JPEG, 100, fileOutputStream);
            fileOutputStream.flush();
            fileOutputStream.close();
            if(fileOutputStream != null){
                Toast.makeText(this, "Image Saved", Toast.LENGTH_SHORT).show();
            }
        } catch (IOException e2) {
            e2.printStackTrace();
        }

    }else {

        OutputStream fos = null;
        File file = new File(resultPath);

        final String relativeLocation = Environment.DIRECTORY_PICTURES;
        final ContentValues  contentValues = new ContentValues();

        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation+"/"+dirName);
        contentValues.put(MediaStore.MediaColumns.TITLE, "Photo");
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
        contentValues.put(MediaStore.MediaColumns.DATE_TAKEN, System.currentTimeMillis ());
        contentValues.put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis());
        contentValues.put(MediaStore.MediaColumns.BUCKET_ID, file.toString().toLowerCase(Locale.US).hashCode());
        contentValues.put(MediaStore.MediaColumns.BUCKET_DISPLAY_NAME, file.getName().toLowerCase(Locale.US));
        
        final ContentResolver resolver = getContentResolver();
        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        Uri uri = resolver.insert(contentUri, contentValues);

        try {
            fos = resolver.openOutputStream(uri);
            bitmap.compress(CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        if(fos != null){
            Toast.makeText(this, "Image Saved", Toast.LENGTH_SHORT).show();
        }

    }


}

0

我找到了一个更简单的代码来完成它。

这是创建图像文件夹的代码:

private File createImageFile(){
        final String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/App Folder/";

        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "AppName_" + timeStamp;

        String file = dir +imageFileName+ ".jpg" ;
        File imageFile = new File(file);

        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = imageFile.getAbsolutePath();

        return imageFile;
    }

这是启动相机应用并拍照的代码:

public void lunchCamera() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = createImageFile();
            // Continue only if the File was successfully created
            if (photoFile != null) {
                Uri photoURI = FileProvider.getUriForFile(this,
                        "com.ziad.sayit",
                        photoFile);

                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
            }
        }
    }

不同实现方式的有用链接:https://www.programcreek.com/java-api-examples/?class=android.os.Environment&method=getExternalStoragePublicDirectory


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接