java - 从Android应用内摄像头拍照并将其上传到服务器的更有效方法
问题描述
我正在构建一个需要从应用内相机拍照的方法的应用程序,但是对于某些 Android 设备(旧设备或低内存),触发拍照时它非常冻结。我可以修改或优化任何代码以使用户体验更好吗?
//this function trigger to take picture (or screenshot) from user screen
private void captureImage() {
mPreview.setDrawingCacheEnabled(true);
final Bitmap[] drawingCache = {Bitmap.createBitmap(mPreview.getDrawingCache())};
mPreview.setDrawingCacheEnabled(false);
mCameraSource.takePicture(null, bytes -> {
int orientation = Exif.getOrientation(bytes);
Bitmap temp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap picture = rotateImage(temp, orientation);
assert picture != null;
Bitmap overlay = Bitmap.createBitmap(mGraphicOverlay.getWidth(), mGraphicOverlay.getHeight(), picture.getConfig());
Canvas canvas = new Canvas(overlay);
Matrix matrix = new Matrix();
matrix.setScale((float) overlay.getWidth() / (float) picture.getWidth(), (float) overlay.getHeight() / (float) picture.getHeight());
// mirror by inverting scale and translating
matrix.preScale(-1, 1);
matrix.postTranslate(canvas.getWidth(), 0);
Paint paint = new Paint();
canvas.drawBitmap(picture, matrix, paint);
canvas.drawBitmap(drawingCache[0], 0, 0, paint);
//this function to save picture taken and put it on app storage cache
try {
String mainpath = getApplicationContext().getFilesDir().getPath() + separator + "e-Presensi" + separator;
File basePath = new File(mainpath);
if (!basePath.exists())
Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success" : "Failed");
//this function to get directory path of saved photo
String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
String namafotoo = "photo_" + getPhotoTime() + ".jpg";
filePath = path;
namafoto = namafotoo;
SessionManager.createNamaFoto(namafoto);
File captureFile = new File(path);
boolean sucess = captureFile.createNewFile();
if (!captureFile.exists())
Log.d("CAPTURE_FILE_PATH", sucess ? "Success" : "Failed");
FileOutputStream stream = new FileOutputStream(captureFile);
overlay.compress(Bitmap.CompressFormat.WEBP, 60, stream);
stream.flush();
stream.close();
if (!picture.isRecycled()) {
picture.recycle();
}
if (drawingCache[0] != null && !drawingCache[0].isRecycled()) {
drawingCache[0].recycle();
drawingCache[0] = null;
}
mPreview.setDrawingCacheEnabled(false);
uploadPicture();
finish();
} catch (IOException e) {
e.printStackTrace();
}
});
}
谢谢你的帮助。
解决方案
一般来说,我建议您单步执行您的代码并查看您在每一行上生成的大量内存资源,并在完成整个方法时考虑将它们设置为空。
例如,您有一个名为temp
“Y”字节的变量,您似乎会旋转它,然后再不使用temp
它。如果picture
是的旋转副本,temp
那么您现在已经使用了 2Y 字节的内存来保存temp
和picture
. 我怀疑如果您temp
在创建后简单地设置为 null picture
,您可能会释放您的旧/较慢手机急需的一半内存。
采用相同的概念并继续使用其余方法,看看是否可以找到其他优化。基本上,在您创建不打算使用的图像数据副本的任何地方,您都应该立即将其设置为 null,以便垃圾收集器可以积极地将其丢弃。
推荐阅读
- c# - 在某个确切时间采取行动的应用程序
- r - 将变量添加到 MonetDBLite 中的表
- python - 如何将图像识别为屏幕截图
- ubuntu - 在使用 XFCE 和 xRDP 访问的 Linux 服务器上打开 atom 时出错
- javascript - 如何将链接的 id 传递给 angularJS 控制器?
- c# - Xpath 以验证开始,以验证结束
- google-bigquery - 从执行查询连接到 BigQuery
- php - PHP日期x和日期y之间的所有日期
- php - 为什么我的 Wordpress 网站设置了 PHPSESSID cookie?
- python - Matplotlib - 散点图周围的边框