zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

android悬浮框设置,支持点击事件。

Android事件 设置 支持 点击 悬浮
2023-09-11 14:18:52 时间

单单上传一个service类我想就够了,在activity中启动这个service。

实现的功能是切换到主界面的时候显示悬浮图标,进入APP的时候取消悬浮图标。

4.0以上的系统如果想显示的话,需要在应用里面选择显示悬浮图标才可以。

代码主要是借助网上的资源,自己添加了一个响应点击事件的功能。

另外我这个类还具有锁屏的功能,这一块请使用者自己忽略掉。

public class ZMLockService extends Service {

	Context context;
	private Intent zdLockIntent = null;
	private int phoneState = 0;
	private KeyguardManager mKeyguardManager = null;
	private KeyguardManager.KeyguardLock mKeyguardLock = null;
	private View.OnClickListener mClickListener;

	public static final String OPERATION = "operation";
	public static final int OPERATION_SHOW = 100;
	public static final int OPERATION_HIDE = 101;

	private static final int HANDLE_CHECK_ACTIVITY = 200;

	private boolean isAdded = false; // 是否已增加悬浮窗
	private static WindowManager wm;
	private static WindowManager.LayoutParams params;
	private Button btn_floatView;

	private List<String> homeList; // 桌面应用程序包名列表
	private ActivityManager mActivityManager;

