{"id":13470383,"url":"https://github.com/limpoxe/Android-Plugin-Framework","last_synced_at":"2025-03-26T11:31:45.414Z","repository":{"id":31455083,"uuid":"35018914","full_name":"limpoxe/Android-Plugin-Framework","owner":"limpoxe","description":"Android插件框架，免安装运行插件APK ，支持独立插件和非独立插件","archived":false,"fork":false,"pushed_at":"2024-05-13T15:57:57.000Z","size":339754,"stargazers_count":1811,"open_issues_count":33,"forks_count":498,"subscribers_count":135,"default_branch":"master","last_synced_at":"2025-03-24T14:08:33.932Z","etag":null,"topics":["android","framework","plugin"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/limpoxe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-05-04T06:48:47.000Z","updated_at":"2025-03-19T00:57:31.000Z","dependencies_parsed_at":"2024-05-02T20:57:44.427Z","dependency_job_id":"5264b2a1-b249-4282-a356-786c45229143","html_url":"https://github.com/limpoxe/Android-Plugin-Framework","commit_stats":{"total_commits":1483,"total_committers":2,"mean_commits":741.5,"dds":"0.0013486176668914274","last_synced_commit":"d152a09292f61435109309bf0795381b74c2b6ab"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/limpoxe%2FAndroid-Plugin-Framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/limpoxe%2FAndroid-Plugin-Framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/limpoxe%2FAndroid-Plugin-Framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/limpoxe%2FAndroid-Plugin-Framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/limpoxe","download_url":"https://codeload.github.com/limpoxe/Android-Plugin-Framework/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245383120,"owners_count":20606265,"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","framework","plugin"],"created_at":"2024-07-31T16:00:29.483Z","updated_at":"2025-03-26T11:31:45.404Z","avatar_url":"https://github.com/limpoxe.png","language":"Java","readme":"# Android-Plugin-Framework\n\nREADME: [中文](https://github.com/limpoxe/Android-Plugin-Framework/blob/master/README.md)\n\nAndroid-Plugin-Framework是一个Android插件化框架，用于通过动态加载的方式免安装运行插件apk\n\n### 最新版本: 'com.github.limpoxe:Android-Plugin-Framework:0.0.73@aar'\n               \n### 此项目主要目标是为了运行非独立插件，而不是任意第三方app。\n\n尽管此框架支持独立插件，但目标并不是为了支持任意三方app，不同于平行空间或应用分身之类的产品。\n非独立插件相比任意三方app来说，可以预见到其使用了哪些系统api和特性，而且所有行为都是可以预测的。而任意三方app是不可预测的。\n框架的做法是按需hook，即需要用到哪些系统特性和api，就对哪些特性和api提供支持。这种做法对开发非独立插件和二方独立插件而言完全足够。\n目前已经添加了对常用特性和api的支持，如需使用的api还未支持请联系作者。\n\n### FEATURE\n- 框架透明, 插件开发与普通apk开发无异，无约定约束\n- 支持非独立插件和独立插件(非任意三方)\n- 支持四大组件/Application/Fragment/Accessibility/LaunchMode/so\n- 支持插件Theme/Style,宿主Theme/Style,轻松支持基于主题属性的皮肤切换\n- 支持插件发送Notification/时在RemoteViews中携带插件中的资源（只支持5.x及以上, 且不支持miui8）\n- 支持插件热更新：即在插件模块已经被唤起的情况先安装新版本插件，无需重启插件进程（前提是插件高度内敛，宿主```不主动```持有插件中的任何对象）\n- 支持全局服务：即插件向容器注册一个服务，其他所有插件已经宿主都获取并调用此服务\n- 支持DataBinding（仅限独立插件）\n- 支持插件WebView加载插件本地HTML文件\n- 支持插件Fragment/View内嵌宿主Activity中\n- 支持FileProvider\n- 支持2.3-12.0\n\n### LIMIT\n- 不支持插件Activity转场动画使用插件中的动画资源\n- 不支持插件Manifest中申请权限，所有权限必须预埋到宿主Manifest中\n- 不支持第三方app试图唤起插件中的组件时直接使用插件组件的Intent。\n  第三方app要唤起插件中的静态组件，例如Activity/service/Provider，必须由宿主程序进行桥接，即此组件需同时预埋到宿主和插件的Manifest中\n- 不支持android.app.NativeActivity\n- 不支持当一个插件依赖另一个插件时，被插件依赖的包含资源\n- 不支持插件中的webview弹出```原生Chrome组件```\n  例如通过html的\u003cinput type=\"date\"/\u003e标签设置时间选择器。\n  说明：是否能支持原生组件取决于系统中使用WebView的实现。\n       如果是使用的Android System Webview，则可以支持。因为它packageId是以0x3f开头；\n       如果是使用的Chrome Webview，则不支持。因为它packageId是以0x7f开头，会和插件冲突。\n       这是采用Public.xml进行资源分组的缺陷。\n- 可能不支持对插件或者宿主进行加壳加固处理，未尝试\n\n# HOW TO USE\n```\n    buildscript {\n        dependencies {\n            //gradle-7.5-all\n            classpath \"com.android.tools.build:gradle:7.4.2\"\n        }\n    }\n    \n    allprojects {\n    \t\trepositories {\n    \t\t\t...\n    \t\t\tmaven { url 'https://jitpack.io' }\n    \t\t}\n    }\n```\n### 宿主侧\n1、 新建一个工程，作为宿主工程\n\n2、 在宿主工程的build.gradle文件下添加如下3个配置\n```\n    //插件脚本\n    apply from: \"https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp7_2_0/host.gradle\"        \n\n    android {\n        defaultConfig {\n            //这个配置不可省略\n            applicationId 宿主app包名        \n        }\n    }\n```\n\n```\n    dependencies {\n        //请务必使用@aar结尾，以中断依赖传递\n        implementation('com.github.limpoxe:Android-Plugin-Framework:latest.release@aar')\n        //可选，用于支持插件全局函数式服务，不使用全局函数式服务不需要添加此依赖\n        //implementation('com.limpoxe.support:android-servicemanager:1.0.5@aar')\n    }\n```\n\n```\n    fairy {\n        //可选配置，用于指定插件进程名。默认插件进程为单独的进程，进程名为\":plugin\"\n        //若设置为空串或者null即是使用宿主进程作为插件进程\n        //pluginProcess = \"\"\n        //pluginProcess = null\n        //pluginProcess = \":xxx\"\n    }\n```\n\n3、 在宿主工程中新建一个类继承自Application类, 并配置到AndroidManifest.xml中并重写这个类的下面2个方法\n```\n    @Override\n    protected void attachBaseContext(Context base) {\n        super.attachBaseContext(base);\n        \n        //框架日志开关, 默认false\n        FairyGlobal.setLogEnable(true);\n        \n        //首次加载插件会创建插件对象，比较耗时，通过弹出loading页来过渡。\n        //这个方法是设置首次加载插件时, 定制loading页面的UI, 不传即默认没有loading页\n        //在宿主中创建任意一个layout传进去即可\n        //注意：首次唤起插件组件时，如果是通过startActivityForResult唤起的，如果配置了loading页，\n        //则实际是先打开了loading页，再转到目标页面，此时会忽略ForResult的结果。这种情况下应该禁用loading页配置\n        FairyGlobal.setLoadingResId(R.layout.loading);\n        \n        //是否支持插件中使用本地html, 默认false\n        FairyGlobal.setLocalHtmlenable(true);\n        \n        //初始化框架\n        PluginLoader.initLoader(this);\n    }\n```\n        \n```\n    @Override\n    public Context getBaseContext() {\n        return PluginLoader.fixBaseContextForReceiver(super.getBaseContext());\n    }\n```\n\n4、在宿主工程中通过下面3个方法进行最基本的插件操作\n```\n    安装: PluginManagerHelper.installPlugin( SDcard上插件apk的路径 );\n    卸载: PluginManagerHelper.remove( 插件packageName );\n    列表: PluginManagerHelper.getPlugins();\n```\n    \n5、通过构造一个插件组件Intent打开插件\n\n   例如打开插件的Launcher界面\n```       \n   Intent launchIntent = getPackageManager().getLaunchIntentForPackage( 插件packageName );\t\t\t\n   startActivity(launchIntent);\n```\n   宿主编译完成后，会在outputs/distrubites目录下生成一个名为host.bar的基线包，作为编译插件的基线。\n   以上所有内容及更多详情可以参考Demo\n\t\n### 插件侧  \n独立插件：\n\n    新建一个工程, 作为插件工程，无需任何其他配置，编译出来即可当插件apk安装到宿主中。\n\n非独立插件：\n\n1、新建一个工程, 作为插件工程。\n            \n2、在build.gradle中添加如下2个配置\n```\n    //插件脚本\n    apply from: \"https://raw.githubusercontent.com/limpoxe/Android-Plugin-Framework/master/FairyPlugin/agp7_2_0/plugin.gradle\"\n\n    android {\n        defaultConfig {\n            //这个配置不可省略\n            applicationId 插件app包名        \n        }\n    }\n    \n    dependencies {\n        //***这是demo中的示例，请根据自己的实际情况修改，作用是指向插件依赖的宿主基线包***\n        //支持文件、maven坐标等写法\n        //baselinePatch 'xxx:xxx:xxx@bar'\n        //debugBaselinePatch 'xxx:xxx:xxx@bar'\n        //releaseBaselinePatch 'xxx:xxx:xxx@bar'\n        baselinePatch files(project(':Samples:PluginMain').getBuildDir().absolutePath + '/distributions/host.bar')\n    }\n\n ```       \n  \n  完成以上2步后即可编译出非独立插件，以上所有内容及更多详情可以参考Demo\n  \n### Demo编译方法\n\n   a）如果是命令行中：\n   \n```\n   cd  Android-Plugin-Framework\n   \n   ./gradlew clean\n  \n   ./gradlew :Samples:PluginMain:assembleF1Debug\n   \n   ./gradlew :Samples:PluginTesBase:assembleF1Debug\n   \n   ./gradlew assembleF1Debug\n   \n   ./gradlew :Samples:PluginMain:assembleF1Debug\n   \n   说明：由于框架、demo宿主和各个demo插件都在同一个工程下，依赖关系互相影响，因此需要一定的编译顺序才能正常运行\n   \n   第一个assembleF1Debug是为了编译宿主，产生基线bar文件\n   \n   第二个assembleF1Debug是为了编译基础插件，产生插件apk和jar，基础插件jar会被其他插件依赖\n   \n   第三个assembleF1Debug是为了编译所有插件，产生插件apk\n   \n   第四个assembleF1Debug是为了重新编译宿主，将前面编译生成的插件apk内置到宿主的assets目录中，作为内置插件使用\n   \n   接下来将宿主的out目录下的apk安装到设备上即可\n   \n```\n   \n\n   b）如果是studio中：\n   \n   打开studio右侧gradle面板区，点clean、点assembleDebug。不要使用菜单栏的菜单编译。\n\n   重要：\n        \n        1、由于编译脚本依赖Task.doLast, 使用其他编译方法（如菜单编译）可能不会触发Task.doLast导致编译失败\n        \n        2、必须先编译宿主，再编译非独立插件。（这也是使用菜单栏编译会失败的原因之一）\n           原因很简单，既然是非独立插件，肯定是需要引用宿主的类和资源的。所以编译非独立插件时会用到编译宿主时的输出物\n\n        3、由于宿主和插件在同一个工程中，点击assembleDebug时编译顺序不可控，会导致每次clean后，首次assembleDebug会失败，此时重新编译即可\n           可能需要执行3次assembleDebug，\n               第一次是编译宿主，产生bar文件，\n               第二次是依赖bar编译插件，产生插件文件\n               第三次是重新编译宿主，将插件文件内置到宿主assets中\n            所以如果使用其他编译方法，请务必仔细阅读build.gradle，了解编译过程和依赖关系后可以自行调整编译脚本，否则可能会失败。\n\n\t    4、Demo中使用了arm平台的so，若在x86平台上测试Demo可能会有so异常，请自行适配so。\n\t\n   待插件编译完成后，即可通过宿主在运行时下载插件apk或者将插件apk复制到sdcard调用PluginManagerHelper.installPlugin(\"插件apk绝对路径\")进行插件安装。\n\n   通常插件会内置一个版本到宿主中随宿主一起发布，则需要将插件配置到宿主的assets目录下，再编译一次宿主（即上述3中的第三次编译）。\n   配置方法如下：\n\n        dependencies {\n            //支持坐标依赖\n            //innerPlugin 'xxx:xxx:xxx@apk'\n            innerPlugin '/xx/xx/xx/xx.apk'\n        }\n\n\n   增加这个配置以后，宿主在打包时会将这个依赖的插件apk打包到宿主的assets目录中\n\n## 其他\n1. [使用指南](https://github.com/limpoxe/Android-Plugin-Framework/wiki/%E5%85%B6%E4%BB%96%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97)\n2. [原理简介](https://github.com/limpoxe/Android-Plugin-Framework/wiki/%E5%8E%9F%E7%90%86%E7%AE%80%E4%BB%8B)\n3. [使用Public.xml的坑和填坑](https://github.com/limpoxe/Android-Plugin-Framework/wiki/%E4%BD%BF%E7%94%A8Public.xml%E7%9A%84%E5%9D%91%E5%92%8C%E5%A1%AB%E5%9D%91).\n4. [更新记录](https://github.com/limpoxe/Android-Plugin-Framework/wiki/%E6%9B%B4%E6%96%B0%E8%AE%B0%E5%BD%95)\n\n## 联系作者：\n  Q：15871365851，添加时请注明插件开发\n  \n  Q群：116993004，重要：添加前请务必仔细阅读此ReadMe！请务必仔细阅读Demo！\n","funding_links":[],"categories":["Java"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flimpoxe%2FAndroid-Plugin-Framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flimpoxe%2FAndroid-Plugin-Framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flimpoxe%2FAndroid-Plugin-Framework/lists"}