2017-11-24 3 views
0

So habe ich eine sehr einfache Kamera-Implementierung. Mein Ziel ist es, automatisch alle 10 Sekunden zwischen der vorderen und hinteren Kamera umzuschalten, bis Sie auf Knopfdruck stehen bleiben.Automatische und automatische Umschaltung der Kamera

ist hier mein MainActivity:

public class MainActivity extends Activity { 
    private Camera mCamera = null; 
    private CameraView mCameraView = null; 
    private CountDownTimer countDownTimer; 
    private int mCamId = 0; 

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

     startCam(); 

     if(mCamera != null) { 
      mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data 
      FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view); 
      camera_view.addView(mCameraView);//add the SurfaceView to the layout 
     } 

     //btn to close the application 
     ImageButton imgClose = (ImageButton)findViewById(R.id.imgClose); 
     imgClose.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       System.exit(0); 
      } 
     }); 
    } 

    private void startCam() { 
     try{ 
      //you can use open(int) to use different cameras 
      mCamId = mCamId == 0 ? 1 : 0; 
      mCamera = Camera.open(mCamId); 
      switchCam(); 

     } catch (Exception e){ 
      Log.d("ERROR", "Failed to get camera: " + e.getMessage()); 
     } 
    } 

    private void switchCam() { 
     //10 seconds 
     countDownTimer = new CountDownTimer(10000, 1000) { 

      @Override 
      public void onTick(long l) { 
       Log.d(TAG, l + " left"); 
      } 

      @Override 
      public void onFinish() { 
       cleanup(); 
       startCam(); 
      } 
     }.start(); 
    } 

    public void cleanup() { 
     Log.i(TAG, "Switching Camera"); 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
      mCamera.release(); 
      mCamera = null; 

     } 
    } 
} 

Und hier ist meine CameraView Klasse:

public class CameraView extends SurfaceView implements SurfaceHolder.Callback{ 

    private SurfaceHolder mHolder; 
    private Camera mCamera; 

