Android 桌面浮动框

    最近公司在做一个支付组件。持续做了一个月,我做了三个版本,现在项目突然终止,我也无事可做,就想把这个项目中用到的浮动框效果拿出来,晒一晒,巩固知识的同时
也顺便帮帮有需要的人,也不失为一件乐事。
    该浮动框其实挺简单,就是一个开机广播启动一个后台Service,不断的从内存中查看商城客户端启动,如果启动,就发送一个广播,运行支付组件;当商城退出时,支付组件
也退出。
    先看来效果图:

(注意:该图为私人收藏图,请勿随意转载。)
    下面说说过程与核心代码。
    一、服务随着开机完成自动启动。

        (1)、开机广播接收者代码。BootCompleteReceiver.java

public class BootCompleteReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			Log.i("BootCompleteReceiver", "接到开机广播");
			Intent iAppServiceIntent = new Intent(context, AppService.class);
			context.startService(iAppServiceIntent);
		}

	}

上面代码中的AppService.class是广播接收者启动的服务。
清单文件内的权限和注册。
权限

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

注册

<receiver android:name=".receiver.BootCompleteReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>



(2)、开机后启动的服务AppService.java

public class AppService extends Service {
	private String TAG = "AppService";
	private RunningTaskInfo info;
	private static WindowManager wm;
	private ActivityManager am;
	private PackageManager pm;
	private String actionStart = "com.handaer.receiver.FLOAT_VIEW_START_ACTION"; //自定义action名字,
	private String actionStop = "com.handaer.receiver.FLOAT_VIEW_STOP_ACTION"; //自定义action名字
	Handler handler = new Handler();
	Timer timer = null;
	TimerTask task = new TimerTask() {
		public void run() {
			handler.post(new Runnable() {
				@Override
				public void run() {
					getAppInfo();
				}
			});
		};
	};


	public int onStartCommand(Intent intent, int flags, int startId) {
		if (timer == null) {
			timer = new Timer();
			timer.scheduleAtFixedRate(task, 0, 500);
		}
		return super.onStartCommand(intent, flags, startId);
	};


	@Override
	public IBinder onBind(Intent intent) {


		return null;
	}


	private void getAppInfo() {
		am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
		pm = this.getPackageManager();
		ApplicationInfo actInfo;


		List<RunningTaskInfo> list = am.getRunningTasks(1);
		info = list.get(0);
		ComponentName cn = info.topActivity;
		String name = cn.getPackageName();
		try {
			actInfo = pm.getApplicationInfo(name, PackageManager.GET_META_DATA);
			Bundle metaData = actInfo.metaData;
			Log.i(TAG, "AppService正在运行");
			if (metaData != null) {
				String metaValue = metaData.getString("com.handaer.newhbddemo");
				if ("com.handaer.around".equals(metaValue)
						|| "com.handaer.pay".equals(metaValue)) {
					// 发送自定义广播 com.handaer.receiver.FLOAT_VIEW_START_ACTION
					Intent intent = new Intent();
					intent.setAction(actionStart);
					sendBroadcast(intent);
				}
			} else {
				// 发送自定义广播 com.handaer.receiver.FLOAT_VIEW_STOP_ACTION
				Intent intent = new Intent();
				intent.setAction(actionStop);
				Bundle bundle = new Bundle();
				sendBroadcast(intent);
			}
		   } catch (NameNotFoundException e) {
			e.printStackTrace();
		   }


		}
	}

getAppInfo()中的代码是从内存中获取任务栈第一个任务,然后通过ActivityManager获取到其详细信息中的name,然后判断是否为商城应用,然后再做相应的处理。

(3)、下面是两个自定义广播FloatViewStartReceiver.java 和 FloatViewStopReceiver.java 


FloatViewStartReceiver比较简单,就是启动 FloatWeigtService服务

