Skip to content

Android APP集成

一、SDK 使用流程介绍

SDK 的使用流程如下:

  1. SDK 依赖并集成
  2. SDK 初始化
  3. 根据业务需求使用相应的功能

二、SDK 集成

SDK 集成需要完成相关依赖库的集成操作。

2.1、集成环境

环境要求
支持最低SDK版本android 5.0系统,SDK_INT>=21
kotlin依赖需要

2.2、配置依赖库

Android 的 SDK 以 kotlin 语言编写,并尽可能兼容 Java 语言的调用。文档中提及的 flow 为 kotlin 中提供的协程类(如asFlow()asFlowOnIO()等方法),具体的使用请参考 kotlin 官方说明。

2.2.1、配置 maven 仓库

在根项目下的build.gradle文件中,添加上依赖库相关的 maven 仓库地址。

groovy
allprojects {
    repositories {
        maven { url "https://code.xlink.cn/xlink_open/xlink_maven/-/raw/master" }
    }
}
  1. 如果 maven 仓库配置出现问题无法正常使用,请确认 settings.gradle 中是否有以下的配置,如果存在请移除掉。
groovy
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        jcenter() // Warning: this repository is going to shut down soon
    }
}
  1. 如果编译的版本太高可能会导致一些编译时的问题,推荐以下的编译版本
groovy
android {
    compileSdkVersion 29

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 26
    }
}
  1. 如果出现 gradle 插件异常时,请确认当前的 gradle 版本,目前不支持 7.0 以上的 gradle 插件。
groovy
//根项目下的 build.gradle 插件版本
buildscript {
    dependencies {
        classpath 'com.android.tools.build:gradle:4.0.0'
    }
}

//gradle/wrapper/gradle-wrapper.properties配置信息
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

2.2.2、配置依赖文件

在主项目(或需要使用 SDK 的项目)下,在其对应的build.gradle的文件中,配置以下的依赖库。其中第三方依赖库可以根据需要调整版本号。

注:

  1. 下述依赖库为默认使用的依赖库及其版本,如果是第三方库/公用库版本与集成的 APP 中的库版本不一致,请自行替换版本并运行
  2. SDK 对所有第三方库不强制要求其版本号,只要第三方库的接口及版本兼容处理好均可替换(取决于第三方库的兼容情况)
  3. 若出现替换版本后确实存在异常情况,请再联系相关对接人员协助处理
groovy
//kotlin 官方依赖库
implementation 'org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version'

//网络请求库及其依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation('com.squareup.retrofit2:converter-gson:2.5.0') {
    exclude group: 'com.google.code.gson', module: 'gson'
}
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'

//xlink依赖库
implementation 'cn.xlink:xmaf_core_config:0.1.1-alpha'

如果基于 kotlin 语言开发,并且需要使用 kotlin 的协程功能,则请添加协程依赖库,否则无法使用相关功能。

groovy
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0'

如果使用 Java 语言开发,并且使用 RxJava,则请添加 RxJava 相关依赖库,当存在 RxAndroid 的依赖库时,默认将会配置主线程 schedules 确保接口的调用最终在主线程中回调。

groovy
implementation "io.reactivex.rxjava2:rxjava:2.2.3"
implementation "io.reactivex.rxjava2:rxandroid:2.1.0"

2.2.3、应用权限要求

仅使用服务功能时,不需要额外的权限,涉及 API 接口请求时(如用户授权服务 XFAuthServer 中的登录操作),请配置网络权限。

xml
<uses-permission android:name="android.permission.INTERNET" />

2.3、SDK 初始化

SDK 集成后需要在使用前初始化。必须确保 SDK 初始化后才能正常使用。初始化 SDK 的部分配置以配置文件的方式提供,需要加载配置文件进行初始化。

在 Android 中不要求 SDK 的初始化必须在 applicatoin 创建时,只需要确保在调用前成功进行了初始化即可。

  1. 将提供的配置文件(默认文件名为xlink_config.xf)置于项目的assets文件夹中,并以下述的方式读取。
kotlin
val configInfo = InputStreamReader(assets.open("xlink_config.xf")).readText()

注:放置在其它任何地方都行,只需要以 UTF-8 的编码读取为文本用于加载配置即可

  1. 配置并初始化 SDK
