ref: 207a95163f5a047e1f8ed8b77f1c4ab2b08edb64
parent: 6dbca8e2f85408be9486a3145f74bb0c3d2e46e1
author: glenda <glenda@9front.local>
date: Thu Apr 14 22:45:58 EDT 2022
devandroid (#N) changes
--- a/gui-android/AndroidManifest.xml
+++ b/gui-android/AndroidManifest.xml
@@ -27,4 +27,6 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>
--- a/gui-android/cpp/android.c
+++ b/gui-android/cpp/android.c
@@ -57,6 +57,30 @@
return 0;
}
+long
+getlocation(char *a, long n)
+{+ JNIEnv *env;
+ jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
+ if(rs != JNI_OK) {+ __android_log_print(ANDROID_LOG_WARN, "drawterm", "AttachCurrentThread returned error: %d", rs);
+ return 0;
+ }
+ jclass clazz = (*env)->GetObjectClass(env, mainActivityObj);
+ jmethodID methodID = (*env)->GetMethodID(env, clazz, "getLocation", "()Ljava/lang/String;");
+ jstring str = (*env)->CallObjectMethod(env, mainActivityObj, methodID);
+ char *s = (*env)->GetStringUTFChars(env, str, NULL);
+ long ret = strlen(s);
+ if (ret > (n-1))
+ ret = n-1;
+ memcpy(a, s, ret);
+ a[ret] = '\n';
+ ret++;
+ (*env)->ReleaseStringUTFChars(env, str, s);
+ (*jvm)->DetachCurrentThread(jvm);
+ return ret;
+}
+
void
show_notification(char *buf)
{--- a/gui-android/cpp/devandroid.c
+++ b/gui-android/cpp/devandroid.c
@@ -4,17 +4,19 @@
#include "fns.h"
#include "error.h"
-#include <android/log.h>
+//#include <android/log.h>
#include <android/sensor.h>
void show_notification(char *buf);
void take_picture(int id);
int num_cameras();
+long getlocation(char *a, long n);
int Ncameras = 0;
uchar *cambuf = nil;
-int camlen;
+int camlen = 0;
+static char camopen = 0;
ASensorManager *sensorManager = NULL;
@@ -21,10 +23,12 @@
enum
{Qdir = 0,
- Qcam = 1,
- Qaccel = 2,
- Qcompass = 4,
- Qnotify = 6,
+ Qaccel,
+ Qcompass,
+ Qnotify,
+ Qlocation,
+ Ntab,
+ Qcam = 8,
};
Dirtab
@@ -31,10 +35,11 @@
androiddir[] =
{ ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,- "camNNNN.jpg", {Qcam}, 0, 0444, "accel", {Qaccel}, 0, 0444, "compass", {Qcompass}, 0, 0444, "notify", {Qnotify}, 0, 0222,+ "location", {Qlocation}, 0, 0444,+ "camNNNN", {Qcam}, 0, 0444,};
static void androidinit(void);
@@ -53,42 +58,53 @@
return devattach('N', param);}
-static int
-androidgen(Chan *c, char *n, Dirtab *d, int nd, int s, Dir *dp)
+int
+androidgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
{Qid q;
- if (s == DEVDOTDOT) {- devdir(c, d->qid, "#N", 0, eve, 0555, dp);
- return 1;
+ if(tab == 0)
+ return -1;
+ if(i == DEVDOTDOT){+ /* nothing */
+ }else if(name){+// __android_log_print(ANDROID_LOG_WARN, "drawterm", "androidgen name %s", name);
+ for(i=1; i<Ntab; i++)
+ if(strcmp(tab[i].name, name) == 0)
+ break;
+ if (i == Ntab) {+ if (strncmp("cam", name, 3) == 0 &&+ name[3] >= '0' && name[3] <= '9' &&
+ strspn(&name[3], "0123456789") == (strlen(name) - 3) &&
+ (i = atoi(&name[3])) < Ncameras)
+ i += Ntab;
+ else
+ return -1;
+ }
+ if(i > Ntab)
+ tab += Ntab;
+ else
+ tab += i;
+ }else{+// __android_log_print(ANDROID_LOG_WARN, "drawterm", "androidgen i %d", i);
+ /* skip over the first element, that for . itself */
+ i++;
+ if(i >= ntab)
+ return -1;
+ if(i >= Ntab)
+ tab += Ntab;
+ else
+ tab += i;
}
- if (s < Ncameras) {- d += 1;
- q = d->qid;
- q.path |= (s << 16);
- sprintf(up->genbuf, "cam%d.jpg", s);
- devdir(c, q, up->genbuf, 0, eve, 0444, dp);
+ if (i >= Ntab) {+ q = tab->qid;
+ q.path |= ((i - Ntab) << 16);
+ sprintf(up->genbuf, "cam%d", i - Ntab);
+ devdir(c, q, up->genbuf, tab->length, eve, tab->perm, dp);
return 1;
}
- if (s == Ncameras) {- d += 2;
- sprintf(up->genbuf, "accel");
- devdir(c, d->qid, up->genbuf, 0, eve, 0444, dp);
- return 1;
- }
- if (s == (Ncameras+1)) {- d += 3;
- sprintf(up->genbuf, "compass");
- devdir(c, d->qid, up->genbuf, 0, eve, 0444, dp);
- return 1;
- }
- if (s == (Ncameras+2)) {- d += 4;
- sprintf(up->genbuf, "notify");
- devdir(c, d->qid, up->genbuf, 0, eve, 0222, dp);
- return 1;
- }
- return -1;
+ devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
+ return 1;
}
static Walkqid*
@@ -106,17 +122,18 @@
static Chan*
androidopen(Chan *c, int omode)
{- p9_uvlong s;
+ int i;
- c = devopen(c, omode, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
-
if (c->qid.path & Qcam) {- s = c->qid.path >> 16;
- take_picture(s);
+ if (camopen != 0) {+ error(Einuse);
+ } else {+ camopen = 1;
+ i = c->qid.path >> 16;
+ take_picture(i);
+ }
}
- c->mode = openmode(omode);
- c->flag |= COPEN;
- c->offset = 0;
+ c = devopen(c, omode, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
return c;
}
@@ -124,20 +141,51 @@
static void
androidclose(Chan *c)
{- if (c->qid.path & Qcam && cambuf != nil) {+ if (c->qid.path & Qcam && camopen != 0) {free(cambuf);
cambuf = nil;
+ camlen = 0;
+ camopen = 0;
}
}
+long
+readsensor(char *a, long n, int type) {+ long l;
+ const ASensor *sensor;
+ ASensorEventQueue *queue = NULL;
+ ASensorEvent data;
+
+ queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL);
+ if (queue == NULL)
+ return 0;
+ sensor = ASensorManager_getDefaultSensor(sensorManager, type);
+ if (sensor == NULL) {+ ASensorManager_destroyEventQueue(sensorManager, queue);
+ return 0;
+ }
+ if (ASensorEventQueue_enableSensor(queue, sensor)) {+ ASensorEventQueue_disableSensor(queue, sensor);
+ ASensorManager_destroyEventQueue(sensorManager, queue);
+ return 0;
+ }
+ l = 0;
+ if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) {+ if (ASensorEventQueue_getEvents(queue, &data, 1)) {+ l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z);
+ }
+ }
+ ASensorEventQueue_disableSensor(queue, sensor);
+ ASensorManager_destroyEventQueue(sensorManager, queue);
+
+ return l;
+}
+
static long
androidread(Chan *c, void *v, long n, vlong off)
{char *a = v;
long l;
- const ASensor *sensor;
- ASensorEventQueue *queue = NULL;
- ASensorEvent data;
switch((ulong)c->qid.path & 0xF) {default:
@@ -145,9 +193,14 @@
return -1;
case Qcam:
- while(cambuf == nil)
+ while(camlen == 0)
usleep(10 * 1000);
+ if(camlen < 0) {+ error(Eio);
+ return -1;
+ }
+
l = camlen - off;
if (l > n)
l = n;
@@ -157,51 +210,11 @@
return l;
case Qaccel:
- queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL);
- if (queue == NULL)
- return 0;
- sensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);
- if (sensor == NULL) {- ASensorManager_destroyEventQueue(sensorManager, queue);
- return 0;
- }
- if (ASensorEventQueue_enableSensor(queue, sensor)) {- ASensorEventQueue_disableSensor(queue, sensor);
- ASensorManager_destroyEventQueue(sensorManager, queue);
- return 0;
- }
- l = 0;
- if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) {- if (ASensorEventQueue_getEvents(queue, &data, 1)) {- l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z);
- }
- }
- ASensorEventQueue_disableSensor(queue, sensor);
- ASensorManager_destroyEventQueue(sensorManager, queue);
- return l;
+ return readsensor(a, n, ASENSOR_TYPE_ACCELEROMETER);
case Qcompass:
- queue = ASensorManager_createEventQueue(sensorManager, ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS), 1, NULL, NULL);
- if (queue == NULL)
- return 0;
- sensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_MAGNETIC_FIELD);
- if (sensor == NULL) {- ASensorManager_destroyEventQueue(sensorManager, queue);
- return 0;
- }
- if (ASensorEventQueue_enableSensor(queue, sensor)) {- ASensorEventQueue_disableSensor(queue, sensor);
- ASensorManager_destroyEventQueue(sensorManager, queue);
- return 0;
- }
- l = 0;
- if (ALooper_pollAll(1000, NULL, NULL, NULL) == 1) {- if (ASensorEventQueue_getEvents(queue, &data, 1)) {- l = snprint(a, n, "%11f %11f %11f\n", data.vector.x, data.vector.y, data.vector.z);
- }
- }
- ASensorEventQueue_disableSensor(queue, sensor);
- ASensorManager_destroyEventQueue(sensorManager, queue);
- return l;
+ return readsensor(a, n, ASENSOR_TYPE_MAGNETIC_FIELD);
+ case Qlocation:
+ return getlocation(a, n);
case Qdir:
return devdirread(c, a, n, androiddir, nelem(androiddir) + Ncameras - 1, androidgen);
}
@@ -248,3 +261,4 @@
devremove,
devwstat,
};
+
--- a/gui-android/cpp/native-lib.c
+++ b/gui-android/cpp/native-lib.c
@@ -163,11 +163,15 @@
JNIEnv* env,
jobject obj,
jbyteArray array) {+ if ((*env)->IsSameObject(env, array, NULL)) {+ camlen = -1;
+ return;
+ }
jint len = (*env)->GetArrayLength(env, array);
jbyte *bytes = (*env)->GetByteArrayElements(env, array, NULL);
- camlen = len;
- cambuf = malloc(camlen);
- memcpy(cambuf, bytes, camlen);
+ cambuf = malloc(len);
+ memcpy(cambuf, bytes, len);
(*env)->ReleaseByteArrayElements(env, array, bytes, 0);
+ camlen = len;
}
--- a/gui-android/java/org/echoline/drawterm/MainActivity.java
+++ b/gui-android/java/org/echoline/drawterm/MainActivity.java
@@ -15,6 +15,8 @@
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.SparseIntArray;
+import android.util.Size;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
@@ -34,17 +36,22 @@
import android.content.ClipData;
import android.content.ClipboardManager;
import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.graphics.ImageFormat;
import android.os.Handler;
import android.os.HandlerThread;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
import java.io.File;
import java.util.Map;
@@ -52,6 +59,8 @@
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
public class MainActivity extends Activity {private Map<String, ?> map;
@@ -59,13 +68,80 @@
private boolean dtrunning = false;
private DrawTermThread dthread;
private int notificationId;
- private CameraDevice cameraDevice = null;
private byte []jpegBytes;
+ private String location;
static { System.loadLibrary("drawterm");}
+ private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+
+ static {+ ORIENTATIONS.append(Surface.ROTATION_0, 0);
+ ORIENTATIONS.append(Surface.ROTATION_90, 90);
+ ORIENTATIONS.append(Surface.ROTATION_180, 180);
+ ORIENTATIONS.append(Surface.ROTATION_270, 270);
+ }
+
+ static class CompareSizesByArea implements Comparator<Size> {+ @Override
+ public int compare(Size lhs, Size rhs) {+ return Long.signum((long) lhs.getWidth() * lhs.getHeight() - (long) rhs.getWidth() * rhs.getHeight());
+ }
+ }
+
+
+ private static boolean contains(int[] modes, int mode) {+ if (modes == null) {+ return false;
+ }
+ for (int i : modes) {+ if (i == mode) {+ return true;
+ }
+ }
+ return false;
+ }
+
+ public String getLocation() {+ LocationManager locationManager = ((LocationManager)getSystemService(Context.LOCATION_SERVICE));
+
+ location = "";
+
+ HandlerThread mBackgroundThread = new HandlerThread("Location Background");+ mBackgroundThread.start();
+
+ locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, new LocationListener() {+ @Override
+ public void onLocationChanged(Location l) {+ location = l.getLatitude() + "\t" + l.getLongitude() + "\t" + l.getAltitude();
+ mBackgroundThread.quitSafely();
+ }
+
+ @Override
+ public void onProviderDisabled(String p) {+ mBackgroundThread.quitSafely();
+ }
+
+ @Override
+ public void onProviderEnabled(String p) {+ }
+
+ @Override
+ public void onStatusChanged(String p, int i, Bundle b) {+ }
+ }, mBackgroundThread.getLooper());
+
+ try {+ mBackgroundThread.join();
+ } catch (Exception e) {+ e.printStackTrace();
+ }
+
+ return location;
+ }
+
public void showNotification(String text) {Notification.Builder builder = new Notification.Builder(this)
.setDefaults(Notification.DEFAULT_SOUND)
@@ -81,86 +157,132 @@
public int numCameras() { try {return ((CameraManager)getSystemService(Context.CAMERA_SERVICE)).getCameraIdList().length;
- } catch (CameraAccessException e) {- Log.w("drawterm", e.toString());+ } catch (Exception e) {+ e.printStackTrace();
return 0;
}
}
+ private static int sensorToDeviceRotation(CameraCharacteristics c, int deviceOrientation) {+ int sensorOrientation = c.get(CameraCharacteristics.SENSOR_ORIENTATION);
+
+ deviceOrientation = ORIENTATIONS.get(deviceOrientation);
+
+ if (c.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {+ deviceOrientation = -deviceOrientation;
+ }
+
+ return (sensorOrientation - deviceOrientation + 360) % 360;
+ }
+
public void takePicture(int id) { try {+ jpegBytes = null;
HandlerThread mBackgroundThread = new HandlerThread("Camera Background");mBackgroundThread.start();
Handler mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
CameraManager manager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
String []cameraIdList = manager.getCameraIdList();
+ CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraIdList[id]);
+ StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ Size size = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new CompareSizesByArea());
+ ImageReader reader = ImageReader.newInstance(size.getWidth(), size.getHeight(), ImageFormat.JPEG, 1);
manager.openCamera(cameraIdList[id], new CameraDevice.StateCallback() { public void onOpened(CameraDevice device) {- cameraDevice = device;
- }
- public void onDisconnected(CameraDevice device) {- if (cameraDevice != null)
- cameraDevice.close();
- cameraDevice = null;
- }
- public void onError(CameraDevice device, int error) {- if (cameraDevice != null)
- cameraDevice.close();
- cameraDevice = null;
- }
- }, mBackgroundHandler);
- ImageReader reader = ImageReader.newInstance(640, 480, ImageFormat.JPEG, 1);
- CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
- captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
- captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
- captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
- captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getWindowManager().getDefaultDisplay().getRotation());
- captureBuilder.addTarget(reader.getSurface());
- reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {- public void onImageAvailable(ImageReader reader) {- Image image = null;
try {- image = reader.acquireLatestImage();
- ByteBuffer buffer = image.getPlanes()[0].getBuffer();
- jpegBytes = new byte[buffer.capacity()];
- buffer.get(jpegBytes);
- } catch (Exception e) {- Log.w("drawterm", e.toString());- } finally {- if (image != null) {- image.close();
+ CaptureRequest.Builder captureBuilder = device.createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG);
+ captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
+ Float minFocusDist = characteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+ if (!(minFocusDist == null || minFocusDist == 0)) {+ if (contains(characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES), CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE))
+ captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ else
+ captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
}
- }
- }
- }, mBackgroundHandler);
- List<Surface> outputSurfaces = new ArrayList<Surface>(1);
- outputSurfaces.add(reader.getSurface());
- cameraDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {- public void onConfigured(CameraCaptureSession session) {- try {- List<CaptureRequest> captureRequests = new ArrayList<CaptureRequest>(10);
- for (int i = 0; i < 10; i++)
- captureRequests.add(captureBuilder.build());
- session.captureBurst(captureRequests, new CameraCaptureSession.CaptureCallback() {- public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {+ if (contains(characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES), CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH))
+ captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+ else
+ captureBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
+ if (contains(characteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES), CaptureRequest.CONTROL_AWB_MODE_AUTO))
+ captureBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, sensorToDeviceRotation(characteristics, getWindowManager().getDefaultDisplay().getRotation()));
+ captureBuilder.addTarget(reader.getSurface());
+ reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {+ public void onImageAvailable(ImageReader reader) {+ Image image = null;
try {- sendPicture(jpegBytes);
- mBackgroundThread.quitSafely();
- mBackgroundThread.join();
+ image = reader.acquireLatestImage();
+ ByteBuffer buffer = image.getPlanes()[0].getBuffer();
+ jpegBytes = new byte[buffer.capacity()];
+ buffer.get(jpegBytes);
} catch (Exception e) {- Log.w("drawterm", e.toString());+ e.printStackTrace();
+ } finally {+ if (image != null) {+ image.close();
+ }
}
}
}, mBackgroundHandler);
- } catch (CameraAccessException e) {+ List<Surface> outputSurfaces = new ArrayList<Surface>(1);
+ outputSurfaces.add(reader.getSurface());
+ device.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() {+ public void onConfigured(CameraCaptureSession session) {+ try {+ List<CaptureRequest> captureRequests = new ArrayList<CaptureRequest>(10);
+ for (int i = 0; i < 10; i++)
+ captureRequests.add(captureBuilder.build());
+ session.captureBurst(captureRequests, new CameraCaptureSession.CaptureCallback() {+ public void onCaptureSequenceCompleted(CameraCaptureSession session, int sequenceId, long frameNumber) {+ Log.w("drawterm", "CaptureSession capture sequence completed");+ sendPicture(jpegBytes);
+ device.close();
+ }
+ }, mBackgroundHandler);
+ } catch (Exception e) {+ Log.w("drawterm", "CaptureSession capture failed");+ e.printStackTrace();
+ sendPicture(jpegBytes);
+ }
+ }
+ public void onConfigureFailed(CameraCaptureSession session) {+ Log.w("drawterm", "createCaptureSession configure failed");+ sendPicture(jpegBytes);
+ }
+ }, mBackgroundHandler);
+ } catch (Exception e) {e.printStackTrace();
+ sendPicture(jpegBytes);
}
+ }
+ public void onDisconnected(CameraDevice device) {+ try {+ device.close();
+ } catch (Exception e) {+ e.printStackTrace();
+ }
+ Log.e("drawterm", "openCamera onDisconnected");}
- public void onConfigureFailed(CameraCaptureSession session) {+ public void onError(CameraDevice device, int error) {+ try {+ device.close();
+ } catch (Exception e) {+ e.printStackTrace();
+ }
+ Log.e("drawterm", "openCamera onError " + error);}
+ public void onClosed(CameraDevice device) {+ try {+ mBackgroundThread.quitSafely();
+ mBackgroundThread.join();
+ } catch (Exception e) {+ e.printStackTrace();
+ }
+ }
}, mBackgroundHandler);
} catch (Exception e) {e.printStackTrace();
+ sendPicture(jpegBytes);
}
}
--
⑨