一、适用场景:
在Android系统开发中,需要监听按键、触摸、或者可见窗口大小变化等需求时,你会考虑什么方法来实现呢?通过广播的方式可以实现,但是效果可能并不好。AIDL可以实现跨进程通讯,可以解决以上需求。下面重点分析下如何具体实现,以实现按键监听功能为例,代码按实现后的调用先后来说明。
二、代码说明以及分析实现:
大致的流程图如下
编辑
1、在frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java文件中添加监听接口。在interceptKeyBeforeDispatching()方法中获取event传递给自定义监听类SxListenerManager中。
@Override
public long interceptKeyBeforeDispatching(IBinder focusedToken, KeyEvent event,
int policyFlags) {
*****
*****
if (mSystemBooted) {
//SxListenerManager使用单例,使用前判断是否为null
if(SxListenerManager.getInstance() != null) {
//通过系统原生接口截取event事件,传递给自定义SxListenerManager
boolean status = SxListenerManager.getInstance().postKeyEventToUser(event);
if(status){
return -1;
}
}
}
*****
*****
}
2、SxListenerManager.java类主要用于绑定service和定义接口。IBinder.DeathRecipient用于检测远程对象是否存活,由于服务端经常意外停止,我们需要重启service,可以使用linkToDeath 机制。
public class SxListenerManager {
private final static String TAG = "SxListenerManager";
private static SxListenerManager mInstance = null;
private static ISxInputListener mSxListenerService;
private SxListenerManager() {
bindSxListenerService();
}
public static SxListenerManager getInstance() {
if (mInstance == null) {
synchronized (SxListenerManager.class) {
if (mInstance == null) {
mInstance = new SxListenerManager();
}
}
}
return mInstance;
}
private static void bindSxListenerService() {
IBinder service = ServiceManager.getService("Sx_service");
try {
mSxListenerService = ISxService.Stub.asInterface(service).getListener();
service.linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private static IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.e("SxListenerManager", "===deathRecipient binderDied===");
if (mSxListenerService != null) {
//注销监听和回收资源
mSxListenerService.asBinder().unlinkToDeath(this, 0);
mSxListenerService = null;
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
//service死掉后重启service
bindSxListenerService();
}
}
};
public boolean postKeyEventToUser(KeyEvent event){
boolean ret = false;
try {
ret = mSxListenerService.postKeyEventToUser(event);
} catch (RemoteException e) {
e.printStackTrace();
}
return ret;
}
}
3、ISxInputListener.aidl为AIDL接口类,只定义一个postKeyEventToUser接口,用于传递event事件。
interface ISxInputListener {
boolean postKeyEventToUser(in KeyEvent event);
}
4、SxListenerService.java类继承ISxInputListener,实现postKeyEventToUser方法。该方法调用KeyEventListener类中的sendKeyEventToListener方法。
public class SxListenerService extends ISxInputListener.Stub {
private static final String TAG = "SxListenerService";
public SxListenerService(Context context) {
Log.d(TAG, "====SxListenerService===");
}
@Override
public boolean postKeyEventToUser(KeyEvent event){
boolean ret = false;
Log.d(TAG, "post Key EventToUser = "+event);
if(KeyEventListener.getInstance() != null){
ret = KeyEventListener.getInstance().sendKeyEventToListener(event);
}else{
Log.d(TAG, "KeyEventListener = null ");
}
return ret;
}
}
5、KeyEventListener类
public class KeyEventListener {
private static final String TAG = "KeyEventListener";
private static KeyEventListener mListener = null;
private Context mContext = null;
private RemoteCallbackList mCallbackList = null;
private HashMap mMap = null;
private KeyEventListener() {
mCallbackList = new RemoteCallbackList() {
@Override
public void onCallbackDied(ISxKeyEventClient client) {
mMap.remove(client.asBinder());
}
};
mMap = new HashMap();
}
public static KeyEventListener getInstance() {
if (mListener == null) {
synchronized (KeyEventListener.class) {
if (mListener == null) {
try {
mListener = new KeyEventListener();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
}
return mListener;
}
public void setClient(IBinder client) {
if (client != null) {
ISxKeyEventClient keyEventClient = ISxKeyEventClient.Stub.asInterface(client);
mCallbackList.register(keyEventClient);
mMap.put(client, keyEventClient);
}
}
public void releaseClient(IBinder client) {
if (client != null && mMap.size() > 0) {
ISxKeyEventClient keyEventClient = mMap.get(client);
mCallbackList.unregister(keyEventClient);
mMap.remove(client);
}
}
public void setContext(Context context) {
this.mContext = context;
}
public boolean sendKeyEventToListener(KeyEvent arg0) {
boolean ret = false;
int count = mCallbackList.beginBroadcast();
while (count > 0) {
count--;
try {
ret = mCallbackList.getBroadcastItem(count).onKeyEvent(arg0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mCallbackList.finishBroadcast();
return ret;
}
}
6、ISxKeyEventClient.aidl为AIDL接口类
interface ISxKeyEventClient {
boolean onKeyEvent(in KeyEvent key);
}
7、KeyEventManager.java类,实现最终event事件监听。
public class KeyEventManager{
private static final String TAG = "KeyEventManager";
public OnKeyEventListener mSxKeyEventListener = null;
public KeyEventManager(Context context) {
mSxKeyEventListener = new SxKeyEventListener();
SxKeyListenerManager.getInstance().registerOnKeyEventListener(mSxKeyEventListener);
}
private class SxKeyEventListener implements OnKeyEventListener {
@Override
public boolean onKeyEvent(KeyEvent event) {
//按键监听,所有的event监听均在此处处理
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
int KeyCode = event.getKeyCode();
switch(KeyCode){
case KeyEvent.KEYCODE_HOME:
break;
case KeyEvent.KEYCODE_BACK:
if(!down ){
}
break;
}
return true;
}
}
}
8、SxKeyListenerManager.java类绑定service,注册listener。
public class SxKeyListenerManager {
private final static String TAG = "SxKeyListenerManager";
static volatile SxKeyListenerManager mInstance = null;
private static ISxKeyListener mKeyListenerService = null;
private SxKeyListenerManager() {
bindSxSourceService();
}
public static SxKeyListenerManager getInstance() {
if (mInstance == null) {
synchronized (SxKeyListenerManager.class) {
if (mInstance == null) {
mInstance = new SxKeyListenerManager();
}
}
}
return mInstance;
}
private static void bindSxSourceService() {
IBinder service = ServiceManager.getService("Sx_service");
try {
mKeyListenerService = ISxService.Stub.asInterface(service).getKeyListener();
service.linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
}
private static IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.e("SxKeyListenerManager", "------------deathRecipient binderDied------------");
if (mKeyListenerService != null) {
//注销监听和回收资源
mKeyListenerService.asBinder().unlinkToDeath(this, 0);
mKeyListenerService = null;
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
bindSxSourceService();
}
}
};
private Client mClient;
private ArrayList mListeners = new ArrayList();
private class Client extends ISxKeyEventClient.Stub {
@Override
public boolean onKeyEvent(KeyEvent arg0) throws RemoteException {
boolean ret = false;
for (OnKeyEventListener l : mListeners) {
ret = l.onKeyEvent(arg0);
}
return ret;
}
}
public boolean registerOnKeyEventListener(OnKeyEventListener listener) {
if (mClient == null) {
mClient = new Client();
try {
if(mKeyListenerService != null) {
mKeyListenerService.addClient("KeyEventListener", mClient);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
mListeners.add(listener);
return true;
}
private final Object LOCK = new Object();
public boolean unregisterOnKeyEventListener(OnKeyEventListener listener) {
synchronized (LOCK)
{
mListeners.remove(listener);
if (mListeners.size() == 0 && mClient != null) {
try {
if(mKeyListenerService != null) {
mKeyListenerService.removeClient("KeyEventListener", mClient);
}
mClient = null;
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
}
return true;
}
}
}
9、ISxKeyListener.aidl为AIDL接口类,定义相关的接口。
interface ISxKeyListener {
IBinder getClient(String name);
void addClient(String name,IBinder client);
void removeClient(String name,IBinder client);
}
10、SxKeyListenerService.java类实现相关的接口。
public class SxKeyListenerService extends ISxKeyListener.Stub {
private static final String TAG = "SxKeyListenerService";
public SxKeyListenerService(Context context) {
}
@Override
public IBinder getClient(String name) {
return null;
}
@Override
public void addClient(String name, IBinder client) {
if (name.equals("KeyEventListener")) {
KeyEventListener.getInstance().setClient(client);
}
}
@Override
public void removeClient(String name, IBinder client) {
if (name.equals("KeyEventListener")) {
KeyEventListener.getInstance().releaseClient(client);
}
}
}
11、OnKeyEventListener.java为AIDL接口类。
public interface OnKeyEventListener {
public boolean onKeyEvent(KeyEvent arg0);
}
12、ISxService.aidl类为aidl接口类。
interface ISxService {
ISxInputListener getListener();
ISxKeyListener getKeyListener();
}
13、SxService.java类用于启动所有service。
public class SxService extends Service {
private SxListenerService mSxListenerService = null;
private SxKeyListenerService mSxKeyListenerService = null;
private Context mContext;
public SxService() {
}
@Override
public void onCreate() {
mContext = this;
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
android.os.ServiceManager.addService("Sx_service", mBinder);
return Service.START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
}
private final ISxService.Stub mBinder = new ISxService.Stub() {
@Override
public ISxInputListener getListener() throws RemoteException {
if (mSxListenerService == null) {
mSxListenerService = new SxListenerService(getApplicationContext());
}
return mSxListenerService;
}
@Override
public ISxKeyListener getKeyListener() throws RemoteException {
DebugLog.debug("");
if (mSxKeyListenerService == null) {
mSxKeyListenerService = new SxKeyListenerService(getApplicationContext());
}
return mSxKeyListenerService;
}
}
}
以上内容全部代码基本已实现,除了监听按键,其他需求也是类似的方法。
留言与评论(共有 0 条评论) “” |