配色: 字号:
在Activity,Service,Window中监听Home键和返回键的一些思考,如何把事件传递出来的做法!
2016-10-08 | 阅:  转:  |  分享 
  
在Activity,Service,Window中监听Home键和返回键的一些思考,如何把事件传递出来的做法!

一.Activity监听返回键



这个其实大家都知道,首先我们要了解流程,你要屏蔽这个返回键,那你就要拿到这个返回键的事件了,所以我们要监听了,而在Activity中,有两种做法,首先,系统是提供了返回键的监听的

/

返回键监听

/

@Override

publicvoidonBackPressed(){

//super.onBackPressed();

}



我们只要不让使用父类的onBackPressed方法,那返回键就没作用了,还有一种办法就是系统提供的按键监听的方法了

/

按键监听

@paramkeyCode

@paramevent

@return

/

@Override

publicbooleanonKeyDown(intkeyCode,KeyEventevent){

switch(keyCode){

caseKeyEvent.KEYCODE_BACK:

//返回键

Toast.makeText(this,"返回键",Toast.LENGTH_SHORT).show();

break;

}

returnsuper.onKeyDown(keyCode,event);

}



onKeyDown是按下的动作,键盘按下的动作就可以,他可以监听到很多的按键,比如数字键,当然,现在数字键的手机还是比较少的,KeyEvent为我们封装了绝大多数的监听,我们来看一下演示的效果



二.Service中监听Home键



onKeyDown中有监听Home键的方法,但是你会发现监听起来是无效的,这里其实可以通过广播的形式来监听Home键,不光适用在Service,同样的也可以适用在Activity中,我们新建一个HomeService

packagecom.liuguilin.keyevevtsample;



/

项目名:KeyEvevtSample

包名:com.liuguilin.keyevevtsample

文件名:HomeService

创建者:LGL

创建时间:2016/8/2011:00

描述:Home键监听

/



importandroid.app.Service;

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.content.IntentFilter;

importandroid.os.IBinder;

importandroid.widget.Toast;



publicclassHomeServiceextendsService{



//监听Home

privateHomeWatcherReceivermHomeKeyReceiver;

publicstaticfinalStringSYSTEM_DIALOG_REASON_KEY="reason";

publicstaticfinalStringSYSTEM_DIALOG_REASON_HOME_KEY="homekey";



@Override

publicIBinderonBind(Intentintent){

returnnull;

}



@Override

publicvoidonCreate(){

super.onCreate();



//注册Home监听广播

mHomeKeyReceiver=newHomeWatcherReceiver();

finalIntentFilterhomeFilter=newIntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

registerReceiver(mHomeKeyReceiver,homeFilter);

}



@Override

publicvoidonDestroy(){

super.onDestroy();



//取消监听

unregisterReceiver(mHomeKeyReceiver);

}



/

监听Home键

/

classHomeWatcherReceiverextendsBroadcastReceiver{



@Override

publicvoidonReceive(Contextcontext,Intentintent){

Stringaction=intent.getAction();

if(action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)){

Stringreason=intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);

if(SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)){

Toast.makeText(context,"Home按键",Toast.LENGTH_SHORT).show();

}

}

}

}

}



OK,为了测试,我们加上两个button




xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center"

android:orientation="vertical"

android:padding="10dp">




android:id="@+id/openHome"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="打开Home监听"/>




android:id="@+id/closeHome"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="关闭Home监听"/>







同时增加两个点击事件

findViewById(R.id.openHome).setOnClickListener(newView.OnClickListener(){

@Override

publicvoidonClick(Viewview){

startService(newIntent(MainActivity.this,HomeService.class));

}

});

findViewById(R.id.closeHome).setOnClickListener(newView.OnClickListener(){

@Override

publicvoidonClick(Viewview){

stopService(newIntent(MainActivity.this,HomeService.class));

}

});



对了,别忘记了注册一下Service





好的,我们来检验一下效果吧



OK

三.在Window中监听返回键



这里,其实也是我项目中的一个需求,首选,我们先不说逻辑,先把window写好,我们为了阅读性,我们再新建一个Service——WindowService,同时去注册一下



1

1

