1

我的相机应用 manifest.xml 中有以下设置:

<uses-sdk
    android:minSdkVersion="7"
    android:targetSdkVersion="8" />

现在我把它改成了:

<uses-sdk
    android:minSdkVersion="7"
    android:targetSdkVersion="13" />

问题是:我的应用程序无法再打开相机了。此行引发错误:

this.camera = Camera.open();

错误信息:

连接相机服务失败

顺便说一句,奇怪的事情:使用新设置启动应用程序后,我不再让相机设备运行(所有其他照片应用程序也在启动时崩溃)。我必须重新启动设备才能再次使用相机。

有人可以帮我吗?

我的 Preview.java 类:

package net.mt.lib.cc;

import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.List;

import net.mt.lib.Tools;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Debug;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import com.crittercism.app.Crittercism;
import com.flurry.android.FlurryAgent;

/**
 *
 * openCamera()
 * onSizeChanged()
 * onLayout()
 * onLayout()
 * surfaceCreated()
 * surfaceChanged()
 * onLayout()
 */
class Preview extends ViewGroup implements SurfaceHolder.Callback { // <1>
    private static final String TAG = "Preview";

    SurfaceHolder mHolder; // <2>
    public Camera camera; // <3>
    SurfaceView mSurfaceView;
    BaseCameraActivity cameraActivity;
    int l2 = 0, t2 = 0, r2 = 0, b2 = 0;
    int padding = 20;
    PreviewCallback cb;
    private double downscalingFactor = 1;
    // the size of this view. gets set in onMeasure()
    int fullWidth, fullHeight;
    Size bestPictureSize = null;
    Size bestPreviewSize = null;

    private String allResolutions;

    private Context context;

    public Preview(Context context, PreviewCallback callback) {
        super(context);
        this.cb = callback;
        init(context);
    }



