mirror of
https://github.com/zxing/zxing.git
synced 2025-02-02 05:41:08 -08:00
Remove some pre-Eclair code, update camera parameters handling to use 2.x APIs
git-svn-id: https://zxing.googlecode.com/svn/trunk@2038 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
be03860ec9
commit
9e9e5671d9
|
@ -17,14 +17,17 @@
|
|||
package com.google.zxing.client.android.camera;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.Camera;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import com.google.zxing.client.android.PreferencesActivity;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A class which deals with reading, parsing, and setting the camera parameters which are used to
|
||||
|
@ -32,15 +35,12 @@ import java.util.regex.Pattern;
|
|||
*/
|
||||
final class CameraConfigurationManager {
|
||||
|
||||
private static final String TAG = CameraConfigurationManager.class.getSimpleName();
|
||||
private static final int TEN_DESIRED_ZOOM = 27;
|
||||
private static final Pattern COMMA_PATTERN = Pattern.compile(",");
|
||||
private static final String TAG = "CameraConfiguration";
|
||||
private static final int MIN_PREVIEW_PIXELS = 320 * 240; // small screen
|
||||
|
||||
private final Context context;
|
||||
private Point screenResolution;
|
||||
private Point cameraResolution;
|
||||
private int previewFormat;
|
||||
private String previewFormatString;
|
||||
|
||||
CameraConfigurationManager(Context context) {
|
||||
this.context = context;
|
||||
|
@ -51,29 +51,33 @@ final class CameraConfigurationManager {
|
|||
*/
|
||||
void initFromCameraParameters(Camera camera) {
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
previewFormat = parameters.getPreviewFormat();
|
||||
previewFormatString = parameters.get("preview-format");
|
||||
Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
|
||||
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display display = manager.getDefaultDisplay();
|
||||
screenResolution = new Point(display.getWidth(), display.getHeight());
|
||||
Log.d(TAG, "Screen resolution: " + screenResolution);
|
||||
cameraResolution = getCameraResolution(parameters, screenResolution);
|
||||
Log.d(TAG, "Camera resolution: " + cameraResolution);
|
||||
Log.i(TAG, "Screen resolution: " + screenResolution);
|
||||
cameraResolution = findBestPreviewSizeValue(parameters, screenResolution, false);
|
||||
Log.i(TAG, "Camera resolution: " + cameraResolution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the camera up to take preview images which are used for both preview and decoding.
|
||||
* We detect the preview format here so that buildLuminanceSource() can build an appropriate
|
||||
* LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
|
||||
* and the planar Y can be used for barcode scanning without a copy in some cases.
|
||||
*/
|
||||
void setDesiredCameraParameters(Camera camera) {
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
Log.d(TAG, "Setting preview size: " + cameraResolution);
|
||||
|
||||
if (parameters == null) {
|
||||
Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
initializeTorch(parameters, prefs);
|
||||
String focusMode = findSettableValue(parameters.getSupportedFocusModes(),
|
||||
Camera.Parameters.FOCUS_MODE_AUTO,
|
||||
Camera.Parameters.FOCUS_MODE_MACRO);
|
||||
if (focusMode != null) {
|
||||
parameters.setFocusMode(focusMode);
|
||||
}
|
||||
|
||||
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
|
||||
setFlash(parameters);
|
||||
setZoom(parameters);
|
||||
camera.setParameters(parameters);
|
||||
}
|
||||
|
||||
|
@ -85,166 +89,81 @@ final class CameraConfigurationManager {
|
|||
return screenResolution;
|
||||
}
|
||||
|
||||
int getPreviewFormat() {
|
||||
return previewFormat;
|
||||
void setTorch(Camera camera, boolean newSetting) {
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
doSetTorch(parameters, newSetting);
|
||||
camera.setParameters(parameters);
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean currentSetting = prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false);
|
||||
if (currentSetting != newSetting) {
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
editor.putBoolean(PreferencesActivity.KEY_FRONT_LIGHT, newSetting);
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
|
||||
String getPreviewFormatString() {
|
||||
return previewFormatString;
|
||||
private static void initializeTorch(Camera.Parameters parameters, SharedPreferences prefs) {
|
||||
boolean currentSetting = prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false);
|
||||
doSetTorch(parameters, currentSetting);
|
||||
}
|
||||
|
||||
private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
|
||||
String previewSizeValueString = parameters.get("preview-size-values");
|
||||
|
||||
// This string is wrong but was seen on the Sony Xperia.
|
||||
if (previewSizeValueString == null) {
|
||||
previewSizeValueString = parameters.get("preview-size-value");
|
||||
private static void doSetTorch(Camera.Parameters parameters, boolean newSetting) {
|
||||
String flashMode;
|
||||
if (newSetting) {
|
||||
flashMode = findSettableValue(parameters.getSupportedFlashModes(),
|
||||
Camera.Parameters.FLASH_MODE_TORCH,
|
||||
Camera.Parameters.FLASH_MODE_ON);
|
||||
} else {
|
||||
flashMode = findSettableValue(parameters.getSupportedFlashModes(),
|
||||
Camera.Parameters.FLASH_MODE_OFF);
|
||||
}
|
||||
if (flashMode != null) {
|
||||
parameters.setFlashMode(flashMode);
|
||||
}
|
||||
}
|
||||
|
||||
Point cameraResolution = null;
|
||||
if (previewSizeValueString != null) {
|
||||
Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
|
||||
cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
|
||||
}
|
||||
|
||||
if (cameraResolution == null) {
|
||||
// Ensure that the camera resolution is a multiple of 8, as the screen may not be.
|
||||
cameraResolution = new Point((screenResolution.x >> 3) << 3, (screenResolution.y >> 3) << 3);
|
||||
}
|
||||
return cameraResolution;
|
||||
}
|
||||
|
||||
private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString,
|
||||
Point screenResolution) {
|
||||
int bestX = 0;
|
||||
int bestY = 0;
|
||||
private static Point findBestPreviewSizeValue(Camera.Parameters parameters,
|
||||
Point screenResolution,
|
||||
boolean portrait) {
|
||||
Point bestSize = null;
|
||||
int diff = Integer.MAX_VALUE;
|
||||
for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
|
||||
previewSize = previewSize.trim();
|
||||
int dimPosition = previewSize.indexOf('x');
|
||||
if (dimPosition < 0) {
|
||||
Log.w(TAG, "Bad preview-size: " + previewSize);
|
||||
for (Camera.Size supportedPreviewSize : parameters.getSupportedPreviewSizes()) {
|
||||
if (supportedPreviewSize.height * supportedPreviewSize.width < MIN_PREVIEW_PIXELS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int newX;
|
||||
int newY;
|
||||
try {
|
||||
newX = Integer.parseInt(previewSize.substring(0, dimPosition));
|
||||
newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.w(TAG, "Bad preview-size: " + previewSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
|
||||
int supportedWidth = portrait ? supportedPreviewSize.height : supportedPreviewSize.width;
|
||||
int supportedHeight = portrait ? supportedPreviewSize.width : supportedPreviewSize.height;
|
||||
int newDiff = Math.abs(screenResolution.x * supportedHeight - supportedWidth * screenResolution.y);
|
||||
if (newDiff == 0) {
|
||||
bestX = newX;
|
||||
bestY = newY;
|
||||
bestSize = new Point(supportedWidth, supportedHeight);
|
||||
break;
|
||||
} else if (newDiff < diff) {
|
||||
bestX = newX;
|
||||
bestY = newY;
|
||||
}
|
||||
if (newDiff < diff) {
|
||||
bestSize = new Point(supportedWidth, supportedHeight);
|
||||
diff = newDiff;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestX > 0 && bestY > 0) {
|
||||
return new Point(bestX, bestY);
|
||||
if (bestSize == null) {
|
||||
Camera.Size defaultSize = parameters.getPreviewSize();
|
||||
bestSize = new Point(defaultSize.width, defaultSize.height);
|
||||
}
|
||||
return null;
|
||||
return bestSize;
|
||||
}
|
||||
|
||||
private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
|
||||
int tenBestValue = 0;
|
||||
for (String stringValue : COMMA_PATTERN.split(stringValues)) {
|
||||
stringValue = stringValue.trim();
|
||||
double value;
|
||||
try {
|
||||
value = Double.parseDouble(stringValue);
|
||||
} catch (NumberFormatException nfe) {
|
||||
return tenDesiredZoom;
|
||||
}
|
||||
int tenValue = (int) (10.0 * value);
|
||||
if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
|
||||
tenBestValue = tenValue;
|
||||
private static String findSettableValue(Collection<String> supportedValues,
|
||||
String... desiredValues) {
|
||||
Log.i(TAG, "Supported values: " + supportedValues);
|
||||
String result = null;
|
||||
if (supportedValues != null) {
|
||||
for (String desiredValue : desiredValues) {
|
||||
if (supportedValues.contains(desiredValue)) {
|
||||
result = desiredValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return tenBestValue;
|
||||
}
|
||||
|
||||
private void setFlash(Camera.Parameters parameters) {
|
||||
// This is a hack to turn the flash off on the Samsung Galaxy and the Behold II
|
||||
// as advised by Samsung, neither of which respected the official parameter.
|
||||
if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
|
||||
parameters.set("flash-value", 1);
|
||||
} else {
|
||||
parameters.set("flash-value", 2);
|
||||
}
|
||||
// This is the standard setting to turn the flash off that all devices should honor.
|
||||
parameters.set("flash-mode", "off");
|
||||
}
|
||||
|
||||
private void setZoom(Camera.Parameters parameters) {
|
||||
String zoomSupportedString = parameters.get("zoom-supported");
|
||||
if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int tenDesiredZoom = TEN_DESIRED_ZOOM;
|
||||
String maxZoomString = parameters.get("max-zoom");
|
||||
if (maxZoomString != null) {
|
||||
try {
|
||||
int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
|
||||
if (tenDesiredZoom > tenMaxZoom) {
|
||||
tenDesiredZoom = tenMaxZoom;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.w(TAG, "Bad max-zoom: " + maxZoomString);
|
||||
}
|
||||
}
|
||||
|
||||
String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
|
||||
if (takingPictureZoomMaxString != null) {
|
||||
try {
|
||||
int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
|
||||
if (tenDesiredZoom > tenMaxZoom) {
|
||||
tenDesiredZoom = tenMaxZoom;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
|
||||
}
|
||||
}
|
||||
|
||||
String motZoomValuesString = parameters.get("mot-zoom-values");
|
||||
if (motZoomValuesString != null) {
|
||||
tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
|
||||
}
|
||||
|
||||
String motZoomStepString = parameters.get("mot-zoom-step");
|
||||
if (motZoomStepString != null) {
|
||||
try {
|
||||
double motZoomStep = Double.parseDouble(motZoomStepString.trim());
|
||||
int tenZoomStep = (int) (10.0 * motZoomStep);
|
||||
if (tenZoomStep > 1) {
|
||||
tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the zoom which helps encourage the user to pull back.
|
||||
// Some devices like the Behold have a zoom parameter.
|
||||
if (maxZoomString != null || motZoomValuesString != null) {
|
||||
parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
|
||||
}
|
||||
|
||||
// Most devices, like the Hero, appear to expose this zoom parameter.
|
||||
// It takes on values like "27" which appears to mean 2.7x zoom.
|
||||
if (takingPictureZoomMaxString != null) {
|
||||
parameters.set("taking-picture-zoom", tenDesiredZoom);
|
||||
}
|
||||
Log.i(TAG, "Settable value: " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,11 +18,9 @@ package com.google.zxing.client.android.camera;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.Camera;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
@ -48,18 +46,6 @@ public final class CameraManager {
|
|||
private static final int MAX_FRAME_WIDTH = 600;
|
||||
private static final int MAX_FRAME_HEIGHT = 400;
|
||||
|
||||
static final int SDK_INT; // Later we can use Build.VERSION.SDK_INT
|
||||
static {
|
||||
int sdkInt;
|
||||
try {
|
||||
sdkInt = Integer.parseInt(Build.VERSION.SDK);
|
||||
} catch (NumberFormatException nfe) {
|
||||
// Just to be safe
|
||||
sdkInt = 10000;
|
||||
}
|
||||
SDK_INT = sdkInt;
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
private final CameraConfigurationManager configManager;
|
||||
private Camera camera;
|
||||
|
@ -68,7 +54,6 @@ public final class CameraManager {
|
|||
private boolean initialized;
|
||||
private boolean previewing;
|
||||
private boolean reverseImage;
|
||||
private final boolean useOneShotPreviewCallback;
|
||||
private int requestedFramingRectWidth;
|
||||
private int requestedFramingRectHeight;
|
||||
/**
|
||||
|
@ -76,22 +61,13 @@ public final class CameraManager {
|
|||
* clear the handler so it will only receive one message.
|
||||
*/
|
||||
private final PreviewCallback previewCallback;
|
||||
|
||||
/** Autofocus callbacks arrive here, and are dispatched to the Handler which requested them. */
|
||||
private final AutoFocusCallback autoFocusCallback;
|
||||
|
||||
public CameraManager(Context context) {
|
||||
|
||||
this.context = context;
|
||||
this.configManager = new CameraConfigurationManager(context);
|
||||
|
||||
// Camera.setOneShotPreviewCallback() has a race condition in Cupcake, so we use the older
|
||||
// Camera.setPreviewCallback() on 1.5 and earlier. For Donut and later, we need to use
|
||||
// the more efficient one shot callback, as the older one can swamp the system and cause it
|
||||
// to run out of memory. We can't use SDK_INT because it was introduced in the Donut SDK.
|
||||
useOneShotPreviewCallback = Integer.parseInt(Build.VERSION.SDK) > 3; // 3 = Cupcake
|
||||
|
||||
previewCallback = new PreviewCallback(configManager, useOneShotPreviewCallback);
|
||||
previewCallback = new PreviewCallback(configManager);
|
||||
autoFocusCallback = new AutoFocusCallback();
|
||||
}
|
||||
|
||||
|
@ -125,9 +101,6 @@ public final class CameraManager {
|
|||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
reverseImage = prefs.getBoolean(PreferencesActivity.KEY_REVERSE_IMAGE, false);
|
||||
if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
|
||||
FlashlightManager.enableFlashlight();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,10 +108,8 @@ public final class CameraManager {
|
|||
*/
|
||||
public void closeDriver() {
|
||||
if (camera != null) {
|
||||
FlashlightManager.disableFlashlight();
|
||||
camera.release();
|
||||
camera = null;
|
||||
|
||||
// Make sure to clear these each time we close the camera, so that any scanning rect
|
||||
// requested by intent is forgotten.
|
||||
framingRect = null;
|
||||
|
@ -162,9 +133,6 @@ public final class CameraManager {
|
|||
*/
|
||||
public void stopPreview() {
|
||||
if (camera != null && previewing) {
|
||||
if (!useOneShotPreviewCallback) {
|
||||
camera.setPreviewCallback(null);
|
||||
}
|
||||
camera.stopPreview();
|
||||
previewCallback.setHandler(null, 0);
|
||||
autoFocusCallback.setHandler(null, 0);
|
||||
|
@ -184,11 +152,7 @@ public final class CameraManager {
|
|||
Camera theCamera = camera;
|
||||
if (theCamera != null && previewing) {
|
||||
previewCallback.setHandler(handler, message);
|
||||
if (useOneShotPreviewCallback) {
|
||||
theCamera.setOneShotPreviewCallback(previewCallback);
|
||||
} else {
|
||||
theCamera.setPreviewCallback(previewCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +165,6 @@ public final class CameraManager {
|
|||
public void requestAutoFocus(Handler handler, int message) {
|
||||
if (camera != null && previewing) {
|
||||
autoFocusCallback.setHandler(handler, message);
|
||||
//Log.d(TAG, "Requesting auto-focus callback");
|
||||
camera.autoFocus(autoFocusCallback);
|
||||
}
|
||||
}
|
||||
|
@ -302,28 +265,9 @@ public final class CameraManager {
|
|||
if (rect == null) {
|
||||
return null;
|
||||
}
|
||||
int previewFormat = configManager.getPreviewFormat();
|
||||
String previewFormatString = configManager.getPreviewFormatString();
|
||||
|
||||
switch (previewFormat) {
|
||||
// This is the standard Android format which all devices are REQUIRED to support.
|
||||
// In theory, it's the only one we should ever care about.
|
||||
case PixelFormat.YCbCr_420_SP:
|
||||
// This format has never been seen in the wild, but is compatible as we only care
|
||||
// about the Y channel, so allow it.
|
||||
case PixelFormat.YCbCr_422_SP:
|
||||
// Go ahead and assume it's YUV rather than die.
|
||||
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
|
||||
rect.width(), rect.height(), reverseImage);
|
||||
default:
|
||||
// The Samsung Moment incorrectly uses this variant instead of the 'sp' version.
|
||||
// Fortunately, it too has all the Y data up front, so we can read it.
|
||||
if ("yuv420p".equals(previewFormatString)) {
|
||||
return new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
|
||||
rect.width(), rect.height(), reverseImage);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported picture format: " +
|
||||
previewFormat + '/' + previewFormatString);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,141 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.client.android.camera;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* This class is used to activate the weak light on some camera phones (not flash)
|
||||
* in order to illuminate surfaces for scanning. There is no official way to do this,
|
||||
* but, classes which allow access to this function still exist on some devices.
|
||||
* This therefore proceeds through a great deal of reflection.
|
||||
*
|
||||
* See http://almondmendoza.com/2009/01/05/changing-the-screen-brightness-programatically/ and
|
||||
* http://code.google.com/p/droidled/source/browse/trunk/src/com/droidled/demo/DroidLED.java .
|
||||
* Thanks to Ryan Alford for pointing out the availability of this class.
|
||||
*/
|
||||
final class FlashlightManager {
|
||||
|
||||
private static final String TAG = FlashlightManager.class.getSimpleName();
|
||||
|
||||
private static final Object iHardwareService;
|
||||
private static final Method setFlashEnabledMethod;
|
||||
static {
|
||||
iHardwareService = getHardwareService();
|
||||
Log.v(TAG, "This device does " + (iHardwareService == null ? "not" : "") + " support control of a flashlight");
|
||||
setFlashEnabledMethod = getSetFlashEnabledMethod(iHardwareService);
|
||||
}
|
||||
|
||||
private FlashlightManager() {
|
||||
}
|
||||
|
||||
private static Object getHardwareService() {
|
||||
Class<?> serviceManagerClass = maybeForName("android.os.ServiceManager");
|
||||
if (serviceManagerClass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method getServiceMethod = maybeGetMethod(serviceManagerClass, "getService", String.class);
|
||||
if (getServiceMethod == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object hardwareService = invoke(getServiceMethod, null, "hardware");
|
||||
if (hardwareService == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> iHardwareServiceStubClass = maybeForName("android.os.IHardwareService$Stub");
|
||||
if (iHardwareServiceStubClass == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method asInterfaceMethod = maybeGetMethod(iHardwareServiceStubClass, "asInterface",
|
||||
IBinder.class);
|
||||
if (asInterfaceMethod == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return invoke(asInterfaceMethod, null, hardwareService);
|
||||
}
|
||||
|
||||
private static Method getSetFlashEnabledMethod(Object iHardwareService) {
|
||||
if (iHardwareService == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?> proxyClass = iHardwareService.getClass();
|
||||
return maybeGetMethod(proxyClass, "setFlashlightEnabled", boolean.class);
|
||||
}
|
||||
|
||||
private static Class<?> maybeForName(String name) {
|
||||
try {
|
||||
return Class.forName(name);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
// OK
|
||||
return null;
|
||||
} catch (RuntimeException re) {
|
||||
Log.w(TAG, "Unexpected error while finding class " + name, re);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Method maybeGetMethod(Class<?> clazz, String name, Class<?>... argClasses) {
|
||||
try {
|
||||
return clazz.getMethod(name, argClasses);
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
// OK
|
||||
return null;
|
||||
} catch (RuntimeException re) {
|
||||
Log.w(TAG, "Unexpected error while finding method " + name, re);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Object invoke(Method method, Object instance, Object... args) {
|
||||
try {
|
||||
return method.invoke(instance, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.w(TAG, "Unexpected error while invoking " + method, e);
|
||||
return null;
|
||||
} catch (InvocationTargetException e) {
|
||||
Log.w(TAG, "Unexpected error while invoking " + method, e.getCause());
|
||||
return null;
|
||||
} catch (RuntimeException re) {
|
||||
Log.w(TAG, "Unexpected error while invoking " + method, re);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static void enableFlashlight() {
|
||||
setFlashlight(true);
|
||||
}
|
||||
|
||||
static void disableFlashlight() {
|
||||
setFlashlight(false);
|
||||
}
|
||||
|
||||
private static void setFlashlight(boolean active) {
|
||||
if (iHardwareService != null) {
|
||||
invoke(setFlashEnabledMethod, iHardwareService, active);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -27,13 +27,11 @@ final class PreviewCallback implements Camera.PreviewCallback {
|
|||
private static final String TAG = PreviewCallback.class.getSimpleName();
|
||||
|
||||
private final CameraConfigurationManager configManager;
|
||||
private final boolean useOneShotPreviewCallback;
|
||||
private Handler previewHandler;
|
||||
private int previewMessage;
|
||||
|
||||
PreviewCallback(CameraConfigurationManager configManager, boolean useOneShotPreviewCallback) {
|
||||
PreviewCallback(CameraConfigurationManager configManager) {
|
||||
this.configManager = configManager;
|
||||
this.useOneShotPreviewCallback = useOneShotPreviewCallback;
|
||||
}
|
||||
|
||||
void setHandler(Handler previewHandler, int previewMessage) {
|
||||
|
@ -44,9 +42,6 @@ final class PreviewCallback implements Camera.PreviewCallback {
|
|||
@Override
|
||||
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||
Point cameraResolution = configManager.getCameraResolution();
|
||||
if (!useOneShotPreviewCallback) {
|
||||
camera.setPreviewCallback(null);
|
||||
}
|
||||
Handler thePreviewHandler = previewHandler;
|
||||
if (thePreviewHandler != null) {
|
||||
Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
|
||||
|
|
Loading…
Reference in a new issue