简体   繁体   中英

Camera Preview freezing on Menu Intent

I have a Glass application where I am trying to use a Live Card to start a Camera Preview activity from the menu options. The application seems to freeze when I move away from the Live Card (say, to the weather) and back, and then try to bring up the camera through the menu options. Sorry for all of the code, here are the following files:

Service.java

. . .
   @Override
    public IBinder onBind(Intent intent) { return mBinder; }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (mLiveCard == null) {
            mLiveCard = new LiveCard(this, LIVE_CARD_TAG);

            mRemoteViews = new RemoteViews(getPackageName(), R.layout.service_layout);
            mLiveCard.setViews(mRemoteViews);

            // Display the options menu when the live card is tapped.
            Intent menuIntent = new Intent(this, MenuActivity.class);
            menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                    Intent.FLAG_ACTIVITY_CLEAR_TASK);

            mLiveCard.setAction(PendingIntent.getActivity(this, 0, menuIntent, 0));
            mLiveCard.attach(this);
            mLiveCard.publish(PublishMode.REVEAL);

        } else {
            mLiveCard.navigate();
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        if (mLiveCard != null && mLiveCard.isPublished()) {
            mLiveCard.unpublish();
            mLiveCard = null;
        }
        super.onDestroy();
    }
}

MenuActivity.java

public class MenuActivity extends Activity {

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        // Open the options menu right away.
        openOptionsMenu();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.layout, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.action_stop:
                // Stop the service which will unpublish the live card.
                stopService(new Intent(MenuActivity.this, Service.class));
                return true;

            case R.id.action_camera:
                startActivity(new Intent(MenuActivity.this, Camera.class));
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onOptionsMenuClosed(Menu menu) { finish(); }
}

Camera.java

public class Camera extends Activity {

    private SurfaceView mPreview = null;
    private SurfaceHolder mPreviewHolder = null;
    private Camera mCamera = null;
    private boolean inPreview = false;
    private boolean cameraConfigured = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.camera);


        mPreview = (SurfaceView) findViewById(R.id.camera_preview);
        mPreviewHolder = mPreview.getHolder();
        mPreviewHolder.addCallback(surfaceCallback);
    }


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

        mCamera = Camera.open();
        startPreview();
    }

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

        if (inPreview) {
            mCamera.stopPreview();
        }

        mCamera.release();
        mCamera = null;
        inPreview = false;
    }

    private Camera.Size getBestPreviewSize(int width, int height,
                                           Camera.Parameters parameters) {
        Camera.Size result = null;

        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
            if (size.width <= width && size.height <= height) {
                if (result == null) {
                    result = size;
                } else {
                    int resultArea = result.width * result.height;
                    int newArea = size.width * size.height;

                    if (newArea > resultArea) {
                        result = size;
                    }
                }
            }
        }
        return (result);
    }

    private void initPreview(int width, int height) {
        if (mCamera != null && mPreviewHolder.getSurface() != null) {
            try {
                mCamera.setPreviewDisplay(mPreviewHolder);
            } catch (Throwable t) {
                Log.e("PreviewDemo-surfaceCallback",
                        "Exception in setPreviewDisplay()", t);
            }

            if (!cameraConfigured) {
                Camera.Parameters parameters = mCamera.getParameters();
                Camera.Size size = getBestPreviewSize(width, height,
                        parameters);

                if (size != null) {
                    parameters.setPreviewSize(size.width, size.height);
                    mCamera.setParameters(parameters);
                    cameraConfigured = true;
                }
            }
        }
    }

    private void startPreview() {
        if (cameraConfigured && mCamera != null) {
            mCamera.startPreview();
            inPreview = true;
        }
    }

I can't seem to figure out why the camera preview works initially but doesn't work when navigating away. I feel like there is something simple that I am just missing here. Any help would be greatly appreciated!

I'm not sure if this would fix your problem, but I would start and stop the camera this way:

private Camera getCameraInstance() {
    Camera mCamera = null;
    try {
        /* attempt to get a Camera instance */
        mCamera = Camera.open();
    } catch (Exception e) {
        /* Camera is not available (in use or does not exist) */
        Log.e(TAG, "Error getting camera: " + e.getMessage());
        // process null error here
        // finish();
    }

    /* returns null if camera is unavailable */
    return mCamera;
}


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

    if (mCamera == null) {

        mCamera = getCameraInstance();

        if (mCamera != null) {
            startPreview();
        } else {
            // process null error here
        }
    }
}

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

    if (mCamera != null) {
        /* stop preview */
        if (inPreview) {
            try {
                mCamera.stopPreview();
            } catch (Exception e) {
                /* ignore: tried to stop a non-existent preview */
            }
        }

        /* release the camera */
        mCamera.release();
        mCamera = null;
        inPreview = false;
    }
} 

I would also check if mCamera or getSurface is null in initPreview .

private void initPreview(int width, int height) {
    if (mCamera != null && mPreviewHolder.getSurface() != null) {
        try {
            mCamera.setPreviewDisplay(mPreviewHolder);
        } catch (Throwable t) {
            Log.e("PreviewDemo-surfaceCallback",
                    "Exception in setPreviewDisplay()", t);
        }

        if (!cameraConfigured) {
            Camera.Parameters parameters = mCamera.getParameters();
            Camera.Size size = getBestPreviewSize(width, height,
                    parameters);

            if (size != null) {
                parameters.setPreviewSize(size.width, size.height);
                mCamera.setParameters(parameters);
                cameraConfigured = true;
            }
        }
    } else {
        Log.e(TAG, "Camera or getSurface is null");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM