2013-11-27 54 views
0

我想知道是否有人試圖使用標準Android Camera API(http://developer.android.com/guide/topics/media/camera.html)在應用程序中控制相機。使用Glass GDK和Android Camera API時出現消息「Camera has stopped」

我能夠使用startActivityForResult()方法讓我的應用程序工作,但對從文件系統獲取圖像需要多長時間有點失望,所以我想嘗試其他路線,使用CameraPreview。

我建立了基於Android相機API例如一些代碼,它建立並運行良好,但經過surfaceChanged執行我得到在屏幕上顯示「相機已停止。」

稍後編輯 - 我將相機活動移到了它自己的項目中,現在它可以工作,但它可以預覽擾碼。但拍完照後顯示很好。下面是佈局代碼:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="horizontal" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
    <FrameLayout 
    android:id="@+id/camera_preview" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_weight="1" 
    /> 
</LinearLayout> 

這裏是活動來源:

package com.example.cameratest; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

import com.google.android.glass.touchpad.Gesture; 
import com.google.android.glass.touchpad.GestureDetector; 

import android.net.Uri; 
import android.os.Bundle; 
import android.os.Environment; 
import android.provider.MediaStore.Files.FileColumns; 
import android.app.Activity; 
import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.PictureCallback; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.WindowManager; 
import android.widget.FrameLayout; 

public class MainActivity extends Activity { 

private static final String TAG = MainActivity.class.getSimpleName(); 

private GestureDetector mGestureDetector; 

private Camera mCamera; 
private CameraPreview mPreview; 

private static boolean gotCamera = false; 

private PictureCallback mPicture = new PictureCallback() { 
    @Override 
    public void onPictureTaken(byte[] data, Camera camera) { 
     File pictureFile = getOutputMediaFile(FileColumns.MEDIA_TYPE_IMAGE); 
     if (pictureFile == null){ 
      Log.d(TAG, "Error creating media file, check storage permissions"); 
      return; 
     } 
     try { 
      FileOutputStream fos = new FileOutputStream(pictureFile); 
      fos.write(data); 
      fos.close(); 
     } catch (FileNotFoundException e) { 
      Log.d(TAG, "File not found: " + e.getMessage()); 
     } catch (IOException e) { 
      Log.d(TAG, "Error accessing file: " + e.getMessage()); 
     } 
    } 
}; 

/** Create a file Uri for saving an image or video */ 
private static Uri getOutputMediaFileUri(int type){ 
    return Uri.fromFile(getOutputMediaFile(type)); 
} 

/** Create a File for saving an image or video */ 
private static File getOutputMediaFile(int type){ 
    // To be safe, you should check that the SDCard is mounted 
    // using Environment.getExternalStorageState() before doing this. 

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
       Environment.DIRECTORY_PICTURES), "MyCameraApp"); 
    // This location works best if you want the created images to be shared 
    // between applications and persist after your app has been uninstalled. 

    // Create the storage directory if it does not exist 
    if (! mediaStorageDir.exists()){ 
     if (! mediaStorageDir.mkdirs()){ 
      Log.d("MyCameraApp", "failed to create directory"); 
      return null; 
     } 
    } 

    // Create a media file name 
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    File mediaFile; 
    if (type == FileColumns.MEDIA_TYPE_IMAGE){ 
     mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
       "IMG_"+ timeStamp + ".jpg"); 
    } else if(type == FileColumns.MEDIA_TYPE_VIDEO) { 
     mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
       "VID_"+ timeStamp + ".mp4"); 
    } else { 
     return null; 
    } 

    return mediaFile; 
} 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

    mGestureDetector = createGestureDetector(this); 

    setContentView(R.layout.activity_main); 

    // Create an instance of Camera 
    mCamera = getCameraInstance(); 

    if (gotCamera) { 
     // Create our Preview view and set it as the content of our activity. 
     Log.v(TAG,"We got the camera"); 
     mPreview = new CameraPreview(this, mCamera); 
     FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
     preview.addView(mPreview); 
    } 
    else { 
     finish(); 
    } 


} 

