首页 > 代码库 > Virual Recent Service

Virual Recent Service

1. MainActivity.java

package com.jianli.virtualrecent;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;

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";
	
	@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);
		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);
		}else{
			stopService(intent);
			editor.putBoolean(KEY_PREF_VIRTUAL_RECENT_SERVICE_STARTED, false);			
		}
		editor.commit();
		finish();

		super.onResume();
	}
}


2. 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.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
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 VRS_TOGGLE_RECENT_INTENT = "com.android.systemui.recent.action.TOGGLE_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 mPreviousX = 0;
	private static float mPreviousY = 0;

	private static boolean bIsMoved = false;

	@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;
		wmParams.x = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_X, 0);
		wmParams.y = mSharedPreferences.getInt(KEY_PREFERENCES_VRS_WINDOW_Y, 0);
		mPreviousX = wmParams.x;
		mPreviousY = wmParams.y;
		wmParams.width = 77;
		wmParams.height = 77;
		
		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");
					mPreviousX = event.getRawX();
					mPreviousY = event.getRawY();
					break;
				case MotionEvent.ACTION_MOVE:
					SecLog.e(TAG, "onTouch, ACTION_MOVE");

					if(Math.abs(mPreviousX - event.getRawX()) < 10 && Math.abs(mPreviousY - event.getRawY()) < 10)
						return false;

					bIsMoved = true;
					wmParams.x = (int) (event.getRawX() - mFloatLayout.getMeasuredWidth()/2);
					wmParams.y = (int) (event.getRawY() - mStatusBarHeight - mFloatLayout.getMeasuredHeight()/2);
					mWindowManager.updateViewLayout(mFloatLayout, wmParams);
					break;
				case MotionEvent.ACTION_UP:
					SecLog.e(TAG, "onTouch, ACTION_UP");
					
					if(true == bIsMoved){
						bIsMoved = 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();

						return false;
					}
					Intent intent = new Intent(VRS_TOGGLE_RECENT_INTENT);
					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);
					break;
				default:
					SecLog.e(TAG, "onTouch,event="+event.getActionMasked());
					break;
				}
				
				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;
    }
}


3. 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();
	}

}


4. Manifest.java

<?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" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".MainActivity"
            android:theme="@android:style/Theme.NoDisplay"
            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>
    </application>

</manifest>


5. 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"
    tools:context="${relativePackage}.${activityClass}" >

</RelativeLayout>


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

Virual Recent Service