android - Android fragment 中的手电筒 - SurfaceView

标签 android android-fragments surfaceview flashlight

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

首先我声明了该类及其变量:

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" />

有人可以帮忙吗?

最佳答案

我也面临着同样的问题。您需要在布局中的按钮上方添加 SurfacePreview:

 <SurfaceView
    android:id="@+id/PREVIEW"
    android:layout_width="1dp"
    android:layout_height="1dp"/>

目前我的 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); 我还无法解决该问题。

希望这有帮助。

关于android - Android fragment 中的手电筒 - SurfaceView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24959664/

相关文章:

android - 如何从 Cast 设备接收状态更新

android - AppCompat Action Bar 库不显示添加的 fragment

android - FragmentTransaction replace 实际上不是替换而是将两者绘制在彼此之上

java - Android 相机 SurfaceView 在上面放置 ImageView 覆盖时消失

javascript - 如何启用长按操作以在 android WebView 中下载图像?

android - 下载时播放 mp3 文件?

Android xxx-hdpi 真机

java - 如何在主 Activity 类中插入内部类(Android Studio)

Android 相机像素操作

android - Color_FormatSurface 实现