refactor: 优化相机工具及迁移FileUtils至iconloader模块
This commit is contained in:
@@ -15,6 +15,7 @@ import com.ttstd.dialer.databinding.ActivitySettingsUtilsBinding;
|
|||||||
import com.ttstd.dialer.mdm.DeviceManagerService;
|
import com.ttstd.dialer.mdm.DeviceManagerService;
|
||||||
import com.ttstd.dialer.service.main.MainService;
|
import com.ttstd.dialer.service.main.MainService;
|
||||||
import com.ttstd.dialer.utils.CameraUtil;
|
import com.ttstd.dialer.utils.CameraUtil;
|
||||||
|
import com.ttstd.iconloader.utils.FileUtils;
|
||||||
import com.ttstd.dialer.utils.Logger;
|
import com.ttstd.dialer.utils.Logger;
|
||||||
import com.ttstd.dialer.utils.SystemUtils;
|
import com.ttstd.dialer.utils.SystemUtils;
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ public class SettingsUtilsActivity extends BaseMvvmActivity<SettingsUtilsViewMod
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void screenshotSnap(View view) {
|
public void screenshotSnap(View view) {
|
||||||
String filepath = getExternalCacheDir().getAbsolutePath() + File.separator + "screenshot_" + System.currentTimeMillis() + ".png";
|
String filepath = FileUtils.getCacheDir(SettingsUtilsActivity.this) + File.separator + "screenshot_" + System.currentTimeMillis() + ".png";
|
||||||
SystemUtils.screenshotSnap(SettingsUtilsActivity.this, filepath, new BlockingBaseObserver<Integer>() {
|
SystemUtils.screenshotSnap(SettingsUtilsActivity.this, filepath, new BlockingBaseObserver<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public void onNext(@NonNull Integer integer) {
|
public void onNext(@NonNull Integer integer) {
|
||||||
@@ -186,27 +187,10 @@ public class SettingsUtilsActivity extends BaseMvvmActivity<SettingsUtilsViewMod
|
|||||||
Map<String, String> params = new HashMap<>();
|
Map<String, String> params = new HashMap<>();
|
||||||
params.put("sn", DeviceManagerService.getInstance().getSerial());
|
params.put("sn", DeviceManagerService.getInstance().getSerial());
|
||||||
params.put("createtime", String.valueOf(createTime));
|
params.put("createtime", String.valueOf(createTime));
|
||||||
// Call<BaseResponse> call = NetInterfaceManager.getInstance().getScreenshotCall().sendScreenshot(params, body);
|
|
||||||
// call.enqueue(new RetryCallback<BaseResponse>(call, 10, 30 * 1000) {
|
|
||||||
// @Override
|
|
||||||
// public void onRequestResponse(Call call, Response response) {
|
|
||||||
// Logger.e(TAG, "onRequestResponse: " + response.body().toString());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onRequestFail(Call call, Throwable t) {
|
|
||||||
// Logger.e(TAG, "onRequestFail: ");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onStartRetry() {
|
|
||||||
// Logger.e(TAG, "onStartRetry: ");
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
cameraUtil.startTakePicture(getExternalCacheDir().getAbsolutePath() + "cameracapture_" + File.separator + createTime + ".jpg");
|
cameraUtil.startTakePicture(FileUtils.getCacheDir(SettingsUtilsActivity.this) + File.separator + "cameracapture_" + File.separator + createTime + ".jpg");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import com.ttstd.dialer.mdm.DeviceManagerService;
|
|||||||
import com.ttstd.dialer.network.api.ContactApi;
|
import com.ttstd.dialer.network.api.ContactApi;
|
||||||
import com.ttstd.dialer.network.api.SnApi;
|
import com.ttstd.dialer.network.api.SnApi;
|
||||||
import com.ttstd.dialer.network.interceptor.AuthInterceptor;
|
import com.ttstd.dialer.network.interceptor.AuthInterceptor;
|
||||||
import com.ttstd.dialer.utils.FileUtils;
|
import com.ttstd.iconloader.utils.FileUtils;
|
||||||
import com.ttstd.dialer.utils.Logger;
|
import com.ttstd.dialer.utils.Logger;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.ttstd.dialer.mdm.DeviceManagerService;
|
|||||||
import com.ttstd.dialer.network.BaseObserver;
|
import com.ttstd.dialer.network.BaseObserver;
|
||||||
import com.ttstd.dialer.network.OkHttpManager;
|
import com.ttstd.dialer.network.OkHttpManager;
|
||||||
import com.ttstd.dialer.utils.CmdUtil;
|
import com.ttstd.dialer.utils.CmdUtil;
|
||||||
|
import com.ttstd.iconloader.utils.FileUtils;
|
||||||
import com.ttstd.dialer.utils.Logger;
|
import com.ttstd.dialer.utils.Logger;
|
||||||
import com.ttstd.dialer.utils.RebootUtils;
|
import com.ttstd.dialer.utils.RebootUtils;
|
||||||
|
|
||||||
@@ -238,7 +239,7 @@ public class PushExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void screenSnapshot() {
|
private void screenSnapshot() {
|
||||||
String filepath = mContext.getExternalCacheDir().getAbsolutePath() + File.separator + "screenshot_" + System.currentTimeMillis() + ".png";
|
String filepath = FileUtils.getCacheDir(mContext) + File.separator + "screenshot_" + System.currentTimeMillis() + ".png";
|
||||||
|
|
||||||
Observable.fromCallable(new Callable<Integer>() {
|
Observable.fromCallable(new Callable<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import android.graphics.Paint;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.util.LruCache;
|
import android.util.LruCache;
|
||||||
|
|
||||||
|
import com.ttstd.iconloader.utils.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -113,7 +115,7 @@ public class AvatarCacheUtil {
|
|||||||
|
|
||||||
// ========== 本地磁盘缓存操作 ==========
|
// ========== 本地磁盘缓存操作 ==========
|
||||||
private static File getCacheDir(Context context) {
|
private static File getCacheDir(Context context) {
|
||||||
File cacheDir = new File(context.getExternalCacheDir(), CACHE_DIR_NAME);
|
File cacheDir = new File(FileUtils.getCacheDir(context), CACHE_DIR_NAME);
|
||||||
if (!cacheDir.exists()) {
|
if (!cacheDir.exists()) {
|
||||||
cacheDir.mkdirs();
|
cacheDir.mkdirs();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,15 @@ import android.hardware.camera2.params.StreamConfigurationMap;
|
|||||||
import android.media.Image;
|
import android.media.Image;
|
||||||
import android.media.ImageReader;
|
import android.media.ImageReader;
|
||||||
import android.media.MediaRecorder;
|
import android.media.MediaRecorder;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
@@ -38,19 +42,14 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
|
||||||
* @作者 Liushihua
|
|
||||||
* @创建时间 2021-2-3 10:54
|
|
||||||
* @描述
|
|
||||||
*/
|
|
||||||
public class CameraUtil {
|
public class CameraUtil {
|
||||||
private static final String TAG = "CameraUtil";
|
private static final String TAG = "CameraUtil";
|
||||||
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private CameraCallBack cameraCallBack;
|
private CameraCallBack cameraCallBack;
|
||||||
private CameraManager cameraManager;
|
private CameraManager cameraManager;
|
||||||
// 默认相机id是0 LENS_FACING_FRONT,LENS_FACING_BACK
|
// 默认相机id
|
||||||
private int cameraId = CameraCharacteristics.LENS_FACING_FRONT;
|
private String mCameraId;
|
||||||
private CameraDevice mCameraDevice;
|
private CameraDevice mCameraDevice;
|
||||||
private String savePath;
|
private String savePath;
|
||||||
|
|
||||||
@@ -58,7 +57,10 @@ public class CameraUtil {
|
|||||||
private CameraCaptureSession mCameraCaptureSession;
|
private CameraCaptureSession mCameraCaptureSession;
|
||||||
private CaptureRequest request;
|
private CaptureRequest request;
|
||||||
private ExecutorService service;
|
private ExecutorService service;
|
||||||
|
private HandlerThread mBackgroundThread;
|
||||||
|
private Handler mBackgroundHandler;
|
||||||
private boolean isTakedPicture = false;//是否已经拍照
|
private boolean isTakedPicture = false;//是否已经拍照
|
||||||
|
private volatile boolean mIsCapturing = false; // 是否正在捕获图片数据
|
||||||
|
|
||||||
private int needSetOrientation = 0;// 设置默认的拍照方向
|
private int needSetOrientation = 0;// 设置默认的拍照方向
|
||||||
private boolean isInitOk = false;// 是否初始化成功
|
private boolean isInitOk = false;// 是否初始化成功
|
||||||
@@ -132,12 +134,9 @@ public class CameraUtil {
|
|||||||
@Override
|
@Override
|
||||||
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
public void onDisconnected(@NonNull CameraDevice cameraDevice) {
|
||||||
Logger.e(TAG, "onDisconnected");
|
Logger.e(TAG, "onDisconnected");
|
||||||
cameraDevice.close();
|
|
||||||
mCameraDevice = null;
|
mCameraDevice = null;
|
||||||
Message message = new Message();
|
sendErrorMessage("后台相机断开连接");
|
||||||
message.what = HANDLER_ERR;
|
onStop();
|
||||||
message.obj = "后台相机断开连接";
|
|
||||||
handler.sendMessage(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,12 +149,9 @@ public class CameraUtil {
|
|||||||
@Override
|
@Override
|
||||||
public void onError(@NonNull CameraDevice cameraDevice, int error) {
|
public void onError(@NonNull CameraDevice cameraDevice, int error) {
|
||||||
Logger.e(TAG, "onError 相机设备异常,请重启!");
|
Logger.e(TAG, "onError 相机设备异常,请重启!");
|
||||||
cameraDevice.close();
|
|
||||||
mCameraDevice = null;
|
mCameraDevice = null;
|
||||||
Message messagef = new Message();
|
sendErrorMessage("相机设备异常,请重启!");
|
||||||
messagef.what = HANDLER_ERR;
|
onStop();
|
||||||
messagef.obj = "相机设备异常,请重启!";
|
|
||||||
handler.sendMessage(messagef);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,75 +194,117 @@ public class CameraUtil {
|
|||||||
this.context = activity;
|
this.context = activity;
|
||||||
this.cameraCallBack = cameraCallBack;
|
this.cameraCallBack = cameraCallBack;
|
||||||
cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
cameraManager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
|
||||||
|
startBackgroundThread();
|
||||||
// 对于静态图片,使用可用的最大值来拍摄。
|
// 对于静态图片,使用可用的最大值来拍摄。
|
||||||
if (cameraManager != null) {
|
if (cameraManager != null) {
|
||||||
isInitOk = true;
|
isInitOk = true;
|
||||||
cameraManager.registerAvailabilityCallback(callback, null);
|
cameraManager.registerAvailabilityCallback(callback, mBackgroundHandler);
|
||||||
|
findFrontCamera();
|
||||||
getCameraInfo();
|
getCameraInfo();
|
||||||
setupImageReader();
|
setupImageReader();
|
||||||
service = Executors.newSingleThreadExecutor();
|
service = Executors.newSingleThreadExecutor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void startBackgroundThread() {
|
||||||
|
mBackgroundThread = new HandlerThread("CameraBackground");
|
||||||
|
mBackgroundThread.start();
|
||||||
|
mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopBackgroundThread() {
|
||||||
|
if (mBackgroundThread != null) {
|
||||||
|
mBackgroundThread.quitSafely();
|
||||||
|
try {
|
||||||
|
mBackgroundThread.join();
|
||||||
|
mBackgroundThread = null;
|
||||||
|
mBackgroundHandler = null;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findFrontCamera() {
|
||||||
|
try {
|
||||||
|
for (String id : cameraManager.getCameraIdList()) {
|
||||||
|
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
|
||||||
|
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||||
|
if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
|
||||||
|
mCameraId = id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果没找到前置,就用第一个
|
||||||
|
String[] ids = cameraManager.getCameraIdList();
|
||||||
|
if (ids.length > 0) {
|
||||||
|
mCameraId = ids[0];
|
||||||
|
}
|
||||||
|
} catch (CameraAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setupImageReader() {
|
private void setupImageReader() {
|
||||||
// Size size = getOutputSize(imgOutputSizes);
|
if (imageReader != null) {
|
||||||
//前三个参数分别是需要的尺寸和格式,最后一个参数代表每次最多获取几帧数据,本例的3代表ImageReader中最多可以获取2帧图像流
|
imageReader.close();
|
||||||
imageReader = ImageReader.newInstance(1600, 1200, ImageFormat.JPEG, 1);
|
}
|
||||||
//监听ImageReader的事件,当有图像流数据可用时会回调onImageAvailable方法,它的参数就是预览帧数据,可以对这帧数据进行处理
|
Size size = getOutputSize(imgOutputSizes);
|
||||||
|
//前三个参数分别是需要的尺寸和格式,最后一个参数代表每次最多获取几帧数据,本例的1代表ImageReader中最多可以获取1帧图像流
|
||||||
|
imageReader = ImageReader.newInstance(size.getWidth(), size.getHeight(), ImageFormat.JPEG, 1);
|
||||||
|
//监听ImageReader的事件,当有图像流数据可用时会回调onImageAvailable方法
|
||||||
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
|
imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onImageAvailable(ImageReader reader) {
|
public void onImageAvailable(ImageReader reader) {
|
||||||
|
if (!mIsCapturing) {
|
||||||
|
// 如果不在捕获状态,直接丢弃帧数据,避免预览流占满内存
|
||||||
|
Image image = reader.acquireLatestImage();
|
||||||
|
if (image != null) image.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mIsCapturing = false; // 标记捕获完成
|
||||||
Image image = reader.acquireLatestImage();
|
Image image = reader.acquireLatestImage();
|
||||||
//我们可以将这帧数据转成字节数组,类似于Camera1的PreviewCallback回调的预览帧数据
|
if (image == null) return;
|
||||||
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
|
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
|
||||||
byte[] data = new byte[buffer.remaining()];
|
byte[] data = new byte[buffer.remaining()];
|
||||||
buffer.get(data);
|
buffer.get(data);
|
||||||
image.close();
|
image.close();
|
||||||
saveFile(data, savePath);
|
saveFile(data, savePath);
|
||||||
}
|
}
|
||||||
}, null);
|
}, mBackgroundHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开相机
|
* 打开相机
|
||||||
*/
|
*/
|
||||||
private void openCamera() {
|
private void openCamera() {
|
||||||
cameraId = getFrontCameraId();
|
if (mCameraId == null) {
|
||||||
Logger.e(TAG, "openCamera: getFrontCameraId = " + getFrontCameraId());
|
findFrontCamera();
|
||||||
Logger.e(TAG, "openCamera:" + cameraId);
|
}
|
||||||
|
Logger.e(TAG, "openCamera: cameraId = " + mCameraId);
|
||||||
isCameraDoing = true;
|
isCameraDoing = true;
|
||||||
// 设置TextureView的缓冲区大小
|
|
||||||
// 获取Surface显示预览数据
|
|
||||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
|
||||||
Message message = new Message();
|
sendErrorMessage("权限不足");
|
||||||
message.what = HANDLER_ERR;
|
|
||||||
message.obj = "权限不足";
|
|
||||||
handler.sendMessage(message);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
cameraManager.openCamera(Integer.toString(cameraId), stateCallback, null);
|
if (imageReader == null) {
|
||||||
Logger.e(TAG, "打开相机成功!");
|
setupImageReader();
|
||||||
|
}
|
||||||
|
cameraManager.openCamera(mCameraId, stateCallback, mBackgroundHandler);
|
||||||
|
Logger.e(TAG, "正在打开相机...");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.e(TAG, "打开相机失败-Exception:" + e.getMessage());
|
Logger.e(TAG, "打开相机失败-Exception:" + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Message messagef = new Message();
|
sendErrorMessage("打开相机失败");
|
||||||
messagef.what = HANDLER_ERR;
|
|
||||||
messagef.obj = "打开相机失败";
|
|
||||||
handler.sendMessage(messagef);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getFrontCameraId() {
|
private void sendErrorMessage(String msg) {
|
||||||
int numberOfCameras = Camera.getNumberOfCameras();
|
Message message = new Message();
|
||||||
for (int i = 0; i < numberOfCameras; i++) {
|
message.what = HANDLER_ERR;
|
||||||
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
message.obj = msg;
|
||||||
Camera.getCameraInfo(i, cameraInfo);
|
handler.sendMessage(message);
|
||||||
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -274,21 +312,16 @@ public class CameraUtil {
|
|||||||
*/
|
*/
|
||||||
private void startPreview() {
|
private void startPreview() {
|
||||||
Logger.e(TAG, "startPreview");
|
Logger.e(TAG, "startPreview");
|
||||||
// CaptureRequest添加imageReaderSurface,不加的话就会导致ImageReader的onImageAvailable()方法不会回调
|
if (mCameraDevice == null || imageReader == null) return;
|
||||||
// 创建CaptureSession时加上imageReaderSurface,如下,这样预览数据就会同时输出到previewSurface和imageReaderSurface了
|
|
||||||
try {
|
try {
|
||||||
// 创建CaptureRequestBuilder,TEMPLATE_PREVIEW比表示预览请求
|
// 创建CaptureRequestBuilder,TEMPLATE_PREVIEW表示预览请求
|
||||||
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
|
mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
||||||
mPreviewRequestBuilder.addTarget(imageReader.getSurface());// 设置Surface作为预览数据的显示界面
|
mPreviewRequestBuilder.addTarget(imageReader.getSurface());
|
||||||
// 创建相机捕获会话,第一个参数是捕获数据的输出Surface列表,第二个参数是CameraCaptureSession的状态回调接口,当它创建好后会回调onConfigured方法,第三个参数用来确定Callback在哪个线程执行,为null的话就在当前线程执行
|
mCameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()), captureSessionStateCallBack, mBackgroundHandler);
|
||||||
mCameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()), captureSessionStateCallBack, null);
|
|
||||||
} catch (CameraAccessException e) {
|
} catch (CameraAccessException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Message messagef = new Message();
|
sendErrorMessage("捕获帧失败");
|
||||||
messagef.what = HANDLER_ERR;
|
Logger.e(TAG, "创建预览Session失败: " + e.getMessage());
|
||||||
messagef.obj = "捕获帧失败";
|
|
||||||
handler.sendMessage(messagef);
|
|
||||||
Logger.e(TAG, "Camera获取成功,创建录制请求或捕获Session失败" + e.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +353,7 @@ public class CameraUtil {
|
|||||||
@Override
|
@Override
|
||||||
public void onConfigureFailed(CameraCaptureSession session) {
|
public void onConfigureFailed(CameraCaptureSession session) {
|
||||||
Logger.e(TAG, "onConfigureFailed");
|
Logger.e(TAG, "onConfigureFailed");
|
||||||
|
sendErrorMessage("开启预览失败");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -341,27 +375,26 @@ public class CameraUtil {
|
|||||||
private void takePicture() {
|
private void takePicture() {
|
||||||
Logger.e(TAG, "takePicture");
|
Logger.e(TAG, "takePicture");
|
||||||
try {
|
try {
|
||||||
if (mCameraDevice == null || mPreviewRequestBuilder == null) return;
|
if (mCameraDevice == null || mCameraCaptureSession == null) return;
|
||||||
mPreviewRequestBuilder.addTarget(imageReader.getSurface());
|
CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
|
||||||
|
captureBuilder.addTarget(imageReader.getSurface());
|
||||||
//设置拍照方向
|
//设置拍照方向
|
||||||
mPreviewRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, this.needSetOrientation);
|
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, this.needSetOrientation);
|
||||||
//这个回调接口用于拍照结束时重启预览,因为拍照会导致预览停止
|
// 自动对焦和自动曝光模式
|
||||||
CameraCaptureSession.CaptureCallback mImageSavedCallback = new CameraCaptureSession.CaptureCallback() {
|
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||||
|
captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
|
||||||
|
|
||||||
|
mIsCapturing = true; // 准备接收ImageReader的数据
|
||||||
|
mCameraCaptureSession.capture(captureBuilder.build(), new CameraCaptureSession.CaptureCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
|
public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
|
||||||
Logger.e(TAG, "拍照完成");
|
Logger.e(TAG, "拍照指令完成");
|
||||||
onStop();
|
|
||||||
}
|
}
|
||||||
};
|
}, mBackgroundHandler);
|
||||||
//开始拍照,然后回调上面的接口重启预览,因为mCaptureBuilder设置ImageReader作为target,所以会自动回调ImageReader的onImageAvailable()方法保存图片
|
|
||||||
mCameraCaptureSession.capture(mPreviewRequestBuilder.build(), mImageSavedCallback, null);
|
|
||||||
} catch (CameraAccessException e) {
|
} catch (CameraAccessException e) {
|
||||||
Logger.e(TAG, "takePhoto CameraAccessException:" + e.getMessage());
|
Logger.e(TAG, "takePhoto CameraAccessException:" + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Message messagef = new Message();
|
sendErrorMessage("拍照失败");
|
||||||
messagef.what = HANDLER_ERR;
|
|
||||||
messagef.obj = "拍照失败";
|
|
||||||
handler.sendMessage(messagef);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,8 +442,10 @@ public class CameraUtil {
|
|||||||
*/
|
*/
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
this.cameraCallBack = null;
|
this.cameraCallBack = null;
|
||||||
|
stopBackgroundThread();
|
||||||
if (cameraManager != null)
|
if (cameraManager != null)
|
||||||
cameraManager.unregisterAvailabilityCallback(callback);
|
cameraManager.unregisterAvailabilityCallback(callback);
|
||||||
|
this.context = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,8 +498,9 @@ public class CameraUtil {
|
|||||||
if (enableCameraList == null) {
|
if (enableCameraList == null) {
|
||||||
getCameras();
|
getCameras();
|
||||||
}
|
}
|
||||||
|
if (mCameraId == null) findFrontCamera();
|
||||||
try {
|
try {
|
||||||
CameraCharacteristics mCameraCharacteristics = cameraManager.getCameraCharacteristics(String.valueOf(cameraId));
|
CameraCharacteristics mCameraCharacteristics = cameraManager.getCameraCharacteristics(mCameraId);
|
||||||
// 设置是否支持闪光灯
|
// 设置是否支持闪光灯
|
||||||
Boolean available = mCameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
|
Boolean available = mCameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
|
||||||
mFlashSupported = available == null ? false : available;
|
mFlashSupported = available == null ? false : available;
|
||||||
@@ -474,7 +510,20 @@ public class CameraUtil {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int mSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);//这个方法来获取CameraSensor的方向。
|
int mSensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);//这个方法来获取CameraSensor的方向。
|
||||||
Logger.e(TAG, "camera sensor orientation:" + mSensorOrientation + ",display rotation=" + context.getDisplay().getRotation());
|
|
||||||
|
int rotation;
|
||||||
|
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
try {
|
||||||
|
rotation = context.getDisplay().getRotation();
|
||||||
|
} catch (Exception e) {
|
||||||
|
rotation = wm != null ? wm.getDefaultDisplay().getRotation() : 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rotation = wm != null ? wm.getDefaultDisplay().getRotation() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.e(TAG, "camera sensor orientation:" + mSensorOrientation + ",display rotation=" + rotation);
|
||||||
|
|
||||||
int[] formats = map.getOutputFormats();//获得手机支持的输出格式,其中jpeg是一定会支持的,yuv_420_888是api21才开始支持的
|
int[] formats = map.getOutputFormats();//获得手机支持的输出格式,其中jpeg是一定会支持的,yuv_420_888是api21才开始支持的
|
||||||
for (int format : formats) {
|
for (int format : formats) {
|
||||||
@@ -553,6 +602,8 @@ public class CameraUtil {
|
|||||||
message.what = HANDLER_TAKE_PHOTO_SUCCESS;
|
message.what = HANDLER_TAKE_PHOTO_SUCCESS;
|
||||||
message.obj = savePath;
|
message.obj = savePath;
|
||||||
handler.sendMessage(message);
|
handler.sendMessage(message);
|
||||||
|
// 保存成功后关闭相机,解决竞态问题
|
||||||
|
handler.post(() -> onStop());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Logger.e(TAG, "图片保存-IOException:" + e.getMessage());
|
Logger.e(TAG, "图片保存-IOException:" + e.getMessage());
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.ttstd.dialer.utils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Environment;
|
|
||||||
|
|
||||||
public class FileUtils {
|
|
||||||
public static String getCacheDir(Context context) {
|
|
||||||
String cachePath;
|
|
||||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|
|
||||||
|| !Environment.isExternalStorageRemovable()) {
|
|
||||||
if (context.getExternalCacheDir() != null) {
|
|
||||||
cachePath = context.getExternalCacheDir().getPath();
|
|
||||||
} else if (context.getExternalFilesDir("cache") != null) {
|
|
||||||
cachePath = context.getExternalFilesDir("cache").getPath();
|
|
||||||
} else {
|
|
||||||
cachePath = context.getCacheDir().getPath();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cachePath = context.getCacheDir().getPath();
|
|
||||||
}
|
|
||||||
return cachePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,7 @@ import android.util.Log;
|
|||||||
import androidx.collection.LruCache;
|
import androidx.collection.LruCache;
|
||||||
|
|
||||||
import com.jakewharton.disklrucache.DiskLruCache;
|
import com.jakewharton.disklrucache.DiskLruCache;
|
||||||
|
import com.ttstd.iconloader.utils.FileUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -63,7 +64,7 @@ public class IconCacheManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 磁盘缓存(50MB)
|
// 磁盘缓存(50MB)
|
||||||
File cacheDir = new File(context.getExternalCacheDir(), "icon_cache");
|
File cacheDir = new File(FileUtils.getCacheDir(context), "icon_cache");
|
||||||
try {
|
try {
|
||||||
mDiskCache = DiskLruCache.open(cacheDir, 1, 1, 50 * 1024 * 1024);
|
mDiskCache = DiskLruCache.open(cacheDir, 1, 1, 50 * 1024 * 1024);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.ttstd.iconloader.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Environment;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class FileUtils {
|
||||||
|
/**
|
||||||
|
* 获取缓存目录
|
||||||
|
* 优先返回外部缓存目录,如果不可用则返回内部缓存目录
|
||||||
|
*/
|
||||||
|
public static String getCacheDir(Context context) {
|
||||||
|
File cacheDir = null;
|
||||||
|
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|
||||||
|
|| !Environment.isExternalStorageRemovable()) {
|
||||||
|
cacheDir = context.getExternalCacheDir();
|
||||||
|
}
|
||||||
|
if (cacheDir == null) {
|
||||||
|
cacheDir = context.getCacheDir();
|
||||||
|
}
|
||||||
|
return cacheDir.getPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user