Android 13中TileService的startActivityAndCollapse无法收起快捷设置面板
解决方案
一、解决快捷设置面板无法收起的问题
方案1:通过原生中转Activity跳转
创建一个无界面的中转Activity,让快捷设置Tile先启动这个中转Activity(此时startActivityAndCollapse能正常触发面板收起逻辑),再由中转Activity启动FlutterActivity。
- 定义中转Activity(需设置透明主题)
class FlutterLauncherActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 获取Tile传递的启动参数 val launchArgs = intent.getStringArrayListExtra("launch_args") // 启动目标FlutterActivity val flutterIntent = FlutterActivity.withNewEngine() .dartEntrypointArgs(launchArgs ?: emptyList()) .build(this) startActivity(flutterIntent) finish() // 完成跳转后销毁中转Activity } }
- 在
AndroidManifest.xml中配置中转Activity
<activity android:name=".FlutterLauncherActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:exported="false"/>
- 修改Tile的
onClick方法,启动中转Activity
override fun onClick() { super.onClick() try { val launcherIntent = Intent(this, FlutterLauncherActivity::class.java) launcherIntent.putStringArrayListExtra("launch_args", ArrayList(listOf("launchFromQuickTile"))) launcherIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivityAndCollapse(launcherIntent) } catch (e: Exception) { Log.d("debug", "Exception ${e.toString()}") } }
方案2:手动触发快捷面板收起
在启动FlutterActivity后,调用系统API强制收起快捷设置面板,需适配不同Android版本:
override fun onClick() { super.onClick() try { val newIntent = FlutterActivity.withNewEngine() .dartEntrypointArgs(listOf("launchFromQuickTile")) .build(this) newIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivityAndCollapse(newIntent) // 手动执行面板收起操作 collapseQuickSettings() } catch (e: Exception) { Log.d("debug", "Exception ${e.toString()}") } } private fun collapseQuickSettings() { val statusBarManager = getSystemService(Context.STATUS_BAR_SERVICE) as StatusBarManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { statusBarManager.collapsePanels() } else { // 低版本通过反射调用系统方法 try { val method = statusBarManager.javaClass.getMethod("collapsePanels") method.invoke(statusBarManager) } catch (e: Exception) { Log.d("debug", "Failed to collapse panels: ${e.toString()}") } } }
注:低版本反射调用存在一定兼容性风险,需针对目标设备范围测试验证。
二、带参数打开Flutter应用的其他方式
除了dartEntrypointArgs,还有以下两种常用实现方式:
通过Intent Extra传递参数
Android侧添加参数:val flutterIntent = FlutterActivity.withNewEngine().build(this) flutterIntent.putExtra("launch_source", "quick_tile") flutterIntent.putStringArrayListExtra("extra_args", ArrayList(listOf("param1", "param2")))Flutter侧通过
MethodChannel获取参数:final MethodChannel channel = MethodChannel('com.your.pname/launch_args'); Future<void> fetchLaunchParams() async { try { final Map<String, dynamic>? params = await channel.invokeMethod('getParams'); if (params != null) { String source = params['launch_source'] ?? ''; List<String>? args = params['extra_args']?.cast<String>(); // 处理参数逻辑 } } on PlatformException catch (e) { print("Params fetch failed: ${e.message}"); } }需在Android的FlutterActivity子类中实现MethodChannel回调:
class CustomFlutterActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.your.pname/launch_args") .setMethodCallHandler { call, result -> if (call.method == "getParams") { val params = hashMapOf<String, Any?>() params["launch_source"] = intent.getStringExtra("launch_source") params["extra_args"] = intent.getStringArrayListExtra("extra_args") result.success(params) } else { result.notImplemented() } } } }通过Deep Link传递参数
配置Flutter的Deep Link,在AndroidManifest.xml中添加对应的intent-filter:<activity android:name=".CustomFlutterActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="your_app_scheme" /> </intent-filter> </activity>Android侧通过带参数的Uri启动:
val deepLinkIntent = Intent(Intent.ACTION_VIEW, Uri.parse("your_app_scheme://launch?source=quick_tile")) deepLinkIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivityAndCollapse(deepLinkIntent)Flutter侧解析Uri获取参数:
void initState() { super.initState(); final uri = Uri.base; String? source = uri.queryParameters['source']; // 处理参数逻辑 }
内容的提问来源于stack exchange,提问作者Pratik Butani
相关产品推荐
相关产品推荐

