我正在研究从web服务器下载图像的功能,在屏幕上显示它,如果用户希望保持图像,将其保存在SD卡的某个文件夹中。有没有一种简单的方法来获取位图并将其保存到我选择的SD卡文件夹中?

我的问题是,我可以下载图像,在屏幕上显示为位图。我能够找到的将图像保存到特定文件夹的唯一方法是使用FileOutputStream,但这需要一个字节数组。我不知道如何转换(如果这是正确的方式)从位图到字节数组,所以我可以使用FileOutputStream写入数据。

我的另一个选择是使用MediaStore:

MediaStore.Images.Media.insertImage(getContentResolver(), bm,
    barcodeNumber + ".jpg Card Image", barcodeNumber + ".jpg Card Image");

它可以很好地保存到SD卡,但不允许您自定义文件夹。


当前回答

一些新设备不保存位图,所以我解释了一点。

请确保您在下面添加了权限

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

并在XML文件夹名为provider_paths.xml下创建一个XML文件

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external_files"
        path="." />
</paths>

and in AndroidManifest under <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider> then simply call saveBitmapFile(passYourBitmapHere) public static void saveBitmapFile(Bitmap bitmap) throws IOException { File mediaFile = getOutputMediaFile(); FileOutputStream fileOutputStream = new FileOutputStream(mediaFile); bitmap.compress(Bitmap.CompressFormat.JPEG, getQualityNumber(bitmap), fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); } where File getOutputMediaFile() { File mediaStorageDir = new File( Environment.getExternalStorageDirectory(), "easyTouchPro"); if (mediaStorageDir.isDirectory()) { // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") .format(Calendar.getInstance().getTime()); String mCurrentPath = mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"; File mediaFile = new File(mCurrentPath); return mediaFile; } else { /// error handling for PIE devices.. mediaStorageDir.delete(); mediaStorageDir.mkdirs(); galleryAddPic(mediaStorageDir); return (getOutputMediaFile()); } } and other methods public static int getQualityNumber(Bitmap bitmap) { int size = bitmap.getByteCount(); int percentage = 0; if (size > 500000 && size <= 800000) { percentage = 15; } else if (size > 800000 && size <= 1000000) { percentage = 20; } else if (size > 1000000 && size <= 1500000) { percentage = 25; } else if (size > 1500000 && size <= 2500000) { percentage = 27; } else if (size > 2500000 && size <= 3500000) { percentage = 30; } else if (size > 3500000 && size <= 4000000) { percentage = 40; } else if (size > 4000000 && size <= 5000000) { percentage = 50; } else if (size > 5000000) { percentage = 75; } return percentage; } and void galleryAddPic(File f) { Intent mediaScanIntent = new Intent( "android.intent.action.MEDIA_SCANNER_SCAN_FILE"); Uri contentUri = Uri.fromFile(f); mediaScanIntent.setData(contentUri); this.sendBroadcast(mediaScanIntent); }

其他回答

您应该使用Bitmap.compress()方法将位图保存为文件。它将压缩(如果所使用的格式允许的话)您的图片并将其推入OutputStream。

下面是一个通过getImageBitmap(myurl)获得的位图实例,可以压缩为JPEG,压缩率为85%:

// Assume block needs to be inside a Try/Catch block.
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
Integer counter = 0;
File file = new File(path, "FitnessGirl"+counter+".jpg"); // the File to save , append increasing numeric counter to prevent files from getting overwritten.
fOut = new FileOutputStream(file);

Bitmap pictureBitmap = getImageBitmap(myurl); // obtaining the Bitmap
pictureBitmap.compress(Bitmap.CompressFormat.JPEG, 85, fOut); // saving the Bitmap to a file compressed as a JPEG with 85% compression rate
fOut.flush(); // Not really required
fOut.close(); // do not forget to close the stream

MediaStore.Images.Media.insertImage(getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());

为视频创建一个视频缩略图。如果视频损坏或格式不支持,它可能返回null。

private void makeVideoPreview() {
    Bitmap thumbnail = ThumbnailUtils.createVideoThumbnail(videoAbsolutePath, MediaStore.Images.Thumbnails.MINI_KIND);
    saveImage(thumbnail);
}

使用以下代码将位图保存在sdcard中

商店形象

private void storeImage(Bitmap image) {
    File pictureFile = getOutputMediaFile();
    if (pictureFile == null) {
        Log.d(TAG,
                "Error creating media file, check storage permissions: ");// e.getMessage());
        return;
    } 
    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        image.compress(Bitmap.CompressFormat.PNG, 90, fos);
        fos.close();
    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
    }  
}

获取图像存储路径

/** 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/"
            + getApplicationContext().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;
} 
outStream = new FileOutputStream(file);

将在AndroidManifest.xml中抛出异常(至少在os2.2中):

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

在onActivityResult:

String filename = "pippo.png";
File sd = Environment.getExternalStorageDirectory();
File dest = new File(sd, filename);

Bitmap bitmap = (Bitmap)data.getExtras().get("data");
try {
     FileOutputStream out = new FileOutputStream(dest);
     bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
     out.flush();
     out.close();
} catch (Exception e) {
     e.printStackTrace();
}

一些新设备不保存位图,所以我解释了一点。

请确保您在下面添加了权限

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

并在XML文件夹名为provider_paths.xml下创建一个XML文件

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external_files"
        path="." />
</paths>

and in AndroidManifest under <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider> then simply call saveBitmapFile(passYourBitmapHere) public static void saveBitmapFile(Bitmap bitmap) throws IOException { File mediaFile = getOutputMediaFile(); FileOutputStream fileOutputStream = new FileOutputStream(mediaFile); bitmap.compress(Bitmap.CompressFormat.JPEG, getQualityNumber(bitmap), fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); } where File getOutputMediaFile() { File mediaStorageDir = new File( Environment.getExternalStorageDirectory(), "easyTouchPro"); if (mediaStorageDir.isDirectory()) { // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") .format(Calendar.getInstance().getTime()); String mCurrentPath = mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"; File mediaFile = new File(mCurrentPath); return mediaFile; } else { /// error handling for PIE devices.. mediaStorageDir.delete(); mediaStorageDir.mkdirs(); galleryAddPic(mediaStorageDir); return (getOutputMediaFile()); } } and other methods public static int getQualityNumber(Bitmap bitmap) { int size = bitmap.getByteCount(); int percentage = 0; if (size > 500000 && size <= 800000) { percentage = 15; } else if (size > 800000 && size <= 1000000) { percentage = 20; } else if (size > 1000000 && size <= 1500000) { percentage = 25; } else if (size > 1500000 && size <= 2500000) { percentage = 27; } else if (size > 2500000 && size <= 3500000) { percentage = 30; } else if (size > 3500000 && size <= 4000000) { percentage = 40; } else if (size > 4000000 && size <= 5000000) { percentage = 50; } else if (size > 5000000) { percentage = 75; } return percentage; } and void galleryAddPic(File f) { Intent mediaScanIntent = new Intent( "android.intent.action.MEDIA_SCANNER_SCAN_FILE"); Uri contentUri = Uri.fromFile(f); mediaScanIntent.setData(contentUri); this.sendBroadcast(mediaScanIntent); }