首页 > 代码库 > Easy Gesture Service

Easy Gesture Service

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=http://www.mamicode.com/"@drawable/intro">

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=http://www.mamicode.com/"@drawable/recent_button">

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>


Easy Gesture Service