APP原生应用开发

一、原生应用开发

如果需要开发原生应用并集成到C端 APP 中使用时,可以通过自定义服务实现该功能。C端 APP 基于 XMAF 服务框架使用,所以将自定义的服务注册到 XMAF 框架后,在C端 APP 中可以通过服务间的通讯与操作完成功能的调用。

下面通过一个简单的示例来表示自定义服务如何实现及使用。详细的说明请参考下文。大概流程是:

  1. 服务开发者创建自定义服务
  2. 应用开发者集成并注册服务
  3. 应用开发者调用相应的服务

注意自定义服务的创建人员是服务提供者,集成到应用中并使用该服务功能的人员是服务调用者,两者的身份是不同的,可以是同一开发人员,也可以是不同的开发人员。

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())
没找到需要的文档?
你可以提交工单反馈 或 阅读常见问题