2017-06-24 1 views
3

Le problème Lors du nettoyage de mon code, je souhaite déplacer mes méthodes de caméra Android vers une classe distincte, conformément à ce que je considère être les meilleures pratiques. Après avoir cherché toute la journée, j'ai encore du mal à comprendre comment le faire exactement. Le principal problème est que les différences dans les méthodes de mise en œuvre et le passage de l'API de la caméra à l'API camera2 conduisent à des solutions trouvées en ligne que je ne peux pas répliquer. S'il vous plaît noter que je suis un débutant en Java et en tant que tel, c'est probablement une erreur très novice que je ne peux pas résoudre en raison de la variété des informations sur le web.Implémentation d'une classe distincte dans l'activité

Code actuel Mon principal problème est que SurfaceTexture texture = surfaceView.getSurfaceTexture(); dans startCamera() dit Cannot resolve method 'getSurfaceTexture()' et que previewBuilder.addTarget(texture); se plaint de addTarget (android.view.surface) in Builder cannot be applied to (android.graphics.SurfaceTexture).

public class CameraView extends TextureView implements TextureView.SurfaceTextureListener{ 

    private Size previewsize; 
    private CameraDevice cameraDevice; 
    private CaptureRequest.Builder previewBuilder; 
    private CameraCaptureSession previewSession; 
    private final Context context; 
    public SurfaceView surfaceView; 
    public TextureView textureView; 

    public CameraView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     this.context = context; 
    } 

    public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) { 
     // Once the surface is created, simply open a handle to the camera hardware. 
     openCamera(); 
    } 

    public void onSurfaceTextureUpdated(SurfaceTexture texture) { 
    } 

    public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int  width, int height) { 

     try { 
      //cameraDevice.setPreviewDisplay(holder); 

      //cameraDevice.startPreview(); 
     } catch (Exception e){ 
      e.printStackTrace(); 
     } 
    } 

    public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) { 
     // stopPreview(); 
     cameraDevice.close(); 
     return true; 
    } 

    public void openCamera() 
    { 
     CameraManager manager = (CameraManager) context.getSystemService (Context.CAMERA_SERVICE); 
     try 
     { 
      String cameraId = manager.getCameraIdList()[0]; 
      CameraCharacteristics  characteristics=manager.getCameraCharacteristics(cameraId); 
      StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 
      previewsize = map.getOutputSizes(SurfaceTexture.class)[0]; 
      try { 
       manager.openCamera(cameraId, stateCallback, null); 
      } catch (SecurityException e){ 
       e.printStackTrace(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() { 
     @Override 
     public void onOpened(CameraDevice camera) { 
      cameraDevice = camera; 
      startCamera(); 
     } 
     @Override 
     public void onClosed(CameraDevice camera) { 
      // nothing 
     } 
     @Override 
     public void onDisconnected(CameraDevice camera) { 
     } 
     @Override 
     public void onError(CameraDevice camera, int error) { 
     } 
    }; 

    void startCamera() 
    { 
     if (cameraDevice == null || previewsize==null) 
     { 
      return; 
     } 

     SurfaceTexture texture = surfaceView.getSurfaceTexture(); 
texture.setDefaultBufferSize(previewsize.getWidth(),previewsize.getHeight()); 

     Surface surface = new Surface(texture); 
     try 
     { 
      // add all the standard stuff to the previewBuilder 
      previewBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
     } catch (Exception e) {} 
     previewBuilder.addTarget(texture); 
     try 
     { 
      cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() { 
      @Override 
      public void onConfigured(CameraCaptureSession session) { 
       previewSession = session; 
       getChangedPreview(); 
      } 
      @Override 
      public void onConfigureFailed(CameraCaptureSession session{ 
      } 
     },null); 
     } catch (Exception e) {} 
    } 

    void getChangedPreview() 
    { 
     previewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON); 

     HandlerThread thread = new HandlerThread("changed Preview"); 
     thread.start(); 
     Handler handler = new Handler(thread.getLooper()); 
     try 
     { 
      previewSession.setRepeatingRequest(previewBuilder.build(), null, handler); 
     }catch (Exception e){} 
    } 
} 

L'objectif Pour garder mon code propre et compréhensible, je voudrais limiter la classe MainActivity à la commutation entre les vues au lieu d'avoir des tonnes de méthodes là-dedans. Je voudrais activer ma vue de caméra dans mon application en basculant l'objet suivant de INVISIBLE à VISIBLE. D'autres suggestions sont appréciées.

cameraView = (CameraView) findViewById(R.id.camera); 

MainActivity.java doit ressembler à:

public class MainActivity extends AppCompatActivity { 

    private TextView mTextMessage; 
    private CameraView cameraView; 
    private MainSurfaceView mGLView; 
    private TextureView textureView; 

    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener 
     = new BottomNavigationView.OnNavigationItemSelectedListener() { 

     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
      switch (item.getItemId()) { 
       case R.id.navigation_home: 
        mTextMessage.setText(R.string.title_home); 
        return true; 
       case R.id.navigation_dashboard: 
        mTextMessage.setText(R.string.title_dashboard); 
        return true; 
       case R.id.navigation_notifications: 
        mTextMessage.setText(R.string.title_notifications); 
        return true; 
      } 
      return false; 
     } 

    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mTextMessage = (TextView) findViewById(R.id.message); 
     cameraView = (CameraView) findViewById(R.id.camera); 
     mGLView = (MainSurfaceView) findViewById(R.id.glSurfaceView); 
     BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation); 
     navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); 

    } 
} 

