Flutter Wear OS:如何正确等待Activity返回结果至Platform Channel
问题描述
在Wear OS端对接Flutter Platform Channel时,需要实现唤起原生输入Activity获取用户输入文本,再将结果回传给Flutter端的功能。当前实现存在问题:调用startActivityForResult后不会等待Activity返回结果就直接执行后续逻辑,Flutter端会立即收到null返回值。
当前错误实现代码:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel( flutterEngine.dartExecutor.binaryMessenger, channel ).setMethodCallHandler { call, result -> myResult = result getInputText() } } private fun getInputText() { val inputText: String val remoteInputs: List<RemoteInput> = listOf(RemoteInput.Builder("quick_reply").setLabel("Quick reply").build()) val intent: Intent = createActionRemoteInputIntent() putRemoteInputsExtra(intent, remoteInputs) startActivityForResult(intent, 0) inputText = RemoteInput.getResultsFromIntent(intent).toString() myResult?.success(inputText) }
问题根因
两个核心错误导致拿不到正确结果:
startActivityForResult是异步非阻塞方法,唤起输入Activity后当前函数会立刻向下执行,不会阻塞等待用户完成输入操作,代码中在启动Activity后立刻调用myResult?.success(),此时用户还没完成输入,自然拿不到有效值- 代码尝试从自己创建的、用于启动Activity的
intent对象中解析RemoteInput结果,但用户输入的内容是存在于Activity结束后系统回传的Intent中,原启动Intent不可能携带输入结果。
正确实现代码
首先定义必要的成员变量,避免魔法值和重复调用问题:
// 替换成你自己的Channel名称 private const val CHANNEL_NAME = "your_wear_input_channel" // 定义输入请求的请求码 private const val REQUEST_CODE_REMOTE_INPUT = 1001 // 暂存Flutter端的方法回调,结果回传后置空 private var pendingMethodResult: MethodChannel.Result? = null
在configureFlutterEngine中注册方法回调,只负责暂存Result对象、唤起输入页:
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_NAME) .setMethodCallHandler { call, result -> when (call.method) { "getInputText" -> { // 防止重复发起请求 if (pendingMethodResult != null) { result.error("REQUEST_BUSY", "当前已有输入请求进行中", null) return@setMethodCallHandler } pendingMethodResult = result launchRemoteInputActivity() } else -> result.notImplemented() } } }
将原getInputText方法拆分为只负责启动输入页的逻辑,不要在这里处理结果:
private fun launchRemoteInputActivity() { val remoteInputs = listOf( RemoteInput.Builder("quick_reply") .setLabel("Quick reply") .build() ) val intent = createActionRemoteInputIntent() putRemoteInputsExtra(intent, remoteInputs) startActivityForResult(intent, REQUEST_CODE_REMOTE_INPUT) }
重写onActivityResult生命周期方法,在回调中解析输入结果、回传给Flutter:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode != REQUEST_CODE_REMOTE_INPUT) return // 取出暂存的回调后立刻置空,避免重复调用 val result = pendingMethodResult pendingMethodResult = null if (result == null) return when (resultCode) { RESULT_OK -> { val inputResult = RemoteInput.getResultsFromIntent(data) val inputText = inputResult?.getCharSequence("quick_reply")?.toString() ?: "" result.success(inputText) } // 用户取消输入的场景,可根据业务需求返回空字符串或者错误 else -> result.success("") } }
注意事项
- 如果你已经适配AndroidX,可以使用官方推荐的Activity Result API替代已废弃的
startActivityForResult,核心逻辑不变:在Activity返回结果的回调中,再调用Platform Channel的Result对象回传值 - 禁止对同一个
MethodChannel.Result对象多次调用success/error/notImplemented,否则会抛出运行时异常 - 解析RemoteInput时必须使用
onActivityResult返回的data参数,不要使用启动时自行构建的Intent对象
内容的提问来源于stack exchange,提问作者SuxoiKorm
相关产品推荐
相关产品推荐

