单单上传一个service类我想就够了,在activity中启动这个service。
实现的功能是切换到主界面的时候显示悬浮图标,进入APP的时候取消悬浮图标。
4.0以上的系统如果想显示的话,需要在应用里面选择显示悬浮图标才可以。
代码主要是借助网上的资源,自己添加了一个响应点击事件的功能。
另外我这个类还具有锁屏的功能,这一块请使用者自己忽略掉。
public class ZMLockService extends Service {
Context context;
private Intent zdLockIntent = null;
private int phoneState = 0;
private KeyguardManager mKeyguardManager = null;
private KeyguardManager.KeyguardLock mKeyguardLock = null;
private View.OnClickListener mClickListener;
public static final String OPERATION = "operation";
public static final int OPERATION_SHOW = 100;
public static final int OPERATION_HIDE = 101;
private static final int HANDLE_CHECK_ACTIVITY = 200;
private boolean isAdded = false; // 是否已增加悬浮窗
private static WindowManager wm;
private static WindowManager.LayoutParams params;
private Button btn_floatView;
private List<String> homeList; // 桌面应用程序包名列表
private ActivityManager mActivityManager;
@Override
public IBinder onBind(Intent intent) {
Log_I("log");
return null;
}
@Override
public void onCreate() {
super.onCreate();
this.context = this;
Log_I("启动了Service");
MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener();
// 取得TelephonyManager
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
// 將電話狀態的Listener加到取得TelephonyManager
telephonyManager.listen(myPhoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
zdLockIntent = new Intent(ZMLockService.this, LockActivity.class);
zdLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
/* 注册广播 */
IntentFilter mScreenOnFilter = new IntentFilter(
"android.intent.action.SCREEN_ON");
ZMLockService.this.registerReceiver(mScreenOnReceiver, mScreenOnFilter);
/* 注册广播 */
IntentFilter mScreenOffFilter = new IntentFilter(
"android.intent.action.SCREEN_OFF");
mScreenOffFilter.setPriority(Integer.MAX_VALUE);
ZMLockService.this.registerReceiver(mScreenOffReceiver,
mScreenOffFilter);
// 创建悬浮框
homeList = getHomes();
createFloatView();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);
switch (operation) {
case OPERATION_SHOW:
mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);
break;
case OPERATION_HIDE:
mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
break;
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
}
Log_I("结束了Service");
ZMLockService.this.unregisterReceiver(mScreenOnReceiver);
ZMLockService.this.unregisterReceiver(mScreenOffReceiver);
// 如果因为手动关闭的原因关闭的话,重新启动该service
// if(this.getSharedPreferences(Constant.SP_JS,
// 0).getString(Constant.SP_JS_LOCK, "1").equals("1")){
// startService(new Intent(ZMLockService.this, ZMLockService.class));
// }
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case HANDLE_CHECK_ACTIVITY:
if (isHome()) {
if (!isAdded) {
wm.addView(btn_floatView, params);
isAdded = true;
}
} else {
if (isAdded) {
wm.removeView(btn_floatView);
isAdded = false;
}
}
mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);
break;
}
}
};
// 屏幕变亮的广播,我们要隐藏默认的锁屏界面
private BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.SCREEN_ON")) {
mKeyguardManager = (KeyguardManager) context
.getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
mKeyguardLock.disableKeyguard();
}
}
};
// 屏幕变暗/变亮的广播 , 我们要调用KeyguardManager类相应方法去解除屏幕锁定
private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (((action.equals("android.intent.action.SCREEN_OFF") || action
.equals("android.intent.action.SCREEN_ON")) && phoneState == 0)) {
// Log.e("TEST", "启动锁屏,phoneState:"+phoneState);
mKeyguardManager = (KeyguardManager) context
.getSystemService(Context.KEYGUARD_SERVICE);
mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
// 屏蔽手机内置的锁屏
mKeyguardLock.disableKeyguard();
Log_I("启动LockActivity,Time" + new Date().getTime());
// 启动该第三方锁屏
startActivity(zdLockIntent);
}
}
};
/**
* 创建悬浮窗
*/
private void createFloatView() {
btn_floatView = new Button(getApplicationContext());
btn_floatView.setBackgroundResource(R.drawable.float_view);
wm = (WindowManager) getApplicationContext().getSystemService(
Context.WINDOW_SERVICE);
params = new WindowManager.LayoutParams();
// 设置window type
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
/*
* 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 那么优先级会降低一些,
* 即拉下通知栏不可见
*/
params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明
// 设置Window flag
params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
/*
* 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
* wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL |
* LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;
*/
// 设置悬浮窗的长得宽
params.width = 100;
params.height = 100;
// 设置悬浮窗的Touch监听
btn_floatView.setOnTouchListener(new OnTouchListener() {
int lastX;
int lastY;
int paramX;
int paramY;
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
paramX = params.x;
paramY = params.y;
Log_I("down");
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
params.x = paramX + dx;
params.y = paramY + dy;
// 更新悬浮窗位置
wm.updateViewLayout(btn_floatView, params);
Log_I("move");
break;
case MotionEvent.ACTION_UP:
if(Math.abs(event.getRawX()-lastX)<5&&Math.abs(event.getRawY()-lastY)<5){
Toast.makeText(context, "别点我,好痛哦!", Toast.LENGTH_SHORT).show();
}
Log_I("up");
break;
}
return true;
}
});
wm.addView(btn_floatView, params);
isAdded = true;
}
/**
* 获得属于桌面的应用的应用包名称
*
* @return 返回包含所有包名的字符串列表
*/
private List<String> getHomes() {
List<String> names = new ArrayList<String>();
PackageManager packageManager = this.getPackageManager();
// 属性
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(
intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo ri : resolveInfo) {
names.add(ri.activityInfo.packageName);
}
return names;
}
/**
* 判断当前界面是否是桌面
*/
public boolean isHome() {
if (mActivityManager == null) {
mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
}
List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
return homeList.contains(rti.get(0).topActivity.getPackageName());
}
void Log_I(String log) {
LogHelper.Log_I(this.getClass().getSimpleName(), log);
}
public View.OnClickListener getmClickListener() {
return mClickListener;
}
public void setmClickListener(View.OnClickListener mClickListener) {
this.mClickListener = mClickListener;
}
class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String phoneNumber) {
switch (state) {
// 電話狀態是閒置的
case TelephonyManager.CALL_STATE_IDLE:
phoneState = TelephonyManager.CALL_STATE_IDLE;
break;
// 電話狀態是接起的
case TelephonyManager.CALL_STATE_OFFHOOK:
phoneState = TelephonyManager.CALL_STATE_OFFHOOK;
break;
// 電話狀態是響起的
case TelephonyManager.CALL_STATE_RINGING:
phoneState = TelephonyManager.CALL_STATE_RINGING;
break;
default:
break;
}
}
}
}