2016-03-09 62 views
2

我正在尝试使用Camera2创建手电筒。我收到错误。当我试图打开或关闭手电筒我得到的错误信息:试图用Android Camera2创建手电筒

android.hardware.camera2.CameraAccessExeption:相机设备已 遇到了一个严重的错误。

MainActivity

package com.nettport.lommelykt; 

import android.Manifest; 
import android.content.pm.PackageManager; 
import android.support.v4.app.ActivityCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.ImageView; 
import android.widget.TextView; 
import android.widget.Toast; 
import android.widget.ToggleButton; 
import android.content.Context; 
import android.graphics.SurfaceTexture; 
import android.hardware.camera2.CameraAccessException; 
import android.hardware.camera2.CameraCaptureSession; 
import android.hardware.camera2.CameraCharacteristics; 
import android.hardware.camera2.CameraDevice; 
import android.hardware.camera2.CameraManager; 
import android.hardware.camera2.CameraMetadata; 
import android.hardware.camera2.CaptureRequest; 
import android.util.Size; 
import android.view.Surface; 
import java.util.ArrayList; 
import java.util.List; 


public class MainActivity extends AppCompatActivity { 
    CameraManager cameraManager; 
    CameraCharacteristics cameraCharacteristics; 

    CameraDevice mCameraDevice; 
    CameraCaptureSession mSession; 

    CaptureRequest.Builder mBuilder; 


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

     // Initialize camera 
     initCamera(); 

     // Click button on or off 
     ToggleButton onOffButton = (ToggleButton) findViewById(R.id.toggleButton); 
     onOffButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       // your click actions go here 
       if (((ToggleButton) v).isChecked()) { 
        changeTextAndIcon(1); 
        turnOnFlashLight(); 
       } else { 
        changeTextAndIcon(0); 
        turnOffFlashLight(); 
       } 
      } 
     }); 

    } 

    /*- Change text and icon ------------------------------------- */ 
    // modus = 1 -> turn on 
    // modus = 0 -> turn off 
    void changeTextAndIcon(int modus) { 
     // Change text 
     TextView statusText = (TextView) findViewById(R.id.textView); 
     if (modus == 1) { 
      statusText.setText("Lommelykten er på"); // Flash is on 
     } else { 
      statusText.setText("Lommelykten er av"); // Flash is off 
     } 

     // Change icon to off 
     ImageView flashlightIcon = (ImageView) findViewById(R.id.imageView); 
     if (modus == 1) { 
      flashlightIcon.setImageResource(R.drawable.flashlight_on); 
     } else { 
      flashlightIcon.setImageResource(R.drawable.flashlight_off); 
     } 
    } 

    private void initCamera() { 
     cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); 
     try { 
      String[] id = cameraManager.getCameraIdList(); 
      if (id != null && id.length > 0) { 
       cameraCharacteristics = cameraManager.getCameraCharacteristics(id[0]); 
       boolean isFlash = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); 
       if (isFlash) { 
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 
         // TODO: Consider calling 
         // ActivityCompat#requestPermissions 
         // here to request the missing permissions, and then overriding 
         // public void onRequestPermissionsResult(int requestCode, String[] permissions, 
         //           int[] grantResults) 
         // to handle the case where the user grants the permission. See the documentation 
         // for ActivityCompat#requestPermissions for more details. 
         return; 
        } 
        cameraManager.openCamera(id[0], new MyCameraDeviceStateCallback(), null); 
        Toast.makeText(this, "Camera initialized", Toast.LENGTH_LONG).show(); 
       } 
      } 
     } 
     catch (CameraAccessException e) 
     { 
      e.printStackTrace(); 
      Toast.makeText(this, "Camera initialization error:\n" + e.toString(), Toast.LENGTH_LONG).show(); 
     } 
    } 

    class MyCameraDeviceStateCallback extends CameraDevice.StateCallback 
    { 

     @Override 
     public void onOpened(CameraDevice camera) 
     { 
      mCameraDevice = camera; 
      // get builder 
      try 
      { 
       mBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 
       List<Surface> list = new ArrayList<Surface>(); 
       SurfaceTexture mSurfaceTexture = new SurfaceTexture(1); 
       Size size = getSmallestSize(mCameraDevice.getId()); 
       mSurfaceTexture.setDefaultBufferSize(size.getWidth(), size.getHeight()); 
       Surface mSurface = new Surface(mSurfaceTexture); 
       list.add(mSurface); 
       mBuilder.addTarget(mSurface); 
       camera.createCaptureSession(list, new MyCameraCaptureSessionStateCallback(), null); 
      } 
      catch (CameraAccessException e) 
      { 
       e.printStackTrace(); 

      } 
     } 

     @Override 
     public void onDisconnected(CameraDevice camera) 
     { 

     } 

     @Override 
     public void onError(CameraDevice camera, int error) 
     { 

     } 
    } 

    private Size getSmallestSize(String cameraId) throws CameraAccessException 
    { 
     Size[] outputSizes = cameraManager.getCameraCharacteristics(cameraId).get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(SurfaceTexture.class); 
     if (outputSizes == null || outputSizes.length == 0) 
     { 
      throw new IllegalStateException("Camera " + cameraId + "doesn't support any outputSize."); 
     } 
     Size chosen = outputSizes[0]; 
     for (Size s : outputSizes) 
     { 
      if (chosen.getWidth() >= s.getWidth() && chosen.getHeight() >= s.getHeight()) 
      { 
       chosen = s; 
      } 
     } 
     return chosen; 
    } 
    class MyCameraCaptureSessionStateCallback extends CameraCaptureSession.StateCallback 
    { 
     @Override 
     public void onConfigured(CameraCaptureSession session) 
     { 
      mSession = session; 
      try 
      { 
       mSession.setRepeatingRequest(mBuilder.build(), null, null); 
      } 
      catch (CameraAccessException e) 
      { 
       e.printStackTrace(); 
      } 
     } 

     @Override 
     public void onConfigureFailed(CameraCaptureSession session) 
     { 

     } 
    } 

    public void turnOnFlashLight() 
    { 
     try 
     { 
      mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH); 
      mSession.setRepeatingRequest(mBuilder.build(), null, null); 
      Toast.makeText(this, "Flash activated", Toast.LENGTH_LONG).show(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      Toast.makeText(this, "Flash failed:\n" + e.toString(), Toast.LENGTH_LONG).show(); 
     } 
    } 

    public void turnOffFlashLight() 
    { 
     try 
     { 
      mBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF); 
      mSession.setRepeatingRequest(mBuilder.build(), null, null); 
      Toast.makeText(this, "Flash disabled", Toast.LENGTH_LONG).show(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      Toast.makeText(this, "Flash failed:\n" + e.toString(), Toast.LENGTH_LONG).show(); 
     } 
    } 

    private void close() 
    { 
     Toast.makeText(this, "Camera closed", Toast.LENGTH_LONG).show(); 
     if (mCameraDevice == null || mSession == null) 
     { 
      return; 
     } 
     mSession.close(); 
     mCameraDevice.close(); 
     mCameraDevice = null; 
     mSession = null; 
    } 

} 

