Android片段中的手电筒 - SurfaceView

Posted

技术标签:

【中文标题】Android片段中的手电筒 - SurfaceView【英文标题】:Flashlight in Android fragment - SurfaceView 【发布时间】:2014-09-17 12:58:14 【问题描述】:

我正在尝试为本地音乐会开发手电筒应用程序。这是一个更大的应用程序的一部分,所以它在一个片段中。这是代码:

首先我声明了这个类和它的变量:

public class ConcertFragment extends Fragment 

    ToggleButton btnFlashlight;
    View rootView;

    private Camera cam;
    private boolean hasFlash;
    boolean hasCamera;
    boolean isFlashOn;
    Parameters params;

    public ConcertFragment() 
    

接下来是 onActivityCreated 方法,它返回 getCamera 方法(进一步声明):

    @Override
    public void onActivityCreated(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        getCamera();
    

然后我创建构建布局的onCreateView 方法:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

        rootView = inflater.inflate(R.layout.fragment_concert, container, false);

        hasFlash = getActivity().getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);

        if (!hasFlash) 
            // device doesn't support flash
            // Show alert message and close the application
            AlertDialog alert = new AlertDialog.Builder(getActivity()).create();

            alert.setTitle("No Flash");
            alert.setMessage("Sorry, device is not flash supported.");
            alert.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new android.content.DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialog, int which) 

                
            );
            alert.show();
        

        btnFlashlight = (ToggleButton) rootView.findViewById(R.id.toggleButton);
        btnFlashlight.setOnCheckedChangeListener(new OnCheckedChangeListener() 

            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) 
                if (isFlashOn) 
                    // turn off flash
                    turnOffFlash();
                 else 
                    // turn on flash
                    turnOnFlash();
                
            
        );

        return rootView;
    

开启闪光灯的方法:

    private void turnOnFlash() 
        if (!isFlashOn) 
            if (cam == null || params == null) 
                return;
            

            params = cam.getParameters();
            params.setFlashMode(Parameters.FLASH_MODE_TORCH);
            cam.setParameters(params);
            cam.startPreview();
            isFlashOn = true;

            // changing button/switch image
            toggleButtonImage();
        
    

关闭闪光灯的方法:

    private void turnOffFlash() 
        if (isFlashOn) 
            if (cam == null || params == null) 
                return;
            

            params = cam.getParameters();
            params.setFlashMode(Parameters.FLASH_MODE_OFF);
            cam.setParameters(params);
            cam.stopPreview();
            isFlashOn = false;

            // changing button/switch image
            toggleButtonImage();
        
    

相机参数设置方法:

       private void getCamera() 
            if (cam != null) 
                try 
                    cam = Camera.open();
                    params = cam.getParameters();
                    cam.startPreview();
                    hasCamera = true;

                 catch (RuntimeException e) 
                    Log.e("Camera Error. Failed to Open. Error: ", e.getMessage());
                
            
               

       private void toggleButtonImage()
            if(isFlashOn)
                btnFlashlight.setBackgroundResource(R.drawable.btn_switch_on);
            else
                btnFlashlight.setBackgroundResource(R.drawable.btn_switch_off);
            
        
   

打开和关闭手电筒的切换按钮会打开和关闭,但我的 Nexus 5 背面的手电筒永远不会打开。

我使用的相关权限如下:

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

有人可以帮忙吗?

【问题讨论】:

您介意剥离代码以仅显示代码的相关部分吗?真的很长。 打开闪光灯和关闭闪光灯这两个例程似乎很好。您是否设置了正确的权限以允许使用此功能? 有没有人发现我该如何解决这个问题?任何帮助表示赞赏:) 【参考方案1】:

我也在努力解决同样的问题。您需要在布局中的按钮上方添加 SurfacePreview:

 <SurfaceView
    android:id="@+id/PREVIEW"
    android:layout_
    android:layout_/>

目前我的 Fragment 看起来像这样:

public class FlashlightFragment extends Fragment implements SurfaceHolder.Callback 

ImageButton btnSwitch;
//flag to detect flash is on or off
private boolean isLighOn = false;