kotlin
//默认的配置初始化,必须使用这个初始化
val config = XFDefaultBuilder()
    //添加依赖的服务,如有其它依赖的服务自行添加
    //.addServerInitBackground(CustomServer)
    .setConfigJson(configInfo)
    .build()
XFUnionKit.initConfig(config)

通过以上的操作,初始化操作就完成了。请留意日志中是否有相关的错误信息输出,有的话请参考错误信息说明处理或进行反馈。

2.4、SDK 使用

SDK 的核心为服务,通过提供各种服务来解决业务需求或功能的使用。

tips:服务的介绍说明请参考APP集成说明

三、服务调用

SDK 初始化成功后,即可调用相关的服务,服务调用时统一从 XFServerManager 中获取服务并使用。

3.1、显式调用

服务支持显式调用,显式调用时表示调用者明确知道自己使用的服务类型,并且必须依赖具体的服务类型。一般的显式调用如下:

kotlin
XFServerManager.getServerAgent<XFAuthServer>("服务ID")
    .getServer()
    .asFlow()
    .onEach{
        //明确知道服务是 XFAuthServer 类型,并直接调用其中的方法,同时也必须在编译时依赖该服务
        it.addAuthChangedListener(xxx)
    }
    ...

其中 getServer() 的操作会确保服务在使用前初始化,该操作是异步的。

tips:如果需要同步操作可以使用其它同步方法,如getServerSync(),但非必要不推荐。

3.2、隐式调用

服务也支持隐式调用,隐式调用时,调用者可以不明确知道自己使用的服务类型,或服务操作,但是必须明确服务调用需要的参数及返回信息。一般的隐式调用如下:

kotlin
//指定调用的服务ID
XFServerManager.createInvokeBuilder("A")
    //指定调用的服务路由
    .setRouterPath("B")
    //配置服务使用的参数
    .withParam("context", context)
    //调用服务操作,泛型数据类型是该操作返回的类型,由被调用者定义
    .invokeServer<Boolean>()
    //转换成异步处理
    .asFlowOnIO()
    .onEach {
        if(it){
            Toast.makeText(this, "隐式启动页面成功", Toast.LENGTH_SHORT).show()
        }
    }
    ...
  1. 隐式调用的前提是调用者与被调用者是通过约定的方法进行调用的,如果双方没有约定好或者是不清楚时,可能导致入参错误或出参类型错误,则无法正确完成调用。 在以上示例中,表示:通过调用服务ID为“A”的服务,并使用路由地址为“B”的功能,提供服务需要的参数“context”,调用服务得到返回类型为“Boolean”类型的数据。
  2. 隐式调用是需要服务本身支持的,如果服务没有实现路由功能的支持与处理,进行隐式调用是肯定会失败的
  3. 隐式调用时,返回的参数类型默认是支持可空类型的,在实现时需要留意一下。

tips:如果不太关心出参等信息,出参类型可以用Any?承载,但是您必须知道您想要做什么和在做什么,需要与被调用方有约定好的使用方式。

四、异步操作对象

对于服务框架中的接口,绝大部分提供了异步操作接口,同时支持同步操作。异步操作是基于XFAsyncAction实现的。

方法说明
execute()同步执行操作,会在当前的线程执行操作
asFlow()转换成 flow 进行处理,注意 flow 是没有指定运行的线程的
asFlowOnDispatchers(dispatcher)转换成 flow 并指定运行的线程进行处理
asFlowOnIO()转换成 flow 并运行在 IO 线程
asObservable()兼容 java 调用方法,转换成 rxjava 的 observable 处理,没有指定运行线程

所有的异步操作基于此类,可根据需要进行同步或异步的调用,或者是转换成需要的方式处理。

示例:

kotlin
XFServerManger.getServerAgent<XFIServer>("server_id")
    .getServer()
    .asFlowOnIO()
    ...

4.1、异步操作的错误处理

对于框架中提供的异步操作,当操作中发生异常时将会被抛出,在catch中可以捕获异常并进行处理。为了方便处理错误,支持将错误类型转换成默认的XFError错误码类型,从而实现统一的错误码处理。需要明确返回XFError类型时,请使用相应的扩展方法onXLinkError

kotlin
//此操作中将返回的异常类型固定为 XFError
flow.onXLinkError { ... }

tips:更多错误码信息及说明请参考错误码的相关章节。

4.2、异步操作的转换

