2015-03-02 64 views
0

我正在通過developer.Android教程building a Camera App工作,但我總是遇到以下問題:當我的應用程序被放入後臺,即根據活動生命週期停止,並且我試着回到它崩潰,告訴我應用程序已停止工作。Android簡單的相機控制應用程序從停止返回時崩潰

我搜索了其他問題,但沒有一個似乎有這個問題,或者我無法識別它。

我試圖找出發生此錯誤的最小代碼量。 的(唯一的)活動時間:

public class CameraActivity extends ActionBarActivity { 

private Camera mCamera; 
private CameraPreview mPreview; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_camera_layout); 

    // if device hardware has a camera 
    if (checkCameraHardware(this)) 
     // Create an instance of Camera 
     mCamera = getCameraInstance(); 

    // Create our Preview view and set it as the content of our activity. 
    mPreview = new CameraPreview(this, mCamera); 
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
    preview.addView(mPreview); 


} 

/** Check if this device has a camera */ 
private boolean checkCameraHardware(Context context) { 
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ 
     // this device has a camera 
     return true; 
    } else { 
     // no camera on this device 
     return false; 
    } 
} 

/** A safe way to get an instance of the Camera object. */ 
public static Camera getCameraInstance(){ 
    Camera c = null; 
    try { 
     c = Camera.open(); // attempt to get a Camera instance 
    } 
    catch (Exception e){ 
     // Camera is not available (in use or does not exist) 
    } 
    return c; // returns null if camera is unavailable 
} 

@Override 
public void onPause() { 
    super.onPause(); 
    releaseCamera();    // release the camera immediately on pause event 
} 

private void releaseCamera(){ 
    if (mCamera != null){ 
     mCamera.stopPreview();  // stop the preview 
     mCamera.release();  // release the camera for other applications 
     mCamera = null; 
    } 
} 

@Override 
public void onResume() { 
    super.onResume(); 

    if (mCamera == null) 
     mCamera = getCameraInstance(); 
} 


} 

的CameraPreview使用這個類實例化:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 

public CameraPreview(Context context, Camera camera) { 
    super(context); 
    mCamera = camera; 

    // Install a SurfaceHolder.Callback so we get notified when the 
    // underlying surface is created and destroyed. 
    mHolder = getHolder(); 
    mHolder.addCallback(this); 
    // deprecated setting, but required on Android versions prior to 3.0 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    // The Surface has been created, now tell the camera where to draw the preview. 
    try { 

     mCamera.setPreviewDisplay(holder); 
     mCamera.startPreview(); 

    } catch (IOException e) { 
     Log.d("PandaHero", "Error setting camera preview: " + e.getMessage()); 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    // empty. Take care of releasing the Camera preview in your activity. 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
    // .. same as in the example of the link 
} 
} 

至於錯誤信息,它總是讓我發現,surfaceCreated()被釋放後稱爲()。這讓我覺得我不得不錯過一些重要的相機重新實例或預覽某處。我試圖停止預覽並在surfaceDestroyed(),onStop()內釋放相機,並且在onStart()內重新打開預覽,但錯誤仍然存​​在。 另外,如果我沒有在第一位添加預覽(但是我的用戶無法看到它,所以這是不可選的),則不會發生崩潰。

所以是的,我認爲在利用生命週期方面我缺少一些至關重要的東西。

編輯:我提到的錯誤消息。

03-02 14:33:45.553 15462-15462/com.example.vrevru.viewlate_camerasetupsimple E/AndroidRuntime﹕ FATAL EXCEPTION: main 
java.lang.RuntimeException: Method called after release() 
     at android.hardware.Camera.setPreviewDisplay(Native Method) 
     at android.hardware.Camera.setPreviewDisplay(Camera.java:428) 
     at com.example.thorsten.viewlate_camerasetupsimple.CameraPreview.surfaceCreated(CameraPreview.java:32) 
     at android.view.SurfaceView.updateWindow(SurfaceView.java:639) 
     at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:262) 
     at android.view.View.dispatchWindowVisibilityChanged(View.java:7440) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042) 
     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1237) 
     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1009) 
     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4236) 
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725) 
     at android.view.Choreographer.doCallbacks(Choreographer.java:555) 
     at android.view.Choreographer.doFrame(Choreographer.java:525) 
     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711) 
     at android.os.Handler.handleCallback(Handler.java:615) 
     at android.os.Handler.dispatchMessage(Handler.java:92) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:4872) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:511) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557) 
     at dalvik.system.NativeStart.main(Native Method) 
+0

崩潰日誌? – AAnkit 2015-03-02 14:19:07

+0

對不起,我不太熟悉編程和所有。錯誤日誌是很多文本,我可以用什麼方法來確定顯示的相關內容? – vruvre 2015-03-02 14:35:32

回答

0

好吧,

我想我得到了一個解決方案,但我不知道這是最好的一個。

我注意到,我從來沒有告訴我的應用程序在onPause()中釋放舊的預覽後創建新的預覽。我認爲Android會處理這個問題,因爲文檔中總是聲明不需要重新創建應用程序的第一次創建。顯然,我誤解了他們(儘管他們是什麼意思?)。

因此,我在onPause()中的Framelayout中添加了一箇舊CameraPreview對象的手動刪除,然後創建了一個新對象並將其添加到onResume()中的Framelayout。

@Override 
public void onPause() { 
    super.onPause(); 
    releaseCamera();    // release the camera immediately on pause event 
    // two new lines for removing the old CameraPreview 
    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
    preview.removeView(mPreview); 
} 
@Override 
public void onResume() { 
    super.onResume(); 

    if (mCamera == null) 
    { 
     mCamera = getCameraInstance(); 
     // three new lines, creating a new CameraPreview, then adding it to the FrameLayout 
     mPreview = new CameraPreview(this, mCamera); 
     FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
     preview.addView(mPreview); 
    } 
} 

然而,雖然現在錯誤已經消失了,我的問題就解決了(應用程序不會崩潰了),我只是把一些代碼看似很昂貴的線到我的暫停和恢復功能。過渡到其他應用程序和後退已經明顯減慢。有沒有更聰明的方法來做到這一點?

相關問題