简体   繁体   中英

Android save bitmap to image file

How to save bitmap to image file? (png/jpg any types don't care...)

I'm running device(hisilicon) & android app.
Android and device are communicating over sockets.
Device send Image (h.264) and show it on Android on TextureView.
I can get Bitmap from TextureView, using textureView.getBitmap() .


I made a button button to save the picture, textureView.getBitmap() .

<Button
  android:id="@+id/btnSavePng"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:onClick="onBtnSavePng"
  android:text="savePicture" />

and, onclick function is like under.


public String getCurrentTimeString() {
  int yyyy = Calendar.getInstance().get(Calendar.YEAR);
  int MM = Calendar.getInstance().get(Calendar.MONTH) + 1;
  int dd = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
  int hh = Calendar.getInstance().get(Calendar.HOUR);
  int mm = Calendar.getInstance().get(Calendar.MINUTE);
  int ss = Calendar.getInstance().get(Calendar.SECOND);
  
  String result = yyyy+"-"+MM+"-"+dd+" "+hh+":"+mm+":"+ss;
  return result;
}

public void onBtnSavePng(View view) {
  try {
    File storage = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
    String fname = getCurrentTimeString() + ".jpg";
    File tp = new File(storage, fname);
    Bitmap bm = textureView.getBitmap();
    tp.createNewFile(); // Result of File.createNewFile() ignored

    FileOutputStream ot = new FileOutputStream(tp);
    bm.compress(Bitmap.CompressFormat.JPEG, 100, ot);
    ot.close();
  } catch(Exception e) {
    Log.d("onBtnSavePng", e.toString()); // java.io.IOException: Operation not permitted
  }
}

I allow uses-permissions AndroidManifest.xml like under, and android:requestLegacyExternalStorage="true" is on application.

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

Is there any problem with my codes?

If so, how to save bitmap to png or jpg file?

I guess, my app don't access to directory.

Thank you for read my question.


Self Solved.


public void onBtnSavePng(View view) {
  try {
    String root = Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES).toString();
    File myDir = new File(root + "/saved_images");
    myDir.mkdirs();
    String fname = getCurrentTimeString() + ".jpg";
    File file = new File(myDir, fname);

    FileOutputStream out = new FileOutputStream(file);
    Bitmap bm = textureView.getBitmap();
    bm.compress(Bitmap.CompressFormat.JPEG, 100, out);
    out.flush();
    out.close();
  } catch( Exception e) {
    Log.d("onBtnSavePng", e.toString());
  }

I don't understand why my code is worked not yet.
Anyway, Thank you for all who helps me.
I'll try all of reply codes.

Thank you.

1.Check it if you don't request the runtime permission yet: https://developer.android.com/training/permissions/requesting

2.Or if your android is higher than 10: https://developer.android.com/about/versions/11/privacy/storage#scoped-storage

  • After you update your app to target Android 11, the system ignores the requestLegacyExternalStorage flag.

Then you have to use SAF or MediaStore API to store the bitmap in the "public directory".

SAF: https://developer.android.com/guide/topics/providers/document-provider

MediaStore API: https://developer.android.com/reference/android/provider/MediaStore

public void onBtnSavePng(View view) {
    try {
        String fileName = getCurrentTimeString() + ".jpg";

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/");
            values.put(MediaStore.MediaColumns.IS_PENDING, 1);
        } else {
            File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            File file = new File(directory, fileName);
            values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
        }

        Uri uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

        try (OutputStream output = getContentResolver().openOutputStream(uri)) {
            Bitmap bm = textureView.getBitmap();
            bm.compress(Bitmap.CompressFormat.JPEG, 100, output);
        }
    } catch (Exception e) {
        Log.d("onBtnSavePng", e.toString()); // java.io.IOException: Operation not permitted
    }
}
 String myDir =new File (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)+pdfDirectoryImage);
            fileName = filename + ".png";
            androidElevenPath = saveImages(mContext,finalBitmap,filename);

 private static Uri saveImages(Context mContext, Bitmap bitmap, @NonNull String name) throws IOException {
        boolean saved;
        OutputStream fos;
        File image = null;
        Uri imageUri = null;
        String imagesDir = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentResolver resolver = mContext.getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name);
            contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
            contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM" + pdfDirectoryImage);
             imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            fos = resolver.openOutputStream(imageUri);
        } else {
             imagesDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM).toString() + File.separator + pdfDirectoryImage;

            File file = new File(imagesDir);

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

             image = new File(imagesDir, name + ".png");
            fos = new FileOutputStream(image);

        }

        saved = bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        fos.flush();
        fos.close();
        return imageUri;
    }

In case you are on Android11+ and you have the storage manager permission granted and are working directly with files (and not the MediaStore API) the cause could be a ":" char (usually from a timestamp) in the name of the created file. Android 11 (unlike older Android versions) does not allow that.

In kotlin This is working for me->

fun saveMediaToStorage(bitmap: Bitmap, context: Context, onUriCreated: (Uri) -> Unit) {
var fos: OutputStream? = null

//Generating a file name
val filename = "${System.currentTimeMillis()}.jpg"

try {
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
        val resolver = context.contentResolver
        val contentValues = ContentValues()
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "$filename.jpg")

        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg")
        val imageUri =
            resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
        fos = Objects.requireNonNull(imageUri)?.let {
            resolver.openOutputStream(it)
        }

        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos)
        Objects.requireNonNull(fos)

        imageUri?.let { onUriCreated(it) }
    } else {
        //These for devices running on android < Q
        val imagesDir =
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
        val image = File(imagesDir, filename)
        fos = FileOutputStream(image)

        fos.use {
            //Finally writing the bitmap to the output stream that we opened
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)
        }

        onUriCreated(Uri.fromFile(image))
    }
} catch (e: Exception) {
    Log.d("error", e.toString())
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM