ActivityManagerService新加listener及触发其回调

2023-11-08

前言

Android版本为7.1,之前调查的时候发现没有太多这个功能实现相关的文章,所以自己来写一篇,第一次分享、记录自己代码,有什么写的不对的地方请见谅。

Android.mk

framework/base/Android.mk中新加一行把新加的aidl文件加入编译

core/java/android/app/ITestListener.aidl

ActivityManager.java

framework/base/core/java/android/app/ActivityManager.java
新加注册监听和注销的接口

import android.app.ITestListener.aidl
public boolean registerTestCallback(ITestListener listener) {
	boolean ret = false;
	try {
		ret = ActivityManagerNative.getDefault().registerTestCallback(listener);
	} catch (RemoteException) {
		ret = false;
		throw e.rethrowFromSystemServer();
	}
	return ret;
}
public boolean unRegisterTestCallback(ITestListener listener) {
	boolean ret = false;
	try {
		ret = ActivityManagerNative.getDefault().unRegisterTestCallback(listener);
	} catch (RemoteException) {
		ret = false;
		throw e.rethrowFromSystemServer();
	}
	return ret;
}

ActivityManagerNative.java

framework/base/core/java/android/app/ActivityManagerNative.java

import android.app.ITestListener.aidl
	case REGISTER_ACTIVITY_FINISH_CALLBACK_TRANSACTION: {
		data.enforceInterface(IActivityManager.descriptor);
		ITestListener listener = ITestListener.Stub.asInterface(data.readStrongBinder());
		boolean result = registerTestCallback(listener);
		reply.writeNoException();
		reply.writeInt(result ? 1 : 0);
		return true;
	}
	case UNREGISTER_ACTIVITY_FINISH_CALLBACK_TRANSACTION: {
		data.enforceInterface(IActivityManager.descriptor);
		ITestListener listener = ITestListener.Stub.asInterface(data.readStrongBinder());
		boolean result = unRegisterTestCallback(listener);
		reply.writeNoException();
		reply.writeInt(result ? 1 : 0);
		return true;
	}
public boolean registerTestCallback(ITestListener listener) throws RemoteException {
	Parcel data = Parcel.obtain();
	Parcel replay = Parcel.obtain();
	data.writeInterfaceToken(IActivityManager.descriptor);
	data.writeStrongInterface(listener);
	mRemote.transact(REGISTER_ACTIVITY_FINISH_CALLBACK_TRANSACTION, data, reply, 0);
	reply.readException();
	boolean res - reply.readInt() != 0;
	data.recycle();
	reply.recycle();
	return res;
}
public boolean unRegisterTestCallback(ITestListener listener) throws RemoteException {
	Parcel data = Parcel.obtain();
	Parcel replay = Parcel.obtain();
	data.writeInterfaceToken(IActivityManager.descriptor);
	data.writeStrongInterface(listener);
	mRemote.transact(UNREGISTER_ACTIVITY_FINISH_CALLBACK_TRANSACTION, data, reply, 0);
	reply.readException();
	boolean res - reply.readInt() != 0;
	data.recycle();
	reply.recycle();
	return res;
}

IActivityManager.java

framework/base/core/java/android/app/IActivityManager.java

import android.app.ITestListener.aidl
public boolean registerTestCallback(ITestListener listener) throws RemoteException
public boolean unRegisterTestCallback(ITestListener listener) throws RemoteException
int REGISTER_ACTIVITY_FINISH_CALLBACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+382;
int UNREGISTER_ACTIVITY_FINISH_CALLBACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+383;

ITestListener.aidl

新加listener文件
framework/base/core/java/android/app/ITestListener.aidl

package android.app;

interface ITestListener {
	void OnNotify();
}

ActivityManagerService.java

framework/base/services/core/java/com/android/server/am/ActivityManagerService.java
service里新加接口,在适当时候触发回调

import android.app.ITestListener.aidl
import android.os.HandlerThread;
	private final Arraylist<TestListenerData>mTestListenerDatas = new ArrayList<TestListenerData>();
	private Object mTestObject = new Object();
	private void handleTestListenerDeath(TestListenerDeath death) {
		int index = -1;
		synchronized(mTestObject) {
			if (null != mTestListenerDatas) {
				for (int i = 0; i < mTestListenerDatas.size(); i++) {
					if (mTestListenerDatas.get(i).getTestListenerDeath() == death) {
						index = i;
						break;
					}
				}
			}
			if (index >= 0) {
				mTestListenerDatas.get(index).getTestListener().asBinder()>unlinkToDeath(death,0);
				mTestListenerDatas.remove(index);
			}
		}
	}

    private class TestListenerDeath implements IBinder.DeathRecipient {
        @Override
        public void binderDied() {
            handleTestListenerDeath(TestListenerDeath.this);
        }
    }	

	private final class TestListenerData {
		private TestListenerDeath mDeath;
		private ITestListener mListener;
	
		public TestListenerData(ITestListener listener, TestListenerDeath death) {
			mDeath = death;
			mListener = listener;
		}
		public ITestListener getTestListener() {
			return mListener;
		}
		public TestListenerDeath getTestListenerDeath() {
			return mDeath;
		}
	}
	private int getIndexOfTestListener(ITestListener listener) {
		int index = -1;
		if (null != listener) {
			for (int i = 0; i < mTestListenerDatas.size(); i++) {
				if (mTestListenerDatas.get(i).getActivityFinishListener().asBinder() == listener.asBinder()) {
					index = i;
					break;
				}
			}
		}
		return index;
	}
	private final static int MESSAGE_TEST = 0;
	private final class TestHandler extends Handler {
		public TestHandler(Looper looper){
			super (looper);
		}
	
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
				case MESSAGE_TEST: {
					synchronized(mTestObject) {
						if (null != mTestListenerDatas){
							for (int i = 0; i < mTestListenerDatas.size(); i++) {
								ITestActivity listener = mTestListenerDatas.get(i).getTestListener();
								try {
									if (listener != null) {
										listener.OnNotify();
									}
								} catch (Throwable e) {
									e.printStackTrace();
								}
							}
						}
					}
				}
				break;
			}
		}
	}
	
	private HandlerThread mHandlerThread1;
	private TestHandler mTestHandler;
	
	// Note: This method is invoked on the main thread but may need to attach various
	// handlers to other threads. So take care to be explicit about the looper.
	public ActivityManagerService(Context systemContext) {
	mContext = systemContext;
	
	mHandlerThread1 = new HandlerThread("ACtivityManagerServiceTestThread");
	mHandlerThread1.start();
	mTestHandler = new TestHandler(mHandlerThread1.getLooper());

在想要触发回调的地方加入:

if (mTestListenerDatas != null && !mTestListenerDatas.isEmpty()) {
	Message msgTest = new Message();
	msgTest.what = MESSAGE_TEST;
	mTestHandler.sendMessage(msgTest);
}

新加接口实现:

	@Override
	public boolean registerTestCallback(ITestListener listener) {
		int index;
		synchronized(mTestObject) {
			if (null != listener) {
				index = getIndexOfTestListener(listener);
	
				if (index < 0) {
					TestListenerDeath death = new TestListenerDeath();
					
					try {
						listener.asBinder().linkToDeath(death, 0);
					} catch (RemoteException e) {
						e.printStackTrace();
					}
					TestListenerDate data = new TestListenerDate(listener, death);
		
					if (null != data) {
						mTestListenerDatas.add(data);
						return true;
					}
				}
			}
			return false;
		}
	}
	
	@Override
	public boolean unRegisterTestCallback(ITestListener listener) {
		int index;
		synchronized(mTestObject) {
			if (null != listener) {
				index = getIndexOfTestListener(listener);
	
				if (index >= 0) {
					mTestListenerDatas.remove(index);
					return true;
				}
			}
			return false;
		}
	}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ActivityManagerService新加listener及触发其回调 的相关文章

  • 从命令行将 clojure 源代码编译为类(AOT)(不使用 lein)

    我正在尝试将 clojure 源代码编译成类文件 并仅使用命令行运行它 没有 lein 也没有 可能 回复 我有 core cljsrc hello目录 src hello core clj 这是源代码 ns hello core defn
  • Android 日期/时间显示 0 而不是 12

    我想知道下面的代码有什么问题 Assign hour set in the picker c set Calendar HOUR selectedHour c set Calendar MINUTE selectedMinute For a
  • 如何从属性中获取枚举值

    我有一个带有值的枚举VALID and INVALID 它们有一个与之关联的布尔属性 我想根据我提供的布尔值获取枚举值 如果是true我应该得到VALID 如果是false我应该得到INVALID 我想根据成员变量的值 在如下所示的 get
  • 如何抑制有关已弃用 api 的 javac 警告?

    当我编译时 javac 输出 Note Some input files use or override a deprecated API Note Recompile with Xlint deprecation for details
  • 将一组 Java 对象转换为另一组对象的最佳方式是什么?

    这是一个真正的新手提出的基本 Java 问题 我有一组实现某个接口 接口 MyIfc 的Java对象 属于 MyClass 类 我有一组这些对象存储在我的类中的私有变量中 声明如下 protected Set
  • 无法向 openfire 服务器发送消息

    我无法使用 SMACK API 向 openfire 服务器上的 XMPP 客户端发送消息 我不确定我哪里出错了 我在 gtalk 上测试了相同的代码 它工作正常 public class SenderTest public static
  • 从文件执行db语句

    我在我的应用程序中使用嵌入式 Apache derby 我有一个名为的 SQL 脚本创建的数据库 sql创建数据库中的所有表并用初始数据填充它 例如 SET SCHEMA APP CREATE TABLE study study id bi
  • 什么时候使用弱引用? [复制]

    这个问题在这里已经有答案了 我了解什么是 Java WeakReference 我想知道的是它通常用于解决哪种具体问题 有没有包含它们的模式 WeakReference and SoftReference当您想保留某些东西以备再次需要时使用
  • 谷歌gson LinkedTreeMap类转换为myclass

    我知道这个问题以前已经被问过 由于我对java和android的新手技能 我一个多星期都无法解决这个问题 我和我的一位朋友正在开发一个 Android 项目 其中有一些类似的事情 最奇怪的部分是 只有当我从 Google Play 商店下载
  • 序列化/反序列化 LinkedHashMap (android) java

    所以我想将 LinkedHashMap 传递给意图 SEND THE MAP Intent singlechannel new Intent getBaseContext singlechannel class singlechannel
  • 如何将 HTML 转换为保留换行符的文本

    我如何将 HTML 转换为保留换行符的文本 由 br p div 等元素生成 可能使用NekoHTML http nekohtml sourceforge net 或任何足够好的 HTML 解析器 Example Hello br Worl
  • 当按下 flutter 中编写的按钮时,有没有办法运行 python 脚本?

    本质上 我想做的是 按下我在 Flutter 中编程的按钮 当按下该按钮时 Python 脚本应该开始在我的 Android 设备上运行 我想在 python 中使用 youtube dl 用于下载 Youtube 视频 库 但我想知道是否
  • 如何在 Android WebView 中从远程 URL 访问本地资源?

    要加载 HTML 中的资源 我使用 URLfile android asset my image png 当我在本地加载 HTML 时 它可以工作 例如 使用WebView loadData method 但是 我无法从远程网站加载本地资源
  • 如何使用带有 ListView 和自定义适配器的选择器来指示所选项目

    我有一个具有 ListView 的活动 并且我创建了一个自定义适配器 基于BaseAdapter 自定义适配器的 GetView 方法使用自定义布局 view context LayoutInflater Inflate Resource
  • “该选择不能在任何服务器上运行”

    我一直在 Eclipse 中开发一个动态 Web 项目 我收到这个错误 该选择不能在任何服务器上运行 早些时候它工作得很好 但现在我收到了这个错误 我删除了服务器并再次添加 Project gt Right Click gt Propert
  • 在 Firebase 中获取用户名、姓氏和 ID

    我使用 firebase 创建了登录 注册 并且工作正常 但我需要从用户那里获取姓名 我怎样才能做到这一点 我想知道是否可以从用户那里获取 ID 因为我想在我的应用程序中创建一个排名页面 因此只有 ID 才是唯一的 要获取唯一 ID 您可以
  • 如何使用放心发送Content-Type表单数据请求?

    我需要使用 Rest Assured 调用表单数据类型 API 这是我的代码 private Map
  • 执行选项卡切换时避免重新创建相同的视图

    目前 我有 2Fragments 可通过以下方式切换ActionBar s tab getSupportActionBar setNavigationMode ActionBar NAVIGATION MODE TABS ActionBar
  • 返回数据集的 kSoap 和 .Net Web 服务

    我知道使用数据集是一个很大的罪恶 但由于该服务不在我的控制之下 并且创建代理服务的前景是不可能的 我想看看是否有人创建了可以使用 kSoap 序列化器反序列化的类结构 或者我是否吸错了东西 同时要启动它 看看是否可行 以下是预期的结果数据
  • Robotium 和系统对话框

    当我尝试与蓝牙设备配对时 会出现带有 PIN 码的系统确认对话框 有 取消 和 确定 按钮 但我无法使用 Robotium 单击它们 如何在 Robotium 中使用 Android 操作系统对话框 谢谢 这对我有用 solo clickO

随机推荐