中间件的核心思想

中间件的核心思想是提供一种通用的接口和服务,将底层系统的复杂性进行抽象,使应用程序更容易调用和使用系统资源。它充当了应用程序和操作系统之间的桥梁,使得应用程序不必直接处理底层细节,而是通过中间件提供的接口来访问系统功能。

中间件的优势

简化开发

从复杂的应用程序中抽象出通用的公共部分,从而降低应用开发的复杂度。 易于扩展

中间件可以通过添加新的模块或更新现有模块来实现系统功能的扩展和升级,而不影响应用程序的正常运行。 提高可维护性

中间件模块的独立性使得对特定功能的修改、升级和维护更加容易。应用程序可以保持不变,只需更新中间件模块即可。 抽象底层复杂性

中间件提供了一个抽象层,隐藏了底层系统和硬件的复杂性。应用程序能够更专注于业务逻辑而不用过多关心底层实现。 跨平台适用性:

中间件提供了统一的接口,应用程序可以跨不同硬件和系统版本使用相同的调用方式,根据业务需求在对应的Android设备上运行,而无需修改代码。 提高应用程序的可移植性。

Android 12 开发项目结构图

中间件应用架构的组成

在Manager/src/main/aidl目录中,在对应目录下对AIDL接口进行定义接口。而IService.aidl文件则是定义了获取各个中间件模块实例的方法,包括音频、网络、图片、信源、系统和事件模块。 在Manager/src/main/java目录中,在对应目录下对各个目录中AIDL接口进行初始化,资源分配等操作。而Manager类是一个单例类,通过getInstance()方法获取各个目录的唯一实例。 在app/src/main/java目录中,Service 类是一个 Android 服务(Service),用于提供中间件模块的绑定和管理。而在对应目录下的Binder则是对服务进行实现

中间件应用架构实现示例

Manager/aidl目录下的IAudio文件中接口实现 package com.middleware.manager.audio;

interface IAudio {

    //-Setting the ARC switch

    void setARC(boolean onoff);

    //-Get the volume of the specified type

    int getVolumeType(int audioHelper);

    //-Determine whether ARC is started or not

    boolean isARCEnable();

}

Manager/java目录下的AudioManager文件中对接口进行初始化 public class AudioManager {

    private static final String TAG = "Manager-Audio";

    private static IAudio getService() {

        LogHelper.service(TAG);

        if (Manager.getInstance() == null) {

            Log.d(TAG, "getService: getInstance is null ");

            return null;

        }

        return Manager.getInstance().getAudio();

    }

    public static void setARC(boolean onoff){

        IAudio service = getService();

        try {

            if(service != null ){

                service.setARC(onoff);

            }

        } catch (RemoteException e) {

            e.printStackTrace();

        }

    }

    public static int getVolumeType(int audioHelper){

        try {

            IAudio service = getService();

            return service == null ? -1 : service.getVolumeType(audioHelper);

        } catch (RemoteException e) {

            e.printStackTrace();

            return -1;

        }

    }

    public static boolean isARCEnable(){

        try {

            IAudio service = getService();

            return service == null ? false : service.isARCEnable();

        } catch (RemoteException e) {

            e.printStackTrace();

            return false;

        }

    }

}

 

app/src/main/java目录下的AudioBinder文件初始化的接口进行实现 public class AudioBinder extends IAudio.Stub {

    private static final String TAG = "Audio";

    private Context mContext;

    public AudioBinder(Context context){

        mContext = context;

    }

    @Override

    public void setARC(boolean onoff) throws RemoteException {

        HitvManager hitvManager = HitvManager.getInstance();

        if (hitvManager != null) {

            Audio audio = hitvManager.getAudio();

            if (audio != null) {

                audio.enableARC(onoff);

                Log.d(TAG, "ARC switched " + (onoff ? "on" : "off"));

            } else {

                Log.e(TAG, "setARC: Audio is null.");

            }

        } else {

            Log.e(TAG, "setARC: HitvManager is null.");

        }

    }

    @Override

    public int getVolumeType(int audioHelper) throws RemoteException {

        HitvManager hitvManager = HitvManager.getInstance();

        if (hitvManager != null) {

            Audio audio = hitvManager.getAudio();

            if (audio != null) {

              return  audio.getVolume(audioHelper);

            }

        }

        return -1;

    }

    @Override

    public boolean isARCEnable() throws RemoteException {

        HitvManager hitvManager = HitvManager.getInstance();

        if (hitvManager != null) {

            Audio audio = hitvManager.getAudio();

            if (audio != null) {

                return  audio.isARCEnable();

            }

        }

        return false;

    }

}

Manager/aidl目录下的IService文件获取各个中间件模块实例的方法 interface IService {

    IAudio getAudio();

    INetWork getNetWork();

    IPicture getPicture();

    ISource getSource();

    ISystem getSystem();

    IEvent getEvent();

}

