赞
踩
本文适用于Android 12中增加系统服务。
目录
2.2.2 AIDL文件Observer/Callback/Listener命名报错修改
在framework/base/core/java/android/app下创建AIDL文件,如果业务比较复杂,可以创建模块文件夹。代码示例如下:
framework/base/core/java/android/app/devicemanager/IDeviceManager.aidl
- //framework/base/core/java/android/app/devicemanager/IDeviceManager.aidl
- package android.app.devicemanager;
-
- import android.app.devicemanager.DeviceEntity;
- import android.app.devicemanager.IDeviceObserver;
-
- interface IDeviceManager {
- int bindDivice(int deviceId);
- DeviceEntity getDeviceEntity(int deviceId);
- void registerDeviceObserver(in IDeviceObserver observer);
- void unregisterDeviceObserver(in IDeviceObserver observer);
- }
framework/base/core/java/android/app/devicemanager/IDiviceObserver.aidl
- //framework/base/core/java/android/app/devicemanager/IDeviceObserver.aidl
- package android.app.devicemanager;
-
- import android.app.devicemanager.DeviceEntity;
- oneway interface IDiviceObserver{
- void onBindChanged(int state, int deviceId);
- void onStateChanged(int state, int deviceId);
- }
framework/base/core/java/android/app/devicemanager/DeviceEntity.aidl
- package android.app.devicemanager;
-
- parcelable DeviceEntity;
上述写法会报非常多的错,请参考Android 12 API规范:请参考 https://www.cnblogs.com/wanghongzhu/p/14729469.html 。
针对上述代码所犯的错误,也就是大家在Android 12版本中使用make -j32 framework-minus-apex编译framework层的报错修改。
这是因为AIDL自动生成的Java文件不满足Android 12 framework API的规范:framework层不能直接暴露原生AIDL文件。
修改的方式是在aidl文件上添加@hide,如下所示,这样就可以解决所有AIDL自动生成的文件。(这是扒遍国内全网都没在找到,在Google中才找到的根本解决办法)
- //framework/base/core/java/android/app/devicemanager/IDeviceManager.aidl
- package android.app.devicemanager;
-
- import android.app.devicemanager.DeviceEntity;
- import android.app.devicemanager.IDeviceObserver;
-
- /** @hide */
- interface IDeviceManager {
- int bindDivice(int deviceId);
- DeviceEntity getDeviceEntity(int deviceId);
- void registerDeviceObserver(in IDeviceObserver observer);
- void unregisterDeviceObserver(in IDeviceObserver observer);
- }
out/srcjars/android/app/devicemanager/IDiviceObserver.java:60: error: Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause) [RethrowRemoteException]
out/srcjars/android/app/devicemanager/IDiviceObserver.java:70: error: Missing nullability on method `asBinder` return [MissingNullability]
out/srcjars/android/app/devicemanager/IDiviceObserver.java:75: error: Raw AIDL interfaces must not be exposed: Stub extends Binder [RawAidl]
Observer命名报错,Android Lint 工具对callback和listener有严格的校验,不建议使用Observer作为回调,要用callback或者listener。
请中招的小伙伴自行修改。
Registration methods should have overload that accepts delivery Executor: `registerDeviceCallback` [ExecutorRegistration]
是不是一脸懵,看不明白啥意思,以前很早的framework层的manager,没啥参考价值,推荐参考新的manager和API规范,因为现有的注册回调的方法必须是两个参数,其中一个必须为Executor,如下所示。
- public void registerFooCallback( @NonNull @CallbackExecutor Executor executor,
- @NonNull FooCallback callback)
- //unregister方法不需要添加Executor
- public void unregisterFooCallback(@NonNull FooCallback callback) {}
在Framework层使用enum会报错:Enums are discouraged in Android APIs [Enum],因此一般都用@intDef代替,使用新的注解表示。
前边2.2.1 AIDL文件自动生成的Java文件报错,为了解决需要添加@hide,但是添加该注解后,Apps就访问不到该callback,如何实现Binder通信呢?
解决办法:
这样做的好处:
//创建暴露给Apps的抽象类
- //framework/base/core/java/android/app/devicemanager/DeviceCallback.java
- package android.app.devicemanager;
-
- public abstract class DiviceCallback {
- void onBindChanged(int state, int deviceId);
- void onStateChanged(int state, int deviceId);
- }
//Manager中对应的映射关系
- //framework/base/core/java/android/app/devicemanager/DeviceManager.java
- package android.app.devicemanager;
-
- import android.app.devicemanager.IDeiceCallback;
- import android.app.devicemanager.DevoceCallback;
- import java.util.concurrent.Executor;
-
- public class DeviceManager {
-
- private ArrayMap<DeviceCallback, DeviceCallbackEntry> mCallbackMap = new ArrayMap<>();
-
- //AIDL ICallback真正实现的类
- private static final class DeviceCallbackEntry extends IDeviceCallback.Stub {
- final DeviceCallback mCallback;
- final Executor mExecutor;
-
- DeviceCallbackEntry( DeviceCallback callback, Executor executor) {
- mCallback = callback;
- mExecutor = executor;
- }
-
- //当Binder server端IDeviceCallback的onBindChanged回调时,会调用Apps端注册的
- // DeviceCallback类对应的方法,此时就完成了ICallback到Callback抽象类的映射。
- public void onBindChanged(int state, int deviceId) {
- mExecutor.executor(() -> mCallback.onBindChanged(state, deviceId));
- }
- ...
- }
-
- public void registerDeviceCallback(@Nullable Executor executor,
- @NonNull DeviceCallback callback) {
- if(callback == null || mCallbackMap.containsKey(calback)) {
- return;
- }
-
- DeviceCallbackEntry entry = new DeviceCallbackEntry(callback, executor);
- mCallbackMap.put(callback, entry);
-
- final IDeviceManager service = getService();
- try {
- //注意:此处调用的系统服务对应的注册方法中参数是ICallback的实现类,即entry,
- //而不是Apps直接注册的抽象类
- service.registerDeviceCallback(entry);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
在frameworks/base/core/java/android/content/Context.java中增加一句
public static final String DEVICE_MANAGER_SERVICE = "device_manager";
在framework/base/services/core/java/com/android/service/下创建系统服务,如果业务比较复杂,可以创建模块文件夹。
framework/base/services/core/java/com/android/service/devicemanage/DeviceManagerService.java
- package com.android.service.devicemanager;
-
- import android.app.devicemanager.DeviceEntity;
- import android.content.Context;
- import android.app.devicemanager.IDeviceManager;
- import android.app.devicemanager.IDeviceObserver;
- import android.os.RemoteException;
-
- public class DeviceManagerService extends IDeviceManager.Stub {
- private final Context mContext;
- public DeviceManagerService(Context mContext) {
- this.mContext = mContext;
- }
-
- public static class Lifecycle extends SystemService {
- private final DeciceManagerService mService;
- public Lifecycle(Context context) {
- super(context);
- mService = new DeciceManagerService(context);
- }
- @Override
- public void onStart() {
- publishBinderService(Context.DEVICE_MANAGER_SERVICE, mService);
- }
- }
-
- @Override
- public int bindDivice(int deviceId) throws RemoteException {
- return 0;
- }
-
- @Override
- public DeviceEntity getDeviceEntity(int deviceId) throws RemoteException {
- return null;
- }
-
- @Override
- public void registerDeviceObserver(IDeviceObserver observer) {
-
- }
-
- @Override
- public void unregisterDeviceObserver(IDeviceObserver observer) throws RemoteException {
-
- }
-
- }
在frameworks/base/services/java/com/android/server/SystemServer.java的startOtherServices()中添加以下代码
- t.traceBegin("StartLocationManagerService");
- mSystemServiceManager.startService(DeviceManagerService.Lifecycle.class);
- t.traceEnd();
在framework/base/core/java/android/app/devicemanager下创建DeviceManager类
- package android.app.devicemanager;
-
- import android.content.Context;
- import android.os.IBinder;
- import android.os.RemoteException;
-
- @SystemService(Context.DEVICE_MANAGER_SERVICE)
- public class DeviceManager {
- private mContext mContext;
- private DeviceManager(Context context) {
- this.mContext = context;
- }
-
- public static IDeviceManager getService() {
- return IDeviceManagerSingleton.get();
- }
-
- public static final Singleton<IDeviceManager> IDeviceManagerSingleton =
- () -> {
- final IBinder binder = ServiceManager.getService(Context.DEVICE_MANAGER_SERVICE);
- return IDeviceManager.Stub.asInterface(binder);
- };
-
- public int bindDivice(int deviceId) {
- final IDeviceManager service = getService();
- try {
- return service.bindDivice(deviceId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- }
在framework/base/core/java/android/app/SystemServiceRegistry.java类的j静态代码块static{}中增加以下代码
- registerService(Context.DEVICE_MANAGER_SERVICE, DeviceManager.class,
- new CachedServiceFetcher<DeviceManager>() {
- @Override
- public DeviceManager createService(ContextImpl ctx) {
- return new DeviceManager(ctx.getOuterContext());
- }});
- DeviceManager mDeviceManager = (DeviceManager) mContext.getSystemService(Context.DEVICE_MANAGER_SERVICE);
- int deviceId = 1;
- mDeviceManager.bindDevice(deviceId);
以上是在framework层添加一个完整SystemService和manager的过程。
在Android 12中添加一个系统service,简直到处踩雷,阅读了整个API规范,各种追踪源码,才把framework层的编译通过,如果你喜欢请收藏或者点赞哦!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。