而我们的需求,就是启动一个service,service里加载一个window,但是这样做其实是拿不到我们的按键时间的,都给其他人拿走了,但是这些都是后话了,我们先把window的代码写好

packagecom.liuguilin.keyevevtsample;



/

项目名:KeyEvevtSample

包名:com.liuguilin.keyevevtsample

文件名:WindowService

创建者:LGL

创建时间:2016/8/2011:11

描述:窗口服务

/



importandroid.app.Service;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.graphics.PixelFormat;

importandroid.os.IBinder;

importandroid.view.View;

importandroid.view.WindowManager;

importandroid.widget.Button;



publicclassWindowServiceextendsServiceimplementsView.OnClickListener{



//窗口管理器

privateWindowManagerwm;

//view

privateViewmView;

//布局参数

privateWindowManager.LayoutParamslayoutParams;

//取消window

privateButtonbtnCloseWindow;



@Override

publicIBinderonBind(Intentintent){

returnnull;

}



@Override

publicvoidonCreate(){

super.onCreate();

initWindow();

}



/

初始化Window

/

privatevoidinitWindow(){

//窗口管理器

wm=(WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

//布局参数

layoutParams=newWindowManager.LayoutParams();

layoutParams.width=WindowManager.LayoutParams.MATCH_PARENT;

layoutParams.height=WindowManager.LayoutParams.MATCH_PARENT;

layoutParams.flags=

//WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|不能触摸

WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

//格式

layoutParams.format=PixelFormat.TRANSLUCENT;

//类型

layoutParams.type=WindowManager.LayoutParams.TYPE_PHONE;



mView=View.inflate(getApplicationContext(),R.layout.layout_window_item,null);

btnCloseWindow=(Button)mView.findViewById(R.id.btnCloseWindow);

btnCloseWindow.setOnClickListwww.hunanwang.netener(this);

}



@Override

publicintonStartCommand(Intentintent,intflags,intstartId){

//显示window

wm.addView(mView,layoutParams);

returnSTART_STICKY;

}



@Override

publicvoidonDestroy(){

super.onDestroy();

}



/

点击事件



@paramview

/

@Override

publicvoidonClick(Viewview){

switch(view.getId()){

caseR.id.btnCloseWindow:

//取消window

wm.removeView(mView);

break;

}

}

}



这里有一点要注意的地方,首先,window是需要权限的





好的,为了测试,我们些个按钮


android:id="@+id/openWindow"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="打开Window"

android:textAllCaps="false"/>



同时给他加上点击事件

findViewById(R.id.openWindow).setOnClickListener(newView.OnClickListener(){

@Override

publicvoidonClick(Viewview){

startService(newIntent(MainActivity.this,WindowService.class));

}

});



OK,到这里,我们的window算是写好了,但是写好了,也就出来我们今天要探讨的问题了



你这个Window,拿不到返回事件,所以我按返回键的时候Activity退出了,window还在,那window就是没有拿到这个事件了,那我们应该怎么去拿到这个事件呢?我们怎么按返回键先退出Window再退出Activity呢?其实我们只要注意这行代码

mView=View.inflate(getApplicationContext(),R.layout.layout_window_item,null);

1

1

我们这里也是有一个View的,我们可用把这个事件给拦截过来,这都是有可能的,想到了就去做,那我们最终要怎么去做?我们可用重写这个view,把事件通过接口的方式绑定在这个window上,如果不听不明白,你可以跟我一起来看下这段代码,我们这个view,我给他一个容器,那我们就重写LinearLayout

packagecom.liuguilin.keyevevtsample;



/

项目名:KeyEvevtSample

包名:com.liuguilin.keyevevtsample

文件名:SessionLinearLayout

创建者:LGL

创建时间:2016/8/2011:33

描述:事件分发/拦截返回按钮

/



importandroid.content.Context;

importandroid.util.AttributeSet;

importandroid.view.KeyEvent;

importandroid.widget.LinearLayout;



publicclassSessionLinearLayoutextendsLinearLayout{





privateDispatchKeyEventListenermDispatchKeyEventListener;



publicSessionLinearLayout(Contextcontext){

super(context);

}



publicSessionLinearLayout(Contextcontext,AttributeSetattrs){

super(context,attrs);

}



publicSessionLinearLayout(Contextcontext,AttributeSetattrs,intdefStyleAttr){

super(context,attrs,defStyleAttr);

}



@Override

publicbooleandispatchKeyEvent(KeyEventevent){

if(mDispatchKeyEventListener!=null){

returnmDispatchKeyEventListener.dispatchKeyEvent(event);

}

returnsuper.dispatchKeyEvent(event);

}



publicDispatchKeyEventListenergetDispatchKeyEventListener(){

returnmDispawww.shanxiwang.nettchKeyEventListener;

}



publicvoidsetDispatchKeyEventListener(DispatchKeyEventListenermDispatchKeyEventListener){

this.mDispatchKeyEventListener=mDispatchKeyEventListener;

}



//监听接口

publicstaticinterfaceDispatchKeyEventListener{

booleandispatchKeyEvent(KeyEventevent);

}



}

我在这里,只是把他作为一个中转站,把事件给传递出来就好了,那我们现在window加载的layout的根布局就是他了




xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:alpha="0.3"

android:background="@color/colorAccent"

android:gravity="center"

android:orientation="vertical">






android:id="@+id/btnCloseWindow"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="关闭窗口"/>







那我们的View也是他了,我们直接来看详细的代码吧

packagecom.liuguilin.keyevevtsample;



/

项目名:KeyEvevtSample

包名:com.liuguilin.keyevevtsample

文件名:WindowService

创建者:LGL

创建时间:2016/8/2011:11

描述:窗口服务

/



importandroid.app.Service;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.graphics.PixelFormat;

importandroid.os.IBinder;

importandroid.view.KeyEvent;

importandroid.view.View;

importandroid.view.WindowManager;

importandroid.widget.Button;



publicclassWindowServiceextendsServiceimplementsView.OnClickListener{



//窗口管理器

privateWindowManagerwm;

//view

privateSessionLinearLayoutmView;

//布局参数

privateWindowManager.LayoutParamslayoutParams;

//取消window

privateButtonbtnCloseWindow;



@Override

publicIBinderonBind(Intentintent){

returnnull;

}



@Override

publicvoidonCreate(){

super.onCreate();

initWindow();

}



/

初始化Window

/

privatevoidinitWindow(){

//窗口管理器

wm=(WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);

//布局参数

layoutParams=newWindowManager.LayoutParams();

layoutParams.width=WindowManager.LayoutParams.MATCH_PARENT;

layoutParams.height=WindowManager.LayoutParams.MATCH_PARENT;

layoutParams.flags=

//WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|不能触摸

WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH

;

//格式

layoutParams.format=PixelFormat.TRANSLUCENT;

//类型

layoutParams.type=WindowManager.LayoutParams.TYPE_PHONE;



mView=(SessionLinearLayout)View.inflate(getApplicationContext(),R.layout.layout_window_item,null);

btnCloseWindow=(Button)mView.findViewById(R.id.btnCloseWindow);

btnCloseWindow.setOnClickListener(this);



//监听返回键

mView.setDispatchKeyEventListener(mDispatchKeyEventListener);

}

/

返回鍵监听

/

privateSessionLinearLayout.DispatchKeyEventListenermDispatchKeyEventListener=newSessionLinearLayout.DispatchKeyEventListener(){



@Override

publicbooleandispatchKeyEvent(KeyEventevent){

if(event.getKeyCode()==KeyEvent.KEYCODE_BACK){

if(mView.getParent()!=null){

wm.removeView(mView);

}

returntrue;

}

returnfalse;

}

};



@Override

publicintonStartCommand(Intentintent,intflags,intstartId){

//显示window

wm.addView(mView,layoutParams);

returnSTART_STICKY;

}



@Override

publicvoidonDestroy(){

super.onDestroy();

}



/

点击事件



@paramview

/

@Override

publicvoidonClick(Viewview){

switch(view.getId()){

caseR.id.btnCloseWindow:

//取消window

wm.removeView(mView);

break;

}

}

}

OK,我们这里只是用了一个小技巧而已,但是在实际开发当中还是很实用的,我们直接来看效果



献花(0)
+1
(本文系网络学习天...首藏)