-
Notifications
You must be signed in to change notification settings - Fork 54
2.开发实例
接下来通过演示今热的基本开发流程加深理解
新建一个Android工程,创建git版本控制后,运行指令
git submodule add https://github.com/RyensX/MediaBoxPlugin.git submodules/MediaBoxPlugin
目前插件API还没有打包上传到Maven,因此建议通过以上submodule的方式引用。
然后在settings.gradle.kts(settings.gradle)底部添加代码导入模块
val pluginApi = ":MediaBoxPluginApi"
include(pluginApi)
project(pluginApi).projectDir = File("./submodules/MediaBoxPlugin/pluginApi")
注意:这是kts,建议把默认的settings.gradle删除新建settings.gradle.kts
完整settings.gradle.kts代码
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "TodayHot"
include(":app")
val pluginApi = ":MediaBoxPluginApi"
include(pluginApi)
project(pluginApi).projectDir = File("./submodules/MediaBoxPlugin/pluginApi")
在任意一个包下新建一个类,继承IPluginFactory
package com.su.todayhot.plugin
import com.su.mediabox.pluginapi.IPluginFactory
import com.su.mediabox.pluginapi.action.Action
import com.su.mediabox.pluginapi.action.CustomPageAction
import com.su.mediabox.pluginapi.action.HomeAction
import com.su.mediabox.pluginapi.components.IBasePageDataComponent
import com.su.todayhot.plugin.components.HotPageComponent
class PluginFactory : IPluginFactory() {
//今热没有具体host所以留空
override val host: String = ""
//自定义了初始化Action,具体看IPluginFactory的文档注释
override val initAction: Action
get() = CustomPageAction.obtain(HotPageComponent::class.java)
//自定义了页面数据组件
@Suppress("UNCHECKED_CAST")
override fun <T : IBasePageDataComponent> createComponent(clazz: Class<T>): T? {
return HotPageComponent() as? T?
}
}
然后打开AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.su.todayhot">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true">
<!--第一步:每个插件必须注册这里才能被识别为插件-->
<!--name固定media_plugin_api_impl-->
<!--value填写上面写的类完整包名-->
<meta-data
android:name="media_plugin_api_impl"
android:value="com.su.todayhot.plugin.PluginFactory" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<!--可选,方便调试-->
<!--name固定media_plugin_debug-->
<action android:name="media_plugin_debug" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这里的<action android:name="media_plugin_debug" />
为可选项,目的是为了让媒体盒子能直接检测到外部以apk方式安装到系统上的插件以方便调试,注意:只有debug版的媒体盒子才能检测到外部插件。
有一点需要注意的是,由于Android的问题,如果你在开发插件时不更新versionCode或versionName覆盖安装的话内部apk是不会更新的,这就导致你会发现明明改了代码但在媒体盒子中启动后没效果。所以最简单办法是直接卸载重装(直接实机调试),媒体盒子可以实时检测到插件变动并自动更新(若插件已在运行则需要重开插件)。
今热只有一个页面数据组件,是一个自定义页面数据组件HotPageComponent,复杂一些。最简单是使用默认的IHomePageDataComponent,继承它写一个页面数据组件,启动插件时默认启动IHomePageDataComponent。
class HomePageDataComponent : IHomePageDataComponent {
override suspend fun getData(page: Int): List<BaseData>? {
val data=mutableListOf<BaseData>()
data.add(SimpleTextData("一个占满整行的文本"))
return data;
}
}
可以去参考插件仓库的各个插件的实现,比如樱花动漫的,也可以直接拷贝整个实现然后根据自己需要改。
写好后在2实现的PluginFactory里返回实例
package com.su.todayhot.plugin
import com.su.mediabox.pluginapi.IPluginFactory
import com.su.mediabox.pluginapi.action.Action
import com.su.mediabox.pluginapi.action.CustomPageAction
import com.su.mediabox.pluginapi.action.HomeAction
import com.su.mediabox.pluginapi.components.IBasePageDataComponent
import com.su.todayhot.plugin.components.HotPageComponent
class PluginFactory : IPluginFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : IBasePageDataComponent> createComponent(clazz: Class<T>): T? {
return HomePageDataComponent() as? T?
}
}
如果实现了很多个不同类型组件需要使用,可以参考:
class PluginFactory : IPluginFactory() {
override val host: String = Const.host
override fun <T : IBasePageDataComponent> createComponent(clazz: Class<T>) = when (clazz) {
IVideoPlayPageDataComponent::class.java -> VideoPlayPageDataComponent()
IMediaSearchPageDataComponent::class.java -> MediaSearchPageDataComponent()
IMediaDetailPageDataComponent::class.java -> MediaDetailPageDataComponent()
IMediaClassifyPageDataComponent::class.java -> MediaClassifyPageDataComponent()
IHomePageDataComponent::class.java -> HomePageDataComponent()
//自定义页面,需要使用具体类而不是它的基类(接口)
RankPageDataComponent::class.java -> RankPageDataComponent()
UpdateTablePageDataComponent::class.java -> UpdateTablePageDataComponent()
else -> null
} as? T
}
更多使用方法可以看API源码,里面有详细的文档注释。
另外欢迎提交插件到官方插件仓库