Dart Uri.parse解析特定格式Intent失败,求Flutter/Dart解决方案
Flutter/Dart 解析特殊格式Intent链接的解决方案
对接外部服务返回的Intent链接时,部分特殊格式的链接无法通过Dart原生的Uri.parse解析,比如:
intent://%7B"CD":"test","TK":"value"%7D/#Intent;package=com.example.appname;scheme=appname;end
无论是否调用Uri.decodeFull解码,都会抛出FormatException,但Android原生的Intent.parseUri(intentUrl, Intent.URI_INTENT_SCHEME)可以正常解析,以下是两种可行的处理方案:
方案1:手动拆分解析Intent结构
Android Intent链接有固定的格式规则,可以手动拆分各部分进行解析:
- 先以
#Intent;为分隔符,拆分出data部分和参数部分 - 对data部分做解码处理,提取核心内容
- 对参数部分按
;分割后,拆分键值对
示例代码:
String intentUrl = 'intent://%7B"CD":"test","TK":"value"%7D/#Intent;package=com.example.appname;scheme=appname;end'; // 拆分Intent的data和参数部分 List<String> splitParts = intentUrl.split('#Intent;'); if (splitParts.length != 2) { throw FormatException('不符合Intent链接格式'); } // 处理data部分:去掉前缀+解码 String rawData = splitParts[0].replaceFirst('intent://', ''); String decodedData = Uri.decodeFull(rawData); // decodedData 结果:{"CD":"test","TK":"value"} // 处理参数部分:去掉末尾的;end,拆分键值对 String paramsRaw = splitParts[1].replaceAll(';end', ''); List<String> paramPairs = paramsRaw.split(';'); Map<String, String> intentParams = {}; for (String pair in paramPairs) { List<String> keyValue = pair.split('='); if (keyValue.length == 2) { intentParams[keyValue[0]] = keyValue[1]; } } // intentParams 结果:{"package": "com.example.appname", "scheme": "appname"}
方案2:调用Android原生解析能力
如果你的Flutter应用仅针对Android平台,或者需要完全复用原生的解析逻辑,可以通过MethodChannel调用Android原生代码,直接使用Intent.parseUri解析后返回结果给Dart层。
第一步:Android端配置MethodChannel
在MainActivity.kt中添加通道逻辑:
import android.content.Intent import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "com.example.intent.parser" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> when (call.method) { "parseIntentUrl" -> { val url = call.argument<String>("url") ?: run { result.error("参数错误", "Intent链接不能为空", null) return@setMethodCallHandler } try { val intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME) val resultMap = mutableMapOf<String, String?>().apply { put("data", intent.dataString) put("package", intent.`package`) put("scheme", intent.scheme) // 可根据需求添加更多字段,比如action、category等 } result.success(resultMap) } catch (e: Exception) { result.error("解析失败", e.message, null) } } else -> result.notImplemented() } } } }
第二步:Dart层调用原生方法
import 'package:flutter/services.dart'; class AndroidIntentParser { static const MethodChannel _channel = MethodChannel('com.example.intent.parser'); static Future<Map<String, dynamic>?> parseIntent(String url) async { try { final result = await _channel.invokeMethod<Map<String, dynamic>>( 'parseIntentUrl', {'url': url}, ); return result; } on PlatformException catch (e) { print("解析Intent出错:${e.message}"); return null; } } } // 使用示例 void main() async { String targetUrl = 'intent://%7B"CD":"test","TK":"value"%7D/#Intent;package=com.example.appname;scheme=appname;end'; var parsedData = await AndroidIntentParser.parseIntent(targetUrl); print(parsedData); }
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