    public CameraView(Context context, Camera camera){ 
     super(context); 

     mCamera = camera; 
     mCamera.setDisplayOrientation(90); 
     //get the holder and set this class as the callback, so we can get camera data here 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL); 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder surfaceHolder) { 
     try{ 
      //when the surface is created, we can set the camera to draw images in this surfaceholder 
      mCamera.setPreviewDisplay(surfaceHolder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      Log.d("ERROR", "Camera error on surfaceCreated " + e.getMessage()); 
     } 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) { 
     //before changing the application orientation, you need to stop the preview, rotate and then start it again 
     if(mHolder.getSurface() == null)//check if the surface is ready to receive camera data 
      return; 

     try{ 
      mCamera.stopPreview(); 
     } catch (Exception e){ 
      //this will happen when you are trying the camera if it's not running 
     } 

     //now, recreate the camera preview 
     try{ 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      Log.d("ERROR", "Camera error on surfaceChanged " + e.getMessage()); 
     } 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) { 
     //our app has only one screen, so we'll destroy the camera in the surface 
     //if you are unsing with more screens, please move this code your activity 
     mCamera.stopPreview(); 
     mCamera.release(); 
    } 

Die erste Kamera ohne Probleme gestartet. Die Schnittstelle friert jedoch beim Umschalten der zweiten Kamera, also nach 10 Sekunden, in ein statisches Bild ein. Ich kann es nicht beheben. Wo irre ich mich?

Minimal, Complete, prüfbare und kompilierbare-Code: LINK

+1

Wird die gesamte Anwendung eingefroren? Gibt es etwas Nützliches in der Logcat-Ausgabe? Der Link zum mitgelieferten Quellcode ist tot! – Al0x

+0

@ Al0x Ich habe den Link sofort aktualisiert! Nein, nur die Kamera friert ein! –

Antwort

0

Ihre CameraView ist nicht mit dem MainActivity synchronisiert. Beide halten Bezug auf mCamera, aber wenn die Aktivität die Kamera wechselt, wird die Ansicht nicht informiert.

Die minimale Änderung an Ihrem Code wäre:

  1. den Code bewegen, die mCameraView zu startCam() schafft.
  2. In cleanup() statt mCamera.stopPreview()etc Entfernen mCameraView vom FrameLayout.

Nun, wenn das Timer-Ereignis geschieht, ruft der Rahmen CameraView.SurfaceDestroyed()mCamera freizugeben, und nach, dass Sie einen neuen CameraView für die nach vorn gerichteten Kamera erstellen.

Ein paar zusätzliche Hinweise:

  1. Sie können das gleiche halten CameraView wenn Sie seine mCamera tauschen.
  2. Es ist eine schlechte Übung Camera.open() auf dem UI-Thread auszuführen, dieser Aufruf kann auf einigen Geräten langsam sein und sogar ANR verursachen.
  3. Der bevorzugte Weg ist use a background HandlerThread, so dass die Kamera Rückrufe auch im Hintergrund passieren.
  4. Google hat dies in der neuen camera2-API behoben (verfügbar auf Lollipop und höher). Ihre minSdkVersion ist 21, Sie haben alle Gründe, diese neue API zu verwenden.
  5. Verwenden Sie FLAG_KEEP_SCREEN_ON, während die Kameravorschau aktiv ist.
-1

Was Sie im Moment tun:

Im onCreate Methode Sie zum FrameLayout nach startCam Aktualisierung().

 if(mCamera != null) { 
     mCameraView = new CameraView(this, mCamera);//create a SurfaceView to show camera data 
     FrameLayout camera_view = (FrameLayout)findViewById(R.id.camera_view); 
     camera_view.addView(mCameraView);//add the SurfaceView to the layout 
    } 

Wenn die Kamera schaltet man die alte Kamera freigeben und die neuen öffnen, aber Sie vergessen auch die FrameLayout zu aktualisieren. Das Problem ist also nicht, dass irgendetwas "einfriert", sondern der Wechsel zur neuen Kamera in Ihrer GUI nicht aktualisiert wird.

Wie Ihr Problem zu beheben:

Bei dem Verfahren switchCam() müssen Sie auch die FrameLayout aktualisieren, so wie Sie in der onCreate Methode taten.

Ein Arbeitsbeispiel des switchCam() -Methode würde wie folgt:

private void switchCam() { 
     //10 seconds 
     countDownTimer = new CountDownTimer(10000, 1000) { 

      @Override 
      public void onTick(long l) { 
       Log.d(TAG, l + " left"); 
      } 

      @Override 
      public void onFinish() { 
       cleanup(); 
       startCam(); 
       if(mCamera != null) { 
        mCameraView = new CameraView(getApplicationContext(), mCamera);//create a SurfaceView to show camera data 
        FrameLayout camera_view = 
(FrameLayout)findViewById(R.id.camera_view); 
    if((camera_view).getChildCount() > 0) 
        { 
         camera_view.removeAllViews(); 
        } 
        camera_view.addView(mCameraView);//add the SurfaceView to the layout 
       } 
      } 
     }.start(); 
    } 

Wenn dies allein das Problem nicht lösen, können Sie auch die folgenden versuchen könnten:

Ändern der uses-feature in Ihrer AndroidManifest hardware.camera zu hardware.camera2 als hardware.camera ist veraltet.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="in.harjot.andorid.cameraswap"> 
... 
    <uses-feature android:name="android.hardware.camera2" /> 
... 
</manifest> 

Auf meinem Nexus5X die App schien auch ein Problem mit Berechtigungen zu haben, so dass ich folgendes zum onCreate Verfahren VOR startCam() hinzugefügt genannt wird (ohne dass dies konnte ich eigentlich nicht sehen alles):

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

    if (ContextCompat.checkSelfPermission(this, 
      Manifest.permission.CAMERA) 
      != PackageManager.PERMISSION_GRANTED) { 

      ActivityCompat.requestPermissions(this, 
        new String[]{Manifest.permission.CAMERA}, 
        1); 
    } 

    startCam(); 
    ... 
} 
+1

Können Sie die Änderung im vollständigen Code vornehmen, damit dies funktioniert? Ich bin verwirrt, wo ich den Ausschnitt setzen muss! Danke übrigens! –

+0

Meine Antwort enthält jetzt ein Arbeitsbeispiel der Methode switchCam(). – Al0x

+0

Funktioniert nicht! Die App friert immer noch ein! –

Verwandte Themen