{"id":15027672,"url":"https://github.com/iqiyi/andromeda","last_synced_at":"2025-05-15T18:10:02.090Z","repository":{"id":39861847,"uuid":"130326077","full_name":"iqiyi/Andromeda","owner":"iqiyi","description":" Andromeda simplifies local/remote communication for Android modularization","archived":false,"fork":false,"pushed_at":"2019-09-16T06:24:59.000Z","size":984,"stargazers_count":2275,"open_issues_count":13,"forks_count":280,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-05-04T20:41:24.162Z","etag":null,"topics":["android","ipc","modularization","router"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iqiyi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-20T07:29:34.000Z","updated_at":"2025-03-31T10:06:42.000Z","dependencies_parsed_at":"2022-08-09T15:20:15.121Z","dependency_job_id":null,"html_url":"https://github.com/iqiyi/Andromeda","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iqiyi%2FAndromeda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iqiyi%2FAndromeda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iqiyi%2FAndromeda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iqiyi%2FAndromeda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iqiyi","download_url":"https://codeload.github.com/iqiyi/Andromeda/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254394723,"owners_count":22063984,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","ipc","modularization","router"],"created_at":"2024-09-24T20:06:52.711Z","updated_at":"2025-05-15T18:10:02.040Z","avatar_url":"https://github.com/iqiyi.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Andromeda\n![Andromeda_license](https://img.shields.io/badge/license-BSD--3--Clause-brightgreen.svg)\n![Andromeda_core_tag](https://img.shields.io/badge/Andromeda%20Core-1.1.8-brightgreen.svg)\n![Andromeda_plugin_tag](https://img.shields.io/badge/Andromeda%20plugin-1.1.1-brightgreen.svg)\n\nAndromeda provides communication among modules for both local and remote service.\n\n**Anno:The reason that differentiate local service from remote service is that parameter types in remote service can only be primitive type or custom type that implements Parcelable, while parameter types in local service can be any type such as View and Context.**\n\n[文档，还是中文好](https://github.com/iqiyi/Andromeda/blob/master/CHINESE_README.md)\n\n# Features\n\n+ Aidl interface and implemention are the only thing developers need do. bindService() and Service definition are not necessary.\n\n+ Remote service could be fetched synchronously instead of asynchronously\n\n+ Process-priority-hencing work is managed along with Fragment/Activity's lifecycle\n\n+ IPC Callback is supported\n \n+ Event bus for all processes is supported\n\n**Anno: service here means interface and it's implementation instead of component Service.**\n\nComparsion between other communication solutions and Andromeda:\n\n|                            | Convenience  | IPC efficiency | IPC | IPC EventBus | IPC Callback |\n| :------------------------: | :--: | :---: | :---: | :-------: | :------------: |\n|         Andromeda          |  good   |   high   |  Yes  |    Yes    |      Yes       |\n|   DDComponentForAndroid    |  normal  |  --   |  No   |    No     |       No       |\n| ModularizationArchitecture |  normal  |   low   |  Yes  |    No     |       No       |\n\n# Download\nadd classpath in buildscript(replace $version with latest version name):\n```groovy\n    classpath \"org.qiyi.video.svg:plugin:$version\"\n```\nadd core lib dependency in Application or library Module:\n```groovy\n    implementation \"org.qiyi.video.svg:core:$version\"\n```\napply gradle plugin in application Module:\n```groovy\n    apply plugin: 'org.qiyi.svg.plugin'\n```\n\n# How to use\n## Dispatcher config\n**Dispatcher should always in the process that live longest cause it manager all process infos!.**\nDefault process of Dispatcher is main process if not configed. \nConsidering some process may live longer than main process in some apps(such as music app), developers should\n config process name for Dispatcher in this case. Just as follows in build.gradle of application module:\n```groovy\n    dispatcher{\n        process \":downloader\"\n    }\n``` \nIn this case, \":downloader\" process is the one that live longest.\n\n## init\nadd init code in Application.onCreate():\n```java\n    Andromeda.init(Context);\n```\n\n## Register and use local service\n### Definition and implementation of local service\nThere are only two differences between local service and normal interfaces:\n+ interfaces should be put in a common module to make it accessible to all modules\n+ Andromeda will only hold one implementation at a time\n\n### Register local service\nThere are two methods to register local service, the first one is as follows:\n```java\n    Andromeda.registerLocalService(ICheckApple.class.getCanonicalName(),new CheckApple());\n```\nAnother is as follows:\n```java\n    Andromeda.registerLocalService(ICheckApple.class,new CheckApple());\n```\nICheckApple is interface definition. Considering proguard, registering local service with fixed String is not recommanded, just as follows:\n```java\n    Andromeda.registerLocalService(\"wang.imallen.blog.moduleexportlib.apple.ICheckApple\",CheckAppleImpl.getInstance());\n```\n\n### How to use local service\nAny module that's in the same process with server module could obtain local service after registration. The first method is as follows:\n```java\n    ICheckApple checkApple = (ICheckApple) Andromeda.getLocalService(ICheckApple.class);\n```\nAnother is as follows:\n```java\n    ICheckApple checkApple = (ICheckApple) Andromeda.getLocalService(ICheckApple.class.getCanonicalName());\n```\nSimilarly, considering proguard, obtaining local service with fixed String is not recommanded neighter:\n```java\n    ICheckApple checkApple = (ICheckApple) Andromeda.getLocalService(\"wang.imallen.blog.moduleexportlib.apple.ICheckApple\");\n```\nLocalServiceDemo shows the details of registration and use of local service。\n\n### Callback of local service\nCallback of local service is just as normal interface, which is all up to developers.\nAs a result, Andromeda will not provide any callbacks.\n\n## Registeration and use of remote service\n### Definition and use of remote service\nFirst, define a aidl interface, and expose it to common module along with its Stub and Proxy.\n```aidl\n    package wang.imallen.blog.moduleexportlib.apple;\n    import org.qiyi.video.svg.IPCCallback;\n    \n    interface IBuyApple {\n        int buyAppleInShop(int userId);\n        void buyAppleOnNet(int userId,IPCCallback callback);\n    }\n```\nThen provide implementation:\n```java\npublic class BuyAppleImpl extends IBuyApple.Stub {\n\n    private static BuyAppleImpl instance;\n\n    public static BuyAppleImpl getInstance() {\n        if (null == instance) {\n            synchronized (BuyAppleImpl.class) {\n                if (null == instance) {\n                    instance = new BuyAppleImpl();\n                }\n            }\n        }\n        return instance;\n    }\n\n    private BuyAppleImpl() {\n    }\n\n    @Override\n    public int buyAppleInShop(int userId) throws RemoteException {\n       ...\n    }\n\n    @Override\n    public void buyAppleOnNet(int userId, IPCCallback callback) throws RemoteException {\n       ...\n    }\n}\n\n```\n### Registration of remote service\nDifferen from registration of local service, IBinder of remote service is need for registration :\n```java\n    Andromeda.registerRemoteService(IBuyApple.class, BuyAppleImpl.getInstance().asBinder());\n```\nThe way as follows is also workable cause BuyAppleImpl extends IBuyApple.Stub, which extends android.os.Binder:\n```java\n    Andromeda.registerRemoteService(IBuyApple.class, BuyAppleImpl.getInstance());\n```\nAnother way to register is as follows:\n```java\n    Andromeda.registerRemoteService(IBuyApple.class.getCanonicalName(),BuyAppleImpl.getInstance().asBinder());\n```\n\n### Use of remote service\n+ with() is need before obtain remote service cause Andromeda need to hence server process priority in accordance with Fragment/Activity's lifecycle;\n+ getRemoteService() will return IBinder. Then you can obtain proxy by XXStub.asInterface(binder);\n\nSet use in a FragmentActivity as example:\n```java\n        IBinder binder = Andromeda.with(this).getRemoteService(IBuyApple.class);\n        if (binder == null) {\n            return;\n        }\n        IBuyApple buyApple = IBuyApple.Stub.asInterface(binder);\n        if (buyApple == null) {\n            return;\n        }\n        try {\n            buyApple.buyAppleInShop(29);\n        } catch (RemoteException ex) {\n            ex.printStackTrace();\n        }\n```\nUse of remote service in android.app.Fragment,android.support.v4.app.Fragment and normal Activity is similar, demos are CustomFragment,CustomSupportFragment and FragActivity,etc.\n\nAttention:**Remote service could be used both in same process and other processes. When use in the same process, it will turned to local interface invoking.**\n\n### Callback of remote service\nConsidering time-consuming work may be done in server process, Callback of remote service is necessary.。\nFor ones that need callback should add IPCCallback parameter in their aidl definitions:\n```aidl\n    interface IBuyApple {\n        int buyAppleInShop(int userId);\n        void buyAppleOnNet(int userId,IPCCallback callback);\n    }\n```\nThe canonical name of IPCCallback is org.qiyi.video.svg.IPCCallback. Its definition is as follows:\n```aidl\n    interface IPCCallback {\n       void onSuccess(in Bundle result);\n       void onFail(String reason);\n    }\n```\nClient can use IPCCallback as follows:\n```java\n        IBinder buyAppleBinder = Andromeda.getRemoteService(IBuyApple.class);\n        if (null == buyAppleBinder) {\n            return;\n        }\n        IBuyApple buyApple = IBuyApple.Stub.asInterface(buyAppleBinder);\n        if (null != buyApple) {\n            try {\n                buyApple.buyAppleOnNet(10, new IPCCallback.Stub() {\n                    @Override\n                    public void onSuccess(Bundle result) throws RemoteException {\n                       ...\n                    }\n\n                    @Override\n                    public void onFail(String reason) throws RemoteException {\n                       ...\n                    }\n                });\n\n            } catch (RemoteException ex) {\n                ex.printStackTrace();\n            }\n        }\n    \n```\nConsidering the callback is in binder thread, while most developers want the callback in UI thread, Andromeda provide a BaseCallback for deverlopers.\n```java\n   IBinder buyAppleBinder = Andromeda.getRemoteService(IBuyApple.class);\n        if (null == buyAppleBinder) {\n            return;\n        }\n        IBuyApple buyApple = IBuyApple.Stub.asInterface(buyAppleBinder);\n        if (null != buyApple) {\n            try {\n                buyApple.buyAppleOnNet(10, new BaseCallback() {\n                    @Override\n                    public void onSucceed(Bundle result) {\n                       ...\n                    }\n\n                    @Override\n                    public void onFailed(String reason) {\n                        ...\n                    }\n                });\n\n            } catch (RemoteException ex) {\n                ex.printStackTrace();\n            }\n        }\n```\n**Use BaseCallback instead of IPCCallback is recommanded!**\n\nBananaActivity shows details of how to use it.\n\n### Lifecycle control\nTo enhence server process's priority, Andromeda will do bindService() when Andromeda.with().getRemoteService() in accordance with Fragment/Activity's lifecycle.\nAs a result, unbind action is need when Fragment/Activity destroyed.\nThere are 2 cases now:\n+ For those who obtain remote service with Fragment/Activity and in main thread, Andromeda will do unbind() action automatically\n\n+ For those who obtain not with Fragment/Activity or in work thread, unbind() action should be invoked by developers:\n\n```java\n    public static void unbind(Class\u003c?\u003e serviceClass);\n    public static void unbind(Set\u003cClass\u003c?\u003e\u003e serviceClasses);\n```\n \n## Subscribe and pushlish event\n### Event\nDefinition of Event in Andromeda is as follows:\n```java\n    public class Event implements Parcelable {\n    \n        private String name;\n    \n        private Bundle data;\n        \n        ...\n    }\n```\nObviously, Event consist of name and data, which is Bundle type that can load primitive type parameters or Parcelable type parameters.\n\n### Subscribe event\nSubscribing event is very simple with one who implements EventListenr such as MainActivity:\n```java\n    Andromeda.subscribe(EventConstants.APPLE_EVENT,MainActivity.this);\n```\nThis means it subscribes Event whose name is EventConstans.APPLE_EVENT.\n\n### Publish event\nPublishing event is as simple as follows:\n```java\n    Bundle bundle = new Bundle();\n    bundle.putString(\"Result\", \"gave u five apples!\");\n    Andromeda.publish(new Event(EventConstants.APPLE_EVENT, bundle));\n```\nAfter published, all listeners in any processes could receive the event.\n\nMainActivity shows details of how to subscribe and publish event.\n\n# License\nBSD-3-Clause. See the [BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause) file for details.\n\n\n# Contact\nQQ group number is 640539737, and its qr code is as follows:\n\n![QQ_group](https://github.com/iqiyi/Andromeda/blob/master/res/qq_group.png)\n\n# Support\n1. Sample codes\n2. Wiki and FAQs\n3. contact bettarwang@gmail.com\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiqiyi%2Fandromeda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiqiyi%2Fandromeda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiqiyi%2Fandromeda/lists"}