2013-04-19 2 views
4

Я разрабатываю приложение для Android-андроида, используя автофокус.takePicture не удалось после автофокусировки во второй раз

Проблема, я могу захватить в первый раз, но когда я пытаюсь захватить во второй раз, возникает следующее исключение.

4-19 11:28:32.509: E/AndroidRuntime(4409): FATAL EXCEPTION: main 
04-19 11:28:32.509: E/AndroidRuntime(4409): java.lang.RuntimeException: takePicture failed 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.hardware.Camera.native_takePicture(Native Method) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.hardware.Camera.takePicture(Camera.java:878) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.hardware.Camera.takePicture(Camera.java:842) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at com.example.camerasample.MainActivity$4.onClick(MainActivity.java:60) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.view.View.performClick(View.java:2485) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.view.View$PerformClick.run(View.java:9080) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.os.Handler.handleCallback(Handler.java:587) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.os.Handler.dispatchMessage(Handler.java:92) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.os.Looper.loop(Looper.java:130) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at android.app.ActivityThread.main(ActivityThread.java:3687) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at java.lang.reflect.Method.invokeNative(Native Method) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at java.lang.reflect.Method.invoke(Method.java:507) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625) 
04-19 11:28:32.509: E/AndroidRuntime(4409):  at dalvik.system.NativeStart.main(Native Method) 

Но отлично работает при съемке в камере без функции автофокуса.

Ниже я прилагаю мои коды

MainActivity.java

package com.example.camerasample; 

import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 

import com.example.camerasample.R; 

import android.app.Activity; 
import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.AutoFocusCallback; 
import android.hardware.Camera.PictureCallback; 
import android.hardware.Camera.ShutterCallback; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.View.OnLongClickListener; 
import android.view.ViewGroup.LayoutParams; 
import android.view.Window; 
import android.view.WindowManager; 
import android.widget.Button; 
import android.widget.FrameLayout; 

public class MainActivity extends Activity { 
    private static final String TAG = "CamTestActivity"; 
    Preview preview; 
    Button buttonClick; 
    Camera camera; 
    String fileName; 
    Activity act; 
    Context ctx; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ctx = this; 
     act = this; 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     setContentView(R.layout.activity_main); 

     preview = new Preview(this, (SurfaceView)findViewById(R.id.surfaceView)); 
     preview.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
     ((FrameLayout) findViewById(R.id.preview)).addView(preview); 
     preview.setKeepScreenOn(true); 

     buttonClick = (Button) findViewById(R.id.buttonClick); 

     buttonClick.setOnClickListener(new OnClickListener() { 
      public void onClick(View v) { 
       camera.takePicture(shutterCallback, rawCallback, jpegCallback); 
      } 
     }); 

     buttonClick.setOnLongClickListener(new OnLongClickListener(){ 
      @Override 
      public boolean onLongClick(View arg0) { 
       camera.autoFocus(new AutoFocusCallback(){ 
        @Override 
        public void onAutoFocus(boolean arg0, Camera arg1) { 
        } 
       }); 
       return true; 
      } 
     }); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     camera = Camera.open(); 
     camera.startPreview(); 
     preview.setCamera(camera); 
    } 

    @Override 
    protected void onPause() { 
     if(camera != null) { 
      camera.stopPreview(); 
      preview.setCamera(null); 
      camera.release(); 
      camera = null; 
     } 
     super.onPause(); 
    } 

    private void resetCam() { 
     camera.startPreview(); 
     preview.setCamera(camera); 
    } 

    ShutterCallback shutterCallback = new ShutterCallback() { 
     public void onShutter() { 
      // Log.d(TAG, "onShutter'd"); 
     } 
    }; 

    PictureCallback rawCallback = new PictureCallback() { 
     public void onPictureTaken(byte[] data, Camera camera) { 
      // Log.d(TAG, "onPictureTaken - raw"); 
     } 
    }; 

    PictureCallback jpegCallback = new PictureCallback() { 
     public void onPictureTaken(byte[] data, Camera camera) { 
      FileOutputStream outStream = null; 
      try { 
       // Write to SD Card 
       fileName = String.format("/sdcard/camtest/%d.jpg", System.currentTimeMillis()); 
       outStream = new FileOutputStream(fileName); 
       outStream.write(data); 
       outStream.close(); 
       Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length); 

       resetCam(); 

      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } finally { 
      } 
      Log.d(TAG, "onPictureTaken - jpeg"); 
     } 
    }; 
} 

Preview.java

package com.example.camerasample; 

import java.io.IOException; 
import java.util.List; 

import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.Size; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.ViewGroup; 

class Preview extends ViewGroup implements SurfaceHolder.Callback { 
    private final String TAG = "Preview"; 

    SurfaceView mSurfaceView; 
    SurfaceHolder mHolder; 
    Size mPreviewSize; 
    List<Size> mSupportedPreviewSizes; 
    Camera mCamera; 