public class FloatViewStartReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		Log.i("FloatViewStartReceiver", "收到启动广播");
		Intent intentStart = new Intent(context, FloatWeigtService.class);
		try {
			context.startService(intentStart);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

清单文件中注册:

<receiver android:name=".receiver.FloatViewStartReceiver" >
            <intent-filter>
                <action android:name="com.handaer.receiver.FLOAT_VIEW_START_ACTION" />
            </intent-filter>
        </receiver>		

自定义广播接收者FloatViewStopReceiver.java ,接收到广播后会停止 FloatWeigtService 

public class FloatViewStopReceiver extends BroadcastReceiver {

	private RunningServiceInfo runningServiceInfo;
	private String serviceName = "com.handaer.hbdpay.service.FloatWeigtService";

	@Override
	public void onReceive(Context context, Intent intent) {
		ActivityManager am = (ActivityManager) context
				.getSystemService(Context.ACTIVITY_SERVICE);
		PackageManager pm = context.getPackageManager();
		List<ActivityManager.RunningServiceInfo> serviceList = am
				.getRunningServices(Integer.MAX_VALUE);
		if (serviceList.size() == 0) {
			return;
		}
		for (int i = 0; i < serviceList.size(); i++) {
			runningServiceInfo = serviceList.get(i);
			if (runningServiceInfo.service.getClassName().equals(serviceName)) {
				ComponentName name = runningServiceInfo.service;
				Intent i2 = new Intent();
				i2.setComponent(name);
				try {
					context.stopService(i2);
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			}
		}
		

	}

}

在清单文件注册 FloatViewStopReceiver

 <receiver android:name=".receiver.FloatViewStopReceiver" >
            <intent-filter>
                <action android:name="com.handaer.receiver.FLOAT_VIEW_STOP_ACTION" />
            </intent-filter>
         </receiver>

 (4)、下面是 负责创建浮动框的 FloatWeigtService.java ,该服务会创建和取消浮动框。FloatView

public class FloatView extends LinearLayout {

	private WindowManager wm;
	public static int viewWidth;
	public static int viewHeight;
	private int screenWidth;
	private int width;
	private int yDown;
	private int xValueInView;
	private int yValueInView;
	private int xInScreen;
	private int yInScreen;
	private WindowManager.LayoutParams params;
	private ImageView iv_short;

	public FloatView(Context context) {
		super(context);
		wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		screenWidth = wm.getDefaultDisplay().getWidth();
		LayoutInflater inflater = LayoutInflater.from(context);
		View view = inflater.inflate(R.layout.float_view, this);
		iv_short = (ImageView) view.findViewById(R.id.iv_short);
		width = view.getWidth();
		LinearLayout deskView = (LinearLayout) view
				.findViewById(R.id.ll_base_title_view);
		viewWidth = deskView.getLayoutParams().width;
		viewHeight = deskView.getLayoutParams().height;
	}

	public void updataLocation() {
		params.x = (int) (xInScreen - xValueInView);
		params.y = (int) (yInScreen - yValueInView);
		wm.updateViewLayout(this, params);
	}

	public void setParams(WindowManager.LayoutParams params) {
		this.params = params;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
		//按下浮动框后记录浮动框的位置
			xValueInView = (int) event.getX();
			yValueInView = (int) event.getY();
			yDown = (int) event.getRawY();

			xInScreen = (int) event.getRawX();
			yInScreen = (int) (event.getRawY());
			break;
		case MotionEvent.ACTION_MOVE:
		//移动浮动框时,不断的更新浮动框updataLocation()
			xInScreen = (int) event.getRawX();
			yInScreen = (int) (event.getRawY());
			//只有浮动框移动位置才会更新。不加这段代码,当按住浮动框时,浮动框会自己弹开一段距离。可能和我桌面有关系。
			int abs = Math.abs(yInScreen - yDown);
			if (abs != 0) {
				updataLocation();
			}
			break;
		case MotionEvent.ACTION_UP:
		//抬起时,将浮动框靠屏幕右边显示。
			params.x = screenWidth;
			params.y = (int) (yInScreen - yValueInView);
			wm.updateViewLayout(this, params);
			break;

		default:
			break;
		}
		return true;
	}

}

完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值