private static Camera getCameraInstance(){ 
    gotCamera = false; 
    Camera c = null; 
    try { 
     c = Camera.open(); // attempt to get a Camera instance 
     gotCamera = true; 
    } 
    catch (Exception e){ 
     // Camera is not available (in use or does not exist) 
     Log.v(TAG,"Camera is not available!"); 
    } 
    return c; // returns null if camera is unavailable 
} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.main, menu); 
    return true; 
} 

/* 
* Send generic motion events to the gesture detector 
*/ 
@Override 
public boolean onGenericMotionEvent(MotionEvent event) { 
    if (mGestureDetector != null) { 
     return mGestureDetector.onMotionEvent(event); 
    } 
    return false; 
} 

private GestureDetector createGestureDetector(Context context) { 
    GestureDetector gestureDetector = new GestureDetector(context); 
     //Create a base listener for generic gestures 
     gestureDetector.setBaseListener(new GestureDetector.BaseListener() { 
      @Override 
      public boolean onGesture(Gesture gesture) { 
       if (gesture == Gesture.TAP) { 
        // do something on tap 
        Log.v(TAG,"tap"); 

        // take a picture 
        takePic(); 

        return true; 
       } else if (gesture == Gesture.TWO_TAP) { 
        // do something on two finger tap 
        return true; 
       } else if (gesture == Gesture.SWIPE_RIGHT) { 
        // do something on right (forward) swipe 
        return true; 
       } else if (gesture == Gesture.SWIPE_LEFT) { 
        // do something on left (backwards) swipe 
        return true; 
       } 
       return false; 
      } 
     }); 
     gestureDetector.setFingerListener(new GestureDetector.FingerListener() { 
      @Override 
      public void onFingerCountChanged(int previousCount, int currentCount) { 
       // do something on finger count changes 
      } 
     }); 
     gestureDetector.setScrollListener(new GestureDetector.ScrollListener() { 
      @Override 
      public boolean onScroll(float displacement, float delta, float velocity) { 
       // do something on scrolling 
       return false; 
      } 
     }); 
     return gestureDetector; 
    } 

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

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

     Log.v(TAG,"In CameraPreview"); 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 

     Log.v(TAG,"Got holder"); 

     mHolder.addCallback(this); 

     Log.v(TAG,"Added callback"); 

     // 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 { 
      Log.v(TAG,"in surface created"); 
      mCamera.setPreviewDisplay(holder); 
      Log.v(TAG,"set preview display"); 
      mCamera.startPreview(); 
      Log.v(TAG,"preview started"); 
     } catch (IOException e) { 
      Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // empty. Take care of releasing the Camera preview in your activity. 
     mCamera.stopPreview(); 
     mCamera.release(); 
     mCamera = null; 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 

     Log.v(TAG,"in surface changted"); 

     if (mHolder.getSurface() == null){ 
      // preview surface does not exist 
      Log.v(TAG,"surface don't exist"); 
      return; 
     } 

     // stop preview before making changes 
     try { 
      mCamera.stopPreview(); 
      Log.v(TAG,"stopped preview"); 
     } catch (Exception e){ 
      // ignore: tried to stop a non-existent preview 
      Log.v(TAG,"preview e"); 
     } 

     // start preview with new settings 
     try { 
      Log.v(TAG,"startpreview"); 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

     } catch (Exception e){ 
      Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
     } 
    } 
} 

public void takePic() { 
    // get an image from the camera 
    mCamera.takePicture(null, null, mPicture); 
} 

} 

回答

3

你有surfaceChanged的代碼看起來不錯,類似於我在我的工作玻璃的應用程序。你有沒有檢查傳遞給Camera.setParameters的相機參數,如預覽尺寸和對焦模式?如果您可以將完整的活動來源發佈在有助於發現問題的問題中。

+0

謝謝。不,我沒有設置參數。這可能就是這樣。其實我只是試圖將相機部分單獨拉入自己的項目,現在它可以工作,但預覽屏幕中的圖像是混亂的,就像它無法獲得正確的幀速率或什麼。我正在編輯該帖子,其中包含活動和版面的完整源代碼。 – Darren

+0

預覽出現亂碼,它是自XE10以來的一個錯誤。有關解決方法,請參閱http://stackoverflow.com/questions/19235477/google-glass-preview-image-scrambled-with-new-xe10-release/19257078#19257078。 – Satish

+0

太棒了!這工作。非常感謝Satish :) – Darren