[英]Android save bitmap to image file
我正在运行设备(海思)和 android 应用程序。
Android 和设备正在通过 sockets 进行通信。
设备发送图像 (h.264) 并在 TextureView 上的 Android 上显示。
我可以使用textureView.getBitmap()
从 TextureView 获取 Bitmap 。
我做了一个按钮按钮来保存图片, textureView.getBitmap()
。
<Button
android:id="@+id/btnSavePng"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnSavePng"
android:text="savePicture" />
并且,onclick function 如下。
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
}
}
我允许使用权限AndroidManifest.xml
如下,并且android:requestLegacyExternalStorage="true"
正在申请中。
<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" />
我的代码有问题吗?
如果是这样,如何将 bitmap 保存为 png 或 jpg 文件?
我想,我的应用程序无法访问目录。
感谢您阅读我的问题。
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());
}
我不明白为什么我的代码还没有工作。
无论如何,感谢所有帮助我的人。
我会尝试所有的回复代码。
谢谢你。
1.如果您还没有请求运行时权限,请检查它: https://developer.android.com/training/permissions/requesting
2.或者如果您的 android 高于 10: https://developer.android.com/about/versions/11/privacy/storage#scoped
然后您必须使用 SAF 或 MediaStore API 将 bitmap 存储在“公共目录”中。
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;
}
如果您使用的是 Android11+ 并且您已授予存储管理器权限并直接处理文件(而不是 MediaStore API),则原因可能是创建文件名称中的“:”字符(通常来自时间戳)。 Android 11(与旧的 Android 版本不同)不允许这样做。
在 kotlin这对我有用->
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())
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.