1. VirtualRecentService.java
package com.jianli.virtualrecent;
import java.lang.reflect.Field;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.os.Vibrator;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageButton;
import android.widget.LinearLayout;
@SuppressLint("InflateParams")
public class VirtualRecentService extends Service {
private static final String TAG = "VirtualRecentService";
private static final String PREFERENCES_VIRTUAL_RECENT_SERVICE = "preferences_virtual_recent_service";
private static final String KEY_PREFERENCES_VRS_WINDOW_X = "key_preferences_vrs_window_x";
private static final String KEY_PREFERENCES_VRS_WINDOW_Y = "key_preferences_vrs_window_y";
private static final String KEY_PREFERENCES_VRS_STATUSBAR_HEIGHT = "key_preferences_vrs_statusbar_height";
private static final String KEY_PREFERENCES_VRS_SCREEN_WIDTH = "key_preferences_vrs_screen_width";
private static final String KEY_PREFERENCES_VRS_SCREEN_HEIGHT = "key_preferences_vrs_screen_height";
private static String VRS_TOGGLE_RECENT_INTENT = "com.android.systemui.recent.action.TOGGLE_RECENTS";
// private static final String VRS_TOGGLE_RECENT_INTENT = "com.android.systemui.recents.SHOW_RECENTS";
private SharedPreferences mSharedPreferences;
private LinearLayout mFloatLayout;
private WindowManager.LayoutParams wmParams;
private WindowManager mWindowManager;
private ImageButton mBtnImage;
private static int mStatusBarHeight = 0;
private static float mPreviousTouchX = 0;
private static float mPreviousTouchY = 0;
private static float mTouchRelativeX = 0;
private static float mTouchRelativeY = 0;
private static boolean bIsMoved = false;
private static boolean bIsLongClicked = false;
private static final int GESTURE_LENGTH = 100;
@Override
public IBinder onBind(Intent arg0) {
SecLog.e(TAG, "onBind");
return null;
}
@Override
public void onCreate() {
SecLog.e(TAG, "onCreate");
super.onCreate();
}
@Override
public void onDestroy() {
SecLog.e(TAG, "onDestroy");
if(mFloatLayout != null)
{
mWindowManager.removeView(mFloatLayout);
}
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
SecLog.e(TAG, "onStartCommand");
mSharedPreferences = getSharedPreferences(PREFERENCES_VIRTUAL_RECENT_SERVICE, Activity.MODE_PRIVATE);
LayoutInflater inflater = LayoutInflater.from(getApplication());
mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null);
mBtnImage = (ImageButton)mFloatLayout.findViewById(R.id.btn_recent);
mStatusBarHeight = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_STATUSBAR_HEIGHT, 0);
if(0 == mStatusBarHeight){
mStatusBarHeight = getStatusBarHeight(getBaseContext());
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(KEY_PREFERENCES_VRS_STATUSBAR_HEIGHT, mStatusBarHeight);
editor.commit();
}
createFloatView();
bIsMoved = false;
return super.onStartCommand(intent, flags, startId);
}
private void createFloatView() {
SecLog.e(TAG, "createFloatView");
wmParams = new WindowManager.LayoutParams();
mWindowManager = (WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE);
wmParams.type = LayoutParams.TYPE_PHONE;
wmParams.format = PixelFormat.RGBA_8888;
wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;
wmParams.gravity = Gravity.LEFT | Gravity.TOP;
if(mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_X, 0) == 0){
wmParams.x = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_SCREEN_WIDTH, 0)/2;
wmParams.y = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_SCREEN_HEIGHT, 0)/2;
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(KEY_PREFERENCES_VRS_WINDOW_X, wmParams.x);
editor.putInt(KEY_PREFERENCES_VRS_WINDOW_Y, wmParams.y);
editor.commit();
}else {
wmParams.x = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_X, 0);
wmParams.y = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_Y, 0);
}
wmParams.width = LayoutParams.WRAP_CONTENT;
wmParams.height = LayoutParams.WRAP_CONTENT;
mWindowManager.addView(mFloatLayout, wmParams);
mBtnImage.setOnTouchListener(new OnTouchListener(){
@Override
public boolean onTouch(View arg0, MotionEvent event) {
SecLog.e(TAG, "onTouch");
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:
SecLog.e(TAG, "onTouch, ACTION_DOWN");
mPreviousTouchX = event.getRawX();
mPreviousTouchY = event.getRawY();
mTouchRelativeX = event.getX();
mTouchRelativeY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
SecLog.e(TAG, "onTouch, ACTION_MOVE");
if(Math.abs(mPreviousTouchX - event.getRawX()) < 10 && Math.abs(mPreviousTouchY - event.getRawY()) < 10)
return false;
bIsMoved = true;
wmParams.x = (int) (event.getRawX() - mFloatLayout.getMeasuredWidth()/2);
wmParams.y = (int) (event.getRawY() - mStatusBarHeight - mFloatLayout.getMeasuredHeight()/2);
// wmParams.x = (int) (event.getRawX() - mTouchRelativeX);
// wmParams.x = (int) (event.getRawY() - mTouchRelativeY - mStatusBarHeight);
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
break;
case MotionEvent.ACTION_UP:
SecLog.e(TAG, "onTouch, ACTION_UP");
if(true == bIsMoved){
bIsMoved = false;
if(bIsLongClicked) {
bIsLongClicked = false;
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(KEY_PREFERENCES_VRS_WINDOW_X, wmParams.x);
editor.putInt(KEY_PREFERENCES_VRS_WINDOW_Y, wmParams.y);
editor.commit();
}else{
wmParams.x = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_X, 0);
wmParams.y = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_Y, 0);
mWindowManager.updateViewLayout(mFloatLayout, wmParams);
if(event.getRawX() - mPreviousTouchX > GESTURE_LENGTH){
Intent intent = new Intent(VRS_TOGGLE_RECENT_INTENT);
if(android.os.Build.VERSION.SDK_INT > 20) {
intent.setClassName("com.android.systemui", "com.android.systemui.recents.RecentsActivity");
}else{
intent.setClassName("com.android.systemui", "com.android.systemui.recent.RecentsActivity");
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
}else if(event.getRawX() - mPreviousTouchX < 0-GESTURE_LENGTH){
Intent intent = new Intent(getBaseContext(), StartAdminActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
}else if(event.getRawY() - mPreviousTouchY > GESTURE_LENGTH){
}else if(event.getRawY() - mPreviousTouchY < 0-GESTURE_LENGTH){
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
}
}
}
break;
default:
SecLog.e(TAG, "onTouch,event="+event.getActionMasked());
break;
}
return false;
}
});
mBtnImage.setOnLongClickListener(new OnLongClickListener(){
@Override
public boolean onLongClick(View arg0) {
SecLog.e(TAG, "onLongClick");
bIsLongClicked = true;
Vibrator vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(100);
return false;
}
});
}
@Override
public boolean onUnbind(Intent intent) {
SecLog.e(TAG, "onUnbind");
return super.onUnbind(intent);
}
public static int getStatusBarHeight(Context context){
SecLog.e(TAG, "getStatusBarHeight");
Class<?> c = null;
Object obj = null;
Field field = null;
int x = 0, statusBarHeight = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
return statusBarHeight;
}
}
2. VirtualRecentBootReceiver.java
package com.jianli.virtualrecent;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.widget.Toast;
public class VirtualRecentBootReceiver extends BroadcastReceiver {
private static final String TAG = "VirtualRecentBootReceiver";
private static final String PREFERENCES_VIRTUAL_RECENT_SERVICE = "preferences_virtual_recent_service";
private static final String KEY_PREF_VIRTUAL_RECENT_SERVICE_STARTED = "key_pref_virtual_recent_service_started";
@Override
public void onReceive(Context context, Intent arg1) {
SecLog.e(TAG, "onReceive");
Toast.makeText(context, "Boot complete", Toast.LENGTH_LONG).show();
Intent intent = new Intent(context, VirtualRecentService.class);
context.startService(intent);
SharedPreferences mSharedPreferences = context.getSharedPreferences(PREFERENCES_VIRTUAL_RECENT_SERVICE, Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(KEY_PREF_VIRTUAL_RECENT_SERVICE_STARTED, true);
editor.commit();
}
}
3. StartAdminActivity.java
package com.jianli.virtualrecent;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
public class StartAdminActivity extends Activity {
private DevicePolicyManager policyManager;
private ComponentName componentName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
policyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
componentName = new ComponentName(this, DeviceLockReceiver.class);
if(policyManager.isAdminActive(componentName)){
policyManager.lockNow();
}else{
activeManage();
}
finish();
super.onResume();
}
private void activeManage(){
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "简易手势");
startActivity(intent);
}
}
4. MainActivity.java
package com.jianli.virtualrecent;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.DisplayMetrics;
public class MainActivity extends Activity {
private static final String TAG = "VirtualRecent";
private static final String PREFERENCES_VIRTUAL_RECENT_SERVICE = "preferences_virtual_recent_service";
private static final String KEY_PREF_VIRTUAL_RECENT_SERVICE_STARTED = "key_pref_virtual_recent_service_started";
private static final String KEY_PREFERENCES_VRS_SCREEN_WIDTH = "key_preferences_vrs_screen_width";
private static final String KEY_PREFERENCES_VRS_SCREEN_HEIGHT = "key_preferences_vrs_screen_height";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SecLog.e(TAG, "onCreate");
}
@Override
protected void onDestroy() {
SecLog.e(TAG, "onDestroy");
super.onDestroy();
}
@Override
protected void onPause() {
SecLog.e(TAG, "onPause");
super.onPause();
}
@Override
protected void onResume() {
SecLog.e(TAG, "onResume");
SharedPreferences mSharedPreferences = getSharedPreferences(PREFERENCES_VIRTUAL_RECENT_SERVICE, Activity.MODE_PRIVATE);
if(mSharedPreferences.getInt(KEY_PREFERENCES_VRS_SCREEN_HEIGHT, 0) == 0){
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenHeight = dm.heightPixels;
int screenWidth = dm.widthPixels;
SecLog.e(TAG, "screenHeight="+screenHeight+",screenWidth="+screenWidth);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putInt(KEY_PREFERENCES_VRS_SCREEN_HEIGHT, screenHeight);
editor.putInt(KEY_PREFERENCES_VRS_SCREEN_WIDTH, screenWidth);
editor.commit();
}
SharedPreferences.Editor editor = mSharedPreferences.edit();
Intent intent = new Intent(this, VirtualRecentService.class);
if(mSharedPreferences.getBoolean(KEY_PREF_VIRTUAL_RECENT_SERVICE_STARTED, false) == false){
startService(intent);
editor.putBoolean(KEY_PREF_VIRTUAL_RECENT_SERVICE_STARTED, true);
}
editor.commit();
super.onResume();
}
}
5. DeviceLockReceiver.java
package com.jianli.virtualrecent;
import android.app.admin.DeviceAdminReceiver;
import android.content.Context;
import android.content.Intent;
public class DeviceLockReceiver extends DeviceAdminReceiver {
@Override
public void onDisabled(Context context, Intent intent) {
super.onDisabled(context, intent);
}
@Override
public void onEnabled(Context context, Intent intent) {
super.onEnabled(context, intent);
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}
6. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jianli.virtualrecent"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".MainActivity"
android:theme="@android:style/Theme.Light"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".VirtualRecentService">
</service>
<receiver android:name="VirtualRecentBootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED">
</action>
</intent-filter>
</receiver>
<receiver
android:name=".DeviceLockReceiver"
android:label="@string/app_name"
android:description="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/lock_screen"/>
<intent-filter>
<action
android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
</intent-filter>
</receiver>
<activity
android:name=".StartAdminActivity"
android:theme="@android:style/Theme.NoDisplay" >
</activity>
</application>
</manifest>
7. activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context="${relativePackage}.${activityClass}" >
<ImageView
android:id="@+id/iv_intro"
android:src="@drawable/intro"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
8. float_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageButton
android:id="@+id/btn_recent"
android:background="#00000000"
android:src="@drawable/recent_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
9. xml/lock_screen.xml
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android" >
<uses-policies>
<!-- 锁定屏幕 -->
<force-lock />
</uses-policies>
</device-admin>