由于框架中很多异步操作通过XFAsyncAction完成,所以可能会出现连续多个操作结果都是XFAsyncAction并需要依赖上一次操作的结果。对此异步操作对象提供了简单的转换方法,用于将异步操作结果暴露到最终目的行为中。

4.2.1、XFAsyncAction转换成目标类型

XFAsyncAction<T>中的值类型为T,可以通过以下的方式将结果直接提取出来,并将T类型转换成任意其它R类型

kotlin
val action=XFAsyncAction.create { "" }
    //提取出 XFAsyncAction 中的 String,并转换成 Int 类型的数据
    .map2X { 0 }
    .asFlowOnIO()
    ...

4.2.2、XFAsyncAction转换成另一个XFAsyncAction并提取目标类型

XFAsyncAction<T>中的值类型为T,可以通过以下的方式将结果直接提取出来,并使用T类型的数据,转换成另一个XFAsyncAction<R>类型,同时返回R

kotlin
val action=XFAsyncAction.create { "" }
    //提取出 XFAsyncAction 中的 String,并转换成另一个 XFAsyncAction 对象
    .map2AsyncX { XFAsyncAction.create { 0 } }
    .map2X { it.toString() }
    .asFlowOnIO()
    ...

此方法在对服务调用时非常便捷。

kotlin
XFServerManager.getServerAgent<XFAuthServer>(XFAuthServer.SERVER_ID)
    .getServer()
    //获取的是一个异步操作对象 XFAsyncAction<XFAuthServer>
    .map2AsyncX { it.authAccount(AuthParams("企业ID", "账号", "密码", false)) }
    .asFlowOnIO()
    ...

用户授权服务

一、简介

用户授权服务是在C端 APP 中提供用户登录后的授权信息管理的服务。包含对授权信息的缓存与更新,并提供基础的用户授权操作。由于用户的实际授权方式有多种(包含账号密码登录、手机短信验证码登录、第三方账号登录等),授权服务仅提供最常用的账号密码登录功能。其它的功能请通过C端 APP 的 API 完成登录操作。

授权服务的主要功能包含:授权信息的缓存与管理

二、服务功能

1、用户授权登录

通过授权服务进行登录时,服务默认会将授权登录成功后的授权信息缓存到服务中,后续需要授权信息时直接使用即可。

kotlin
XFServerManager.getServerAgent<XFAuthServer>(XFAuthServer.SERVER_ID)
    .getServer()
    .map2AsyncX { it.authAccount(AuthParams("企业ID", "账号", "密码", false)) }
    .asFlowOnIO()
    .onEach { println("userId=${it.userId}") }
    .launchIn(GlobalScope)

tips:示例中使用 GlobalScope,实际场景中请根据需要自行替换,示例不保证协程运行作用域的合理性与有效性

2、缓存授权信息

当不通过授权服务进行登录,或者是授权服务无法满足需要的登录方式,通过外部的登录方式获取到授权信息后,可以通过以下的方式将授权信息缓存到授权服务中,以便在其它地方或供其它的服务使用。

kotlin
XFServerManager.getServerAgent<XFAuthServer>(XFAuthServer.SERVER_ID)
    .getServer()
    .asFlowOnIO()
    .onEach {
        it.saveUserAuthInfo(XFAuthInfo("userId","accessToken","refreshToken","authorize",7200))
    }
    .launchIn(GlobalScope)

3、监听授权信息变更

如果需要对授权信息变更进行监听,授权服务也提供了相应的功能以便其它服务使用。

kotlin
XFServerManager.getServerAgent<XFAuthServer>(XFAuthServer.SERVER_ID)
    .getServer()
    .map2X { it.addAuthChangedListener(listener) }
    .asFlowOnIO()
    ...

移除授权信息监听时,可以使用以下方式移除监听。

kotlin
XFServerManager.getServerAgent<XFAuthServer>(XFAuthServer.SERVER_ID)
    .getServer()
    .map2X { it.removeAuthChangedListener(listener) }
    .asFlowOnIO()
    ...

4、获取授权信息

如果需要访问授权信息时,可以通过以下方法访问。

kotlin
XFServerManager.getServerAgent<XFAuthServer>(XFAuthServer.SERVER_ID)
    .getServer()
    .asFlow()
    .map { it.getUserAuthInfo() }
    .onEach { println(it?.accessToken) }
    ...

注意授权服务默认是在 SDK 初始化后即可使用,但是授权信息是需要在用户登录或者是调用了缓存授权信息接口后才会存在数据,请尽量确保用户在授权完成之后再调用此接口