AndroidManifest

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.nettport.lommelykt"> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme" 
     > 
     <activity android:name=".MainActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

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


    <!-- Allows access to the flashlight --> 

    <uses-permission android:name="android.permission.CAMERA" /> 
    <uses-permission android:name="android.permission.FLASHLIGHT" /> 

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


</manifest> 
+0

如果您遇到崩溃,请始终包含您的LogCat。 –

+0

@梭罗,我刚刚面临同样的问题,但我把'SurfaceTexture'声明放在了我的灵活性'onCreate'中。那是Eddy在答复中所说的“将SurfaceTexture存储在MainActivity中”吗?我只是想确认,因为我认为这个问题已经解决,但不希望它在未来重复。 – San

回答

3

你不是抱着你的表面纹理;从它创建的Surface大致等于一个弱指针,并且不会保持SurfaceTexture不被垃圾收集。

看看是否将SurfaceTexture存储在MainActivity中可以解决您的问题。 如果没有,您需要提供崩溃logcat(不只是应用程序日志记录,整个系统),以更详细地了解摄像机服务的抱怨。

+0

真是个好主意!我移动了SurfaceTexture,现在它工作了!非常感谢你! – Solo

0

问题在于SurfaceTexture。当您将SurfaceTexture初始化为局部变量时,它很可能会被垃圾收集。因此将SurfaceTexture作为全局变量。

我在创建FlashLight应用程序时遇到了同样的问题。希望这也能解决你的问题。