# WMPF Client 与 Service 通信

在 [WMPF Client Demo](https://github.com/wmpf/wmpf_demo_external/tree/master/wmpf-demo) 中，你需要集成最新的 [wmpf-cli.aar](download)，才能顺利的和 WMPF Service 进行交互，wmpf-cli.aar 中集成了交互的数据类，序列化工具以及 IPC 调用能力。

## 交互模型

* Task：在 WMPF Service 中定义了一组 Task ，一个 Task 可以理解为一个 API ，定义了某种服务，比如用于激活设备的 [`ActivateDevice`](api/client/ActivateDevice) ，用于启动小程序的 [`LaunchWxaApp`](api/client/LaunchWxaApp) 
* WMPFRequest：Task 的请求参数
* WMPFResponse：Task 请求的响应

**注意**：这里的协议都是强类型的，所以只能用我们定义好的数据类来发起请求和获取应答。同样，也只能用我们封装好的 `WMPFIPCInvoker.class` 来发起请求。

![](https://res8.wxqcloud.qq.com.cn/wxdoc/49f9cb96-b2f0-491e-981a-81660359078f.png)

## 示例代码

```kotlin
findViewById(R.id.btn_init_wmpf_activate_device).setOnClickListener {
  Api.activateDevice(Constants.PRODUCTID, Constants.KEYVERSION,
                     Constants.DEVICEID, Constants.SIGNATURE, Constants.APP_ID)
  .subscribe({
    Log.i(TAG, "success: $it")
    InvokeTokenHelper.initInvokeToken(this, it.invokeToken)
    postToMainThread(Runnable {
      Toast.makeText(this, String.format("init finish, err %d",
                                         it?.baseResponse?.ret), Toast.LENGTH_SHORT).show()
    })
  }, {
    Log.e(TAG, "error: $it")
  })
}
```
以激活设备为例，用户点击到激活设备的按钮后，代码将请求的参数传入了 `Api.activateDevice()` 并且订阅了结果。
```kotlin
object Api {

  fun activateDevice(productId: Int, keyVerion: Int,
                     deviceId: String, signature: String, hostAppId: String): Single {
    return Single.create {
      val request = WMPFActivateDeviceRequest().apply {
        this.baseRequest = WMPFBaseRequestHelper.checked()
        this.productId = productId
        this.keyVersion = keyVerion
        this.deviceId = deviceId
        this.signature = signature
        this.hostAppId = hostAppId
      }

      var result = WMPFIPCInvoker.invokeAsync(
        request,
        IPCInvokerTask_ActivateDevice::class.java,
        object : IPCInvokeCallbackEx {
          override fun onBridgeNotFound() {
            it.onError(Exception("bridge not found"))
          }

          override fun onCallback(response: WMPFActivateDeviceResponse) {
            it.onSuccess(response)
          }
        })

      if (!result) {
        it.onError(Exception("invoke activateDevice fail"))
      }
    }
  }
}
```
在 `activateDevice` 方法中，发起了真正的请求。这里先组装 `WMPFActivateDeviceRequest` ，然后调用 `WMPFBaseRequestHelper.checked()` 对基本的字段进行检查，最后调用 ` WMPFIPCInvoker.invokeAsync<IPCInvokerTask_ActivateDevice, WMPFActivateDeviceRequest, WMPFActivateDeviceResponse>(task,request,response)` 发起请求，请求的响应将在第三个参数中 `callback` 回来。

## 备注

* [Client Task 文档](api/client/ActivateDevice)
