2013-01-19 18 views
13

Mam problem z aparatem. Chcę uzyskać zdjęcie w onPreviewFrame, ale nigdy nie jest wywoływane. Otworzyłem kamerę, ustawiłem podgląd wyświetlacza i podgląd Callback, ale nic. Chcę tylko zrozumieć, gdzie się myliłem.Android onPreviewFrame nie nazywa się

public class VideoCall extends Activity implements View.OnClickListener, Callback, PreviewCallback 
{ 

    TabHost thVideoChat; 
    Button btnVideoUp, btnVideoDown; 
    Handler uiHandler; 
    SurfaceView videoPrev; 
    SurfaceHolder surfaceHolder; 
    Camera camera; 

    Timer timer; 
    boolean getPic; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.a_video); 
     initialize(); 

     Log.d("RAYZ", "onCreate"); 
    } 

    private void initialize() 
    { 

     thVideoChat = (TabHost) findViewById(R.id.thVideoChat); 
     thVideoChat.setup(); 

     TabSpec specs = thVideoChat.newTabSpec("1"); 
     specs.setContent(R.id.tabVideo); 
     specs.setIndicator("Видео", getResources().getDrawable(R.drawable.mcam)); 
     thVideoChat.addTab(specs); 

     specs = thVideoChat.newTabSpec("2"); 
     specs.setContent(R.id.tabChat); 
     specs.setIndicator("Чат", getResources().getDrawable(R.drawable.mchat)); 
     thVideoChat.addTab(specs); 

     btnVideoUp = (Button) findViewById(R.id.btnVideoUp); 
     btnVideoDown = (Button) findViewById(R.id.btnVideoDown); 
     btnVideoUp.setOnClickListener(this); 
     btnVideoDown.setOnClickListener(this); 

     videoPrev = (SurfaceView) findViewById(R.id.videoPrev); 

     if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) 
     { 

      LayoutParams lp = videoPrev.getLayoutParams(); 
      lp.height = 320; 
      lp.width = 240; 
      videoPrev.setLayoutParams(lp); 

     } 
     else 
     { 
      LayoutParams lp = videoPrev.getLayoutParams(); 
      lp.height = 240; 
      lp.width = 320; 
      videoPrev.setLayoutParams(lp); 
     } 

     surfaceHolder = videoPrev.getHolder(); 
     surfaceHolder.addCallback(this); 
     surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

     uiHandler = new Handler(); 
     getPic = false; 
    } 

    @Override 
    protected void onPause() 
    { 
     Log.d("RAYZ", "onPause"); 
     if (camera != null) 
     { 
      camera.setPreviewCallback(null); 
      camera.stopPreview(); 
      camera.release(); 
      camera = null; 
     } 
     if (timer != null) 
     { 
      timer.cancel(); 
     } 
     super.onPause(); 
    } 

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

    @Override 
    public void onClick(View v) 
    { 
     switch (v.getId()) 
     { 
      case R.id.btnVideoUp: 
      { 
       btnVideoUp.setEnabled(false); 
       btnVideoDown.setEnabled(true); 

       timer = new Timer(); 

       Log.d("RAYZ", "G_BTN"); 

       timer.schedule(new TimerTask() 
       { 

        @Override 
        public void run() 
        { 
         uiHandler.post(new Runnable() 
         { 

          @Override 
          public void run() 
          { 
           getPic = true; 
          } 
         }); 
        } 
       }, 0L, 1L * 500L); 

       break; 
      } 
      case R.id.btnVideoDown: 
      { 
       btnVideoUp.setEnabled(true); 
       btnVideoDown.setEnabled(false); 
       Log.d("RAYZ", "R_BTN"); 
       timer.cancel(); 
       timer = null; 
       break; 
      } 
      default: 
       break; 
     } 

    } 

    @Override 
    public void onPreviewFrame(byte[] data, Camera camera) 
    { 
     Log.d("RAYZ", "getPic"); 
     // if (getPic) 
     // { 

     // } 

    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
    { 

    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) 
    { 

     try 
     { 

      camera.setPreviewDisplay(holder); 
      camera.setPreviewCallback(this); 
      camera.startPreview(); 
     } 
     catch (IOException e) 
     { 
      e.printStackTrace(); 
     } 

    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 

    } 

} 

Próbowałem ten kod na 2 innych urządzeń (telefony HTS i Sony Xperia) i wszystko działało w porządku. Ale na moim tablecie to nie działa. Jestem zmieszany.

Odpowiedz

0

