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.
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
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.