网络请求服务

一、简介

C端 APP 提供了默认的网络请求服务,默认情况下是针对 XLINK 的接口使用。网络请求服务用于 SDK 统一发起接口请求,并返回统一的错误码格式及信息的 HTTP 请求处理服务。如果是需要发起 XLINK 相关的 API 请求,推荐优先使用网络请求服务。

网络请求服务默认将会使用授权服务中的用户授权信息,不再需要另行指定 Access-Token;网络请求服务也预定义了部分 XLINK 接口服务实现,可以通过接口直接进行 XLINK API 的调用,不用再另行定义接口并调用。

tips:默认情况下,网络请求服务在 SDK 初始化时一并初始化,不需要再另行注册初始化。

如果需要发起 XLINK API 请求时,可以优先使用请求框架中提供的请求接口。以用户登录操作请求为例:

kotlin
XLinkApiImplUser.postUserAuth(RequestUserAuth("企业ID","账号","密码",false))
    .asFlow()
    .onEach { println(it.accessToken) }
    .launchIn(GlobalScope)

tips:flow 为 kotlin 中提供的协程类,具体的使用请参考 kotlin 官方说明。

所有的 XLINK 接口遵循以下的命名规范:

  1. 可以直接调用的 API 接口为XLinkApiImpl前缀,后接相应的 API 模块名称,如用户相关接口为XLinkApiImplUser,设备相关接口为XLinkApiImplDevice
  2. 所有的请求参数类以Request前缀,后接 API 接口的相关描述,如用户登录授权请求参数为RequestUserAuth
  3. 所有的响应参数类以Response前缀,后接 API 接口的相关描述,与Request请求基本对应,如用户授权登录响应参数为ResponseUserAuth

注意在 XLINK API 发生变更时,相应的接口的参数和返回信息也可能会发生变更,使用 XLINK API 请求时,将会有以下的默认配置。

  1. 默认将会使用指定的路径进行请求,所有的请求路径在XLinkApiPath前缀,不同模块的名称作为后缀,如用户相关接口路径XLinkApiPathUser
  2. 默认使用的路径为相对路径,将会拼接上网络请求服务配置的域名。域名信息在xlink_config.xf的初始化配置文件中定义。
  3. 默认请求接口都会使用授权信息中的数据,在请求时拼接上Access-Token的授权信息。

tips:XLINK API 接口的请求仅适用于 XLINK 平台的请求,并且初始化配置文件中使用的域名相应的 XLINK 平台域名,以确保服务接口可以正常调用。如需灵活或定制性更强的接口,请使用通用 HTTP 请求

三、通用的 HTTP 请求服务

网络请求服务允许发起任意类型的 HTTP 请求操作,包含 XLINK 平台的 API 与非 XLINK 平台的接口都是允许的。HTTP 请求默认是使用 retrofit 请求框架发起的请求。

kotlin
//请求类
class Request(val userId:String)
//返回类
class Response{
    //此处使用的是 gson 的序列化
    @SerializedName("access_token")
    var accessToken:String=""
}

fun sendRequest(){
    val params = Request("用户ID")
    HttpRequest()
        //指定请求方式
        .post()
        //设置请求路径,可以是相对地址或绝对地址
        .setUrl("/v2/xlink/test/{path_1}")
        //设置header中的参数
        .addHeaderParams("Access-Token","授权信息")
        //设置路径中的参数
        .addPathParams("{path_1}","路径")
        //设置查询参数
        .addQueryParam("id","查询参数")
        //设置body
        .setBodyFormatByGson(params)
        .createExecutor<Response>()
        .asFlow()
        .onEach { println(it.accessToken) }
        .launchIn(GlobalScope)
}

一般情况下,参考上述的请求构建方式,即可发起一个 http 请求,满足大部分情况下的需求。

tips:XLINK API 请求时数据序列化依赖于 Gson,对于参数与返回数据序列化时,请使用 Gson 进行序列化标识

1、其它请求操作

HttpRequest 提供了多种场景的使用接口,根据接口的要求可以使用不同的功能。

1.1、设置完整的请求链接

如果需要使用完整的请求链接,而不需要拼接配置文件中定义好的 baseUrl 时,请使用以下方法。

kotlin
HttpRequest()
    ...
    .setCompleteUrl("完整的URL")
    ...
