在配置文件中添加悬浮窗权限和手电所需要的权限
<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干货文章
欢迎关注我们,一起讨论技术,扫描和长按下方的二维码可快速关注我们
网友评论