Votre aide est appréciée!

+0

Pouvez-vous nous en dire un peu plus sur ce que vous voulez faire/pouvez-vous nous montrer le code pertinent de MainActivity? –

Répondre

0

SurfaceTexture texture = surfaceView.getSurfaceTexture(); dans startCamera() dit Cannot resolve method 'getSurfaceTexture()'

Vous appelez la méthode getSurfaceTexture de surfaceView. surfaceView est un SurfaceView. Jetons un coup d'oeil à la documentation: https://developer.android.com/reference/android/view/SurfaceView.html Apparemment SurfaceView n'a pas de méthode appelée "getSurfaceTexture()". Cependant, une recherche sur Google pour "getSurfaceTexture() Android" nous montre que la méthode appartient à la classe TextureView. Votre classe CameraView a un champ appelé "textureView", donc (je ne sais pas ce que vous voulez atteindre exactement) pouvez appeler la méthode sur ce champ si vous le souhaitez. De plus, votre classe CameraView est un TextureView lui-même (vous le voulez), vous pouvez donc aussi appeler getSurfaceTexture() si vous voulez l'appeler sur la classe elle-même.

previewBuilder.addTarget(texture); se plaint de addTarget (android.view.surface) in Builder cannot be applied to (android.graphics.SurfaceTexture). Jetons un coup d'œil à la documentation à nouveau: https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.Builder.html Apparemment CaptureRequest.builder (le type de previewBuilder) a une méthode appelée addTarget, mais cette méthode accepte seulement la surface! Vous passez une texture. Vous voulez probablement changer texture en surface

+0

Joost, merci pour votre réponse. Changer la texture à la surface pour la deuxième plainte du SDK résout le problème comme je l'ai trouvé plus tôt, bien que je n'étais pas sûr que cela aurait à voir avec le problème. Sur le premier problème, changer cela en 'SurfaceTexture texture = TextureView.getSurfaceTexture();' conduit à une 'Méthode non statique' getSurfaceTexture(); ne peut pas être référencé à partir d'une erreur de contexte statique qui ne m'amène pas plus loin. Pourriez-vous s'il vous plaît faire un suivi? Mon CameraView devrait être une vue de texture oui, basée sur la recherche web. Le but est que je peux juste appeler une vue dans ma MainActivity. – j73951

+0

Vous pouvez résoudre votre premier problème en appelant getSurfaceTexture sur un objet (donc pas une classe) avec le type TextureView. Si vous voulez l'appeler dans le champ textureView, vous pouvez utiliser 'textureView.getSurfaceTexture()'. Si vous voulez l'appeler sur CameraView lui-même (cela me semble étrange), vous pouvez simplement utiliser 'getSurfaceTexture()' ou 'this.getSurfaceTexture()' –

+0

Merci pour les clarifications! J'ai réussi à utiliser getSurfaceTexture(), même si je n'ai pas encore d'entrée de caméra sur l'écran, mais je vais vérifier plus loin et donner un aperçu du code mis à jour pour les autres utilisateurs. Merci encore:) – j73951