Może być konieczne ustawienie niższej rozdzielczości podglądu dla urządzeń o niskim poborze mocy. Ustawienie rozmiaru widoku powierzchni na 320x240 nie ma wpływu na rozdzielczość podglądu samego aparatu, rozdzielczość podglądu musi być ustawiona jawnie. Można spróbować czegoś takiego:

List<Camera.Size> resList = camera.getParameters().getSupportedPreviewSizes(); 
int w=0, h=0; 
final int desiredRes_W = 176; 
for (Camera.Size size : resList) { 
    // find a supported res nearest to desired_Res 
    if (w==0) { 
     w = size.width; 
     h = size.height; 
    } 
    else if (size.width >= desiredRes_W && size.width <= w ) { 
     w=size.width; 
     h = size.height; 
    } 
} // 176x144, 320x240 ... 
Parameters par = camera.getParameters(); 
par.setPreviewSize(w, h); 
// ALSO set width/height of the SurfaceView to the same aspect ratio. 
camera.setParameters(par); 
camera.setPreviewDisplay(holder); 
4

polecam przeniesienie kodu w surfaceCreated do surfaceChanged, zwłaszcza, że ​​jesteś nadrzędny układ powierzchni preview podczas onCreate (w initialize()).

Generalnie bezpieczniej jest reagować na surfaceChanged, ponieważ będzie on wywoływany za każdym razem, gdy nastąpi zmiana rozmiaru powierzchni. Powinieneś prawdopodobnie sprawdzić, czy masz już podgląd w surfaceChanged.

Jak już powiedzieli inni, rozmiar powierzchni podglądu nie określa rozmiaru buforów podglądu, które odbierasz w wywołaniu podglądu; który jest ustawiony metodą setPreviewSize, i trzeba użyć wartości z listy obsługiwanych rozmiarów podglądu, które można uzyskać z

Camera.Parameters.getSupportedPreviewSizes(). 
2

Musisz zadzwonić setPreviewCallback w metodzie surfaceChanged, nie tylko w surfaceCreated. To jest mój główny CameraActivity.java:

package com.example.cameraview; 

import java.util.Hashtable; 

import android.app.Activity; 
import android.hardware.Camera; 
import android.hardware.Camera.Size; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.FrameLayout; 
import android.widget.ImageView; 

import com.google.zxing.BinaryBitmap; 
import com.google.zxing.DecodeHintType; 
import com.google.zxing.MultiFormatReader; 
import com.google.zxing.NotFoundException; 
import com.google.zxing.PlanarYUVLuminanceSource; 
import com.google.zxing.Result; 
import com.google.zxing.common.HybridBinarizer; 

public class CameraActivity extends Activity implements Camera.PreviewCallback { 

    private Camera mCamera; 
    private CameraPreview mPreview; 

    private Result result; 
    private MultiFormatReader reader; 

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

     reader = new MultiFormatReader(); 
     Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(); 
     hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); 
     reader.setHints(hints); 

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

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

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

     if (mCamera != null) { 
      mCamera.setPreviewCallback(null); 
      mPreview.getHolder().removeCallback(mPreview); 
      mCamera.release(); 
     } 
    } 

    /** A safe way to get an instance of the Camera object. */ 
    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) 
    } 
    return c; // returns null if camera is unavailable 
    } 

    public void onPreviewFrame(byte[] data, Camera camera) { 
    Size size = mCamera.getParameters().getPreviewSize(); 
     PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, size.width, size.height, 0, 0, size.width, size.height, false); 
     HybridBinarizer hybBin = new HybridBinarizer(source); 
     BinaryBitmap bitmap = new BinaryBitmap(hybBin); 

    ImageView myImage = (ImageView) findViewById(R.id.foto); 

     try { 
      result = reader.decode(bitmap); 
     Log.d("Result", "Result found!: " + String.valueOf(result)); 

     myImage.setVisibility(View.VISIBLE); 

     if (String.valueOf(result).contentEquals("1")) 
      myImage.setImageResource(R.drawable.juan); 
     else if (String.valueOf(result).contentEquals("2")) 
      myImage.setImageResource(R.drawable.antonio); 

     } catch (NotFoundException e1) { 

      if (myImage != null) 
     myImage.setVisibility(View.INVISIBLE); 

     Log.d("NotFoundException", "NotFoundException"); 
     } finally { 
     reader.reset(); 
     } 
    } 

} 

A to moja CameraPreview.java:

package com.example.cameraview; 

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