1.2、设置 json 字符串形式的 body

如果请求的 body 比较复杂或者是临时性数据,不方便构建成一个对象时,可以直接设置字符串形式的 body。

kotlin
HttpRequest()
    ...
    .setBodyAsJson("""{"参数":"值"}""")
    ...

由于网络服务中包含了 XLINK API 的接口处理,其中就包含了 XLINK API 的路径定义。常用的一些 API 路径已经定义到接口中了。所以对于 XLINK API 的接口请求也可以通过通用 HTTP 请求构建出来,以下的处理方式适用于某些接口变更或参数定制性较强的场景

下面以用户登录授权接口为例,该操作与XLinkApiImplUser.postUserAuth()的方法调用是相同的。

kotlin
val request=RequestUserAuth("企业ID","账号","密码",false)
HttpRequest()
    .post()
    .setBodyFormatByGson(request)
    .createExecutor<ResponseUserAuth>()
    .asFlow()
    ...

APP原生应用开发

一、原生应用开发

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

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

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

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

1、创建自定义服务

自定义服务是由服务提供者创建的。

1.1、实现 XIServer 接口

所有的服务都需要实现 XFIServer 的接口。服务有自己的生命周期,由服务管理模块进行调度与处理。

由于大部分情况下并不需要实现或处理服务的所有生命周期,所以提供了两个可选的抽象类方便服务实现。推荐选择以下两个抽象类快速实现服务,当然也可以完全实现 XFIServer 并自行处理。

抽象类说明及使用场景
AbsXFEmptyServer默认的空服务实现类,继承自该类需要实现服务的路由处理及服务ID
AbsXFUnsupportedRouterServer默认的无路由功能服务实现类,继承自该类需要实现服务ID,该类不支持隐式方式调用
kotlin
object XFCustomServer : AbsXFUnsupportedRouterServer() {
    //定义服务ID,建议添加上自身模块的前缀或包名等标识性信息
    const val SERVER_ID = "XFCustomServer"

    override fun getId(): String {
        return SERVER_ID
    }
}
1.2、定义服务功能

每个服务都可以有自己单独的功能,功能以普通的实例方法提供。

kotlin
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、定义路由功能

定义当前服务需要提供的功能以隐式方式提供时,使用的路由信息。调用者将通过该路由信息对相应的功能准确地调用。

kotlin
object XFCustomServer : AbsXFUnsupportedRouterServer() {
    //...省略上述创建的内容

    //定义路由的功能,此处为登录页面的跳转
    const val ROUTER_LOGIN = "/$SERVER_ID/login/page"
}
1.3.2、实现路由功能的支持与处理

确定了路由信息后,需要实现与路由相关的方法,用于实现路由的功能处理。本质上相当于通过约定类似于 API 的访问方式,以指定的路由信息访问相关的功能或资源,并且返回操作的结果。

请注意所有的服务隐式调用时,返回的结果都是异步操作对象 XFAsyncAction

kotlin
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、初始化时注册服务
kotlin
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、服务使用前注册

在任何时候,如果服务未注册时,都可以在使用前再进行注册并使用。

kotlin
//注册并初始化返回该服务
XFServerManager.registerServerAgent<XFCustomServer>(XFCustomServer)
    .registerAndGetServer()
    .asFlow()
    .onEach { 
        it.startCustomActivity(this)
    }
    .launchIn(MainScope())

如果不需要立即使用该服务,也可以选择提前注册服务,后续在需要的地方再初始化使用。所有的服务默认会在首次被使用时才初始化。

kotlin
//提前注册服务
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、显式调用
kotlin
XFServerManagergetServerAgent<XFCustomServer(XFCustomServer.SERVER_ID)
    .getServer()
    .map2X {
        it.startCustomActivity(this)
    }
    .asFlowOnIO()
    .onEach {
        Toast.makeText(this, "显式启动页面成功", Toast.LENGTH_SHORT).show()
    }
    .launchIn(MainScope())
3.2、隐式调用
kotlin
XFServerManager.createInvokeBuilde("XFCustomServer")
    .setRouterPath("/XFCustomServer/login")
    .withParam("context", this)
    .invokeServer<Any?>()
    .asFlowOnIO()
    .onEach {
        Toast.makeText(this, "隐式启动页面成功", Toast.LENGTH_SHORT).show()
    }
    .launchIn(MainScope())