You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过home_widget包实现点击桌面小组件启动Flutter应用

实现Flutter home_widget 0.3.1点击桌面组件启动应用

要实现桌面组件点击启动App,需要分别配置Android/iOS原生端,再配合Flutter端的逻辑,下面是完整的实现步骤和代码示例:


一、Android 端配置

1. 配置主Activity

打开android/app/src/main/AndroidManifest.xml,给主Activity添加android:exported="true"(Android 12+强制要求),并新增一个接收跳转的intent-filter:

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTop">
    <!-- 原有启动配置 -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    <!-- 新增:接收桌面组件点击的跳转 -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="homewidget" />
    </intent-filter>
</activity>

2. 给组件设置点击跳转逻辑

找到你的HomeWidgetProvider类(通常在android/app/src/main/kotlin/[你的包名]/HomeWidgetProvider.kt),在onUpdate方法中给组件视图绑定启动App的PendingIntent:

override fun onUpdate(
    context: Context,
    appWidgetManager: AppWidgetManager,
    appWidgetIds: IntArray
) {
    appWidgetIds.forEach { appWidgetId ->
        // 创建启动主Activity的Intent
        val launchIntent = Intent(context, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pendingIntent = PendingIntent.getActivity(
            context,
            0,
            launchIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )

        // 绑定到组件根视图(替换成你自己的组件布局ID)
        val views = RemoteViews(context.packageName, R.layout.widget_layout).apply {
            setOnClickPendingIntent(R.id.widget_root, pendingIntent)
        }

        appWidgetManager.updateAppWidget(appWidgetId, views)
    }
}

注意:R.layout.widget_layout是你的桌面组件布局文件,R.id.widget_root是布局的根控件ID,要和你自己的布局对应。


二、iOS 端配置

1. 添加URL Scheme

打开ios/Runner/Info.plist,添加自定义URL Scheme,用于组件跳转唤醒App:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>homewidget</string>
        </array>
    </dict>
</array>

2. 配置组件点击跳转

打开ios/Runner/HomeWidget.swift,在getTimeline方法中给组件条目添加跳转URL:

func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
    let entry = SimpleEntry(date: Date(), configuration: configuration)
    
    // 设置点击跳转的URL
    entry.link = WidgetURL(URL(string: "homewidget://openapp")!)
    
    let timeline = Timeline(entries: [entry], policy: .atEnd)
    completion(timeline)
}

3. 处理App唤醒逻辑

如果是用UIKit的AppDelegate,在ios/Runner/AppDelegate.swift中添加:

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    // 这里可以添加跳转后的自定义逻辑,比如跳转到指定页面
    return true
}

如果是SwiftUI的App结构,在ios/Runner/App.swift中处理:

@main
struct RunnerApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    // 处理跳转逻辑,比如导航到特定页面
                }
        }
    }
}

三、Flutter 端代码

1. 初始化与监听点击事件

在main.dart中初始化home_widget,并监听组件点击事件(可选,用于处理跳转后的逻辑):

import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await HomeWidget.init();
  
  // 监听组件点击的URI(如果需要处理跳转后的逻辑)
  HomeWidget.widgetClicked.listen((Uri? uri) {
    if (uri != null) {
      print('组件被点击,URI:$uri');
      // 这里可以做页面跳转等操作
    }
  });
  
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Home Widget Demo',
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    // 初始化时更新桌面组件内容(可选)
    _updateWidget();
  }

  Future<void> _updateWidget() async {
    await HomeWidget.updateWidget(
      name: 'HomeWidgetProvider', // Android的Provider名称
      iOSName: 'HomeWidget', // iOS的Widget名称
      data: const {
        'message': '点击打开App',
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home Widget 示例')),
      body: Center(
        child: ElevatedButton(
          onPressed: _updateWidget,
          child: const Text('更新桌面组件'),
        ),
      ),
    );
  }
}

关键注意事项

  • Android 12+ 必须给PendingIntent添加FLAG_IMMUTABLE或FLAG_MUTABLE,否则会崩溃。
  • iOS的Widget需要确保是支持交互的类型(比如IntentConfiguration),否则无法触发跳转。
  • 测试时,先安装App到设备,再添加桌面组件,之后点击组件测试跳转。

内容的提问来源于stack exchange,提问作者Harsh Sureja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 20:41:00