美文网首页AndroidAndroid知识Android开发
Android悬浮手电的简单实现,简单但是很实用的功能

Android悬浮手电的简单实现,简单但是很实用的功能

作者: 唐码农 | 来源:发表于2016-12-23 15:53 被阅读310次

在配置文件中添加悬浮窗权限和手电所需要的权限

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!--flashlight-->
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.flash" />

Activity中开启service悬浮窗用来控制,当手机没有手电功能时候,直接就不用开启了,开启了也没有用

if(!FlashLightUtils.hasFlash(MainActivity.this))
{
    Toast.makeText(MainActivity.this,"not flashlight",Toast.LENGTH_LONG).show();
    return;
}
Intent intent=new Intent();
intent.setClass(MainActivity.this,FBService.class);
startService(intent);

service创建悬浮窗(不同机型需要适配,许多手机rom默认关闭的,所以手动去开启,
Android6.0以上解决方案看这篇文章
Android6.0系统悬浮窗权限的问题解决方法
在Service里面onCreate方法里面创建悬浮窗口和控件的点击事件

wManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
mParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;// 系统提示window
mParams.format = PixelFormat.TRANSLUCENT;// 支持透明
// mParams.format = PixelFormat.RGBA_8888;
mParams.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 焦点
mParams.width = WindowManager.LayoutParams.WRAP_CONTENT;// 窗口的宽和高
mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
mParams.gravity = Gravity.START | Gravity.TOP;
mParams.y = 100;
mParams.x = 100;
mParams.windowAnimations = android.R.style.Animation_Toast;
// mParams.alpha = 0.8f;//窗口的透明度
LayoutInflater layoutInflater = LayoutInflater.from(getApplicationContext());
windowView = layoutInflater.inflate(R.layout.float_button_layout, null);
// ivFlashLight = (ImageView)
// windowView.findViewById(R.id.iv_flashlight);
SurfaceView localSurfaceView = (SurfaceView) windowView.findViewById(R.id.sfPreview);
this.holder = localSurfaceView.getHolder();
this.holder.addCallback(this);
windowView.setVisibility(View.VISIBLE);
wManager.addView(windowView, mParams);// 添加窗口
windowView.findViewById(R.id.iv_icon).setOnClickListener(this);

注意这个参数:WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
为了就是使悬浮窗权限比较高,在锁屏状态下能显示出来悬浮窗
如图所示锁屏状态下能显示浮悬浮,方便控制手电使用,



悬浮窗布局SurfaceView为了显示手电准备的

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fb_window"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:padding="1dp">
    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="match_parent"
        android:src="@mipmap/ic_launcher"
        android:layout_height="match_parent" />
    <SurfaceView
        android:id="@+id/sfPreview"
        android:layout_width="0.5dip"
        android:layout_height="0.5dip" />
</FrameLayout>

布局很简单吧 就是使用一个默认的icon的图片和SurfaceView
FlashLight的工具类主要用于闪光灯的各项处理,比如初始化手电,开启手电,关闭手电,是否存在手电和手电是否开启

**
 * 闪光灯控制器工具类
 *
 * @author tangyc
 */
public class FlashLightUtils {

    private static Camera sCamera;

    public FlashLightUtils() {
        try {
            sCamera = Camera.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 初始化闪光灯
     *
     * @param context
     *
     * @return
     */
    public static Camera getCamera(Context context) {
        if (!hasFlash(context))
            return null;
        if (sCamera == null) {
            sCamera = Camera.open();
        }
        return sCamera;
    }

    private static void ensureCamera(Context context) {
        getCamera(context);
    }

    /**
     * 打开闪光灯
     *
     * @param context
     */
    @SuppressLint("NewApi")
    public static void openFlash(Context context) throws Exception {
        ensureCamera(context);
        if (sCamera == null)
            return;
        try {
            Camera.Parameters parameters = sCamera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            sCamera.setParameters(parameters);
            sCamera.startPreview();
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }
    
    public static boolean isOpen() {
        boolean isOpen = false;
        if (sCamera == null)
            return false;
        try {
            Camera.Parameters p = sCamera.getParameters();
            String openString = p.getFlashMode();// 获取闪光灯的状态
            if (openString.equals(Parameters.FLASH_MODE_TORCH)) {
                isOpen = true;//关闭
            } else {
                isOpen = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            isOpen = false;
        }
        return isOpen;
    }
    /**
     * 关闭闪光灯
     */
    public static void closeFlash() {
        if (sCamera == null)
            return;
        try {
            Camera.Parameters parameters = sCamera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            sCamera.setParameters(parameters);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 释放
     */
    public static void release() {
        if (sCamera != null) {
            sCamera.release();
            sCamera = null;
        }
    }
    /**
     * 检查设备是否存在闪光灯
     *
     * @param context
     * @return
     */
    public static boolean hasFlash(Context context) {
        PackageManager pm = context.getPackageManager();
        FeatureInfo[] featureInfos = pm.getSystemAvailableFeatures();
        for (FeatureInfo f : featureInfos) {
            if (PackageManager.FEATURE_CAMERA_FLASH.equals(f.name)) {
                return true;
            }
        }
        return false;
    }


悬浮窗控制手电开关
4

就是是在悬浮按钮中监听点击事件来控制闪光灯的开启和关闭状态
//手电
if(!FlashLightUtils.isOpen()){

    try {
        FlashLightUtils.openFlash(this);
        Toast.makeText(this,"open flashlight",Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(this,"open flashlight fail",Toast.LENGTH_LONG).show();
    }
}else{
    try {
        FlashLightUtils.closeFlash();
        Toast.makeText(this,"close flashlight",Toast.LENGTH_LONG).show();
    } catch (Exception e) {
        Toast.makeText(this,"close flashlight",Toast.LENGTH_LONG).show();
        e.printStackTrace();
    }
}

onDestory方法里面要销毁悬浮窗和释放手电

@Override
public void onDestroy() {
    super.onDestroy();
    if( wManager!=null&&windowView!=null)
    {
        FlashLightUtils.release();
        wManager.removeView(windowView);
    }
}

这样一个简单的悬浮手电就完成了,因为这是一个简单的Demo所以没有细化好多东西 ,比如悬浮窗的拖动效果,开机自启悬浮窗,防止悬浮窗杀死等效果。后面有机会我会继续这这个基础上完善一些功能

源码已经上传到github
需要源码在微信公众号回复:

1222
                                                             END

Android订阅是探讨Android开发的公众号,分享最有价值的Android干货文章
欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们

1480345206391598.jpg

相关文章

网友评论

    本文标题:Android悬浮手电的简单实现,简单但是很实用的功能

    本文链接:https://www.haomeiwen.com/subject/kbmkvttx.html