android 添加灭屏手势动画功能

首先解释一下这个功能,在灭屏时,在屏幕上面进行一些滑动的操作,实现一些功能,像亮屏,进入apk。

还是直接上图吧,看的清楚点。

下面来说下实现这个的思路。这个功能需要驱动上报键值,比如说我在屏幕上画了一个V,驱动就要向上面上报一个事件,所有的上报事件都在PhoneWindowManager.java里面处理。

@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
     ...
     	// add by jueme for gesture wakeup at 20180926
			//C
			case KeyEvent.KEYCODE_C: {//gesture_c_key_value
				
				if (1 == gesture_switch) {
					isWakeKey = true;
					SystemProperties.set("persist.sys.gesture.anim", "15");
					SystemProperties.set("service.bootanim.exit", "0");
					SystemProperties.set("ctl.start", "bootanim");
					mHandler.sendEmptyMessageDelayed(MSG_GESTURE_C, 6000);						
					HandlerDissmisskeyguardLw();			
				}
				break;
			}
			//E
			case KeyEvent.KEYCODE_E: {
			
				if (1 == gesture_switch) {
					isWakeKey = true;
					SystemProperties.set("persist.sys.gesture.anim", "16");
					SystemProperties.set("service.bootanim.exit", "0");
					SystemProperties.set("ctl.start", "bootanim");
					mHandler.sendEmptyMessageDelayed(MSG_GESTURE_E, 6000);	
					HandlerDissmisskeyguardLw();
				}
				break;
			}
			//M
			case KeyEvent.KEYCODE_M: {
				if (1 == gesture_switch) {
					isWakeKey = true;
					SystemProperties.set("persist.sys.gesture.anim", "18");
					SystemProperties.set("service.bootanim.exit", "0");
					SystemProperties.set("ctl.start", "bootanim");
					mHandler.sendEmptyMessageDelayed(MSG_GESTURE_M, 6000);
					HandlerDissmisskeyguardLw();
				}
				break;
			}
			//O
			case KeyEvent.KEYCODE_O: {
				if (1 == gesture_switch) {
					isWakeKey = true;
					SystemProperties.set("persist.sys.gesture.anim", "19");
					SystemProperties.set("service.bootanim.exit", "0");
					SystemProperties.set("ctl.start", "bootanim");
					mHandler.sendEmptyMessageDelayed(MSG_GESTURE_O, 6000);	
					HandlerDissmisskeyguardLw();
				}
				break;
			}
			//?
			case KeyEvent.KEYCODE_BUTTON_5: {
				break;
			}
			//V
			case KeyEvent.KEYCODE_V: {
				if (1 == gesture_switch) {
					isWakeKey = true;
					SystemProperties.set("persist.sys.gesture.anim", "17");
					SystemProperties.set("service.bootanim.exit", "0");
					SystemProperties.set("ctl.start", "bootanim");
					mHandler.sendEmptyMessageDelayed(MSG_GESTURE_V, 6000);
					HandlerDissmisskeyguardLw();
				}
				break;
			}
			//W
			case KeyEvent.KEYCODE_W: {
				if (1 == gesture_switch) {
					isWakeKey = true;
					SystemProperties.set("persist.sys.gesture.anim", "20");
					SystemProperties.set("service.bootanim.exit", "0");
					SystemProperties.set("ctl.start", "bootanim");
					mHandler.sendEmptyMessageDelayed(MSG_GESTURE_W, 6000);
					HandlerDissmisskeyguardLw();
				}
				break;
			}
	
			//UP
			case KeyEvent.KEYCODE_DPAD_UP: {
				Log.e(TAG, "gesture_switch=" + gesture_switch + ", gesture_up=" + gesture_up);
				if (1 == gesture_switch && 1 == gesture_up) {
					isWakeKey = true;
					HandlerDissmisskeyguardLw();
				}
				break;
			}
			//DOWN
			case KeyEvent.KEYCODE_DPAD_DOWN: {
				if (1 == gesture_switch && 1 == gesture_music&&down) {
					controlMusic(event, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
				}
				break;
			}
			//LEFT
			case KeyEvent.KEYCODE_DPAD_LEFT: {
				if (1 == gesture_switch && 1 == gesture_left&&down) {
					controlMusic(event, KeyEvent.KEYCODE_MEDIA_PREVIOUS);
				}
				break;
			}
			//RIGHT
			case KeyEvent.KEYCODE_DPAD_RIGHT: {
				if (1 == gesture_switch && 1 == gesture_right&&down) {
					controlMusic(event, KeyEvent.KEYCODE_MEDIA_NEXT);		// -- NEXTSONG
				}
				break;
			}
			//DOUBLE
			case KeyEvent.KEYCODE_U: {
				if (1 == gesture_switch && 1 == gesture_doubletap) {
					isWakeKey = true;
				}
				break;
			}
			//add end
     ...
}

我这个项目加了几个字母,上下左右滑动,双击的事件。我是在8.0上面添加的,不同版本的代码,这一块的处理都差不多,

isWakeKey = true //把这个设置为true屏幕才会亮