private Camera camera;
Parameters params;

@Override
public void onStart() 
    super.onStart();
    SurfaceView preview = (SurfaceView)getView().findViewById(R.id.PREVIEW);
    SurfaceHolder mHolder = preview.getHolder();
    mHolder.addCallback(this);


@Override
public void onPause()
    super.onPause();
    turnOffFlash();


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    View view = inflater.inflate(R.layout.flashlight_fragment,
            container, false);

    // flash switch button
    btnSwitch = (ImageButton) view.findViewById(R.id.flashlight_button);

    // displaying button image
    toggleButtonImage();

    // Switch button click event to toggle flash on/off
    btnSwitch.setOnClickListener(new View.OnClickListener() 

        @Override
        public void onClick(View v) 
            if (isLighOn) 
                // turn off flash
                turnOffFlash();
             else 
                // turn on flash
                turnOnFlash();
            
        
    );

    return view;


// Turning On flash
private void turnOnFlash() 

    if (!isLighOn) 
        if (camera == null || params == null) 
            return;
        
        params = camera.getParameters();
        params.setFlashMode(Parameters.FLASH_MODE_TORCH);
        camera.setParameters(params);
        camera.startPreview();
        isLighOn = true;

        // changing button/switch image
        toggleButtonImage();
    



// Turning Off flash
private void turnOffFlash() 

    if (isLighOn) 
        if (camera == null || params == null) 
            return;
        

        params = camera.getParameters();
        params.setFlashMode(Parameters.FLASH_MODE_OFF);
        camera.setParameters(params);
        camera.stopPreview();
        isLighOn = false;

        // changing button/switch image
        toggleButtonImage();
    


/*
 * Toggle switch button images
 * changing image states to on / off
 * */
private void toggleButtonImage()
    if(isLighOn)
        btnSwitch.setImageResource(R.drawable.icon_bulb_on);
    else
        btnSwitch.setImageResource(R.drawable.icon_bulb_off);
    


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



@Override
public void surfaceDestroyed(SurfaceHolder holder) 
    if (camera != null) 
        camera.stopPreview();
        camera.setPreviewCallback(null);
        camera.release();
        camera = null;
    


@Override
public void surfaceCreated(SurfaceHolder holder) 
    if (camera == null) 
        camera = Camera.open();
        params = camera.getParameters();
        try 
            camera.setPreviewDisplay(holder);
         catch (IOException e) 
            camera.release();
            camera = null;
        
    

这似乎在我的 Nexus 5 上运行良好,但在 Xperia Z 上强制关闭 camera.setPreviewDisplay(mHolder); 我还不能解决这个问题。

希望这会有所帮助。

【讨论】:

嗨@Niels,我会试试的,然后会回复你。 谢谢 Neils,它成功了 :) 如果我设法让它在全球范围内的 Android 操作系统上运行,我会更新这篇文章,而不仅仅是在我的 Nexus 5 上。在此期间,请您发送给我们LogCat 与您在 Xperia 上遇到的错误? 它工作得很好,现在似乎正在 xperia 上工作,我猜这是与自定义 rom 相关的东西。 欢迎您,如果您发现任何代码改进,请告诉我,我是 Android 的初级开发人员,所以可能会犯一些错误。 这对我有用(Xperia Z3),谢谢! Android API 指南中的小注释:注意:使用 Camera.open() 时始终检查异常。如果相机正在使用或不存在,未能检查异常将导致您的应用程序被系统关闭。

以上是关于Android片段中的手电筒 - SurfaceView的主要内容,如果未能解决你的问题,请参考以下文章

Android 以编程方式打开手电筒按钮

在 zxing 片段库中打开/关闭手电筒

有啥方法可以访问 Android 中的手电筒灯状态。我想以编程方式检查闪光灯是处于开启状态还是关闭状态

如何让手电筒应用程序中的手电筒关闭?

Android开启手电筒功能(完美适配Android4x,5x,6x)

Android : 如何使用 WEBRTC android io.pristine.libjingle:11139 打开手电筒