2017-11-24 14 views
0

私は非常に基本的なカメラの実装を持っています。 私の目標は、ボタンをクリックすることで停止するまで、10秒ごとに前面カメラと背面カメラを自動的に切り替えることです。ここで自動的に前面と背面のカメラを切り替える

は私MainActivityです:

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

最初のカメラは問題なく起動します:

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; 

     } 
    } 
} 

そして、ここでは私のCameraViewクラスです。しかしながら、インターフェースは、第2のカメラの切り替え時に、すなわち10秒後に静止画像に凍結する。私はそれを修正することができません。私は間違っていますか?

、最小の完全、検証可能でコンパイル可能なコードLINK

+1

アプリケーション全体がフリーズしますか? logcatの出力に役立つものはありますか?提供されたソースコードへのリンクが死んでいます! – Al0x

+0

@ Al0xすぐにリンクを更新しました!いいえ、ちょうどカメラはフリーズします! –

答えて

0

あなたCameraViewMainActivityと同期されていません。どちらもmCameraを参照していますが、アクティビティがカメラをスワップすると、Viewには通知されません。

あなたのコードに最小限の変更は、次のようになります。

    startCam()mCameraViewを作成するコードを移動し
  1. などクリーンアップ()において
  2. 、代わりのmCamera.stopPreview()、でframeLayoutからmCameraViewを除去します。タイマーイベントが発生したときに

さて、フレームワークは、mCameraを解放し、その後、あなたが前面カメラのための新しいCameraViewを作成しますCameraView.SurfaceDestroyed()を呼び出します。

いくつかの追加の注意事項:

  1. あなたはそのmCameraを交換する場合は、同じCameraViewを維持することができます。
  2. Camera.open()をUIスレッドで実行することは悪い習慣ですが、この呼び出しは一部のデバイスでは遅く、さらにANRを引き起こす可能性があります。
  3. 好ましい方法はuse a background HandlerThreadです。カメラのコールバックもバックグラウンドで発生します。
  4. Googleは新しいcamera2 API(Lollipop以上で使用可能)でこれを修正しました。 minSdkVersionが21の場合、この新しいAPIを使用するすべての理由があります。
  5. カメラプレビューがライブ中にFLAG_KEEP_SCREEN_ONを使用します。
-1

あなたは、現時点では何:あなたはstartCam後でframeLayoutを更新しているのonCreateメソッドで

()。

 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 
    } 

カメラのスイッチを使用すると、古いカメラを解放し、新しいものを開くが、あなたはまたでframeLayoutを更新するのを忘れ。だから問題は何かが「フリーズ」するのではなく、あなたのGUIで新しいカメラへの切り替えが更新されないということです。あなたの問題を解決する方法

:メソッドswitchCam(で

)あなたはまた、あなたがのonCreateメソッドでやったように、でframeLayoutを更新する必要があります。以下のように

switchCam()メソッドの実施例は次のようになります。これだけで問題が解決しない場合は

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

、あなたはまた、次のことを試みることができる:

変更インクルードAndroidManifestのhardware.cameraのhardware.cameraへの使用 - 機能は、hardware.cameraが推奨されなくなりました。私はstartCam()が呼び出される前に(これなしで私が実際に全く何も見えませんでした)のonCreateメソッドに以下を追加して、私のNexus5Xで

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

は、このアプリは、アクセス権に問題があるように見えた。

@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

フルコードを変更してこれを動作させることはできますか?私はスニペットをどこに置かなければならないのか混乱しています!ありがとうbtw! –

+0

私の答えにswitchCam()メソッドの実際の例が含まれています。 – Al0x

+0

動作しません!アプリはまだフリーズ! –

関連する問題