    private void init(Context context) {
        setKeepScreenOn(true);
        cameraActivity = (BaseCameraActivity) context;
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);
        this.context = context;
        mHolder = mSurfaceView.getHolder(); // <4>
        mHolder.addCallback(this); // <5>
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // <6>
    }


    public void openCamera() {
        Log.d(TAG,"openCamera()");
        if (this.camera == null) {
            try{
                this.camera = Camera.open();
                this.camera.setErrorCallback(new ErrorCallback() {
                    @Override
                    public void onError(int error, Camera camera) {
                        Log.e(TAG, "error! code:"+error);
                        Toast.makeText(cameraActivity, "Camera error occured: "+error, 8000).show();
                    }
                });
                requestLayout(); // -> onSizeChanged() -> onLayout()
            }catch (Exception e) {
                String errorMessage = "Manufacturer: "+Build.MANUFACTURER+"; Model:"+Build.MODEL+"; Camera: "+this.camera+"; Stacktrace:"+Tools.exception2String(e);
                Log.d(TAG,"error occured: "+errorMessage);
                FlurryAgent.onError("1", errorMessage, "Preview.openCamera()");
                Toast.makeText(cameraActivity, "Uuups, I am sorry! Could not connect to the camera device. Please restart me or your phone.", 8000).show();
                Crittercism.logHandledException(e);
            }
        }
    }



    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Log.d(TAG,"onSizeChanged() "+w+" "+h);
        fullWidth = w;
        fullHeight = h;
        if(fullWidth < fullHeight){ 
            int tmp = fullHeight;
            fullHeight = fullWidth;
            fullWidth = tmp;
            Log.d(TAG,"switched:"+fullWidth+"x"+fullHeight);
        }else{
            Log.d(TAG,"fullSize:"+fullWidth+"x"+fullHeight);
        }
        if(this.camera != null){
            this.setCameraPreviewSize();
            this.setCameraPictureSize();
            if (getChildCount() > 0) {
                final View child = getChildAt(0);
                Log.d(TAG,"r:"+this.getPreviewRight()+" l:"+this.getPreviewLeft()+" b:"+this.getPreviewBottom()+" t:"+this.getPreviewTop());
                child.layout(this.getPreviewLeft(), this.getPreviewTop(), this.getPreviewRight(), this.getPreviewBottom());
                cb.previewReady(getPreviewLeft(), getPreviewTop(), getPreviewRight()-getPreviewLeft(), getPreviewBottom() - getPreviewTop(), getBestPictureSize().width, getBestPictureSize().height, (int) downscalingFactor, allResolutions);
            }
        }

        super.onSizeChanged(w, h, oldw, oldh);
    }

    private void calcScaledPreviewSize(){       
        int previewWidth = getBestPreviewSize().width;
        int previewHeight = getBestPreviewSize().height;
        float scaledWidth;
        float scaledHeight;

        Log.d(TAG,"preview width: "+previewWidth+", preview height: "+previewHeight);
        Log.d(TAG,"display width: "+fullWidth+", display height: "+fullHeight);
        float previewRatio = (float) previewWidth / (float) previewHeight;
        float displayRatio = (float) fullWidth / (float) fullHeight;

        if(displayRatio >= previewRatio){ // the display is wider then the preview image
            scaledHeight = fullHeight - 2*padding;
            scaledWidth = scaledHeight * previewRatio;
            l2 = (int) (fullWidth - scaledWidth) / 2;
            t2 = padding;
            r2 = (int) (fullWidth + scaledWidth) / 2;
            b2 = (int) scaledHeight + padding;

        }else{
            scaledWidth = fullWidth - 2*padding;
            scaledHeight = scaledWidth / previewRatio;
            l2 = padding;
            t2 = (int) (fullHeight - scaledHeight) / 2;
            r2 = (int) scaledWidth + padding;
            b2 = (int) (fullHeight + scaledHeight) / 2;     
        }
    }

    public int getPreviewTop() {
        if(this.t2 == 0){
            this.calcScaledPreviewSize();
        }
        return t2;
    }
    public int getPreviewBottom() {
        if(this.b2 == 0){
            this.calcScaledPreviewSize();
        }
        return b2;
    }
    public int getPreviewLeft() {
        if(this.l2 == 0){
            this.calcScaledPreviewSize();
        }
        return l2;
    }
    public int getPreviewRight() {
        if(this.r2 == 0){
            this.calcScaledPreviewSize();
        }
        return r2;
    }
    public int getPreviewWidth() {
        return this.getPreviewRight()-this.getPreviewLeft();
    }
    public int getPreviewHeight() {
        return this.getPreviewBottom()-this.getPreviewTop();
    }

    private void setCameraPreviewSize() {
        Camera.Parameters parameters = camera.getParameters();
        if(parameters.getPreviewSize() != this.getBestPreviewSize()){
            parameters.setPreviewSize(this.getBestPreviewSize().width, this.getBestPreviewSize().height);
            this.camera.setParameters(parameters);
        }
    }

    private void setCameraPictureSize() {
        Camera.Parameters parameters = this.camera.getParameters();
        if(parameters.getPictureSize() != this.getBestPictureSize()){
            parameters.setPictureSize(getBestPictureSize().width, getBestPictureSize().height);
            this.camera.setParameters(parameters);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.d(TAG,"onLayout()");
        /*
        if (changed && getChildCount() > 0 && this.camera != null) {
            final View child = getChildAt(0);
            Log.d(TAG,"r:"+this.getPreviewRight()+" l:"+this.getPreviewLeft()+" b:"+this.getPreviewBottom()+" t:"+this.getPreviewTop());
            child.layout(this.getPreviewLeft(), this.getPreviewTop(), this.getPreviewRight(), this.getPreviewBottom());
            cameraActivity.initOverlay(this.getPreviewLeft(),this.getPreviewTop(),this.getPreviewRight(),this.getPreviewBottom());
        }*/
    }
    public Size getBestPictureSize() {
        if(this.bestPictureSize == null){
            this.calculateOptimalPictureAndPreviewSizes();
        }
        return bestPictureSize;
    }

    public Size getBestPreviewSize() {
        if(this.bestPreviewSize == null){
            this.calculateOptimalPictureAndPreviewSizes();
        }
        return bestPreviewSize;
    }



    // Called once the holder is ready
    public void surfaceCreated(SurfaceHolder holder) { // <7>
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
        Log.d(TAG,"surfaceCreated()");
        try {
            if (this.camera != null) {
                this.camera.setPreviewDisplay(holder);
            }
        } catch (IOException exception) {
            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);

        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Log.d(TAG,"surfaceChanged()");
        if (camera != null) {

            Camera.Parameters parameters = camera.getParameters();
            parameters.setPreviewSize(getBestPreviewSize().width, getBestPreviewSize().height);
            camera.setParameters(parameters);
            camera.startPreview();
            cb.onPreviewStart();
            requestLayout();
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) { // <14>
        Log.d(TAG,"surfaceDestroyed()");
        if(this.camera != null){
            camera.stopPreview();
            camera.lock();
            camera.release();
            this.camera = null;
        }
    }

    public void releaseCamera(){
        Log.d(TAG,"releaseCamera()");
        if (camera != null) {
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
        }
    }


}

预览是这样初始化的(来自主要活动):

@Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG,"onResume()");

        previewLayout.removeAllViews();
        preview = new Preview(this, this);
        previewLayout.addView(preview, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
        preview.openCamera();

    }

和清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.mc.ccPro"
    android:versionCode="35"
    android:versionName="3.5" >

    <application
        android:hardwareAccelerated="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:largeHeap="true" >
        <activity
            android:name=".ccProActivity"
            android:configChanges="keyboard|orientation|keyboardHidden"
            android:label="@string/app_name"
            android:windowSoftInputMode="adjustPan" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.media.action.IMAGE_CAPTURE" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <activity
            android:name="net.mc.lib.cc.PreferenceActivity"
            android:label="@string/set_preferences" >
        </activity>

    </application>

    <supports-screens 
           android:largeScreens="true" 
           android:normalScreens="true" 
           android:smallScreens="true" 
           android:resizeable="true" 
           android:anyDensity="true" />


    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="8" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-library android:name="net.mc.lib.cc" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="false" />

    <supports-screens
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:xlargeScreens="true" />

</manifest>
4

2 回答 2

0

尝试将此行添加到您的 AndroidManifest 中:

<uses-feature android:name="android.hardware.camera" />
于 2012-07-16T14:53:17.300 回答
0

使用此代码初始化相机:

        Camera camera;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
            int numberOfCameras = Camera.getNumberOfCameras();
            CameraInfo cameraInfo = new CameraInfo();
            for (int i = 0; i < numberOfCameras; i++) {
                Camera.getCameraInfo(i, cameraInfo);
                if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK)
                    camera = Camera.open(i);
            }
        }
        if (camera == null)
            camera = Camera.open();
        ...
于 2012-07-11T07:17:22.273 回答