	@Override
	public IBinder onBind(Intent intent) {
		Log_I("log");

		return null;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		this.context = this;
		Log_I("启动了Service");

		MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener();
		// 取得TelephonyManager
		TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		// 將電話狀態的Listener加到取得TelephonyManager
		telephonyManager.listen(myPhoneStateListener,
				PhoneStateListener.LISTEN_CALL_STATE);

		zdLockIntent = new Intent(ZMLockService.this, LockActivity.class);
		zdLockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

		/* 注册广播 */
		IntentFilter mScreenOnFilter = new IntentFilter(
				"android.intent.action.SCREEN_ON");
		ZMLockService.this.registerReceiver(mScreenOnReceiver, mScreenOnFilter);

		/* 注册广播 */
		IntentFilter mScreenOffFilter = new IntentFilter(
				"android.intent.action.SCREEN_OFF");
		mScreenOffFilter.setPriority(Integer.MAX_VALUE);
		ZMLockService.this.registerReceiver(mScreenOffReceiver,
				mScreenOffFilter);

		// 创建悬浮框
		homeList = getHomes();
		createFloatView();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {

		flags = START_STICKY;

		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);

		int operation = intent.getIntExtra(OPERATION, OPERATION_SHOW);
		switch (operation) {
		case OPERATION_SHOW:
			mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
			mHandler.sendEmptyMessage(HANDLE_CHECK_ACTIVITY);
			break;
		case OPERATION_HIDE:
			mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
			break;
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		if (mHandler != null) {
			mHandler.removeMessages(HANDLE_CHECK_ACTIVITY);
		}
		Log_I("结束了Service");
		ZMLockService.this.unregisterReceiver(mScreenOnReceiver);
		ZMLockService.this.unregisterReceiver(mScreenOffReceiver);
		// 如果因为手动关闭的原因关闭的话,重新启动该service
		// if(this.getSharedPreferences(Constant.SP_JS,
		// 0).getString(Constant.SP_JS_LOCK, "1").equals("1")){
		// startService(new Intent(ZMLockService.this, ZMLockService.class));
		// }
	}

	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case HANDLE_CHECK_ACTIVITY:
				if (isHome()) {
					if (!isAdded) {
						wm.addView(btn_floatView, params);
						isAdded = true;
					}
				} else {
					if (isAdded) {
						wm.removeView(btn_floatView);
						isAdded = false;
					}
				}
				mHandler.sendEmptyMessageDelayed(HANDLE_CHECK_ACTIVITY, 1000);
				break;
			}
		}
	};

	// 屏幕变亮的广播,我们要隐藏默认的锁屏界面
	private BroadcastReceiver mScreenOnReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {

			if (intent.getAction().equals("android.intent.action.SCREEN_ON")) {
				mKeyguardManager = (KeyguardManager) context
						.getSystemService(Context.KEYGUARD_SERVICE);
				mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
				mKeyguardLock.disableKeyguard();
			}
		}

	};

	// 屏幕变暗/变亮的广播 , 我们要调用KeyguardManager类相应方法去解除屏幕锁定
	private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (((action.equals("android.intent.action.SCREEN_OFF") || action
					.equals("android.intent.action.SCREEN_ON")) && phoneState == 0)) {

				// Log.e("TEST", "启动锁屏,phoneState:"+phoneState);
				mKeyguardManager = (KeyguardManager) context
						.getSystemService(Context.KEYGUARD_SERVICE);
				mKeyguardLock = mKeyguardManager.newKeyguardLock("zdLock 1");
				// 屏蔽手机内置的锁屏
				mKeyguardLock.disableKeyguard();
				Log_I("启动LockActivity,Time" + new Date().getTime());
				// 启动该第三方锁屏
				startActivity(zdLockIntent);
			}
		}

	};

	/**
	 * 创建悬浮窗
	 */
	private void createFloatView() {
		btn_floatView = new Button(getApplicationContext());
		btn_floatView.setBackgroundResource(R.drawable.float_view);

		wm = (WindowManager) getApplicationContext().getSystemService(
				Context.WINDOW_SERVICE);
		params = new WindowManager.LayoutParams();

		// 设置window type
		params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
		/*
		 * 如果设置为params.type = WindowManager.LayoutParams.TYPE_PHONE; 那么优先级会降低一些,
		 * 即拉下通知栏不可见
		 */

		params.format = PixelFormat.RGBA_8888; // 设置图片格式,效果为背景透明

		// 设置Window flag
		params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
				| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		/*
		 * 下面的flags属性的效果形同“锁定”。 悬浮窗不可触摸,不接受任何事件,同时不影响后面的事件响应。
		 * wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL |
		 * LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;
		 */

		// 设置悬浮窗的长得宽
		params.width = 100;
		params.height = 100;

		// 设置悬浮窗的Touch监听
		btn_floatView.setOnTouchListener(new OnTouchListener() {

			int lastX;
			int lastY;
			int paramX;
			int paramY;

			public boolean onTouch(View v, MotionEvent event) {
				
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					lastX = (int) event.getRawX();
					lastY = (int) event.getRawY();
					paramX = params.x;
					paramY = params.y;
					Log_I("down");
					break;
				case MotionEvent.ACTION_MOVE:
					int dx = (int) event.getRawX() - lastX;
					int dy = (int) event.getRawY() - lastY;
					params.x = paramX + dx;
					params.y = paramY + dy;
					// 更新悬浮窗位置
					wm.updateViewLayout(btn_floatView, params);
					Log_I("move");
					break;
				case MotionEvent.ACTION_UP:
					if(Math.abs(event.getRawX()-lastX)<5&&Math.abs(event.getRawY()-lastY)<5){
						Toast.makeText(context, "别点我,好痛哦!", Toast.LENGTH_SHORT).show();
					}
					Log_I("up");
					break;
				}
				return true;
			}
		});

		wm.addView(btn_floatView, params);
		isAdded = true;
	}

	/**
	 * 获得属于桌面的应用的应用包名称
	 * 
	 * @return 返回包含所有包名的字符串列表
	 */
	private List<String> getHomes() {
		List<String> names = new ArrayList<String>();
		PackageManager packageManager = this.getPackageManager();
		// 属性
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(
				intent, PackageManager.MATCH_DEFAULT_ONLY);
		for (ResolveInfo ri : resolveInfo) {
			names.add(ri.activityInfo.packageName);
		}
		return names;
	}

	/**
	 * 判断当前界面是否是桌面
	 */
	public boolean isHome() {
		if (mActivityManager == null) {
			mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		}
		List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1);
		return homeList.contains(rti.get(0).topActivity.getPackageName());
	}

	void Log_I(String log) {
		LogHelper.Log_I(this.getClass().getSimpleName(), log);
	}

	public View.OnClickListener getmClickListener() {
		return mClickListener;
	}

	public void setmClickListener(View.OnClickListener mClickListener) {
		this.mClickListener = mClickListener;
	}

	class MyPhoneStateListener extends PhoneStateListener {
		@Override
		public void onCallStateChanged(int state, String phoneNumber) {
			switch (state) {
			// 電話狀態是閒置的
			case TelephonyManager.CALL_STATE_IDLE:
				phoneState = TelephonyManager.CALL_STATE_IDLE;
				break;
			// 電話狀態是接起的
			case TelephonyManager.CALL_STATE_OFFHOOK:
				phoneState = TelephonyManager.CALL_STATE_OFFHOOK;
				break;
			// 電話狀態是響起的
			case TelephonyManager.CALL_STATE_RINGING:
				phoneState = TelephonyManager.CALL_STATE_RINGING;
				break;
			default:
				break;
			}
		}
	}

}