这个是屏幕解锁的代码HandlerDissmisskeyguardLw

private void HandlerDissmisskeyguardLw(){
		            mHandler.postDelayed((new Runnable(){
		                @Override
		                public void run() {
		                    // TODO Auto-generated method stub
		                    if(isKeyguardLocked()){
		                        dismissKeyguardLw(myIKeyguardDismissCallback);
		                    }
		                }}), 50);
}

在7.0的代码不需要传这个回调myIKeyguardDismissCallback,在8.0在dismissKeyguardLw里面把myIKeyguardDismissCallback=callback;

  @Override
  public void dismissKeyguardLw(IKeyguardDismissCallback callback) {
        ...
		myIKeyguardDismissCallback = callback;
        ...
  }

到此,接收到手势并且亮屏解锁的代码已完成。

下面是动画的处理,这里遇到的坑比较多。首先说一下属性动画,实现方式是画一个黑色的背景,然后画一个点,让这个点沿着固定的轨迹运动。这里有两个问题第一,关于轨迹的的坐标不知道如何做;第二不能全屏,想着用悬浮窗盖在最上层,然后在悬浮窗里面实现动画,但是悬浮窗不能遮盖虚拟按键。接着是帧动画,这种实现方式也是不能全屏,而且播放帧动画消耗的资源太多。接下来就是我最终选用的方式了,走系统的开机流程,在开机的时候会播放开机动画,可以利用这个。

调用系统的开机动画很简单,只需要

SystemProperties.set("service.bootanim.exit", "0");
SystemProperties.set("ctl.start", "bootanim");

注意在播放完了后要重新调用

SystemProperties.set("service.bootanim.exit", "1");

否则就会一直在开机界面不能进入系统。

这里做了一个延时发送,就是为了播放完后再退出播放动画

mHandler.sendEmptyMessageDelayed(MSG_GESTURE_C, 6000);
 private class PolicyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            ...
            case MSG_GESTURE_C:
						intent.setClassName(gesture_c_key_value, gesture_c_key_value2);
						intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
						mContext.startActivityAsUser(intent, UserHandle.CURRENT);
						SystemProperties.set("service.bootanim.exit", "1");
						SystemProperties.set("persist.sys.gesture.anim", "0");
						break;
					case MSG_GESTURE_E:
						intent.setClassName(gesture_e_key_value, gesture_e_key_value2);
						intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
						mContext.startActivityAsUser(intent, UserHandle.CURRENT);
						SystemProperties.set("service.bootanim.exit", "1");
						SystemProperties.set("persist.sys.gesture.anim", "0");
						break;
					case MSG_GESTURE_V:
						intent.setClassName(gesture_v_key_value, gesture_v_key_value2);
						intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
						mContext.startActivityAsUser(intent, UserHandle.CURRENT);
						SystemProperties.set("service.bootanim.exit", "1");
						SystemProperties.set("persist.sys.gesture.anim", "0");						
						break;
					case MSG_GESTURE_M:
						intent.setClassName(gesture_m_key_value, gesture_m_key_value2);
						intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
						mContext.startActivityAsUser(intent, UserHandle.CURRENT);
						SystemProperties.set("service.bootanim.exit", "1");
						SystemProperties.set("persist.sys.gesture.anim", "0");
						break;
					case MSG_GESTURE_O:
						intent.setClassName(gesture_o_key_value, gesture_o_key_value2);
						intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
						mContext.startActivityAsUser(intent, UserHandle.CURRENT);
						SystemProperties.set("service.bootanim.exit", "1");
						SystemProperties.set("persist.sys.gesture.anim", "0");
						break;
					case MSG_GESTURE_W:
						intent.setClassName(gesture_w_key_value, gesture_w_key_value2);
						intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
						mContext.startActivityAsUser(intent, UserHandle.CURRENT);
						SystemProperties.set("service.bootanim.exit", "1");
						SystemProperties.set("persist.sys.gesture.anim", "0");
						break;
					// add end
        }
}

这个persist.sys.gesture.anim属性是用来控制当前播放什么动画。

同时还需要修改BootAnimation.cpp文件

status_t BootAnimation::readyToRun() {
    ...
    //add by jueme for gesture wakeup
	char gesture_anim[PROPERTY_VALUE_MAX];
    property_get("persist.sys.gesture.anim", gesture_anim, "0");
		
	switch (atoi(gesture_anim)) {
		case 11:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_up.zip";
			break;
		case 12:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_right.zip";
			break;
		case 13:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_left.zip";
			break;
		case 14:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_down.zip";
			break;
		case 15:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_c.zip";
			break;
		case 16:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_e.zip";
			break;
		case 17:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_v.zip";
			break;
		case 18:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_m.zip";
			break;
		case 19:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_o.zip";
			break;
		case 20:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/gesture_w.zip";
			break;
		default:
			SYSTEM_BOOTANIMATION_FILE = "/system/media/bootanimation.zip";
			break;
	}
	//add end
    ...
}

如果需要添加开关可以在设置里面添加,比较简单

          

到此这个功能添加完成。。。

猜你喜欢

转载自blog.csdn.net/qq_32072451/article/details/83339442