Manager/java目录下的Manager文件获取各个目录的唯一实例 public class Manager {

    private static final String TAG = "Manager";

    private static volatile Manager sInstance = null;

    private static IAudio sAudio = null;

    private static INetWork sNetWork = null;

    private static IPicture sPicture = null;

    private static ISource sSource = null;

    private static ISystem sSystem = null;

    private static IEvent sEvent = null;

    private static final DeathRecipient sDeathRecipient = () -> {

        sInstance = null;

        sAudio = null;

        sNetWork = null;

        sPicture = null;

        sSource = null;

        sSystem = null;

        sEvent = null;

    };

    private final IService mService;

    private Manager(IService service) {

        mService = service;

    }

    public static Manager getInstance() {

        // Double-checked locking

        if (sInstance == null) {

            synchronized (Manager.class) {

                if (sInstance == null) {

                    IBinder binder = ServiceManager.getService("kitkingservice");

                    int count = 0;

                    while (binder == null && count < 60) {

                        try {

                            Thread.currentThread().sleep(10);

                        } catch (InterruptedException e) {

                            e.printStackTrace();

                        }

                        binder = ServiceManager.getService("kitkingservice");

                        count++;

                    }

                    try {

                        if (binder != null) {

                            binder.linkToDeath(sDeathRecipient, 0);

                            sInstance = new Manager(IService.Stub.asInterface(binder));

                        }

                    } catch (RemoteException e) {

                        e.printStackTrace();

                    }

                }

            }

        }

        return sInstance;

    }

    public IAudio getAudio() {

        if (sAudio == null) {

            try {

                sAudio = mService.getAudio();

            } catch (RemoteException e) {

                e.printStackTrace();

                return null;

            }

        }

        return sAudio;

    }

    public INetWork getNetWork() {

        if (sNetWork == null) {

            try {

                sNetWork = mService.getNetWork();

            } catch (RemoteException e) {

                e.printStackTrace();

                return null;

            }

        }

        return sNetWork;

    }

    public IPicture getPicture() {

        if (sPicture == null) {

            try {

                sPicture = mService.getPicture();

            } catch (RemoteException e) {

                e.printStackTrace();

                return null;

            }

        }

        return sPicture;

    }

    public ISource getSource() {

        if (sSource == null) {

            try {

                sSource = mService.getSource();

            } catch (RemoteException e) {

                e.printStackTrace();

                return null;

            }

        }

        return sSource;

    }

    public ISystem getSystem() {

        if (sSystem == null) {

            try {

                sSystem = mService.getSystem();

            } catch (RemoteException e) {

                e.printStackTrace();

                return null;

            }

        }

        return sSystem;

    }

    public IEvent getEvent() {

        if (sEvent == null) {

            try {

                sEvent = mService.getEvent();

            } catch (RemoteException e) {

                e.printStackTrace();

                return null;

            }

        }

        return sEvent;

    }

}

app/src/main/java目录下的Service文件对中间件模块的绑定和管理 public class Service extends Service {

    private static final String TAG = "Service";

    public Context context;

    private AudioBinder mAudioBinder = null;

    private PictureBinder mPictureBinder = null;

    private NetBinder mNetWorkBinder = null;

    private SourceBinder mSourceBinder = null;

    private SystemBinder mSystemBinder = null;

    private EventBinder mEventBinder = null;

    private final IService.Stub mBinder = new IService.Stub() {

        @Override

        public synchronized IAudio getAudio() {

            if (mAudioBinder == null) {

                mAudioBinder = new AudioBinder(getApplicationContext());

            }

            return mAudioBinder;

        }

        @Override

        public synchronized INetWork getNetWork() {

            if (mNetWorkBinder == null) {

                mNetWorkBinder = new NetBinder(getApplicationContext());

            }

            return mNetWorkBinder;

        }

        @Override

        public synchronized IPicture getPicture() {

            if (mPictureBinder == null) {

                mPictureBinder = new PictureBinder(getApplicationContext());

            }

            return mPictureBinder;

        }

        @Override

        public synchronized ISource getSource() {

            if (mSourceBinder == null) {

                mSourceBinder = new SourceBinder(getApplicationContext());

            }

            return mSourceBinder;

        }

        @Override

        public synchronized ISystem getSystem() {

            if (mSystemBinder == null) {

                mSystemBinder = new SystemBinder(getApplicationContext());

            }

            return mSystemBinder;

        }

        @Override

        public synchronized IEvent getEvent() {

            if (mEventBinder == null) {

                mEventBinder = new EventBinder(getApplicationContext());

            }

            return mEventBinder;

        }

    };

    @Override

    public IBinder onBind(Intent intent) {

        return mBinder;

    }

    @Override

    public void onCreate() {

        super.onCreate();

        context = getApplicationContext();

    }

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

        ServiceManager.addService("kitkingservice", mBinder);

        return START_STICKY;

    }

    @Override

    public boolean onUnbind(Intent intent) {

        return super.onUnbind(intent);

    }

    @Override

    public void onDestroy() {

        super.onDestroy();

    }

}

UML 流程图

数据流程

App 向中间件请求数据:

App通过 Manager 获取中间件的实例。 通过中间件实例调用相应的接口方法,例如 getAudio()、getNetWork() 等。 中间件处理请求:

中间件收到请求后,根据请求的类型,创建相应的中间件模块实例(例如,AudioBinder、NetBinder)。 调用中间件模块的相应方法,处理具体的功能逻辑,例如获取音频信息、网络状态等。 中间件向系统请求数据:

中间件可能需要向系统请求底层数据,例如通过 HitvManager 获取 TV 的音频信息。 系统返回数据给中间件:

系统接收到中间件的请求,执行相应的系统功能,例如获取 TV 的音频信息。 系统将获取的数据返回给中间件。 中间件处理系统返回的数据:

中间件收到系统返回的数据,进行相应的处理和加工,确保符合中间件的接口规范。 中间件返回数据给 App:

中间件将处理后的数据返回给App,App 进一步处理或显示这些数据。

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: