Note that there are some explanatory texts on larger screens.

plurals
  1. POMessage "Camera has stopped" when using Glass GDK and Android Camera API
    primarykey
    data
    text
    <p>I wondered if anyone has tried using the standard Android Camera API (<a href="http://developer.android.com/guide/topics/media/camera.html" rel="nofollow">http://developer.android.com/guide/topics/media/camera.html</a>) to control the camera in an app.</p> <p>I was able to get my app to work using the startActivityForResult() method, but was a bit disappointed in how long it took to get an image back from the file system, so I wanted to try the other route, using the CameraPreview.</p> <p>I set up some code based on the Android Camera API example, and it builds and runs fine, but after <strong><em>surfaceChanged</em></strong> executes I get a message in the screen "The Camera has stopped."</p> <p><em><strong>Later Edit - I moved the camera activity into its own project and now it works but it gets the preview scrambled. But after the pic is taken it shows fine. Here is the layout code:</em></strong></p> <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt; &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" &gt; &lt;FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /&gt; &lt;/LinearLayout&gt; </code></pre> <p>And here is the Activity source:</p> <pre><code>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); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload