【问题标题】:Google Glass app failing with takePicture谷歌眼镜应用因 takePicture 失败
【发布时间】:2014-10-30 22:04:56
【问题描述】:

我是 Android(但不完全是 Java)编码的新手,我正在尝试为 Google Glass 制作一个简单的相机应用程序。我希望它每隔几分钟自动拍摄一张照片并处理输入,但如果您使用本机相机实现,Google glass 会强制您“点击接受”每张照片。所以我尝试使用 Android Camera API 来代替拍照,这样我就可以跳过这个“点击接受”。

但是,在预览显示时,从不调用 PictureCallback,因此在尝试将结果发送回主 Activity 时会引发 NullPointerException。

当前代码是网络上各种潜在变通办法的混杂,如果混乱,请见谅!

我的相机活动类:

package com.example.cerveau.blah;

import android.app.Activity;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.FrameLayout;

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

public class CameraActivity extends Activity {

    private Camera mCamera;
    private CameraPreview mPreview;
    private Intent resultIntent;
    private PictureCallback mPicture;
    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;
    private static final String TAG = "CameraActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recognize_places);

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

        // Make the callback
        mPicture = new PictureCallback() {

            private static final String TAG = "PictureCallback";

            @Override
            public void onPictureTaken(byte[] data, Camera camera) {

                File pictureFile = getOutputMediaFile(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());
                }
                Log.d(TAG, "Callback made and picture taken!");
            }
        };

        // 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);
        Log.d(TAG, "Preview made!");

        mCamera.startPreview();

        // have a delay so the camera can set up
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        mCamera.takePicture(null, null, mPicture);
        setIntent(getOutputMediaFileUri(MEDIA_TYPE_IMAGE));
        releaseCamera();

    }


    public void setIntent(Uri photoURI){
        resultIntent = new Intent();
        resultIntent.setData(photoURI);
        setResult(Activity.RESULT_OK, resultIntent);
        finish();
    }

    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)
        }

        // Parameters needed for Google Glass
        c.setDisplayOrientation(0);
        Camera.Parameters params = c.getParameters();
        params.setPreviewFpsRange(30000, 30000);
        params.setJpegQuality(90);
// hard-coding is bad, but I'm a bit lazy
        params.setPictureSize(640, 480);
        params.setPreviewSize(640, 480);
        c.setParameters(params);

        return c; // returns null if camera is unavailable
    }


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

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

    /** 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 == MEDIA_TYPE_IMAGE){
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "IMG_"+ timeStamp + ".jpg");
        } else if(type == MEDIA_TYPE_VIDEO) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator +
                    "VID_"+ timeStamp + ".mp4");
        } else {
            return null;
        }

        return mediaFile;
    }
}

我在主 Activity 中这样称呼它:

    Intent intent = new Intent(this, CameraActivity.class);
    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);

我已经在我的 AndroidManifest 中拥有所有必要的权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>

这是错误日志:

10-30 18:00:58.599  11361-11361/com.example.cerveau.recognizeplaces D/OpenGLRenderer﹕ Enabling debug mode 0
10-30 18:00:58.833  11361-11361/com.example.cerveau.recognizeplaces D/CameraActivity﹕ Preview made!
10-30 18:01:08.654  11361-11361/com.example.cerveau.recognizeplaces I/Choreographer﹕ Skipped 601 frames!  The application may be doing too much work on its main thread.
10-30 18:01:08.677  11361-11361/com.example.cerveau.recognizeplaces I/RecogPlaces﹕ Got to onActivity
10-30 18:01:08.677  11361-11361/com.example.cerveau.recognizeplaces I/RecogPlaces﹕ Request code: 100, Result code: -1, what it wants: -1
10-30 18:01:08.677  11361-11361/com.example.cerveau.recognizeplaces I/RecogPlaces﹕ Got inside the IF
10-30 18:01:08.685  11361-11361/com.example.cerveau.recognizeplaces D/AndroidRuntime﹕ Shutting down VM
10-30 18:01:08.685  11361-11361/com.example.cerveau.recognizeplaces W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41600bd8)
10-30 18:01:08.685  11361-11361/com.example.cerveau.recognizeplaces E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.cerveau.recognizeplaces, PID: 11361
    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=100, result=-1, data=Intent { dat=file:///storage/emulated/0/Pictures/MyCameraApp/IMG_20141030_180059.jpg }} to activity {com.example.cerveau.recognizeplaces/com.example.cerveau.recognizeplaces.LiveCardMenuActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.deliverResults(ActivityThread.java:3391)
            at android.app.ActivityThread.handleSendResult(ActivityThread.java:3434)
            at android.app.ActivityThread.access$1300(ActivityThread.java:138)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:149)
            at android.app.ActivityThread.main(ActivityThread.java:5045)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at java.io.File.fixSlashes(File.java:185)
            at java.io.File.<init>(File.java:134)
            at com.example.cerveau.recognizeplaces.LiveCardMenuActivity.processPictureWhenReady(LiveCardMenuActivity.java:166)
            at com.example.cerveau.recognizeplaces.LiveCardMenuActivity.onActivityResult(LiveCardMenuActivity.java:157)
            at android.app.Activity.dispatchActivityResult(Activity.java:5430)
            at android.app.ActivityThread.deliverResults(ActivityThread.java:3387)
            at android.app.ActivityThread.handleSendResult(ActivityThread.java:3434)
            at android.app.ActivityThread.access$1300(ActivityThread.java:138)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:149)
            at android.app.ActivityThread.main(ActivityThread.java:5045)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
            at dalvik.system.NativeStart.main(Native Method)
10-30 18:01:09.130  11361-11361/com.example.cerveau.recognizeplaces I/Process﹕ Sending signal. PID: 11361 SIG: 9

提前致谢!

【问题讨论】:

    标签: android android-camera google-glass


    【解决方案1】:

    LiveCardMenuActivity 类中的 processPictureWhenReady() 方法有问题。

    首先,这是一件非常糟糕的事情:

    Thread.sleep(1000);
    

    永远不要在 UI 线程上这样做。
    你应该直接调用

    mCamera.startPreview();
    mCamera.takePicture(null, null, mPicture);
    

    在onPictureTaken() 回调结束时:

    setIntent(pictureFile.getPath());
    

    【讨论】:

    • 感谢您的建议...我试过了,但没有任何效果!我似乎无法在 Google Glass 上找到适合我的相机 API 实现......目前正在尝试这个:stackoverflow.com/questions/23073180/… 但相机预览不会出现,也不会拍照。我可能在 MainActivity 端做错了吗?我将其称为 Intent,然后我 startActivityForResult。这也使用了 SurfaceView,而我的只是在我的应用程序上显示为一个皱眉的大云......
    • 您看过 Glass 开发者指南吗? developers.google.com/glass/develop/gdk/camera我用这个用玻璃设备拍照。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多