import android.content.Context; 
import android.hardware.Camera; 
import android.hardware.Camera.PreviewCallback; 
import android.hardware.Camera.Size; 
import android.hardware.Camera.Parameters; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 


/** A basic Camera preview class */ 
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 
    private String TAG = "CameraPreview"; 
    private Context context; 

    @SuppressWarnings("deprecation") 
    public CameraPreview(Context context, Camera camera) { 
    super(context); 
    mCamera = camera; 
    this.context = context; 

    // Install a SurfaceHolder.Callback so we get notified when the 
    // underlying surface is created and destroyed. 
    mHolder = getHolder(); 
    // deprecated setting, but required on Android versions prior to 3.0 
    mHolder.addCallback(this); 
    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 { 
     mCamera.setPreviewDisplay(holder); 
     mCamera.startPreview(); 

    } catch (NullPointerException e) { 
     Log.d(TAG, "Error setting camera preview - nullpointerexception: " + e.getMessage()); 
    } 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. 
    } 

    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. 

    if (mHolder.getSurface() == null){ 
     // preview surface does not exist 
     return; 
    } 

    // stop preview before making changes 
    try { 
     mCamera.stopPreview(); 
    } catch (Exception e){ 
     // ignore: tried to stop a non-existent preview 
    } 

    // set preview size and make any resize, rotate or 
    // reformatting changes here 

    // start preview with new settings 
    try { 
     Parameters parameters = mCamera.getParameters(); 

     List<Size> sizes = parameters.getSupportedPreviewSizes(); 
     Size optimalSize = getOptimalPreviewSize(sizes, w, h); 
     parameters.setPreviewSize(optimalSize.width, optimalSize.height); 

     if (context.getPackageManager().hasSystemFeature("android.hardware.camera.autofocus")) 
      parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 

     mCamera.setParameters(parameters); 

     mCamera.setPreviewCallback((PreviewCallback) context); 
     mCamera.setPreviewDisplay(mHolder); 
     mCamera.startPreview(); 

    } catch (Exception e){ 
     Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
    } 
    } 

    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
    final double ASPECT_TOLERANCE = 0.05; 
    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; 
    } 
} 

Ignoruj ​​czytnika i ZXing rzeczy, jest to dowód koncepcji występów układów detekcji qr w ciągu Biblioteka ZXing.

To jest mieszane rozwiązanie znalezione podczas wyszukiwania moich błędów kodu w StackOverflow.

+0

Mój podgląd nigdy się nie zmienił od czasu jego utworzenia. – Rayz

+1

Zobacz odpowiedź @Eddy na temat rekomendacji, aby przejść do surfaceChanged. Będę edytować moją odpowiedź, pokazując cały mój działający kod. – Neonigma

+0

@Neonigma can u pls pomóż mi, jak mogę pokazać podgląd na żywo w więcej niż jednym framelayouts .... nie udało mi się pokazać podglądu kamery na żywo w drugim framelayouts – Erum

14

mam zmaga się z tym problemem do rozwiązania i kiedyś była dla mnie zadzwonić Camera.setPreviewCallback tuż po Camera.setPreviewDisplay w SurfaceView.surfaceChanged:

public void onCreate(Bundle state) { log("onCreate"); 
    try { 
     super.onCreate(state); 
     setContentView(R.layout.main); 
     text = (TextView) findViewById(R.id.text); 
     surface = (SurfaceView) findViewById(R.id.surface); 
     int type = SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS; 
     surface.getHolder().setType(type);//REQUIRED:API10 
     surface.getHolder().addCallback(this); 
     camera = Camera.open(); 
     camera.setDisplayOrientation(90); // portrait mode only 
    } catch (Exception e) { 
     showException(e); 
    } 
} 


public void surfaceChanged(SurfaceHolder sh, int format, int w, int h) { log("surfaceChanged"); 
    try { 
     camera.stopPreview(); 
     Size s = camera.getParameters().getPreviewSize(); 
     LayoutParams params = surface.getLayoutParams(); 
     params.height = w*s.width/s.height; // portrait mode only 
     surface.setLayoutParams(params); 
     camera.setPreviewDisplay(sh); 
     camera.setPreviewCallback(this); 
     camera.startPreview(); 
    } catch (Exception ex) { 
     showException(ex); 
    } 
} 

Czytając liczne artykuł zdałem sobie sprawę setPreviewCallback może zawieść jeśli kamera nie ma w pełni zainicjalizowanego urządzenia SurfaceHolder.

Mam nadzieję, że to pomoże ...

+0

Sup'b Works Fine.Thanks –