一、原生应用开发
如果需要开发原生应用并集成到C端 APP 中使用时,可以通过自定义服务实现该功能。C端 APP 基于 XMAF 服务框架使用,所以将自定义的服务注册到 XMAF 框架后,在C端 APP 中可以通过服务间的通讯与操作完成功能的调用。
下面通过一个简单的示例来表示自定义服务如何实现及使用。详细的说明请参考下文。大概流程是:
- 服务开发者创建自定义服务
- 应用开发者集成并注册服务
- 应用开发者调用相应的服务
注意自定义服务的创建人员是服务提供者,集成到应用中并使用该服务功能的人员是服务调用者,两者的身份是不同的,可以是同一开发人员,也可以是不同的开发人员。
1、创建自定义服务
自定义服务是由服务提供者创建的。
1.1、实现 XIServer 接口
所有的服务都需要实现 XFIServer 的接口。服务有自己的生命周期,由服务管理模块进行调度与处理。
由于大部分情况下并不需要实现或处理服务的所有生命周期,所以提供了两个可选的抽象类方便服务实现。推荐选择以下两个抽象类快速实现服务,当然也可以完全实现 XFIServer 并自行处理。
抽象类 | 说明及使用场景 |
---|---|
AbsXFEmptyServer | 默认的空服务实现类,继承自该类需要实现服务的路由处理及服务ID |
AbsXFUnsupportedRouterServer | 默认的无路由功能服务实现类,继承自该类需要实现服务ID,该类不支持隐式方式调用 |
object XFCustomServer : AbsXFUnsupportedRouterServer() {
//定义服务ID,建议添加上自身模块的前缀或包名等标识性信息
const val SERVER_ID = "XFCustomServer"
override fun getId(): String {
return SERVER_ID
}
}
1.2、定义服务功能
每个服务都可以有自己单独的功能,功能以普通的实例方法提供。
object XFCustomServer : AbsXFUnsupportedRouterServer() {
//...省略上述创建的内容
//创建的实例方法,用于显性调用
fun startCustomActivity(context:Context){
context.startActivity(Intent(context, CustomActivity::class.java))
}
}
tips:某些场景可能需要使用到C端 APP 中的基础信息,如用户授权信息,用户数据等,请参考C端 APP 提供的基础服务。
1.3、确认服务提供的调用方式
在APP SDK的使用中,提及了服务的调用方式有两种,显式调用与隐式调用。在定义了服务的功能方法之后,服务就可以满足显式调用的方式使用了。
但是如果需要服务支持隐式调用,则需要实现服务的路由功能,否则无法完成服务的隐式调用。实现服务的路由功能时,需要实现服务接口中路由相关的方法。
1.3.1、定义路由功能
定义当前服务需要提供的功能以隐式方式提供时,使用的路由信息。调用者将通过该路由信息对相应的功能准确地调用。
object XFCustomServer : AbsXFUnsupportedRouterServer() {
//...省略上述创建的内容
//定义路由的功能,此处为登录页面的跳转
const val ROUTER_LOGIN = "/$SERVER_ID/login/page"
}
1.3.2、实现路由功能的支持与处理
确定了路由信息后,需要实现与路由相关的方法,用于实现路由的功能处理。本质上相当于通过约定类似于 API 的访问方式,以指定的路由信息访问相关的功能或资源,并且返回操作的结果。
请注意所有的服务隐式调用时,返回的结果都是异步操作对象 XFAsyncAction。
object XFCustomServer : AbsXFUnsupportedRouterServer() {
//...省略上述创建的内容
//判断外部需要调用的路由是否匹配,当前服务是否支持该路由功能
override fun isSupportRouter(router: String): Boolean {
return router == ROUTER_LOGIN
}
//处理路由功能
override fun <T> invokeServer(router: String, params: Map<String, Any?>): XFAsyncAction<T> {
return when (router) {
ROUTER_LOGIN -> {
//创建异步操作对象并返回
XFAsyncAction.create {
val context = params["context"] as Context
startCustomActivity(context)
true as T
}
}
else -> XFIServer.createErrorUnsupportedOperation("不支持的路由调用")
}
}
}
2、注册服务
在服务创建成功后,需要注册服务到 XMAF 服务框架中,否则其它开发者无法通过 XMAF 访问并使用该服务。注册并使用服务是由服务调用者完成的。
tips:服务注册是由外部应用完成的,服务本身无法完成服务的注册。一般需要在应用初始化或在使用此服务前,显式地将服务注册到 XMAF 中,后续才能使用该服务。
服务的注册可以分两个不同的时机,在服务初始化时注册;或者是在使用该服务前再进行注册使用。两种方式都是允许的。
2.1、初始化时注册服务
val configInfo = InputStreamReader(assets.open("xlink_config.xf")).readText()
val config = XFDefaultBuilder()
//初始化时注册自定义服务
.addServerInitBackground(XFCustomServer)
.setConfigJson(configInfo)
.build()
XFUnionKit.initConfig(config)
注意在上面的初始化流程中,除.addServerInitBackground(XFCustomServer)
是注册自定义服务之外,其它的都是初始化的默认操作,请参考SDK 初始化。
2.2、服务使用前注册
在任何时候,如果服务未注册时,都可以在使用前再进行注册并使用。
//注册并初始化返回该服务
XFServerManager.registerServerAgent<XFCustomServer>(XFCustomServer)
.registerAndGetServer()
.asFlow()
.onEach {
it.startCustomActivity(this)
}
.launchIn(MainScope())
如果不需要立即使用该服务,也可以选择提前注册服务,后续在需要的地方再初始化使用。所有的服务默认会在首次被使用时才初始化。
//提前注册服务
XFServerManager.registerServerAgent<XFCustomServer>(XFCustomServer)
.registerServer()
.asFlowOnIO()
.launchIn(CoroutineScope(Dispatchers.Default))
//...应用运行一段时间后
//在需要的调用的地方,进行服务的调用
XFServerManager.getServerAgent<XFCustomServer>(XFCustomServer.SERVER_ID)
.getServer()
.asFlowOnIO()
.onEach { it.startCustomActivity(this) }
.launchIn(MainScope())
tips:所有的注册与调用都有区分异步与同步操作的,根据需要自行选择即可。优先推荐使用异步操作,这是因为服务的初始化过程可能会有延迟或耗时操作。
3、服务调用
服务的调用与开发指南中的服务调用一致。主要有两种方式,其中隐式的调用方式由服务提供方决定是否支持。在需要进行模块依赖的解耦与功能模块化时,推荐实现并使用隐式服务,调用者不需要关心具体的服务由谁提供,仅需要提前约定好使用的服务ID,路由信息及参数即可,在约定的规范不变的情况下,服务的提供方可以进行任何的更换。
3.1、显式调用
XFServerManagergetServerAgent<XFCustomServer(XFCustomServer.SERVER_ID)
.getServer()
.map2X {
it.startCustomActivity(this)
}
.asFlowOnIO()
.onEach {
Toast.makeText(this, "显式启动页面成功", Toast.LENGTH_SHORT).show()
}
.launchIn(MainScope())
3.2、隐式调用
XFServerManager.createInvokeBuilde("XFCustomServer")
.setRouterPath("/XFCustomServer/login")
.withParam("context", this)
.invokeServer<Any?>()
.asFlowOnIO()
.onEach {
Toast.makeText(this, "隐式启动页面成功", Toast.LENGTH_SHORT).show()
}
.launchIn(MainScope())