    @SuppressWarnings("deprecation") 
    Preview(Context context, SurfaceView sv) { 
     super(context); 

     mSurfaceView = sv; 

     mHolder = mSurfaceView.getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void setCamera(Camera camera) { 
     mCamera = camera; 
     if (mCamera != null) { 
      mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
      requestLayout(); 

      // get Camera parameters 
      Camera.Parameters params = mCamera.getParameters(); 

      List<String> focusModes = params.getSupportedFocusModes(); 
      if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { 
       // set the focus mode 
       params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 
       // set Camera parameters 
       mCamera.setParameters(params); 
      } 
     } 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     // We purposely disregard child measurements because act as a 
     // wrapper to a SurfaceView that centers the camera preview instead 
     // of stretching it. 
     final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); 
     final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); 
     setMeasuredDimension(width, height); 

     if (mSupportedPreviewSizes != null) { 
      mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height); 
     } 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     if (changed && getChildCount() > 0) { 
      final View child = getChildAt(0); 

      final int width = r - l; 
      final int height = b - t; 

      int previewWidth = width; 
      int previewHeight = height; 
      if (mPreviewSize != null) { 
       previewWidth = mPreviewSize.width; 
       previewHeight = mPreviewSize.height; 
      } 

      // Center the child SurfaceView within the parent. 
      if (width * previewHeight > height * previewWidth) { 
       final int scaledChildWidth = previewWidth * height/previewHeight; 
       child.layout((width - scaledChildWidth)/2, 0, 
         (width + scaledChildWidth)/2, height); 
      } else { 
       final int scaledChildHeight = previewHeight * width/previewWidth; 
       child.layout(0, (height - scaledChildHeight)/2, 
         width, (height + scaledChildHeight)/2); 
      } 
     } 
    } 

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

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // Surface will be destroyed when we return, so stop the preview. 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
     } 
    } 


    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
     final double ASPECT_TOLERANCE = 0.1; 
     double targetRatio = (double) w/h; 
     if (sizes == null) return null; 

     Size optimalSize = null; 
     double minDiff = Double.MAX_VALUE; 

     int targetHeight = h; 

     // Try to find an size match aspect ratio and size 
     for (Size size : sizes) { 
      double ratio = (double) size.width/size.height; 
      if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 

     // Cannot find the one match the aspect ratio, ignore the requirement 
     if (optimalSize == null) { 
      minDiff = Double.MAX_VALUE; 
      for (Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
     } 
     return optimalSize; 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     if(mCamera != null) { 
      Camera.Parameters parameters = mCamera.getParameters(); 
      parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
      requestLayout(); 

      mCamera.setParameters(parameters); 
      mCamera.startPreview(); 
     } 
    } 

} 

Manifest:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.camerasample" 
    android:versionCode="1" 
    android:versionName="1.0" > 

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

    <uses-feature android:name="android.hardware.camera" /> 

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

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 
     <activity 
      android:label="@string/app_name" 
      android:name=".MainActivity" 
      android:screenOrientation="landscape" > 
      <intent-filter > 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

Я не смог найти точное решение в любом месте, п помощь в аренде.

+0

Решение найдено? Имея ту же проблему на галактике s3 (i9300) – tofi9

ответ

1

Да, код сработает, если вы дважды автофокусируете камеру. Вы можете решить эту проблему, указав флаг, который будет проверять, запускался автофокусировка, а затем снова пропустить выполнение автофокуса.

+0

Как? какое свойство камеры связано с этой проблемой? – Behzad

3

Я предлагаю два решения, которые работали для меня. 1) Остановите и возобновите работу камеры. Я делаю это с помощью вызова этих методов на OnPause и onResume, а также в середине камеры предварительного просмотра, где я сканировать QR-коды в моем приложении:

public void stopCamera(){ 
    mCamera.cancelAutoFocus(); 
    mCamera.setPreviewCallback(null); 
    mCamera.stopPreview(); 
    mPreviewing = false; 
    } 

public void rethrottleCamera(){ 
     updateViews(); //Updates my Layouts 
     mPreviewing = true; 
     mCamera.startPreview(); 
     mCamera.setPreviewCallback(previewCb); 
     mCamera.autoFocus(autoFocusCB); 
     } 

2) Очень сложно, но работал как волшебство! Убедитесь, что вы вызываете автофокусировку ПОСЛЕ получения поверхности предварительного просмотра. Для этого запустите Autofocus с задержкой в ​​200 мс, чтобы выиграть время для создания поверхности. Установите это, нажав Ctrl + Clic над «CameraPreview» объект декларацией, такие как:

CameraPreview my_camera; 

Посмотрите на «общественную пустоту surfaceChanged» способ и сделать это изменениями:

//Add a delay to AUTOFOCUS after mCamera.startpreview();!!: 
    mCamera.startPreview();     
    final Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() { 
     @Override 
     public void run() {      
      mCamera.autoFocus(autoFocusCallback); 
      } 
    }, 200); //<-200 millisecond delay 

    //If you call autofocus right after startPreview, chances are, 
    //that the previewSurface will have not been created yet, 
    //and autofocus will fail: 
    mCamera.startPreview();    //Bad idea! 
    mCamera.autoFocus(autoFocusCallback); //Bad idea! 

Есть много других исправления, но эти двое могут сэкономить ваш день.

Смежные вопросы