该篇文章从eoeAndroid搬迁过来的,原文地址:[Android实例] 仿Easy Touch,实现Home键,锁屏,清理内存功能
有的时候我们会面临物理键失灵的情况,这个时候就需要用软件进行代替物理键,苹果有一款软件叫Easy Touch,就是用来代替物理键功能的,而安卓同样也有一款相同名字的软件,在这里,我模仿android的Easy Touch做了部分功能,如实现Home键功能,锁屏和清理内存功能,可能有些不完善的地方,敬请见谅。
1.创建WindowManager窗口,需要设置为WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,即为系统级别的,这样的话,当打开其他应用程序的时候,我们的WindowManager窗口就会存在最上方
private void createWM() {
windowManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
layoutParams = new WindowManager.LayoutParams();
layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
layoutParams.format = PixelFormat.TRANSLUCENT;
layoutParams.flags = WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
}
增加权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
由于Easy Touch有两种界面,一种是展示个小图标,另一种是点击小图标后呈现的功能操作界面,所以这里面我用的是同一个WindowManager窗口,不同的页面进行替换 小图标界面:
iconView = new Button(context); iconView.setBackgroundResource(R.drawable.selector_btn_launcher);
layoutParams.alpha = 0.6f;
layoutParams.x = iconViewX;
layoutParams.y = iconViewY;
layoutParams.width = 98;
layoutParams.height = 98;
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
windowManager.addView(iconView, layoutParams);
功能操作界面:
mainView = LayoutInflater.from(context).inflate(
R.layout.wm_main_layout, null);
layoutParams.alpha = 1f;
layoutParams.x = 0;
layoutParams.y = 0;
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.gravity = layoutParams.gravity = Gravity.LEFT
| Gravity.TOP;
windowManager.addView(mainView, layoutParams);
2.实现操作方法 点击小图标或移动小图标的监听事件:
iconView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
// 获取相对屏幕的坐标,即以屏幕左上角为原点
float rawX = event.getRawX();
// 为状态栏高度 Math.ceil(25
// * context.getResources().getDisplayMetrics().density))
float rawY = (float) (event.getRawY() - stateHeight);
int sumX = (int) (rawX - startRawX);
int sumY = (int) (event.getRawY() - startRawY);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 获取相对View的坐标,即以此View左上角为原点
startX = event.getX();
startY = event.getY();
startRawX = event.getRawX();
startRawY = event.getRawY();
layoutParams.alpha = 1f;
windowManager.updateViewLayout(iconView, layoutParams);
break;
case MotionEvent.ACTION_UP:
Log.i("Log", "sumX=" + sumX + ";sumY=" + sumY);
layoutParams.alpha = 0.6f;
windowManager.updateViewLayout(iconView, layoutParams);
if (sumX > -10 && sumX < 10 && sumY > -10 && sumY < 10) {
addMainView();
} else {
float endRawX = rawX - startX;
float endRawY = rawY - startY;
if (endRawX < width / 2) {
if (endRawX > endRawY) {
updateIconViewPosition(endRawX, 0);
} else if (endRawX > height - event.getRawY()
- 98) {
updateIconViewPosition(endRawX,
(float) (height - stateHeight - 98));
} else {
updateIconViewPosition(0, endRawY);
}
} else {
if (width - endRawX - 98 > endRawY) {
updateIconViewPosition(endRawX, 0);
} else if (width - endRawX - 98 > height
- event.getRawY() - 98) {
updateIconViewPosition(endRawX,
(float) (height - stateHeight - 98));
} else {
updateIconViewPosition(width - 98, endRawY);
}
}
}
startX = 0;
startY = 0;
startRawX = 0;
startRawY = 0;
break;
case MotionEvent.ACTION_MOVE:
if (sumX < -10 || sumX > 10 || sumY < -10 || sumY > 10) {
updateIconViewPosition(rawX - startX, rawY - startY);
}
break;
default:
break;
}
return true;
}
});
}
home键:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_HOME);
activity.startActivity(intent);
锁屏键:
devicePolicyManager = (DevicePolicyManager)activity.getSystemService(Activity.DEVICE_POLICY_SERVICE);
componentName = new ComponentName(activity,PowerAdminreceiver.class);
if (devicePolicyManager.isAdminActive(componentName)) {
devicePolicyManager.lockNow();
} else {// 第一次运行程序
Intent intent = new Intent(
DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
componentName);
intent.putExtra(
DevicePolicyManager.EXTRA_ADD_EXPLANATION,
"One key lock screen need to active");
activity.startActivity(intent);
}
其中PowerAdminreceiver是集成DeviceAdminReceiver,不需要实现什么方法
AndroidManifest.xml里增加
<receiver android:name="com.example.windowmanagertest.PowerAdminreceiver" android:description="@string/app_name" android:label="@string/app_name" android:permission="android.permission.BIND_DEVICE_ADMIN" >
<meta-data android:name="android.app.device_admin" android:resource="@xml/lock_screen_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
在res/xml文件夹下增加lock_screen_admin.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
</uses-policies>
</device-admin>
清理内存:
activityManager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
currentProcessId = android.os.Process.myPid();
long buforeMemory = getAvailMemory();
int count = 0;
RunningAppProcessInfo runningAppProcessInfo = null;
List<RunningAppProcessInfo> runningAppProcessInfos = activityManager
.getRunningAppProcesses();
if (runningAppProcessInfos != null) {
for (int i = 0; i < runningAppProcessInfos.size(); ++i) {
runningAppProcessInfo = runningAppProcessInfos
.get(i);
// 一般数值大于RunningAppProcessInfo.IMPORTANCE_SERVICE
// 的进程即为长时间未使用进程或者空进程
// 一般数值大于RunningAppProcessInfo.IMPORTANCE_VISIBLE
// 的进程都是非可见进程,即在后台运行
if (runningAppProcessInfo.importance > RunningAppProcessInfo.IMPORTANCE_VISIBLE
&& runningAppProcessInfo.pid != currentProcessId) {
String[] pkgList = runningAppProcessInfo.pkgList;
for (int j = 0; j < pkgList.length; ++j) {
activityManager
.killBackgroundProcesses(pkgList[j]);
count++;
}
}
}
String str = "共结束" + count + "个进程;" + "清理"
+ (getAvailMemory() - buforeMemory) + "MB内存";
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
private long getAvailMemory() {
MemoryInfo memoryInfo = new MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
return memoryInfo.availMem / (1024 * 1024);
}
增加权限
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
3.调用WindowManager窗口,由于我将该窗口封装成单例,所以使用方法如下
WMInstance.getInstance(this);
至此,我的大部分代码已经复制粘贴完毕,本人比较懒,很多代码没注释,请见谅
下载地址:项目代码