我在 Android 上使用 Mezzofanti OSR 开源,但我被卡住了。当我在应用程序中按下相机按钮时,应用程序突然崩溃。这是 CameraManeger.java 代码:
package com.itwizard.mezzofanti;
import java.io.IOException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.WindowManager;
final class CameraManager {
private static final String TAG = "MLOG: CameraManager.java: ";
private static byte m_cImgDivisor = 2; // given the limited memory space, we
// cannot allocate memory for all
// the image
// thus we lower a bit the
// resolution by a factor of 2/4
private static CameraManager m_CameraManager; // the camera manager itself
private Camera m_Camera; // the camera
private final Context m_Context; // screen context
private Point m_ptScreenResolution; // the screen resolution
private Rect m_FramingRect; // the framing rectangle
private boolean m_bInitialized; // is the driver initialized
private boolean m_bPreviewing; // is camera in preview mode
private Handler m_ParentMessageHandler; // the parent's message handler
private SurfaceHolder m_ParentSurfaceHolder = null; // the parent's surface
// holder
/**
* called when jpeg-image ready, just send to the parent handler the whole
* image to be processed
*/
Camera.PictureCallback m_PictureCallbackJPG = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
Log.i(TAG, "pcjpg - started");
Mezzofanti.CompareTime(TAG + "just started picture callback");
if (data == null) {
Log.i(TAG, "data is null");
} else {
Message message = m_ParentMessageHandler.obtainMessage(
R.id.cameramanager_requestpicture, data);
message.sendToTarget();
m_ParentMessageHandler = null;
Log.i(TAG, "pcjpg - finish");
m_Camera.startPreview();
Mezzofanti.CompareTime(TAG + "just sent picture to handler");
}
}
};
/**
* save the parent handler, in order to process the image-request
*/
public void RequestPicture(Handler handler) {
if (m_Camera != null && m_bPreviewing) {
m_ParentMessageHandler = handler;
}
}
/**
* called on autofocus
*/
private Camera.AutoFocusCallback m_AutoFocusCallback = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
if (success) {
Log.v(TAG, " Focus succeded.");
m_ParentMessageHandler
.sendEmptyMessage(R.id.cameramanager_focus_succeded);
} else {
Log.v(TAG, " Focus failed.");
m_ParentMessageHandler
.sendEmptyMessage(R.id.cameramanager_focus_failed);
}
}
};
/**
* Save the parent message handler.
*
* @param handler
* parent message handler
*/
public void RequestCameraFocus(Handler handler) {
if (m_Camera != null && m_bPreviewing)
m_ParentMessageHandler = handler;
}
/**
* Allocate the camera manager
*/
public static void Initialize(Context context) {
if (m_CameraManager == null) {
m_CameraManager = new CameraManager(context);
}
}
/**
* set the local image divisor
*/
public static void SetImgDivisor(int imgDivisor) {
if (imgDivisor != 1 && imgDivisor != 2 && imgDivisor != 4)
m_cImgDivisor = (byte) 2;
else
m_cImgDivisor = (byte) imgDivisor;
}
/**
* Retrieve the private camera manager
*/
public static CameraManager get() {
return m_CameraManager;
}
/**
* constructor
*/
private CameraManager(Context context) {
m_Context = context;
GetScreenResolution();
m_Camera = null;
m_bInitialized = false;
m_bPreviewing = false;
}
/**
* set the parent surface holder
*/
public void SetSurfaceHolder(SurfaceHolder holder) {
m_ParentSurfaceHolder = holder;
}
/**
* open the camera driver, using the saved parent-surface-holder
*
* @return a boolean variable indicating if the open-driver procedure
* succeeded
*/
public boolean OpenDriver() {
if (m_ParentSurfaceHolder == null)
return false;
if (m_Camera == null) {
m_Camera = Camera.open();
try {
m_Camera.setPreviewDisplay(m_ParentSurfaceHolder);
} catch (IOException e) {
Log.v(TAG, e.toString());
return false;
}
if (!m_bInitialized) {
m_bInitialized = true;
GetScreenResolution();
}
SetCameraParameters();
}
return true;
}
/**
* open camera driver using a parameter surface-holder
*
* @return a boolean variable indicating if the open-driver procedure
* succeeded
*/
public void OpenDriver(SurfaceHolder holder) {
if (m_Camera == null) {
m_Camera = Camera.open();
try {
m_Camera.setPreviewDisplay(holder);
} catch (IOException e) {
m_Camera.release();
m_Camera = null;
Log.v(TAG, e.toString());
}
if (!m_bInitialized) {
m_bInitialized = true;
GetScreenResolution();
}
SetCameraParameters();
}
}
/**
* close the camera driver
*/
public void CloseDriver() {
if (m_Camera != null) {
m_Camera.release();
m_Camera = null;
m_ParentSurfaceHolder = null;
}
}
/**
* start camera preview mode
*/
public void StartPreview() {
if (m_Camera != null && !m_bPreviewing) {
m_Camera.startPreview();
m_bPreviewing = true;
}
}
/**
* stop camera preview mode
*/
public void StopPreview() {
if (m_Camera != null && m_bPreviewing) {
m_Camera.setPreviewCallback(null);
m_Camera.stopPreview();
m_bPreviewing = false;
}
}
/**
* set the camera auto-focus callback
*/
public void RequestAutoFocus() {
if (m_Camera != null && m_bPreviewing) {
m_Camera.autoFocus(m_AutoFocusCallback);
}
}
/**
* Calculates the framing rect which the UI should draw to show the user
* where to place the text. The actual captured image should be a bit larger
* than indicated because they might frame the shot too tightly. This target
* helps with alignment as well as forces the user to hold the device far
* enough away to ensure the image will be in focus.
*
* @return The rectangle to draw on screen in window coordinates.
*/
public Rect GetFramingRect(boolean linemode) {
int border = 10;
if (linemode)
m_FramingRect = new Rect(m_ptScreenResolution.x / 4,
m_ptScreenResolution.y / 2 - 20,
m_ptScreenResolution.x * 3 / 4,
m_ptScreenResolution.y / 2 + 20);
else
m_FramingRect = new Rect(border, border, m_ptScreenResolution.x
- border, m_ptScreenResolution.y - border - 30);
return m_FramingRect;
}
/**
* take a picture, and set the jpg callback
*/
public void GetPicture() {
m_Camera.takePicture(null, null, m_PictureCallbackJPG);
}
/**
* Sets the camera up to take preview images which are used for both preview
* and decoding.
*/
public void SetCameraParameters() {
if (m_ptScreenResolution == null)
return;
Camera.Parameters parameters = m_Camera.getParameters();
parameters.setPreviewSize(m_ptScreenResolution.x,
m_ptScreenResolution.y);
parameters.setPictureSize(2048 / m_cImgDivisor, 1536 / m_cImgDivisor);
m_Camera.setParameters(parameters);
Log.v(TAG, parameters.flatten());
}
/**
* @return the screen resolution
*/
private Point GetScreenResolution() {
if (m_ptScreenResolution == null) {
WindowManager manager = (WindowManager) m_Context
.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
m_ptScreenResolution = new Point(display.getWidth(),
display.getHeight());
}
return m_ptScreenResolution;
}
}
这是日志猫:
10-09 20:19:23.551: V/MLOG: Mezzofonti.java:(11728): Call startCamera.
10-09 20:19:23.576: V/MLOG: Mezzofonti.java:(11728): InitCamera: start
10-09 20:19:23.576: V/MLOG: Mezzofonti.java:(11728): InitCamera: OpenDriver
10-09 20:19:23.806: V/MLOG: CameraManager.java:(11728): preferred-preview-size-for-video=640x480;zoom=0;max-num-detected-faces-hw=0;zoom-supported=true;whitebalance=auto;scene-mode=auto;jpeg-quality=100;preview-format-values=yuv420sp,yuv420p,yuv422i-yuyv,yuv422sp,rgb565;jpeg-thumbnail-quality=100;preview-format=yuv420sp;video-size-values=720x480,176x144,320x240,352x288,640x480,1280x720,1920x1080;preview-size=800x480;focal-length=4.030000;flash-mode-values=off,auto,on,torch;preview-frame-rate-values=30,25,20,15,10,7;preview-frame-rate=30;focus-mode-values=auto,infinity,macro,fixed,facedetect,continuous-video;jpeg-thumbnail-width=320;video-size=720x480;scene-mode-values=auto,portrait,landscape,night,beach,snow,sunset,fireworks,sports,party,candlelight,dusk-dawn,fall-color,back-light,text;preview-fps-range-values=(7000,30000);jpeg-thumbnail-size-values=320x240,400x240,0x0;zoom-ratios=100,102,104,109,111,113,119,121,124,131,134,138,146,150,155,159,165,170,182,189,200,213,222,232,243,255,283,300,319,364,400;preview-size-values=640x480,720x480,800x480,800x450,352x288,320x240,176x144;picture-size-values=3264x2448,3264x1968,2048x1536,2048x1232,800x480,640x480;preview-fps-range=7000,30000;auto-whitebalance-lock=false;min-exposure-compensation=-4;max-num-focus-areas=1;vertical-view-angle=47.1;horizontal-view-angle=60.5;jpeg-thumbnail-height=240;smooth-zoom-supported=false;focus-mode=auto;video-frame-format=yuv420sp;max-num-detected-faces-sw=3;picture-format-values=jpeg;max-exposure-compensation=4;focus-areas=(0,0,0,0,0);exposure-compensation=0;exposure-compensation-step=0.5;flash-mode=off;auto-exposure-lock=false;effect-values=none,mono,negative,sepia,aqua;picture-size=1024x768;max-zoom=30;effect=none;whitebalance-values=auto,incandescent,fluorescent,daylight,cloudy-daylight;picture-format=jpeg;focus-distances=0.15,1.20,Infinity
10-09 20:19:23.811: V/MLOG: Mezzofonti.java:(11728): InitCamera: StartPreview
10-09 20:19:24.116: V/MLOG: Mezzofonti.java:(11728): InitCamera: end
10-09 20:19:24.121: V/MLOG: Mezzofonti.java:(11728): InitCamera: start
10-09 20:19:24.121: V/MLOG: Mezzofonti.java:(11728): InitCamera: OpenDriver
10-09 20:19:24.121: V/MLOG: Mezzofonti.java:(11728): InitCamera: StartPreview
10-09 20:19:24.121: V/MLOG: Mezzofonti.java:(11728): InitCamera: end
10-09 20:19:32.771: V/MLOG: Mezzofonti.java:(11728): CameraButton OnClick
10-09 20:19:32.771: D/AndroidRuntime(11728): Shutting down VM
10-09 20:19:32.771: W/dalvikvm(11728): threadid=1: thread exiting with uncaught exception (group=0x40c5f1f8)
10-09 20:19:32.781: E/AndroidRuntime(11728): FATAL EXCEPTION: main
10-09 20:19:32.781: E/AndroidRuntime(11728): java.lang.NullPointerException
10-09 20:19:32.781: E/AndroidRuntime(11728): at com.itwizard.mezzofanti.Mezzofanti.RequestCameraFocus(Mezzofanti.java:544)
10-09 20:19:32.781: E/AndroidRuntime(11728): at com.itwizard.mezzofanti.Mezzofanti.access$22(Mezzofanti.java:542)
10-09 20:19:32.781: E/AndroidRuntime(11728): at com.itwizard.mezzofanti.Mezzofanti$4.onClick(Mezzofanti.java:177)
10-09 20:19:32.781: E/AndroidRuntime(11728): at android.view.View.performClick(View.java:3591)
10-09 20:19:32.781: E/AndroidRuntime(11728): at android.view.View$PerformClick.run(View.java:14263)
10-09 20:19:32.781: E/AndroidRuntime(11728): at android.os.Handler.handleCallback(Handler.java:605)
10-09 20:19:32.781: E/AndroidRuntime(11728): at android.os.Handler.dispatchMessage(Handler.java:92)
10-09 20:19:32.781: E/AndroidRuntime(11728): at android.os.Looper.loop(Looper.java:137)
10-09 20:19:32.781: E/AndroidRuntime(11728): at android.app.ActivityThread.main(ActivityThread.java:4507)
10-09 20:19:32.781: E/AndroidRuntime(11728): at java.lang.reflect.Method.invokeNative(Native Method)
10-09 20:19:32.781: E/AndroidRuntime(11728): at java.lang.reflect.Method.invoke(Method.java:511)
10-09 20:19:32.781: E/AndroidRuntime(11728): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
10-09 20:19:32.781: E/AndroidRuntime(11728): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
10-09 20:19:32.781: E/AndroidRuntime(11728): at dalvik.system.NativeStart.main(Native Method)
10-09 20:22:25.481: D/dalvikvm(11728): GC_CONCURRENT freed 82K, 3% free 10105K/10311K, paused 7ms+8ms
10-09 20:22:28.836: I/Process(11728): Sending signal. PID: 11728 SIG: 9