├── .gitignore
├── .metadata
├── CHANGELOG.md
├── CODEOWNERS
├── LICENSE
├── README-ZH.md
├── README.md
├── analysis_options.yaml
├── example
├── .gitignore
├── README.md
├── analysis_options.yaml
├── ios
│ ├── .gitignore
│ ├── Flutter
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ └── Release.xcconfig
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ ├── Runner
│ │ ├── AppDelegate.swift
│ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── Runner-Bridging-Header.h
│ │ └── Runner.entitlements
│ ├── live_activity_test
│ │ ├── Assets.xcassets
│ │ │ ├── AccentColor.colorset
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ │ ├── Contents.json
│ │ │ └── WidgetBackground.colorset
│ │ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ ├── live_activity_test.intentdefinition
│ │ ├── live_activity_testBundle.swift
│ │ └── live_activity_testLiveActivity.swift
│ └── live_activity_testExtension.entitlements
├── lib
│ ├── helper
│ │ └── image_helper.dart
│ └── main.dart
├── pubspec.lock
└── pubspec.yaml
├── ios
├── .gitignore
├── Assets
│ └── .gitkeep
├── Classes
│ ├── FlutterLiveActivities.swift
│ ├── FlutterLiveActivitiesPlugin.h
│ ├── FlutterLiveActivitiesPlugin.m
│ └── SwiftFlutterLiveActivitiesPlugin.swift
└── flutter_live_activities.podspec
├── lib
├── flutter_live_activities.dart
├── flutter_live_activities_method_channel.dart
├── flutter_live_activities_platform_interface.dart
└── src
│ └── live_activities_status.dart
└── pubspec.yaml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26 | /pubspec.lock
27 | **/doc/api/
28 | .dart_tool/
29 | .packages
30 | build/
31 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: 6928314d505d2bb4777be05e45d7808a5aa91d2a
8 | channel: stable
9 |
10 | project_type: plugin
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: 6928314d505d2bb4777be05e45d7808a5aa91d2a
17 | base_revision: 6928314d505d2bb4777be05e45d7808a5aa91d2a
18 | - platform: ios
19 | create_revision: 6928314d505d2bb4777be05e45d7808a5aa91d2a
20 | base_revision: 6928314d505d2bb4777be05e45d7808a5aa91d2a
21 |
22 | # User provided section
23 |
24 | # List of Local paths (relative to this file) that should be
25 | # ignored by the migrate tool.
26 | #
27 | # Files that are not part of the templates will be ignored by default.
28 | unmanaged_files:
29 | - 'lib/main.dart'
30 | - 'ios/Runner.xcodeproj/project.pbxproj'
31 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.0.1
2 |
3 | * First commit
4 |
5 | ## 0.0.2
6 |
7 | * Update README
8 |
9 | ## 0.0.3
10 |
11 | * Edit example
12 |
13 | ## 0.0.4
14 |
15 | * Add multiple streams to coexist, add Chinese documents
16 |
17 | ## 0.0.4+1
18 |
19 | * Add Lock screen/banner UI example
20 |
21 | ## 0.0.4+2
22 |
23 | * Fix the bug of url callback twice
24 |
25 | ## 0.0.4+3
26 |
27 | * Update README
28 |
29 | ## 0.0.4+4
30 |
31 | * Fix stream bug
32 |
33 | ## 0.0.5
34 |
35 | * Add apis
36 | * Add image solution
37 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @xSILENCEx
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 FlutterCandies
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README-ZH.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Flutter Live Activities
4 |
5 | Live Activities 的 Flutter 插件。用于创建、更新和处理 [DynamicIsland UI] 和 [Lock screen/banner UI] 的动作
6 |
7 | [English](README.md) | 中文说明
8 |
9 | [](https://pub.dev/packages/flutter_live_activities)
10 | [](https://github.com/fluttercandies/flutter_live_activities/stargazers)
11 | [](https://github.com/fluttercandies/flutter_live_activities/network/members)
12 |
13 |
14 | > 此插件需要通知权限
15 |
16 | 

17 |
18 | #### 1. 在iOS项目中添加 Widget
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | * 创建成功后的目录结构
28 |
29 |
30 |
31 | #### 2. 编辑 `Runner/Info.plist` 和 `live_activity_test/Info.plist`
32 |
33 | 两个文件中都添加以下内容:
34 | ```xml
35 |
36 |
37 | ...
38 | NSSupportsLiveActivities
39 |
40 | ...
41 |
42 |
43 | ```
44 |
45 | #### 3. 在小部件 swift 文件中创建数据通道
46 |
47 | [live_activity_test/live_activity_testLiveActivity.swift](https://github.com/fluttercandies/flutter_live_activities/blob/main/example/ios/live_activity_test/live_activity_testLiveActivity.swift)
48 |
49 | ```swift
50 | import ActivityKit
51 | import SwiftUI
52 | import WidgetKit
53 |
54 | // 自定义Model
55 | struct TestData {
56 | var text: String
57 |
58 | init?(JSONData data: [String: String]) {
59 | self.text = data["text"] ?? ""
60 | }
61 |
62 | init(text: String) {
63 | self.text = text
64 | }
65 | }
66 |
67 | // 数据通道 <- 必要!不能更改任何内容
68 | struct FlutterLiveActivities: ActivityAttributes, Identifiable {
69 | public typealias LiveData = ContentState
70 |
71 | public struct ContentState: Codable, Hashable {
72 | var data: [String: String]
73 | }
74 |
75 | var id = UUID()
76 | }
77 |
78 | @available(iOSApplicationExtension 16.1, *)
79 | struct live_activity_testLiveActivity: Widget {
80 | var body: some WidgetConfiguration {
81 | // 绑定通道
82 | ActivityConfiguration(for: FlutterLiveActivities.self) { context in
83 |
84 | // 锁屏上显示的内容
85 |
86 | // Json to model
87 | let data = TestData(JSONData: context.state.data)
88 |
89 | // UI
90 | VStack {
91 | Text(data?.text ?? "")
92 | }
93 | .activityBackgroundTint(Color.cyan)
94 | .activitySystemActionForegroundColor(Color.black)
95 | } dynamicIsland: { context in
96 | // Json to model
97 | let data = TestData(JSONData: context.state.data)
98 |
99 | // 灵动岛
100 | return DynamicIsland {
101 | // Expanded UI goes here. Compose the expanded UI through
102 | // various regions, like leading/trailing/center/bottom
103 | DynamicIslandExpandedRegion(.leading) {
104 | Text("Leading")
105 | }
106 | DynamicIslandExpandedRegion(.trailing) {
107 | Text("Trailing")
108 | }
109 | DynamicIslandExpandedRegion(.bottom) {
110 | // 显示 Flutter 传递过来的数据
111 | Text(data?.text ?? "")
112 | }
113 | } compactLeading: {
114 | Text("L")
115 | } compactTrailing: {
116 | Text("T")
117 | } minimal: {
118 | Text("Min")
119 | }
120 | .keylineTint(Color.red)
121 | }
122 | }
123 | }
124 | ```
125 |
126 | 更多布局信息,请参考: [live activities](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities)
127 |
128 | #### 4. APIs
129 |
130 | ```dart
131 | import 'package:flutter_live_activities/flutter_live_activities.dart';
132 |
133 | ...
134 |
135 | final FlutterLiveActivities _liveActivities = FlutterLiveActivities();
136 |
137 | String? _activityId;
138 | ```
139 |
140 | * 检查设备是否开启此功能
141 | ```dart
142 | await _liveActivities.areActivitiesEnabled();
143 | ```
144 |
145 | * 获取启动Link
146 | ```dart
147 | await _liveActivities.getInitUri()
148 | ```
149 |
150 | * 创建一个 Live Activity
151 | ```dart
152 | _activityId = await _liveActivities.createActivity({'text': 'Hello World'});
153 | ```
154 |
155 | * 更新 Live Activity
156 | ```dart
157 | if(_activityId != null) {
158 | await _liveActivities.updateActivity(_activityId!, {'text': 'Update Hello World'});
159 | }
160 | ```
161 |
162 | > ActivityKit 更新和远程推送通知更新的更新动态数据大小不能超过 4KB。 [相关文档](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities)
163 |
164 |
165 |
166 | > 其它解决方案请参考 [live_activities](https://pub.dev/packages/live_activities)
167 |
168 | * 结束 Live Activity
169 | ```dart
170 | if(_activityId != null) {
171 | await _liveActivities.endActivity(_activityId!);
172 | }
173 | ```
174 |
175 | * 结束全部 Live Activities
176 | ```dart
177 | await _liveActivities.endAllActivities();
178 | ```
179 |
180 | * 获取全部 Live Activities id
181 | ```dart
182 | await _liveActivities.getAllActivities()
183 | ```
184 |
185 | #### 5. Deeplink(点击动作)
186 |
187 | * 默认 urlScheme 为 `fla`
188 |
189 | > `FlutterLiveActivities({this.urlScheme = 'fla'})`
190 |
191 | * 在项目中添加 urlScheme
192 |
193 |
194 |
195 | * Swift 代码:
196 |
197 | ```swift
198 | @available(iOSApplicationExtension 16.1, *)
199 | struct live_activity_testLiveActivity: Widget {
200 | var body: some WidgetConfiguration {
201 | ActivityConfiguration(for: FlutterLiveActivities.self) { context in
202 | let data = TestData(JSONData: context.state.data)
203 |
204 | // Lock screen/banner UI goes here
205 |
206 | VStack(alignment: .leading) {
207 | Text(data?.text ?? "")
208 | HStack {
209 | // 通过 `Link` 创建一个动作
210 | Link(destination: URL(string: "fla://xx.xx/tap/A")!) {
211 | Text("A")
212 | .frame(width: 40, height: 40)
213 | .background(.blue)
214 | }
215 | // 通过 `Link` 创建一个动作
216 | Link(destination: URL(string: "fla://xx.xx/tap/B")!) {
217 | Text("B")
218 | .frame(width: 40, height: 40)
219 | .background(.blue)
220 | }
221 | // 通过 `Link` 创建一个动作
222 | Link(destination: URL(string: "fla://xx.xx/tap/C")!) {
223 | Text("C")
224 | .frame(width: 40, height: 40)
225 | .background(.blue)
226 | }
227 | }
228 | .frame(width: .infinity, height: .infinity)
229 | }
230 | .padding(20)
231 | .activityBackgroundTint(Color.cyan)
232 | .activitySystemActionForegroundColor(Color.black)
233 |
234 | } dynamicIsland: { context in
235 |
236 | let data = TestData(JSONData: context.state.data)
237 |
238 | return DynamicIsland {
239 | DynamicIslandExpandedRegion(.bottom) {
240 | // 通过 `Link` 创建一个动作
241 | Link(destination: URL(string: "fla://xxxxxxx.xxxxxx")!) {
242 | Text(data?.text ?? "")
243 | .background(.red)
244 | }
245 | }
246 | } compactLeading: {
247 | Text("L")
248 | } compactTrailing: {
249 | Text("T")
250 | } minimal: {
251 | Text("Min")
252 | }
253 | .widgetURL(URL(string: "fla://www.apple.com")) // 或使用 widgetURL
254 | .keylineTint(Color.red)
255 | }
256 | }
257 | }
258 | ```
259 |
260 | * Dart 代码:
261 |
262 | ```dart
263 | _subscription ??= _liveActivities.uriStream().listen((String? uri) {
264 | dev.log('deeplink uri: $uri');
265 | });
266 | ```
267 |
268 | #### 6. Display image
269 |
270 | > 由于数据块大小的限制。我们无法向LiveActivities发送图片元数据
271 |
272 | > LiveActivities不支持异步加载,所以我们不能使用AsyncImage或读取本地文件
273 |
274 | > 开发者论坛的解决方案: [716902](https://developer.apple.com/forums/thread/716902)
275 |
276 | * 添加 AppGroup (此操作需要付费Apple账户)
277 |
278 |
279 |
280 | * 在 Runner 和 Widget 中创建/选择同样的 groupId
281 |
282 |
283 |
284 | * 发送图片到 group:
285 |
286 | Dart代码:
287 | ```dart
288 | Future _sendImageToGroup() async {
289 | const String url = 'https://cdn.iconscout.com/icon/free/png-256/flutter-2752187-2285004.png';
290 |
291 | final String? path = await ImageHelper.getFilePathFromUrl(url);
292 |
293 | if (path != null) {
294 | _liveActivities.sendImageToGroup(
295 | id: 'test-img',
296 | filePath: path,
297 | groupId: 'group.live_example',
298 | );
299 | }
300 | }
301 | ```
302 |
303 | Swift代码:
304 | ```swift
305 | DynamicIslandExpandedRegion(.leading) {
306 | if let imageContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.live_example")?.appendingPathComponent("test-img"), /// Use id here
307 | let uiImage = UIImage(contentsOfFile: imageContainer.path())
308 | {
309 | Image(uiImage: uiImage)
310 | .resizable()
311 | .frame(width: 53, height: 53)
312 | .cornerRadius(13)
313 | } else {
314 | Text("Leading")
315 | }
316 | }
317 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Flutter Live Activities
4 |
5 | Flutter plugin for Live Activities. Use to create, update and handling action for [DynamicIsland UI] and [Lock screen/banner UI]
6 |
7 | English | [中文说明](README-ZH.md)
8 |
9 | [](https://pub.dev/packages/flutter_live_activities)
10 | [](https://github.com/fluttercandies/flutter_live_activities/stargazers)
11 | [](https://github.com/fluttercandies/flutter_live_activities/network/members)
12 |
13 |
14 | > This plugin requires notification permission
15 |
16 | 

17 |
18 | #### 1. Add a Widget to the iOS project
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | * Directory structure
28 |
29 |
30 |
31 | #### 2. Edit `Runner/Info.plist` and `live_activity_test/Info.plist`
32 |
33 | both add:
34 | ```xml
35 |
36 |
37 | ...
38 | NSSupportsLiveActivities
39 |
40 | ...
41 |
42 |
43 | ```
44 |
45 | #### 3. Create a data channel in widget swift file
46 |
47 | [live_activity_test/live_activity_testLiveActivity.swift](https://github.com/fluttercandies/flutter_live_activities/blob/main/example/ios/live_activity_test/live_activity_testLiveActivity.swift)
48 |
49 | ```swift
50 | import ActivityKit
51 | import SwiftUI
52 | import WidgetKit
53 |
54 | // Custom data model
55 | struct TestData {
56 | var text: String
57 |
58 | init?(JSONData data: [String: String]) {
59 | self.text = data["text"] ?? ""
60 | }
61 |
62 | init(text: String) {
63 | self.text = text
64 | }
65 | }
66 |
67 | // Data channel <- Must!
68 | struct FlutterLiveActivities: ActivityAttributes, Identifiable {
69 | public typealias LiveData = ContentState
70 |
71 | public struct ContentState: Codable, Hashable {
72 | var data: [String: String]
73 | }
74 |
75 | var id = UUID()
76 | }
77 |
78 | @available(iOSApplicationExtension 16.1, *)
79 | struct live_activity_testLiveActivity: Widget {
80 | var body: some WidgetConfiguration {
81 | // Binding
82 | ActivityConfiguration(for: FlutterLiveActivities.self) { context in
83 |
84 | // Lock screen/banner UI goes here
85 |
86 | // Json to model
87 | let data = TestData(JSONData: context.state.data)
88 |
89 | // UI
90 | VStack {
91 | Text(data?.text ?? "")
92 | }
93 | .activityBackgroundTint(Color.cyan)
94 | .activitySystemActionForegroundColor(Color.black)
95 | } dynamicIsland: { context in
96 | // Json to model
97 | let data = TestData(JSONData: context.state.data)
98 |
99 | // DynamicIsland
100 | return DynamicIsland {
101 | // Expanded UI goes here. Compose the expanded UI through
102 | // various regions, like leading/trailing/center/bottom
103 | DynamicIslandExpandedRegion(.leading) {
104 | Text("Leading")
105 | }
106 | DynamicIslandExpandedRegion(.trailing) {
107 | Text("Trailing")
108 | }
109 | DynamicIslandExpandedRegion(.bottom) {
110 | // Show data from flutter
111 | Text(data?.text ?? "")
112 | }
113 | } compactLeading: {
114 | Text("L")
115 | } compactTrailing: {
116 | Text("T")
117 | } minimal: {
118 | Text("Min")
119 | }
120 | .keylineTint(Color.red)
121 | }
122 | }
123 | }
124 | ```
125 |
126 | For more layout information, please refer to: [live activities](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities)
127 |
128 | #### 4. APIs
129 |
130 | ```dart
131 | import 'package:flutter_live_activities/flutter_live_activities.dart';
132 |
133 | ...
134 |
135 | final FlutterLiveActivities _liveActivities = FlutterLiveActivities();
136 |
137 | String? _activityId;
138 | ```
139 |
140 | * Check if the Live Activities function is enabled
141 | ```dart
142 | await _liveActivities.areActivitiesEnabled();
143 | ```
144 |
145 | * Get launch url
146 | ```dart
147 | await _liveActivities.getInitUri()
148 | ```
149 |
150 | * Create a Live Activity
151 | ```dart
152 | _activityId = await _liveActivities.createActivity({'text': 'Hello World'});
153 | ```
154 |
155 | * Update a Live Activity
156 | ```dart
157 | if(_activityId != null) {
158 | await _liveActivities.updateActivity(_activityId!, {'text': 'Update Hello World'});
159 | }
160 | ```
161 |
162 | > The updated dynamic data for both ActivityKit updates and remote push notification updates can’t exceed 4KB in size. [doc](https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities)
163 |
164 |
165 |
166 | > For more solutions, please refer to [live_activities](https://pub.dev/packages/live_activities)
167 |
168 | * End a Live Activity
169 | ```dart
170 | if(_activityId != null) {
171 | await _liveActivities.endActivity(_activityId!);
172 | }
173 | ```
174 |
175 | * End all Live Activities
176 | ```dart
177 | await _liveActivities.endAllActivities();
178 | ```
179 |
180 | * Get all Live Activities id
181 | ```dart
182 | await _liveActivities.getAllActivities()
183 | ```
184 |
185 | #### 5. Deeplink
186 |
187 | * The default urlScheme is `fla`
188 |
189 | > `FlutterLiveActivities({this.urlScheme = 'fla'})`
190 |
191 | * Add urlScheme in your project
192 |
193 |
194 |
195 | * Swift code:
196 |
197 | ```swift
198 | @available(iOSApplicationExtension 16.1, *)
199 | struct live_activity_testLiveActivity: Widget {
200 | var body: some WidgetConfiguration {
201 | ActivityConfiguration(for: FlutterLiveActivities.self) { context in
202 | let data = TestData(JSONData: context.state.data)
203 |
204 | // Lock screen/banner UI goes here
205 |
206 | VStack(alignment: .leading) {
207 | Text(data?.text ?? "")
208 | HStack {
209 | // Create an action via `Link`
210 | Link(destination: URL(string: "fla://xx.xx/tap/A")!) {
211 | Text("A")
212 | .frame(width: 40, height: 40)
213 | .background(.blue)
214 | }
215 | // Create an action via `Link`
216 | Link(destination: URL(string: "fla://xx.xx/tap/B")!) {
217 | Text("B")
218 | .frame(width: 40, height: 40)
219 | .background(.blue)
220 | }
221 | // Create an action via `Link`
222 | Link(destination: URL(string: "fla://xx.xx/tap/C")!) {
223 | Text("C")
224 | .frame(width: 40, height: 40)
225 | .background(.blue)
226 | }
227 | }
228 | .frame(width: .infinity, height: .infinity)
229 | }
230 | .padding(20)
231 | .activityBackgroundTint(Color.cyan)
232 | .activitySystemActionForegroundColor(Color.black)
233 |
234 | } dynamicIsland: { context in
235 |
236 | let data = TestData(JSONData: context.state.data)
237 |
238 | return DynamicIsland {
239 | DynamicIslandExpandedRegion(.bottom) {
240 | // Create an action via `Link`
241 | Link(destination: URL(string: "fla://xxxxxxx.xxxxxx")!) {
242 | Text(data?.text ?? "")
243 | .background(.red)
244 | }
245 | }
246 | } compactLeading: {
247 | Text("L")
248 | } compactTrailing: {
249 | Text("T")
250 | } minimal: {
251 | Text("Min")
252 | }
253 | .widgetURL(URL(string: "fla://www.apple.com")) // or use widgetURL
254 | .keylineTint(Color.red)
255 | }
256 | }
257 | }
258 | ```
259 |
260 | * Dart code:
261 |
262 | ```dart
263 | _subscription ??= _liveActivities.uriStream().listen((String? uri) {
264 | dev.log('deeplink uri: $uri');
265 | });
266 | ```
267 |
268 | #### 6. Display image
269 |
270 | > Due to block size limitations. We can't send metadata to LiveActivities
271 |
272 | > LiveActivities does not support async loading, so we can't use AsyncImage or read local file
273 |
274 | > Solution from Developer Forums: [716902](https://developer.apple.com/forums/thread/716902)
275 |
276 | * Add group config (Paid account required)
277 |
278 |
279 |
280 | * Add group id both Runner and Widget
281 |
282 |
283 |
284 | * Send image to group:
285 |
286 | Dart code:
287 | ```dart
288 | Future _sendImageToGroup() async {
289 | const String url = 'https://cdn.iconscout.com/icon/free/png-256/flutter-2752187-2285004.png';
290 |
291 | final String? path = await ImageHelper.getFilePathFromUrl(url);
292 |
293 | if (path != null) {
294 | _liveActivities.sendImageToGroup(
295 | id: 'test-img',
296 | filePath: path,
297 | groupId: 'group.live_example',
298 | );
299 | }
300 | }
301 | ```
302 |
303 | Swift code:
304 | ```swift
305 | DynamicIslandExpandedRegion(.leading) {
306 | if let imageContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.live_example")?.appendingPathComponent("test-img"), /// Use id here
307 | let uiImage = UIImage(contentsOfFile: imageContainer.path())
308 | {
309 | Image(uiImage: uiImage)
310 | .resizable()
311 | .frame(width: 53, height: 53)
312 | .cornerRadius(13)
313 | } else {
314 | Text("Leading")
315 | }
316 | }
317 | ```
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # Specify analysis options.
2 | #
3 | # Until there are meta linter rules, each desired lint must be explicitly enabled.
4 | # See: https://github.com/dart-lang/linter/issues/288
5 | #
6 | # For a list of lints, see: http://dart-lang.github.io/linter/lints/
7 | # See the configuration guide for more
8 | # https://github.com/dart-lang/sdk/tree/main/pkg/analyzer#configuring-the-analyzer
9 | #
10 | # There are other similar analysis options files in the flutter repos,
11 | # which should be kept in sync with this file:
12 | #
13 | # - analysis_options.yaml (this file)
14 | # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
15 | # - https://github.com/flutter/engine/blob/master/analysis_options.yaml
16 | # - https://github.com/flutter/packages/blob/master/analysis_options.yaml
17 | #
18 | # This file contains the analysis options used by Flutter tools, such as IntelliJ,
19 | # Android Studio, and the `flutter analyze` command.
20 |
21 | analyzer:
22 | strong-mode:
23 | implicit-casts: false
24 | implicit-dynamic: false
25 | errors:
26 | # treat missing required parameters as a warning (not a hint)
27 | missing_required_param: warning
28 | # treat missing returns as a warning (not a hint)
29 | missing_return: warning
30 | # allow having TODO comments in the code
31 | # todo: ignore
32 | # allow self-reference to deprecated members (we do this because otherwise we have
33 | # to annotate every member in every test, assert, etc, when we deprecate something)
34 | deprecated_member_use_from_same_package: ignore
35 | # TODO(ianh): https://github.com/flutter/flutter/issues/74381
36 | # Clean up existing unnecessary imports, and remove line to ignore.
37 | unnecessary_import: ignore
38 | # Turned off until null-safe rollout is complete.
39 | unnecessary_null_comparison: ignore
40 | exclude:
41 | - "bin/cache/**"
42 | # Ignore protoc generated files
43 | - "dev/conductor/lib/proto/*"
44 | - "lib/core/l10n/**"
45 | - "lib/res/images.dart"
46 | - "lib/generated_plugin_registrant.dart"
47 | - "lib/widgets/country_code/flag_codes.dart"
48 | - "build/**"
49 | - "lib/**.freezed.dart"
50 | - "lib/**.g.dart"
51 | - "lib/data_source/database/database.g.dart"
52 | - "lib/domain/enum/gps_proto/**"
53 |
54 | linter:
55 | rules:
56 | # these rules are documented on and in the same order as
57 | # the Dart Lint rules page to make maintenance easier
58 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml
59 | - always_declare_return_types
60 | # - always_put_control_body_on_new_line
61 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
62 | - always_require_non_null_named_parameters
63 | - always_specify_types
64 | # - always_use_package_imports # we do this commonly
65 | - annotate_overrides
66 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types
67 | - avoid_bool_literals_in_conditional_expressions
68 | # - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023
69 | # - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/3023
70 | - avoid_classes_with_only_static_members
71 | - avoid_double_and_int_checks
72 | - avoid_dynamic_calls
73 | - avoid_empty_else
74 | - avoid_equals_and_hash_code_on_mutable_classes
75 | - avoid_escaping_inner_quotes
76 | - avoid_field_initializers_in_const_classes
77 | - avoid_function_literals_in_foreach_calls
78 | - avoid_implementing_value_types
79 | - avoid_init_to_null
80 | - avoid_js_rounded_ints
81 | # - avoid_multiple_declarations_per_line # seems to be a stylistic choice we don't subscribe to
82 | - avoid_null_checks_in_equality_operators
83 | # - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it
84 | - avoid_print
85 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
86 | - avoid_redundant_argument_values
87 | - avoid_relative_lib_imports
88 | - avoid_renaming_method_parameters
89 | - avoid_return_types_on_setters
90 | # - avoid_returning_null # still violated by some pre-nnbd code that we haven't yet migrated
91 | - avoid_returning_null_for_future
92 | - avoid_returning_null_for_void
93 | # - avoid_returning_this # there are enough valid reasons to return `this` that this lint ends up with too many false positives
94 | - avoid_setters_without_getters
95 | - avoid_shadowing_type_parameters
96 | - avoid_single_cascade_in_expression_statements
97 | - avoid_slow_async_io
98 | - avoid_type_to_string
99 | - avoid_types_as_parameter_names
100 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types
101 | - avoid_unnecessary_containers
102 | - avoid_unused_constructor_parameters
103 | - avoid_void_async
104 | # - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere
105 | - await_only_futures
106 | - camel_case_extensions
107 | - camel_case_types
108 | - cancel_subscriptions
109 | # - cascade_invocations # doesn't match the typical style of this repo
110 | - cast_nullable_to_non_nullable
111 | # - close_sinks # not reliable enough
112 | # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142
113 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204
114 | - control_flow_in_finally
115 | # - curly_braces_in_flow_control_structures # not required by flutter style
116 | - depend_on_referenced_packages
117 | - deprecated_consistency
118 | # - diagnostic_describe_all_properties # enabled only at the framework level (packages/flutter/lib)
119 | - directives_ordering
120 | # - do_not_use_environment # there are appropriate times to use the environment, especially in our tests and build logic
121 | - empty_catches
122 | - empty_constructor_bodies
123 | - empty_statements
124 | - eol_at_end_of_file
125 | - exhaustive_cases
126 | - file_names
127 | - flutter_style_todos
128 | - hash_and_equals
129 | - implementation_imports
130 | # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
131 | - iterable_contains_unrelated_type
132 | # - join_return_with_assignment # not required by flutter style
133 | - leading_newlines_in_multiline_strings
134 | - library_names
135 | - library_prefixes
136 | - library_private_types_in_public_api
137 | # - lines_longer_than_80_chars # not required by flutter style
138 | - list_remove_unrelated_type
139 | # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/linter/issues/453
140 | - missing_whitespace_between_adjacent_strings
141 | - no_adjacent_strings_in_list
142 | - no_default_cases
143 | - no_duplicate_case_values
144 | - no_logic_in_create_state
145 | # - no_runtimeType_toString # ok in tests; we enable this only in packages/
146 | - non_constant_identifier_names
147 | - noop_primitive_operations
148 | - null_check_on_nullable_type_parameter
149 | - null_closures
150 | # - omit_local_variable_types # opposite of always_specify_types
151 | # - one_member_abstracts # too many false positives
152 | - only_throw_errors # this does get disabled in a few places where we have legacy code that uses strings et al
153 | - overridden_fields
154 | - package_api_docs
155 | - package_names
156 | - package_prefixed_library_names
157 | # - parameter_assignments # we do this commonly
158 | - prefer_adjacent_string_concatenation
159 | - prefer_asserts_in_initializer_lists
160 | # - prefer_asserts_with_message # not required by flutter style
161 | - prefer_collection_literals
162 | - prefer_conditional_assignment
163 | - prefer_const_constructors
164 | - prefer_const_constructors_in_immutables
165 | - prefer_const_declarations
166 | - prefer_const_literals_to_create_immutables
167 | # - prefer_constructors_over_static_methods # far too many false positives
168 | - prefer_contains
169 | # - prefer_double_quotes # opposite of prefer_single_quotes
170 | - prefer_equal_for_default_values
171 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
172 | - prefer_final_fields
173 | - prefer_final_in_for_each
174 | - prefer_final_locals
175 | # - prefer_final_parameters # we should enable this one day when it can be auto-fixed (https://github.com/dart-lang/linter/issues/3104), see also parameter_assignments
176 | - prefer_for_elements_to_map_fromIterable
177 | - prefer_foreach
178 | - prefer_function_declarations_over_variables
179 | - prefer_generic_function_type_aliases
180 | - prefer_if_elements_to_conditional_expressions
181 | - prefer_if_null_operators
182 | - prefer_initializing_formals
183 | - prefer_inlined_adds
184 | # - prefer_int_literals # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#use-double-literals-for-double-constants
185 | - prefer_interpolation_to_compose_strings
186 | - prefer_is_empty
187 | - prefer_is_not_empty
188 | - prefer_is_not_operator
189 | - prefer_iterable_whereType
190 | # - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018
191 | - prefer_null_aware_operators
192 | # - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere
193 | # - prefer_relative_imports
194 | - prefer_single_quotes
195 | - prefer_spread_collections
196 | - prefer_typing_uninitialized_variables
197 | - prefer_void_to_null
198 | - provide_deprecation_message
199 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
200 | - recursive_getters
201 | # - require_trailing_commas # blocked on https://github.com/dart-lang/sdk/issues/47441
202 | - sized_box_for_whitespace
203 | - slash_for_doc_comments
204 | - sort_child_properties_last
205 | - sort_constructors_first
206 | # - sort_pub_dependencies # prevents separating pinned transitive dependencies
207 | - sort_unnamed_constructors_first
208 | - test_types_in_equals
209 | - throw_in_finally
210 | - tighten_type_of_initializing_formals
211 | # - type_annotate_public_apis # subset of always_specify_types
212 | - type_init_formals
213 | # - unawaited_futures # too many false positives, especially with the way AnimationController works
214 | - unnecessary_await_in_return
215 | - unnecessary_brace_in_string_interps
216 | - unnecessary_const
217 | - unnecessary_constructor_name
218 | # - unnecessary_final # conflicts with prefer_final_locals
219 | - unnecessary_getters_setters
220 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
221 | - unnecessary_new
222 | - unnecessary_null_aware_assignments
223 | - unnecessary_null_checks
224 | - unnecessary_null_in_if_null_operators
225 | - unnecessary_nullable_for_final_variable_declarations
226 | - unnecessary_overrides
227 | - unnecessary_parenthesis
228 | # - unnecessary_raw_strings # what's "necessary" is a matter of opinion; consistency across strings can help readability more than this lint
229 | - unnecessary_statements
230 | - unnecessary_string_escapes
231 | - unnecessary_string_interpolations
232 | - unnecessary_this
233 | - unrelated_type_equality_checks
234 | - unsafe_html
235 | # - use_build_context_synchronously
236 | - use_full_hex_values_for_flutter_colors
237 | - use_function_type_syntax_for_parameters
238 | # - use_if_null_to_convert_nulls_to_bools # blocked on https://github.com/dart-lang/sdk/issues/47436
239 | - use_is_even_rather_than_modulo
240 | - use_key_in_widget_constructors
241 | - use_late_for_private_fields_and_variables
242 | - use_named_constants
243 | - use_raw_strings
244 | - use_rethrow_when_possible
245 | - use_setters_to_change_properties
246 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
247 | - use_test_throws_matchers
248 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
249 | - valid_regexps
250 | - void_checks
251 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Symbolication related
36 | app.*.symbols
37 |
38 | # Obfuscation related
39 | app.*.map.json
40 |
41 | # Android Studio will place build artifacts here
42 | /android/app/debug
43 | /android/app/profile
44 | /android/app/release
45 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # flutter_live_activities_example
2 |
3 | Demonstrates how to use the flutter_live_activities plugin.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
13 |
14 | For help getting started with Flutter development, view the
15 | [online documentation](https://docs.flutter.dev/), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # Specify analysis options.
2 | #
3 | # Until there are meta linter rules, each desired lint must be explicitly enabled.
4 | # See: https://github.com/dart-lang/linter/issues/288
5 | #
6 | # For a list of lints, see: http://dart-lang.github.io/linter/lints/
7 | # See the configuration guide for more
8 | # https://github.com/dart-lang/sdk/tree/main/pkg/analyzer#configuring-the-analyzer
9 | #
10 | # There are other similar analysis options files in the flutter repos,
11 | # which should be kept in sync with this file:
12 | #
13 | # - analysis_options.yaml (this file)
14 | # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
15 | # - https://github.com/flutter/engine/blob/master/analysis_options.yaml
16 | # - https://github.com/flutter/packages/blob/master/analysis_options.yaml
17 | #
18 | # This file contains the analysis options used by Flutter tools, such as IntelliJ,
19 | # Android Studio, and the `flutter analyze` command.
20 |
21 | analyzer:
22 | strong-mode:
23 | implicit-casts: false
24 | implicit-dynamic: false
25 | errors:
26 | # treat missing required parameters as a warning (not a hint)
27 | missing_required_param: warning
28 | # treat missing returns as a warning (not a hint)
29 | missing_return: warning
30 | # allow having TODO comments in the code
31 | # todo: ignore
32 | # allow self-reference to deprecated members (we do this because otherwise we have
33 | # to annotate every member in every test, assert, etc, when we deprecate something)
34 | deprecated_member_use_from_same_package: ignore
35 | # TODO(ianh): https://github.com/flutter/flutter/issues/74381
36 | # Clean up existing unnecessary imports, and remove line to ignore.
37 | unnecessary_import: ignore
38 | # Turned off until null-safe rollout is complete.
39 | unnecessary_null_comparison: ignore
40 | exclude:
41 | - "bin/cache/**"
42 | # Ignore protoc generated files
43 | - "dev/conductor/lib/proto/*"
44 | - "lib/core/l10n/**"
45 | - "lib/res/images.dart"
46 | - "lib/generated_plugin_registrant.dart"
47 | - "lib/widgets/country_code/flag_codes.dart"
48 | - "build/**"
49 | - "lib/**.freezed.dart"
50 | - "lib/**.g.dart"
51 | - "lib/data_source/database/database.g.dart"
52 | - "lib/domain/enum/gps_proto/**"
53 |
54 | linter:
55 | rules:
56 | # these rules are documented on and in the same order as
57 | # the Dart Lint rules page to make maintenance easier
58 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml
59 | - always_declare_return_types
60 | # - always_put_control_body_on_new_line
61 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
62 | - always_require_non_null_named_parameters
63 | - always_specify_types
64 | # - always_use_package_imports # we do this commonly
65 | - annotate_overrides
66 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types
67 | - avoid_bool_literals_in_conditional_expressions
68 | # - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023
69 | # - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/3023
70 | - avoid_classes_with_only_static_members
71 | - avoid_double_and_int_checks
72 | - avoid_dynamic_calls
73 | - avoid_empty_else
74 | - avoid_equals_and_hash_code_on_mutable_classes
75 | - avoid_escaping_inner_quotes
76 | - avoid_field_initializers_in_const_classes
77 | - avoid_function_literals_in_foreach_calls
78 | - avoid_implementing_value_types
79 | - avoid_init_to_null
80 | - avoid_js_rounded_ints
81 | # - avoid_multiple_declarations_per_line # seems to be a stylistic choice we don't subscribe to
82 | - avoid_null_checks_in_equality_operators
83 | # - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it
84 | - avoid_print
85 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
86 | - avoid_redundant_argument_values
87 | - avoid_relative_lib_imports
88 | - avoid_renaming_method_parameters
89 | - avoid_return_types_on_setters
90 | # - avoid_returning_null # still violated by some pre-nnbd code that we haven't yet migrated
91 | - avoid_returning_null_for_future
92 | - avoid_returning_null_for_void
93 | # - avoid_returning_this # there are enough valid reasons to return `this` that this lint ends up with too many false positives
94 | - avoid_setters_without_getters
95 | - avoid_shadowing_type_parameters
96 | - avoid_single_cascade_in_expression_statements
97 | - avoid_slow_async_io
98 | - avoid_type_to_string
99 | - avoid_types_as_parameter_names
100 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types
101 | - avoid_unnecessary_containers
102 | - avoid_unused_constructor_parameters
103 | - avoid_void_async
104 | # - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere
105 | - await_only_futures
106 | - camel_case_extensions
107 | - camel_case_types
108 | - cancel_subscriptions
109 | # - cascade_invocations # doesn't match the typical style of this repo
110 | - cast_nullable_to_non_nullable
111 | # - close_sinks # not reliable enough
112 | # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142
113 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204
114 | - control_flow_in_finally
115 | # - curly_braces_in_flow_control_structures # not required by flutter style
116 | - depend_on_referenced_packages
117 | - deprecated_consistency
118 | # - diagnostic_describe_all_properties # enabled only at the framework level (packages/flutter/lib)
119 | - directives_ordering
120 | # - do_not_use_environment # there are appropriate times to use the environment, especially in our tests and build logic
121 | - empty_catches
122 | - empty_constructor_bodies
123 | - empty_statements
124 | - eol_at_end_of_file
125 | - exhaustive_cases
126 | - file_names
127 | - flutter_style_todos
128 | - hash_and_equals
129 | - implementation_imports
130 | # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
131 | - iterable_contains_unrelated_type
132 | # - join_return_with_assignment # not required by flutter style
133 | - leading_newlines_in_multiline_strings
134 | - library_names
135 | - library_prefixes
136 | - library_private_types_in_public_api
137 | # - lines_longer_than_80_chars # not required by flutter style
138 | - list_remove_unrelated_type
139 | # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/linter/issues/453
140 | - missing_whitespace_between_adjacent_strings
141 | - no_adjacent_strings_in_list
142 | - no_default_cases
143 | - no_duplicate_case_values
144 | - no_logic_in_create_state
145 | # - no_runtimeType_toString # ok in tests; we enable this only in packages/
146 | - non_constant_identifier_names
147 | - noop_primitive_operations
148 | - null_check_on_nullable_type_parameter
149 | - null_closures
150 | # - omit_local_variable_types # opposite of always_specify_types
151 | # - one_member_abstracts # too many false positives
152 | - only_throw_errors # this does get disabled in a few places where we have legacy code that uses strings et al
153 | - overridden_fields
154 | - package_api_docs
155 | - package_names
156 | - package_prefixed_library_names
157 | # - parameter_assignments # we do this commonly
158 | - prefer_adjacent_string_concatenation
159 | - prefer_asserts_in_initializer_lists
160 | # - prefer_asserts_with_message # not required by flutter style
161 | - prefer_collection_literals
162 | - prefer_conditional_assignment
163 | - prefer_const_constructors
164 | - prefer_const_constructors_in_immutables
165 | - prefer_const_declarations
166 | - prefer_const_literals_to_create_immutables
167 | # - prefer_constructors_over_static_methods # far too many false positives
168 | - prefer_contains
169 | # - prefer_double_quotes # opposite of prefer_single_quotes
170 | - prefer_equal_for_default_values
171 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
172 | - prefer_final_fields
173 | - prefer_final_in_for_each
174 | - prefer_final_locals
175 | # - prefer_final_parameters # we should enable this one day when it can be auto-fixed (https://github.com/dart-lang/linter/issues/3104), see also parameter_assignments
176 | - prefer_for_elements_to_map_fromIterable
177 | - prefer_foreach
178 | - prefer_function_declarations_over_variables
179 | - prefer_generic_function_type_aliases
180 | - prefer_if_elements_to_conditional_expressions
181 | - prefer_if_null_operators
182 | - prefer_initializing_formals
183 | - prefer_inlined_adds
184 | # - prefer_int_literals # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#use-double-literals-for-double-constants
185 | - prefer_interpolation_to_compose_strings
186 | - prefer_is_empty
187 | - prefer_is_not_empty
188 | - prefer_is_not_operator
189 | - prefer_iterable_whereType
190 | # - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018
191 | - prefer_null_aware_operators
192 | # - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere
193 | # - prefer_relative_imports
194 | - prefer_single_quotes
195 | - prefer_spread_collections
196 | - prefer_typing_uninitialized_variables
197 | - prefer_void_to_null
198 | - provide_deprecation_message
199 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
200 | - recursive_getters
201 | # - require_trailing_commas # blocked on https://github.com/dart-lang/sdk/issues/47441
202 | - sized_box_for_whitespace
203 | - slash_for_doc_comments
204 | - sort_child_properties_last
205 | - sort_constructors_first
206 | # - sort_pub_dependencies # prevents separating pinned transitive dependencies
207 | - sort_unnamed_constructors_first
208 | - test_types_in_equals
209 | - throw_in_finally
210 | - tighten_type_of_initializing_formals
211 | # - type_annotate_public_apis # subset of always_specify_types
212 | - type_init_formals
213 | # - unawaited_futures # too many false positives, especially with the way AnimationController works
214 | - unnecessary_await_in_return
215 | - unnecessary_brace_in_string_interps
216 | - unnecessary_const
217 | - unnecessary_constructor_name
218 | # - unnecessary_final # conflicts with prefer_final_locals
219 | - unnecessary_getters_setters
220 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
221 | - unnecessary_new
222 | - unnecessary_null_aware_assignments
223 | - unnecessary_null_checks
224 | - unnecessary_null_in_if_null_operators
225 | - unnecessary_nullable_for_final_variable_declarations
226 | - unnecessary_overrides
227 | - unnecessary_parenthesis
228 | # - unnecessary_raw_strings # what's "necessary" is a matter of opinion; consistency across strings can help readability more than this lint
229 | - unnecessary_statements
230 | - unnecessary_string_escapes
231 | - unnecessary_string_interpolations
232 | - unnecessary_this
233 | - unrelated_type_equality_checks
234 | - unsafe_html
235 | # - use_build_context_synchronously
236 | - use_full_hex_values_for_flutter_colors
237 | - use_function_type_syntax_for_parameters
238 | # - use_if_null_to_convert_nulls_to_bools # blocked on https://github.com/dart-lang/sdk/issues/47436
239 | - use_is_even_rather_than_modulo
240 | - use_key_in_widget_constructors
241 | - use_late_for_private_fields_and_variables
242 | - use_named_constants
243 | - use_raw_strings
244 | - use_rethrow_when_possible
245 | - use_setters_to_change_properties
246 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
247 | - use_test_throws_matchers
248 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
249 | - valid_regexps
250 | - void_checks
251 |
--------------------------------------------------------------------------------
/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 11.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '11.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - flutter_live_activities (0.0.1):
4 | - Flutter
5 | - path_provider_ios (0.0.1):
6 | - Flutter
7 |
8 | DEPENDENCIES:
9 | - Flutter (from `Flutter`)
10 | - flutter_live_activities (from `.symlinks/plugins/flutter_live_activities/ios`)
11 | - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
12 |
13 | EXTERNAL SOURCES:
14 | Flutter:
15 | :path: Flutter
16 | flutter_live_activities:
17 | :path: ".symlinks/plugins/flutter_live_activities/ios"
18 | path_provider_ios:
19 | :path: ".symlinks/plugins/path_provider_ios/ios"
20 |
21 | SPEC CHECKSUMS:
22 | Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
23 | flutter_live_activities: 49925d06d6bcbe36ab07c04d7a84ac907114b67f
24 | path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
25 |
26 | PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
27 |
28 | COCOAPODS: 1.11.3
29 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 51;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 2770E018291511C500771F44 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2770E017291511C500771F44 /* WidgetKit.framework */; };
12 | 2770E01A291511C500771F44 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2770E019291511C500771F44 /* SwiftUI.framework */; };
13 | 2770E01D291511C500771F44 /* live_activity_testBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2770E01C291511C500771F44 /* live_activity_testBundle.swift */; };
14 | 2770E01F291511C500771F44 /* live_activity_testLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2770E01E291511C500771F44 /* live_activity_testLiveActivity.swift */; };
15 | 2770E024291511C600771F44 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2770E023291511C600771F44 /* Assets.xcassets */; };
16 | 2770E026291511C600771F44 /* live_activity_test.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 2770E022291511C500771F44 /* live_activity_test.intentdefinition */; };
17 | 2770E027291511C600771F44 /* live_activity_test.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 2770E022291511C500771F44 /* live_activity_test.intentdefinition */; };
18 | 2770E02A291511C600771F44 /* live_activity_testExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2770E016291511C500771F44 /* live_activity_testExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
19 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
20 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
21 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
22 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
23 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
24 | C15A7BBE550183F5860C9555 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60B91EA2AF415F3D26D60DC3 /* Pods_Runner.framework */; };
25 | /* End PBXBuildFile section */
26 |
27 | /* Begin PBXContainerItemProxy section */
28 | 2770E028291511C600771F44 /* PBXContainerItemProxy */ = {
29 | isa = PBXContainerItemProxy;
30 | containerPortal = 97C146E61CF9000F007C117D /* Project object */;
31 | proxyType = 1;
32 | remoteGlobalIDString = 2770E015291511C500771F44;
33 | remoteInfo = live_activity_testExtension;
34 | };
35 | /* End PBXContainerItemProxy section */
36 |
37 | /* Begin PBXCopyFilesBuildPhase section */
38 | 2770E02F291511C600771F44 /* Embed Foundation Extensions */ = {
39 | isa = PBXCopyFilesBuildPhase;
40 | buildActionMask = 2147483647;
41 | dstPath = "";
42 | dstSubfolderSpec = 13;
43 | files = (
44 | 2770E02A291511C600771F44 /* live_activity_testExtension.appex in Embed Foundation Extensions */,
45 | );
46 | name = "Embed Foundation Extensions";
47 | runOnlyForDeploymentPostprocessing = 0;
48 | };
49 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
50 | isa = PBXCopyFilesBuildPhase;
51 | buildActionMask = 2147483647;
52 | dstPath = "";
53 | dstSubfolderSpec = 10;
54 | files = (
55 | );
56 | name = "Embed Frameworks";
57 | runOnlyForDeploymentPostprocessing = 0;
58 | };
59 | /* End PBXCopyFilesBuildPhase section */
60 |
61 | /* Begin PBXFileReference section */
62 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
63 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
64 | 2770E016291511C500771F44 /* live_activity_testExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = live_activity_testExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
65 | 2770E017291511C500771F44 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
66 | 2770E019291511C500771F44 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
67 | 2770E01C291511C500771F44 /* live_activity_testBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = live_activity_testBundle.swift; sourceTree = ""; };
68 | 2770E01E291511C500771F44 /* live_activity_testLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = live_activity_testLiveActivity.swift; sourceTree = ""; };
69 | 2770E022291511C500771F44 /* live_activity_test.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = live_activity_test.intentdefinition; sourceTree = ""; };
70 | 2770E023291511C600771F44 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
71 | 2770E025291511C600771F44 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
72 | 2770E0302915123700771F44 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
73 | 2770E0312915129600771F44 /* live_activity_testExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = live_activity_testExtension.entitlements; sourceTree = ""; };
74 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
75 | 458DA777FB8597417C298567 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
76 | 58941C887787630E0DC83CF7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
77 | 60B91EA2AF415F3D26D60DC3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
78 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
79 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
80 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
81 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
82 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
83 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
84 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
85 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
86 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
87 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
88 | FFA92E86F409F6A9AA3BBE58 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
89 | /* End PBXFileReference section */
90 |
91 | /* Begin PBXFrameworksBuildPhase section */
92 | 2770E013291511C500771F44 /* Frameworks */ = {
93 | isa = PBXFrameworksBuildPhase;
94 | buildActionMask = 2147483647;
95 | files = (
96 | 2770E01A291511C500771F44 /* SwiftUI.framework in Frameworks */,
97 | 2770E018291511C500771F44 /* WidgetKit.framework in Frameworks */,
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
102 | isa = PBXFrameworksBuildPhase;
103 | buildActionMask = 2147483647;
104 | files = (
105 | C15A7BBE550183F5860C9555 /* Pods_Runner.framework in Frameworks */,
106 | );
107 | runOnlyForDeploymentPostprocessing = 0;
108 | };
109 | /* End PBXFrameworksBuildPhase section */
110 |
111 | /* Begin PBXGroup section */
112 | 2770E01B291511C500771F44 /* live_activity_test */ = {
113 | isa = PBXGroup;
114 | children = (
115 | 2770E01C291511C500771F44 /* live_activity_testBundle.swift */,
116 | 2770E01E291511C500771F44 /* live_activity_testLiveActivity.swift */,
117 | 2770E022291511C500771F44 /* live_activity_test.intentdefinition */,
118 | 2770E023291511C600771F44 /* Assets.xcassets */,
119 | 2770E025291511C600771F44 /* Info.plist */,
120 | );
121 | path = live_activity_test;
122 | sourceTree = "";
123 | };
124 | 42E2FA8A5218D71213299155 /* Pods */ = {
125 | isa = PBXGroup;
126 | children = (
127 | FFA92E86F409F6A9AA3BBE58 /* Pods-Runner.debug.xcconfig */,
128 | 58941C887787630E0DC83CF7 /* Pods-Runner.release.xcconfig */,
129 | 458DA777FB8597417C298567 /* Pods-Runner.profile.xcconfig */,
130 | );
131 | path = Pods;
132 | sourceTree = "";
133 | };
134 | 6C05ED94426A36133CF94D04 /* Frameworks */ = {
135 | isa = PBXGroup;
136 | children = (
137 | 60B91EA2AF415F3D26D60DC3 /* Pods_Runner.framework */,
138 | 2770E017291511C500771F44 /* WidgetKit.framework */,
139 | 2770E019291511C500771F44 /* SwiftUI.framework */,
140 | );
141 | name = Frameworks;
142 | sourceTree = "";
143 | };
144 | 9740EEB11CF90186004384FC /* Flutter */ = {
145 | isa = PBXGroup;
146 | children = (
147 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
148 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
149 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
150 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
151 | );
152 | name = Flutter;
153 | sourceTree = "";
154 | };
155 | 97C146E51CF9000F007C117D = {
156 | isa = PBXGroup;
157 | children = (
158 | 2770E0312915129600771F44 /* live_activity_testExtension.entitlements */,
159 | 9740EEB11CF90186004384FC /* Flutter */,
160 | 97C146F01CF9000F007C117D /* Runner */,
161 | 2770E01B291511C500771F44 /* live_activity_test */,
162 | 97C146EF1CF9000F007C117D /* Products */,
163 | 42E2FA8A5218D71213299155 /* Pods */,
164 | 6C05ED94426A36133CF94D04 /* Frameworks */,
165 | );
166 | sourceTree = "";
167 | };
168 | 97C146EF1CF9000F007C117D /* Products */ = {
169 | isa = PBXGroup;
170 | children = (
171 | 97C146EE1CF9000F007C117D /* Runner.app */,
172 | 2770E016291511C500771F44 /* live_activity_testExtension.appex */,
173 | );
174 | name = Products;
175 | sourceTree = "";
176 | };
177 | 97C146F01CF9000F007C117D /* Runner */ = {
178 | isa = PBXGroup;
179 | children = (
180 | 2770E0302915123700771F44 /* Runner.entitlements */,
181 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
182 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
183 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
184 | 97C147021CF9000F007C117D /* Info.plist */,
185 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
186 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
187 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
188 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
189 | );
190 | path = Runner;
191 | sourceTree = "";
192 | };
193 | /* End PBXGroup section */
194 |
195 | /* Begin PBXNativeTarget section */
196 | 2770E015291511C500771F44 /* live_activity_testExtension */ = {
197 | isa = PBXNativeTarget;
198 | buildConfigurationList = 2770E02B291511C600771F44 /* Build configuration list for PBXNativeTarget "live_activity_testExtension" */;
199 | buildPhases = (
200 | 2770E012291511C500771F44 /* Sources */,
201 | 2770E013291511C500771F44 /* Frameworks */,
202 | 2770E014291511C500771F44 /* Resources */,
203 | );
204 | buildRules = (
205 | );
206 | dependencies = (
207 | );
208 | name = live_activity_testExtension;
209 | productName = live_activity_testExtension;
210 | productReference = 2770E016291511C500771F44 /* live_activity_testExtension.appex */;
211 | productType = "com.apple.product-type.app-extension";
212 | };
213 | 97C146ED1CF9000F007C117D /* Runner */ = {
214 | isa = PBXNativeTarget;
215 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
216 | buildPhases = (
217 | 8E66A351ECE4730D6CB5F797 /* [CP] Check Pods Manifest.lock */,
218 | 9740EEB61CF901F6004384FC /* Run Script */,
219 | 97C146EA1CF9000F007C117D /* Sources */,
220 | 97C146EB1CF9000F007C117D /* Frameworks */,
221 | 97C146EC1CF9000F007C117D /* Resources */,
222 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
223 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
224 | 1613AA33CF4A811D03437973 /* [CP] Embed Pods Frameworks */,
225 | 2770E02F291511C600771F44 /* Embed Foundation Extensions */,
226 | );
227 | buildRules = (
228 | );
229 | dependencies = (
230 | 2770E029291511C600771F44 /* PBXTargetDependency */,
231 | );
232 | name = Runner;
233 | productName = Runner;
234 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
235 | productType = "com.apple.product-type.application";
236 | };
237 | /* End PBXNativeTarget section */
238 |
239 | /* Begin PBXProject section */
240 | 97C146E61CF9000F007C117D /* Project object */ = {
241 | isa = PBXProject;
242 | attributes = {
243 | LastSwiftUpdateCheck = 1410;
244 | LastUpgradeCheck = 1300;
245 | ORGANIZATIONNAME = "";
246 | TargetAttributes = {
247 | 2770E015291511C500771F44 = {
248 | CreatedOnToolsVersion = 14.1;
249 | };
250 | 97C146ED1CF9000F007C117D = {
251 | CreatedOnToolsVersion = 7.3.1;
252 | LastSwiftMigration = 1100;
253 | };
254 | };
255 | };
256 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
257 | compatibilityVersion = "Xcode 9.3";
258 | developmentRegion = en;
259 | hasScannedForEncodings = 0;
260 | knownRegions = (
261 | en,
262 | Base,
263 | );
264 | mainGroup = 97C146E51CF9000F007C117D;
265 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
266 | projectDirPath = "";
267 | projectRoot = "";
268 | targets = (
269 | 97C146ED1CF9000F007C117D /* Runner */,
270 | 2770E015291511C500771F44 /* live_activity_testExtension */,
271 | );
272 | };
273 | /* End PBXProject section */
274 |
275 | /* Begin PBXResourcesBuildPhase section */
276 | 2770E014291511C500771F44 /* Resources */ = {
277 | isa = PBXResourcesBuildPhase;
278 | buildActionMask = 2147483647;
279 | files = (
280 | 2770E024291511C600771F44 /* Assets.xcassets in Resources */,
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | };
284 | 97C146EC1CF9000F007C117D /* Resources */ = {
285 | isa = PBXResourcesBuildPhase;
286 | buildActionMask = 2147483647;
287 | files = (
288 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
289 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
290 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
291 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
292 | );
293 | runOnlyForDeploymentPostprocessing = 0;
294 | };
295 | /* End PBXResourcesBuildPhase section */
296 |
297 | /* Begin PBXShellScriptBuildPhase section */
298 | 1613AA33CF4A811D03437973 /* [CP] Embed Pods Frameworks */ = {
299 | isa = PBXShellScriptBuildPhase;
300 | buildActionMask = 2147483647;
301 | files = (
302 | );
303 | inputFileListPaths = (
304 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
305 | );
306 | name = "[CP] Embed Pods Frameworks";
307 | outputFileListPaths = (
308 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
309 | );
310 | runOnlyForDeploymentPostprocessing = 0;
311 | shellPath = /bin/sh;
312 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
313 | showEnvVarsInLog = 0;
314 | };
315 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
316 | isa = PBXShellScriptBuildPhase;
317 | buildActionMask = 2147483647;
318 | files = (
319 | );
320 | inputPaths = (
321 | );
322 | name = "Thin Binary";
323 | outputPaths = (
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | shellPath = /bin/sh;
327 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
328 | };
329 | 8E66A351ECE4730D6CB5F797 /* [CP] Check Pods Manifest.lock */ = {
330 | isa = PBXShellScriptBuildPhase;
331 | buildActionMask = 2147483647;
332 | files = (
333 | );
334 | inputFileListPaths = (
335 | );
336 | inputPaths = (
337 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
338 | "${PODS_ROOT}/Manifest.lock",
339 | );
340 | name = "[CP] Check Pods Manifest.lock";
341 | outputFileListPaths = (
342 | );
343 | outputPaths = (
344 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
345 | );
346 | runOnlyForDeploymentPostprocessing = 0;
347 | shellPath = /bin/sh;
348 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
349 | showEnvVarsInLog = 0;
350 | };
351 | 9740EEB61CF901F6004384FC /* Run Script */ = {
352 | isa = PBXShellScriptBuildPhase;
353 | buildActionMask = 2147483647;
354 | files = (
355 | );
356 | inputPaths = (
357 | );
358 | name = "Run Script";
359 | outputPaths = (
360 | );
361 | runOnlyForDeploymentPostprocessing = 0;
362 | shellPath = /bin/sh;
363 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
364 | };
365 | /* End PBXShellScriptBuildPhase section */
366 |
367 | /* Begin PBXSourcesBuildPhase section */
368 | 2770E012291511C500771F44 /* Sources */ = {
369 | isa = PBXSourcesBuildPhase;
370 | buildActionMask = 2147483647;
371 | files = (
372 | 2770E01D291511C500771F44 /* live_activity_testBundle.swift in Sources */,
373 | 2770E01F291511C500771F44 /* live_activity_testLiveActivity.swift in Sources */,
374 | 2770E026291511C600771F44 /* live_activity_test.intentdefinition in Sources */,
375 | );
376 | runOnlyForDeploymentPostprocessing = 0;
377 | };
378 | 97C146EA1CF9000F007C117D /* Sources */ = {
379 | isa = PBXSourcesBuildPhase;
380 | buildActionMask = 2147483647;
381 | files = (
382 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
383 | 2770E027291511C600771F44 /* live_activity_test.intentdefinition in Sources */,
384 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
385 | );
386 | runOnlyForDeploymentPostprocessing = 0;
387 | };
388 | /* End PBXSourcesBuildPhase section */
389 |
390 | /* Begin PBXTargetDependency section */
391 | 2770E029291511C600771F44 /* PBXTargetDependency */ = {
392 | isa = PBXTargetDependency;
393 | target = 2770E015291511C500771F44 /* live_activity_testExtension */;
394 | targetProxy = 2770E028291511C600771F44 /* PBXContainerItemProxy */;
395 | };
396 | /* End PBXTargetDependency section */
397 |
398 | /* Begin PBXVariantGroup section */
399 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
400 | isa = PBXVariantGroup;
401 | children = (
402 | 97C146FB1CF9000F007C117D /* Base */,
403 | );
404 | name = Main.storyboard;
405 | sourceTree = "";
406 | };
407 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
408 | isa = PBXVariantGroup;
409 | children = (
410 | 97C147001CF9000F007C117D /* Base */,
411 | );
412 | name = LaunchScreen.storyboard;
413 | sourceTree = "";
414 | };
415 | /* End PBXVariantGroup section */
416 |
417 | /* Begin XCBuildConfiguration section */
418 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
419 | isa = XCBuildConfiguration;
420 | buildSettings = {
421 | ALWAYS_SEARCH_USER_PATHS = NO;
422 | CLANG_ANALYZER_NONNULL = YES;
423 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
424 | CLANG_CXX_LIBRARY = "libc++";
425 | CLANG_ENABLE_MODULES = YES;
426 | CLANG_ENABLE_OBJC_ARC = YES;
427 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
428 | CLANG_WARN_BOOL_CONVERSION = YES;
429 | CLANG_WARN_COMMA = YES;
430 | CLANG_WARN_CONSTANT_CONVERSION = YES;
431 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
432 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
433 | CLANG_WARN_EMPTY_BODY = YES;
434 | CLANG_WARN_ENUM_CONVERSION = YES;
435 | CLANG_WARN_INFINITE_RECURSION = YES;
436 | CLANG_WARN_INT_CONVERSION = YES;
437 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
438 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
439 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
440 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
441 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
442 | CLANG_WARN_STRICT_PROTOTYPES = YES;
443 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
444 | CLANG_WARN_UNREACHABLE_CODE = YES;
445 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
446 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
447 | COPY_PHASE_STRIP = NO;
448 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
449 | ENABLE_NS_ASSERTIONS = NO;
450 | ENABLE_STRICT_OBJC_MSGSEND = YES;
451 | GCC_C_LANGUAGE_STANDARD = gnu99;
452 | GCC_NO_COMMON_BLOCKS = YES;
453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
455 | GCC_WARN_UNDECLARED_SELECTOR = YES;
456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
457 | GCC_WARN_UNUSED_FUNCTION = YES;
458 | GCC_WARN_UNUSED_VARIABLE = YES;
459 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
460 | MTL_ENABLE_DEBUG_INFO = NO;
461 | SDKROOT = iphoneos;
462 | SUPPORTED_PLATFORMS = iphoneos;
463 | TARGETED_DEVICE_FAMILY = "1,2";
464 | VALIDATE_PRODUCT = YES;
465 | };
466 | name = Profile;
467 | };
468 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
469 | isa = XCBuildConfiguration;
470 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
471 | buildSettings = {
472 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
473 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
474 | CLANG_ENABLE_MODULES = YES;
475 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
476 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
477 | DEVELOPMENT_TEAM = 3U3296XZA5;
478 | ENABLE_BITCODE = NO;
479 | INFOPLIST_FILE = Runner/Info.plist;
480 | LD_RUNPATH_SEARCH_PATHS = (
481 | "$(inherited)",
482 | "@executable_path/Frameworks",
483 | );
484 | PRODUCT_BUNDLE_IDENTIFIER = com.fluttercandies.flutterLiveActivitiesExample;
485 | PRODUCT_NAME = "$(TARGET_NAME)";
486 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
487 | SWIFT_VERSION = 5.0;
488 | VERSIONING_SYSTEM = "apple-generic";
489 | };
490 | name = Profile;
491 | };
492 | 2770E02C291511C600771F44 /* Debug */ = {
493 | isa = XCBuildConfiguration;
494 | buildSettings = {
495 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
496 | ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
497 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
498 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
499 | CLANG_ENABLE_OBJC_WEAK = YES;
500 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
501 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
502 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
503 | CODE_SIGN_ENTITLEMENTS = live_activity_testExtension.entitlements;
504 | CODE_SIGN_STYLE = Automatic;
505 | CURRENT_PROJECT_VERSION = 1;
506 | DEVELOPMENT_TEAM = 3U3296XZA5;
507 | GCC_C_LANGUAGE_STANDARD = gnu11;
508 | GENERATE_INFOPLIST_FILE = YES;
509 | INFOPLIST_FILE = live_activity_test/Info.plist;
510 | INFOPLIST_KEY_CFBundleDisplayName = live_activity_test;
511 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
512 | IPHONEOS_DEPLOYMENT_TARGET = 16.1;
513 | LD_RUNPATH_SEARCH_PATHS = (
514 | "$(inherited)",
515 | "@executable_path/Frameworks",
516 | "@executable_path/../../Frameworks",
517 | );
518 | MARKETING_VERSION = 1.0;
519 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
520 | MTL_FAST_MATH = YES;
521 | PRODUCT_BUNDLE_IDENTIFIER = "com.fluttercandies.flutterLiveActivitiesExample.live-activity-test";
522 | PRODUCT_NAME = "$(TARGET_NAME)";
523 | SKIP_INSTALL = YES;
524 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
525 | SWIFT_EMIT_LOC_STRINGS = YES;
526 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
527 | SWIFT_VERSION = 5.0;
528 | TARGETED_DEVICE_FAMILY = "1,2";
529 | };
530 | name = Debug;
531 | };
532 | 2770E02D291511C600771F44 /* Release */ = {
533 | isa = XCBuildConfiguration;
534 | buildSettings = {
535 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
536 | ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
537 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
538 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
539 | CLANG_ENABLE_OBJC_WEAK = YES;
540 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
541 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
542 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
543 | CODE_SIGN_ENTITLEMENTS = live_activity_testExtension.entitlements;
544 | CODE_SIGN_STYLE = Automatic;
545 | CURRENT_PROJECT_VERSION = 1;
546 | DEVELOPMENT_TEAM = 3U3296XZA5;
547 | GCC_C_LANGUAGE_STANDARD = gnu11;
548 | GENERATE_INFOPLIST_FILE = YES;
549 | INFOPLIST_FILE = live_activity_test/Info.plist;
550 | INFOPLIST_KEY_CFBundleDisplayName = live_activity_test;
551 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
552 | IPHONEOS_DEPLOYMENT_TARGET = 16.1;
553 | LD_RUNPATH_SEARCH_PATHS = (
554 | "$(inherited)",
555 | "@executable_path/Frameworks",
556 | "@executable_path/../../Frameworks",
557 | );
558 | MARKETING_VERSION = 1.0;
559 | MTL_FAST_MATH = YES;
560 | PRODUCT_BUNDLE_IDENTIFIER = "com.fluttercandies.flutterLiveActivitiesExample.live-activity-test";
561 | PRODUCT_NAME = "$(TARGET_NAME)";
562 | SKIP_INSTALL = YES;
563 | SWIFT_EMIT_LOC_STRINGS = YES;
564 | SWIFT_VERSION = 5.0;
565 | TARGETED_DEVICE_FAMILY = "1,2";
566 | };
567 | name = Release;
568 | };
569 | 2770E02E291511C600771F44 /* Profile */ = {
570 | isa = XCBuildConfiguration;
571 | buildSettings = {
572 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
573 | ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
574 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
575 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
576 | CLANG_ENABLE_OBJC_WEAK = YES;
577 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
578 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
579 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
580 | CODE_SIGN_ENTITLEMENTS = live_activity_testExtension.entitlements;
581 | CODE_SIGN_STYLE = Automatic;
582 | CURRENT_PROJECT_VERSION = 1;
583 | DEVELOPMENT_TEAM = 3U3296XZA5;
584 | GCC_C_LANGUAGE_STANDARD = gnu11;
585 | GENERATE_INFOPLIST_FILE = YES;
586 | INFOPLIST_FILE = live_activity_test/Info.plist;
587 | INFOPLIST_KEY_CFBundleDisplayName = live_activity_test;
588 | INFOPLIST_KEY_NSHumanReadableCopyright = "";
589 | IPHONEOS_DEPLOYMENT_TARGET = 16.1;
590 | LD_RUNPATH_SEARCH_PATHS = (
591 | "$(inherited)",
592 | "@executable_path/Frameworks",
593 | "@executable_path/../../Frameworks",
594 | );
595 | MARKETING_VERSION = 1.0;
596 | MTL_FAST_MATH = YES;
597 | PRODUCT_BUNDLE_IDENTIFIER = "com.fluttercandies.flutterLiveActivitiesExample.live-activity-test";
598 | PRODUCT_NAME = "$(TARGET_NAME)";
599 | SKIP_INSTALL = YES;
600 | SWIFT_EMIT_LOC_STRINGS = YES;
601 | SWIFT_VERSION = 5.0;
602 | TARGETED_DEVICE_FAMILY = "1,2";
603 | };
604 | name = Profile;
605 | };
606 | 97C147031CF9000F007C117D /* Debug */ = {
607 | isa = XCBuildConfiguration;
608 | buildSettings = {
609 | ALWAYS_SEARCH_USER_PATHS = NO;
610 | CLANG_ANALYZER_NONNULL = YES;
611 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
612 | CLANG_CXX_LIBRARY = "libc++";
613 | CLANG_ENABLE_MODULES = YES;
614 | CLANG_ENABLE_OBJC_ARC = YES;
615 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
616 | CLANG_WARN_BOOL_CONVERSION = YES;
617 | CLANG_WARN_COMMA = YES;
618 | CLANG_WARN_CONSTANT_CONVERSION = YES;
619 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
620 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
621 | CLANG_WARN_EMPTY_BODY = YES;
622 | CLANG_WARN_ENUM_CONVERSION = YES;
623 | CLANG_WARN_INFINITE_RECURSION = YES;
624 | CLANG_WARN_INT_CONVERSION = YES;
625 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
626 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
627 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
628 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
629 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
630 | CLANG_WARN_STRICT_PROTOTYPES = YES;
631 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
632 | CLANG_WARN_UNREACHABLE_CODE = YES;
633 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
634 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
635 | COPY_PHASE_STRIP = NO;
636 | DEBUG_INFORMATION_FORMAT = dwarf;
637 | ENABLE_STRICT_OBJC_MSGSEND = YES;
638 | ENABLE_TESTABILITY = YES;
639 | GCC_C_LANGUAGE_STANDARD = gnu99;
640 | GCC_DYNAMIC_NO_PIC = NO;
641 | GCC_NO_COMMON_BLOCKS = YES;
642 | GCC_OPTIMIZATION_LEVEL = 0;
643 | GCC_PREPROCESSOR_DEFINITIONS = (
644 | "DEBUG=1",
645 | "$(inherited)",
646 | );
647 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
648 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
649 | GCC_WARN_UNDECLARED_SELECTOR = YES;
650 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
651 | GCC_WARN_UNUSED_FUNCTION = YES;
652 | GCC_WARN_UNUSED_VARIABLE = YES;
653 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
654 | MTL_ENABLE_DEBUG_INFO = YES;
655 | ONLY_ACTIVE_ARCH = YES;
656 | SDKROOT = iphoneos;
657 | TARGETED_DEVICE_FAMILY = "1,2";
658 | };
659 | name = Debug;
660 | };
661 | 97C147041CF9000F007C117D /* Release */ = {
662 | isa = XCBuildConfiguration;
663 | buildSettings = {
664 | ALWAYS_SEARCH_USER_PATHS = NO;
665 | CLANG_ANALYZER_NONNULL = YES;
666 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
667 | CLANG_CXX_LIBRARY = "libc++";
668 | CLANG_ENABLE_MODULES = YES;
669 | CLANG_ENABLE_OBJC_ARC = YES;
670 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
671 | CLANG_WARN_BOOL_CONVERSION = YES;
672 | CLANG_WARN_COMMA = YES;
673 | CLANG_WARN_CONSTANT_CONVERSION = YES;
674 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
675 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
676 | CLANG_WARN_EMPTY_BODY = YES;
677 | CLANG_WARN_ENUM_CONVERSION = YES;
678 | CLANG_WARN_INFINITE_RECURSION = YES;
679 | CLANG_WARN_INT_CONVERSION = YES;
680 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
681 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
682 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
683 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
684 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
685 | CLANG_WARN_STRICT_PROTOTYPES = YES;
686 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
687 | CLANG_WARN_UNREACHABLE_CODE = YES;
688 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
689 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
690 | COPY_PHASE_STRIP = NO;
691 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
692 | ENABLE_NS_ASSERTIONS = NO;
693 | ENABLE_STRICT_OBJC_MSGSEND = YES;
694 | GCC_C_LANGUAGE_STANDARD = gnu99;
695 | GCC_NO_COMMON_BLOCKS = YES;
696 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
697 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
698 | GCC_WARN_UNDECLARED_SELECTOR = YES;
699 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
700 | GCC_WARN_UNUSED_FUNCTION = YES;
701 | GCC_WARN_UNUSED_VARIABLE = YES;
702 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
703 | MTL_ENABLE_DEBUG_INFO = NO;
704 | SDKROOT = iphoneos;
705 | SUPPORTED_PLATFORMS = iphoneos;
706 | SWIFT_COMPILATION_MODE = wholemodule;
707 | SWIFT_OPTIMIZATION_LEVEL = "-O";
708 | TARGETED_DEVICE_FAMILY = "1,2";
709 | VALIDATE_PRODUCT = YES;
710 | };
711 | name = Release;
712 | };
713 | 97C147061CF9000F007C117D /* Debug */ = {
714 | isa = XCBuildConfiguration;
715 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
716 | buildSettings = {
717 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
718 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
719 | CLANG_ENABLE_MODULES = YES;
720 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
721 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
722 | DEVELOPMENT_TEAM = 3U3296XZA5;
723 | ENABLE_BITCODE = NO;
724 | INFOPLIST_FILE = Runner/Info.plist;
725 | LD_RUNPATH_SEARCH_PATHS = (
726 | "$(inherited)",
727 | "@executable_path/Frameworks",
728 | );
729 | PRODUCT_BUNDLE_IDENTIFIER = com.fluttercandies.flutterLiveActivitiesExample;
730 | PRODUCT_NAME = "$(TARGET_NAME)";
731 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
732 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
733 | SWIFT_VERSION = 5.0;
734 | VERSIONING_SYSTEM = "apple-generic";
735 | };
736 | name = Debug;
737 | };
738 | 97C147071CF9000F007C117D /* Release */ = {
739 | isa = XCBuildConfiguration;
740 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
741 | buildSettings = {
742 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
743 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
744 | CLANG_ENABLE_MODULES = YES;
745 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
746 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
747 | DEVELOPMENT_TEAM = 3U3296XZA5;
748 | ENABLE_BITCODE = NO;
749 | INFOPLIST_FILE = Runner/Info.plist;
750 | LD_RUNPATH_SEARCH_PATHS = (
751 | "$(inherited)",
752 | "@executable_path/Frameworks",
753 | );
754 | PRODUCT_BUNDLE_IDENTIFIER = com.fluttercandies.flutterLiveActivitiesExample;
755 | PRODUCT_NAME = "$(TARGET_NAME)";
756 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
757 | SWIFT_VERSION = 5.0;
758 | VERSIONING_SYSTEM = "apple-generic";
759 | };
760 | name = Release;
761 | };
762 | /* End XCBuildConfiguration section */
763 |
764 | /* Begin XCConfigurationList section */
765 | 2770E02B291511C600771F44 /* Build configuration list for PBXNativeTarget "live_activity_testExtension" */ = {
766 | isa = XCConfigurationList;
767 | buildConfigurations = (
768 | 2770E02C291511C600771F44 /* Debug */,
769 | 2770E02D291511C600771F44 /* Release */,
770 | 2770E02E291511C600771F44 /* Profile */,
771 | );
772 | defaultConfigurationIsVisible = 0;
773 | defaultConfigurationName = Release;
774 | };
775 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
776 | isa = XCConfigurationList;
777 | buildConfigurations = (
778 | 97C147031CF9000F007C117D /* Debug */,
779 | 97C147041CF9000F007C117D /* Release */,
780 | 249021D3217E4FDB00AE95B9 /* Profile */,
781 | );
782 | defaultConfigurationIsVisible = 0;
783 | defaultConfigurationName = Release;
784 | };
785 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
786 | isa = XCConfigurationList;
787 | buildConfigurations = (
788 | 97C147061CF9000F007C117D /* Debug */,
789 | 97C147071CF9000F007C117D /* Release */,
790 | 249021D4217E4FDB00AE95B9 /* Profile */,
791 | );
792 | defaultConfigurationIsVisible = 0;
793 | defaultConfigurationName = Release;
794 | };
795 | /* End XCConfigurationList section */
796 | };
797 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
798 | }
799 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CADisableMinimumFrameDurationOnPhone
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleDisplayName
10 | Flutter Live Activities
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | flutter_live_activities_example
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | $(FLUTTER_BUILD_NAME)
23 | CFBundleSignature
24 | ????
25 | CFBundleURLTypes
26 |
27 |
28 | CFBundleTypeRole
29 | Editor
30 | CFBundleURLSchemes
31 |
32 | fla
33 |
34 |
35 |
36 | CFBundleVersion
37 | $(FLUTTER_BUILD_NUMBER)
38 | LSRequiresIPhoneOS
39 |
40 | NSSupportsLiveActivities
41 |
42 | UIApplicationSupportsIndirectInputEvents
43 |
44 | UILaunchStoryboardName
45 | LaunchScreen
46 | UIMainStoryboardFile
47 | Main
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UISupportedInterfaceOrientations~ipad
55 |
56 | UIInterfaceOrientationPortrait
57 | UIInterfaceOrientationPortraitUpsideDown
58 | UIInterfaceOrientationLandscapeLeft
59 | UIInterfaceOrientationLandscapeRight
60 |
61 | UIViewControllerBasedStatusBarAppearance
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.live_example
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/Assets.xcassets/WidgetBackground.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSExtension
6 |
7 | NSExtensionPointIdentifier
8 | com.apple.widgetkit-extension
9 |
10 | NSSupportsLiveActivities
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/live_activity_test.intentdefinition:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | INEnums
6 |
7 | INIntentDefinitionModelVersion
8 | 1.2
9 | INIntentDefinitionNamespace
10 | 88xZPY
11 | INIntentDefinitionSystemVersion
12 | 20A294
13 | INIntentDefinitionToolsBuildVersion
14 | 12A6144
15 | INIntentDefinitionToolsVersion
16 | 12.0
17 | INIntents
18 |
19 |
20 | INIntentCategory
21 | information
22 | INIntentDescriptionID
23 | tVvJ9c
24 | INIntentEligibleForWidgets
25 |
26 | INIntentIneligibleForSuggestions
27 |
28 | INIntentName
29 | Configuration
30 | INIntentResponse
31 |
32 | INIntentResponseCodes
33 |
34 |
35 | INIntentResponseCodeName
36 | success
37 | INIntentResponseCodeSuccess
38 |
39 |
40 |
41 | INIntentResponseCodeName
42 | failure
43 |
44 |
45 |
46 | INIntentTitle
47 | Configuration
48 | INIntentTitleID
49 | gpCwrM
50 | INIntentType
51 | Custom
52 | INIntentVerb
53 | View
54 |
55 |
56 | INTypes
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/live_activity_testBundle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // live_activity_testBundle.swift
3 | // live_activity_test
4 | //
5 | // Created by Mike on 2022/11/4.
6 | //
7 |
8 | import WidgetKit
9 | import SwiftUI
10 |
11 | @main
12 | struct live_activity_testBundle: WidgetBundle {
13 | var body: some Widget {
14 | live_activity_testLiveActivity()
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/example/ios/live_activity_test/live_activity_testLiveActivity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // live_activity_testLiveActivity.swift
3 | // live_activity_test
4 | //
5 | // Created by Mike on 2022/11/4.
6 | //
7 |
8 | import ActivityKit
9 | import SwiftUI
10 | import WidgetKit
11 |
12 | // TestData
13 | struct TestData {
14 | var text: String
15 |
16 | init?(JSONData data: [String: String]) {
17 | self.text = data["text"] ?? ""
18 | }
19 |
20 | init(text: String) {
21 | self.text = text
22 | }
23 | }
24 |
25 | struct FlutterLiveActivities: ActivityAttributes, Identifiable {
26 | public typealias LiveData = ContentState
27 |
28 | public struct ContentState: Codable, Hashable {
29 | var data: [String: String]
30 | }
31 |
32 | var id = UUID()
33 | }
34 |
35 | @available(iOSApplicationExtension 16.1, *)
36 | struct live_activity_testLiveActivity: Widget {
37 | var body: some WidgetConfiguration {
38 | ActivityConfiguration(for: FlutterLiveActivities.self) { context in
39 | let data = TestData(JSONData: context.state.data)
40 |
41 | // Lock screen/banner UI goes here
42 |
43 | VStack(alignment: .leading) {
44 | Text(data?.text ?? "")
45 | HStack {
46 | Link(destination: URL(string: "fla://xx.xx/tap/A")!) {
47 | Text("A")
48 | .frame(width: 40, height: 40)
49 | .background(.blue)
50 | }
51 |
52 | Link(destination: URL(string: "fla://xx.xx/tap/B")!) {
53 | Text("B")
54 | .frame(width: 40, height: 40)
55 | .background(.blue)
56 | }
57 |
58 | Link(destination: URL(string: "fla://xx.xx/tap/C")!) {
59 | Text("C")
60 | .frame(width: 40, height: 40)
61 | .background(.blue)
62 | }
63 | }
64 | .frame(width: .infinity, height: .infinity)
65 | }
66 | .padding(20)
67 | .activityBackgroundTint(Color.cyan)
68 | .activitySystemActionForegroundColor(Color.black)
69 |
70 | } dynamicIsland: { context in
71 |
72 | let data = TestData(JSONData: context.state.data)
73 |
74 | return DynamicIsland {
75 | // Expanded UI goes here. Compose the expanded UI through
76 | // various regions, like leading/trailing/center/bottom
77 | DynamicIslandExpandedRegion(.leading) {
78 | if let imageContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.live_example")?.appendingPathComponent("test-img"),
79 | let uiImage = UIImage(contentsOfFile: imageContainer.path())
80 | {
81 | Image(uiImage: uiImage)
82 | .resizable()
83 | .frame(width: 53, height: 53)
84 | .cornerRadius(13)
85 | .overlay(
86 | RoundedRectangle(cornerRadius: 15)
87 | .stroke(.white.opacity(0.15), lineWidth: 1)
88 | )
89 | } else {
90 | Text("Leading")
91 | }
92 | }
93 | DynamicIslandExpandedRegion(.trailing) {
94 | Text("Trailing")
95 | }
96 | DynamicIslandExpandedRegion(.bottom) {
97 | Link(destination: URL(string: "fla://xx.xx/tap/HelloWorld")!) {
98 | Text(data?.text ?? "")
99 | .background(.red)
100 | }
101 | // more content
102 | }
103 | } compactLeading: {
104 | Text("L")
105 | } compactTrailing: {
106 | Text("T")
107 | } minimal: {
108 | Text("Min")
109 | }
110 | .widgetURL(URL(string: "fla://xx.xx/tap/DynamicIsland"))
111 | .keylineTint(Color.red)
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/example/ios/live_activity_testExtension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.application-groups
6 |
7 | group.live_example
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/lib/helper/image_helper.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:extended_image/extended_image.dart';
4 | import 'package:path/path.dart';
5 | import 'package:path_provider/path_provider.dart';
6 |
7 | /// Image Helper
8 | class ImageHelper {
9 | ImageHelper._();
10 |
11 | /// get file path from url
12 | static Future getFilePathFromUrl(String url) async {
13 | await preloadImage(url);
14 | return (await getImageFile(url))?.path;
15 | }
16 |
17 | /// Pre-cache images by url
18 | static Future preloadImage(String url) async {
19 | final ExtendedNetworkImageProvider provider =
20 | ExtendedNetworkImageProvider(url, cache: true);
21 |
22 | await provider.getNetworkImageData();
23 | }
24 |
25 | /// Get the cache file by url
26 | static Future getImageFile(String? url) async {
27 | try {
28 | if (url == null) {
29 | return null;
30 | }
31 |
32 | final Directory _cacheImagesDirectory = Directory(
33 | join((await getTemporaryDirectory()).path, cacheImageFolderName));
34 |
35 | if (!_cacheImagesDirectory.existsSync()) {
36 | return null;
37 | }
38 |
39 | final String md5Key = keyToMd5(url);
40 | final File cacheFlie = File(join(_cacheImagesDirectory.path, md5Key));
41 |
42 | if (cacheFlie.existsSync()) {
43 | return cacheFlie;
44 | }
45 | } catch (e) {
46 | // error('getImageFile error : $e');
47 | }
48 |
49 | return null;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:developer' as dev;
3 |
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter_live_activities/flutter_live_activities.dart';
6 | import 'package:flutter_live_activities_example/helper/image_helper.dart';
7 |
8 | void main() {
9 | runApp(const MyApp());
10 | }
11 |
12 | class MyApp extends StatelessWidget {
13 | const MyApp({super.key});
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return const MaterialApp(
18 | title: 'Flutter Demo',
19 | home: Home(),
20 | );
21 | }
22 | }
23 |
24 | class Home extends StatefulWidget {
25 | const Home({super.key});
26 |
27 | @override
28 | State createState() => _HomeState();
29 | }
30 |
31 | class _HomeState extends State {
32 | final FlutterLiveActivities _liveActivities = FlutterLiveActivities();
33 | String? _activityId;
34 | bool? _enabled;
35 |
36 | StreamSubscription? _subscription;
37 |
38 | String _info = '';
39 |
40 | @override
41 | void initState() {
42 | super.initState();
43 | _initStream();
44 | _getInitUri();
45 | }
46 |
47 | Future _initStream() async {
48 | _subscription ??= _liveActivities.uriStream().listen((Uri? uri) {
49 | dev.log('deeplink uri: $uri');
50 | if (uri != null) _setInfo(uri.toString());
51 | });
52 | }
53 |
54 | void _cancelStream() {
55 | _subscription?.cancel();
56 | _subscription = null;
57 | }
58 |
59 | @override
60 | void dispose() {
61 | _cancelStream();
62 | super.dispose();
63 | }
64 |
65 | Future _getInitUri() async {
66 | _setInfo('initUri : ${(await _liveActivities.getInitUri()) ?? ''}');
67 | }
68 |
69 | void _setInfo(String info) {
70 | setState(() {
71 | _info = info;
72 | });
73 | }
74 |
75 | Future _checkEnabled() async {
76 | _enabled = await _liveActivities.areActivitiesEnabled();
77 | setState(() {});
78 | }
79 |
80 | Future _getAllActivities() async {
81 | _setInfo((await _liveActivities.getAllActivities()).toString());
82 | }
83 |
84 | Future _endAllActivities() async {
85 | await _liveActivities.endAllActivities();
86 | }
87 |
88 | Future _createActivity() async {
89 | _initStream();
90 |
91 | _activityId = await _liveActivities
92 | .createActivity({'text': 'Hello World'});
93 |
94 | setState(() {});
95 | }
96 |
97 | Future _updateActivity() async {
98 | _liveActivities.updateActivity(
99 | _activityId!, {'text': 'Update Hello World'});
100 | }
101 |
102 | Future _endActivity() async {
103 | _cancelStream();
104 | _liveActivities.endActivity(_activityId!);
105 | _activityId = null;
106 | _setInfo('');
107 | }
108 |
109 | Future _sendImageToGroup() async {
110 | const String url =
111 | 'https://cdn.iconscout.com/icon/free/png-256/flutter-2752187-2285004.png';
112 | final String? path = await ImageHelper.getFilePathFromUrl(url);
113 |
114 | if (path != null) {
115 | _liveActivities.sendImageToGroup(
116 | id: 'test-img',
117 | filePath: path,
118 | groupId: 'group.live_example',
119 | );
120 | }
121 | }
122 |
123 | @override
124 | Widget build(BuildContext context) {
125 | return Scaffold(
126 | appBar: AppBar(
127 | title: const Text('Flutter Live Activities'),
128 | ),
129 | body: SizedBox.expand(
130 | child: Padding(
131 | padding: const EdgeInsets.all(16.0),
132 | child: Column(
133 | mainAxisAlignment: MainAxisAlignment.center,
134 | children: [
135 | Text('Info: $_info', textAlign: TextAlign.center),
136 | ElevatedButton(
137 | onPressed: _checkEnabled,
138 | child: Text('Enabled: $_enabled'),
139 | ),
140 | if (_enabled == true)
141 | ElevatedButton(
142 | onPressed: _getAllActivities,
143 | child: const Text('getAllActivities'),
144 | ),
145 | if (_enabled == true)
146 | ElevatedButton(
147 | onPressed: _getInitUri,
148 | child: const Text('getInitUri'),
149 | ),
150 | ElevatedButton(
151 | onPressed: _sendImageToGroup,
152 | child: const Text('Send image to group'),
153 | ),
154 | if (_enabled == true && _activityId == null)
155 | ElevatedButton(
156 | onPressed: _createActivity,
157 | child: const Text('Create live activity'),
158 | ),
159 | if (_activityId != null)
160 | ElevatedButton(
161 | onPressed: _updateActivity,
162 | child: Text(
163 | 'Update live activity $_activityId',
164 | textAlign: TextAlign.center,
165 | ),
166 | ),
167 | if (_activityId != null)
168 | ElevatedButton(
169 | onPressed: _endActivity,
170 | child: Text(
171 | 'End live activity $_activityId',
172 | textAlign: TextAlign.center,
173 | ),
174 | ),
175 | if (_enabled == true)
176 | ElevatedButton(
177 | onPressed: _endAllActivities,
178 | child: const Text('endAllActivities'),
179 | ),
180 | ],
181 | ),
182 | ),
183 | ),
184 | );
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/example/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.flutter-io.cn"
9 | source: hosted
10 | version: "2.9.0"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.flutter-io.cn"
16 | source: hosted
17 | version: "2.1.0"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.flutter-io.cn"
23 | source: hosted
24 | version: "1.2.1"
25 | clock:
26 | dependency: transitive
27 | description:
28 | name: clock
29 | url: "https://pub.flutter-io.cn"
30 | source: hosted
31 | version: "1.1.1"
32 | collection:
33 | dependency: transitive
34 | description:
35 | name: collection
36 | url: "https://pub.flutter-io.cn"
37 | source: hosted
38 | version: "1.16.0"
39 | crypto:
40 | dependency: transitive
41 | description:
42 | name: crypto
43 | url: "https://pub.flutter-io.cn"
44 | source: hosted
45 | version: "3.0.2"
46 | cupertino_icons:
47 | dependency: "direct main"
48 | description:
49 | name: cupertino_icons
50 | url: "https://pub.flutter-io.cn"
51 | source: hosted
52 | version: "1.0.5"
53 | extended_image:
54 | dependency: "direct main"
55 | description:
56 | name: extended_image
57 | url: "https://pub.flutter-io.cn"
58 | source: hosted
59 | version: "6.3.2"
60 | extended_image_library:
61 | dependency: transitive
62 | description:
63 | name: extended_image_library
64 | url: "https://pub.flutter-io.cn"
65 | source: hosted
66 | version: "3.4.1"
67 | fake_async:
68 | dependency: transitive
69 | description:
70 | name: fake_async
71 | url: "https://pub.flutter-io.cn"
72 | source: hosted
73 | version: "1.3.1"
74 | ffi:
75 | dependency: transitive
76 | description:
77 | name: ffi
78 | url: "https://pub.flutter-io.cn"
79 | source: hosted
80 | version: "2.0.1"
81 | file:
82 | dependency: transitive
83 | description:
84 | name: file
85 | url: "https://pub.flutter-io.cn"
86 | source: hosted
87 | version: "6.1.4"
88 | flutter:
89 | dependency: "direct main"
90 | description: flutter
91 | source: sdk
92 | version: "0.0.0"
93 | flutter_lints:
94 | dependency: "direct dev"
95 | description:
96 | name: flutter_lints
97 | url: "https://pub.flutter-io.cn"
98 | source: hosted
99 | version: "2.0.1"
100 | flutter_live_activities:
101 | dependency: "direct main"
102 | description:
103 | path: ".."
104 | relative: true
105 | source: path
106 | version: "0.0.5"
107 | flutter_test:
108 | dependency: "direct dev"
109 | description: flutter
110 | source: sdk
111 | version: "0.0.0"
112 | http:
113 | dependency: transitive
114 | description:
115 | name: http
116 | url: "https://pub.flutter-io.cn"
117 | source: hosted
118 | version: "0.13.5"
119 | http_client_helper:
120 | dependency: transitive
121 | description:
122 | name: http_client_helper
123 | url: "https://pub.flutter-io.cn"
124 | source: hosted
125 | version: "2.0.3"
126 | http_parser:
127 | dependency: transitive
128 | description:
129 | name: http_parser
130 | url: "https://pub.flutter-io.cn"
131 | source: hosted
132 | version: "4.0.2"
133 | lints:
134 | dependency: transitive
135 | description:
136 | name: lints
137 | url: "https://pub.flutter-io.cn"
138 | source: hosted
139 | version: "2.0.1"
140 | matcher:
141 | dependency: transitive
142 | description:
143 | name: matcher
144 | url: "https://pub.flutter-io.cn"
145 | source: hosted
146 | version: "0.12.12"
147 | material_color_utilities:
148 | dependency: transitive
149 | description:
150 | name: material_color_utilities
151 | url: "https://pub.flutter-io.cn"
152 | source: hosted
153 | version: "0.1.5"
154 | meta:
155 | dependency: transitive
156 | description:
157 | name: meta
158 | url: "https://pub.flutter-io.cn"
159 | source: hosted
160 | version: "1.8.0"
161 | path:
162 | dependency: "direct main"
163 | description:
164 | name: path
165 | url: "https://pub.flutter-io.cn"
166 | source: hosted
167 | version: "1.8.2"
168 | path_provider:
169 | dependency: "direct main"
170 | description:
171 | name: path_provider
172 | url: "https://pub.flutter-io.cn"
173 | source: hosted
174 | version: "2.0.11"
175 | path_provider_android:
176 | dependency: transitive
177 | description:
178 | name: path_provider_android
179 | url: "https://pub.flutter-io.cn"
180 | source: hosted
181 | version: "2.0.21"
182 | path_provider_ios:
183 | dependency: transitive
184 | description:
185 | name: path_provider_ios
186 | url: "https://pub.flutter-io.cn"
187 | source: hosted
188 | version: "2.0.11"
189 | path_provider_linux:
190 | dependency: transitive
191 | description:
192 | name: path_provider_linux
193 | url: "https://pub.flutter-io.cn"
194 | source: hosted
195 | version: "2.1.7"
196 | path_provider_macos:
197 | dependency: transitive
198 | description:
199 | name: path_provider_macos
200 | url: "https://pub.flutter-io.cn"
201 | source: hosted
202 | version: "2.0.6"
203 | path_provider_platform_interface:
204 | dependency: transitive
205 | description:
206 | name: path_provider_platform_interface
207 | url: "https://pub.flutter-io.cn"
208 | source: hosted
209 | version: "2.0.5"
210 | path_provider_windows:
211 | dependency: transitive
212 | description:
213 | name: path_provider_windows
214 | url: "https://pub.flutter-io.cn"
215 | source: hosted
216 | version: "2.1.3"
217 | platform:
218 | dependency: transitive
219 | description:
220 | name: platform
221 | url: "https://pub.flutter-io.cn"
222 | source: hosted
223 | version: "3.1.0"
224 | plugin_platform_interface:
225 | dependency: transitive
226 | description:
227 | name: plugin_platform_interface
228 | url: "https://pub.flutter-io.cn"
229 | source: hosted
230 | version: "2.1.3"
231 | process:
232 | dependency: transitive
233 | description:
234 | name: process
235 | url: "https://pub.flutter-io.cn"
236 | source: hosted
237 | version: "4.2.4"
238 | sky_engine:
239 | dependency: transitive
240 | description: flutter
241 | source: sdk
242 | version: "0.0.99"
243 | source_span:
244 | dependency: transitive
245 | description:
246 | name: source_span
247 | url: "https://pub.flutter-io.cn"
248 | source: hosted
249 | version: "1.9.0"
250 | stack_trace:
251 | dependency: transitive
252 | description:
253 | name: stack_trace
254 | url: "https://pub.flutter-io.cn"
255 | source: hosted
256 | version: "1.10.0"
257 | stream_channel:
258 | dependency: transitive
259 | description:
260 | name: stream_channel
261 | url: "https://pub.flutter-io.cn"
262 | source: hosted
263 | version: "2.1.0"
264 | string_scanner:
265 | dependency: transitive
266 | description:
267 | name: string_scanner
268 | url: "https://pub.flutter-io.cn"
269 | source: hosted
270 | version: "1.1.1"
271 | term_glyph:
272 | dependency: transitive
273 | description:
274 | name: term_glyph
275 | url: "https://pub.flutter-io.cn"
276 | source: hosted
277 | version: "1.2.1"
278 | test_api:
279 | dependency: transitive
280 | description:
281 | name: test_api
282 | url: "https://pub.flutter-io.cn"
283 | source: hosted
284 | version: "0.4.12"
285 | typed_data:
286 | dependency: transitive
287 | description:
288 | name: typed_data
289 | url: "https://pub.flutter-io.cn"
290 | source: hosted
291 | version: "1.3.1"
292 | vector_math:
293 | dependency: transitive
294 | description:
295 | name: vector_math
296 | url: "https://pub.flutter-io.cn"
297 | source: hosted
298 | version: "2.1.2"
299 | win32:
300 | dependency: transitive
301 | description:
302 | name: win32
303 | url: "https://pub.flutter-io.cn"
304 | source: hosted
305 | version: "3.1.1"
306 | xdg_directories:
307 | dependency: transitive
308 | description:
309 | name: xdg_directories
310 | url: "https://pub.flutter-io.cn"
311 | source: hosted
312 | version: "0.2.0+2"
313 | sdks:
314 | dart: ">=2.18.2 <3.0.0"
315 | flutter: ">=3.3.0"
316 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_live_activities_example
2 | description: Demonstrates how to use the flutter_live_activities plugin.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `flutter pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | environment:
9 | sdk: '>=2.18.2 <3.0.0'
10 |
11 | # Dependencies specify other packages that your package needs in order to work.
12 | # To automatically upgrade your package dependencies to the latest versions
13 | # consider running `flutter pub upgrade --major-versions`. Alternatively,
14 | # dependencies can be manually updated by changing the version numbers below to
15 | # the latest version available on pub.dev. To see which dependencies have newer
16 | # versions available, run `flutter pub outdated`.
17 | dependencies:
18 | flutter:
19 | sdk: flutter
20 |
21 | flutter_live_activities:
22 | # When depending on this package from a real application you should use:
23 | # flutter_live_activities: ^x.y.z
24 | # See https://dart.dev/tools/pub/dependencies#version-constraints
25 | # The example app is bundled with the plugin so we use a path dependency on
26 | # the parent directory to use the current plugin's version.
27 | path: ../
28 |
29 | # The following adds the Cupertino Icons font to your application.
30 | # Use with the CupertinoIcons class for iOS style icons.
31 | cupertino_icons: ^1.0.2
32 | extended_image: ^6.3.2
33 | path: ^1.8.2
34 | path_provider: ^2.0.11
35 |
36 | dev_dependencies:
37 | flutter_test:
38 | sdk: flutter
39 |
40 | # The "flutter_lints" package below contains a set of recommended lints to
41 | # encourage good coding practices. The lint set provided by the package is
42 | # activated in the `analysis_options.yaml` file located at the root of your
43 | # package. See that file for information about deactivating specific lint
44 | # rules and activating additional ones.
45 | flutter_lints: ^2.0.0
46 |
47 | # For information on the generic Dart part of this file, see the
48 | # following page: https://dart.dev/tools/pub/pubspec
49 |
50 | # The following section is specific to Flutter packages.
51 | flutter:
52 |
53 | # The following line ensures that the Material Icons font is
54 | # included with your application, so that you can use the icons in
55 | # the material Icons class.
56 | uses-material-design: true
57 |
58 | # To add assets to your application, add an assets section, like this:
59 | # assets:
60 | # - images/a_dot_burr.jpeg
61 | # - images/a_dot_ham.jpeg
62 |
63 | # An image asset can refer to one or more resolution-specific "variants", see
64 | # https://flutter.dev/assets-and-images/#resolution-aware
65 |
66 | # For details regarding adding assets from package dependencies, see
67 | # https://flutter.dev/assets-and-images/#from-packages
68 |
69 | # To add custom fonts to your application, add a fonts section here,
70 | # in this "flutter" section. Each entry in this list should have a
71 | # "family" key with the font family name, and a "fonts" key with a
72 | # list giving the asset and other descriptors for the font. For
73 | # example:
74 | # fonts:
75 | # - family: Schyler
76 | # fonts:
77 | # - asset: fonts/Schyler-Regular.ttf
78 | # - asset: fonts/Schyler-Italic.ttf
79 | # style: italic
80 | # - family: Trajan Pro
81 | # fonts:
82 | # - asset: fonts/TrajanPro.ttf
83 | # - asset: fonts/TrajanPro_Bold.ttf
84 | # weight: 700
85 | #
86 | # For details regarding fonts from package dependencies,
87 | # see https://flutter.dev/custom-fonts/#from-packages
88 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 | /Flutter/ephemeral/
38 | /Flutter/flutter_export_environment.sh
--------------------------------------------------------------------------------
/ios/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluttercandies/flutter_live_activities/b0c2c0c27df7349b84361b2ed00c0bbfa9e5ed76/ios/Assets/.gitkeep
--------------------------------------------------------------------------------
/ios/Classes/FlutterLiveActivities.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FlutterLiveActivities.swift
3 | // flutter_live_activities
4 | //
5 | // Created by Mike on 2022/11/4.
6 | //
7 |
8 | import ActivityKit
9 |
10 | struct FlutterLiveActivities: ActivityAttributes, Identifiable {
11 | public typealias LiveData = ContentState
12 |
13 | public struct ContentState: Codable, Hashable {
14 | var data: [String: String]
15 | }
16 |
17 | var id = UUID()
18 | }
19 |
--------------------------------------------------------------------------------
/ios/Classes/FlutterLiveActivitiesPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface FlutterLiveActivitiesPlugin : NSObject
4 | @end
5 |
--------------------------------------------------------------------------------
/ios/Classes/FlutterLiveActivitiesPlugin.m:
--------------------------------------------------------------------------------
1 | #import "FlutterLiveActivitiesPlugin.h"
2 | #if __has_include()
3 | #import
4 | #else
5 | // Support project import fallback if the generated compatibility header
6 | // is not copied when this plugin is created as a library.
7 | // https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816
8 | #import "flutter_live_activities-Swift.h"
9 | #endif
10 |
11 | @implementation FlutterLiveActivitiesPlugin
12 | + (void)registerWithRegistrar:(NSObject*)registrar {
13 | [SwiftFlutterLiveActivitiesPlugin registerWithRegistrar:registrar];
14 | }
15 | @end
16 |
--------------------------------------------------------------------------------
/ios/Classes/SwiftFlutterLiveActivitiesPlugin.swift:
--------------------------------------------------------------------------------
1 | import ActivityKit
2 | import Flutter
3 | import UIKit
4 |
5 | public class SwiftFlutterLiveActivitiesPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
6 | private var eventSink: FlutterEventSink?
7 | private var urlScheme: String?
8 |
9 | private var initialUrl: URL?
10 |
11 | public static func register(with registrar: FlutterPluginRegistrar) {
12 | let channel = FlutterMethodChannel(name: "flutter_live_activities", binaryMessenger: registrar.messenger())
13 | let eventChannel = FlutterEventChannel(name: "flutter_live_activities/event", binaryMessenger: registrar.messenger())
14 |
15 | let instance = SwiftFlutterLiveActivitiesPlugin()
16 | registrar.addMethodCallDelegate(instance, channel: channel)
17 | eventChannel.setStreamHandler(instance)
18 | registrar.addApplicationDelegate(instance)
19 | }
20 |
21 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
22 | if #available(iOS 16.1, *) {
23 | switch call.method {
24 | case "init":
25 | guard let args = call.arguments as? [String: Any] else {
26 | return
27 | }
28 | if let scheme = args["urlScheme"] as? String {
29 | urlScheme = scheme
30 | } else {
31 | result(FlutterError(code: "DATA_ERROR", message: "'liveId' is invalid", details: nil))
32 | }
33 | case "getInitUri":
34 | result(initialUrl?.absoluteString)
35 | case "createActivity":
36 | guard let args = call.arguments as? [String: Any] else {
37 | return
38 | }
39 | if let data = args["data"] as? [String: String] {
40 | createActivity(data: data, result: result)
41 | } else {
42 | result(FlutterError(code: "DATA_ERROR", message: "'data' is invalid", details: nil))
43 | }
44 | case "updateActivity":
45 | guard let args = call.arguments as? [String: Any] else {
46 | return
47 | }
48 | if let liveId = args["liveId"] as? String, let data = args["data"] as? [String: String] {
49 | updateActivity(liveId: liveId, data: data, result: result)
50 | } else {
51 | result(FlutterError(code: "DATA_ERROR", message: "'data' or 'liveId' is invalid", details: nil))
52 | }
53 | case "endActivity":
54 | guard let args = call.arguments as? [String: Any] else {
55 | return
56 | }
57 | if let liveId = args["liveId"] as? String {
58 | endActivity(liveId: liveId, result: result)
59 | } else {
60 | result(FlutterError(code: "DATA_ERROR", message: "'liveId' is invalid", details: nil))
61 | }
62 | case "getAllActivities":
63 | getAllActivities(result: result)
64 | case "endAllActivities":
65 | endAllActivities(result: result)
66 | case "getActivityState":
67 | guard let args = call.arguments as? [String: Any] else {
68 | return
69 | }
70 |
71 | if let liveId = args["liveId"] as? String {
72 | getActivityState(liveId: liveId, result: result)
73 | } else {
74 | result(FlutterError(code: "DATA_ERROR", message: "'liveId' is invalid", details: nil))
75 | }
76 |
77 | case "areActivitiesEnabled":
78 | areActivitiesEnabled(result: result)
79 | case "sendImageToGroup":
80 | guard let args = call.arguments as? [String: Any] else {
81 | result(FlutterError(code: "DATA_ERROR", message: "parameter is invalid", details: nil))
82 | return
83 | }
84 |
85 | if let data = args as? [String: String] {
86 | receiveImage(data: data, result: result)
87 | } else {
88 | result(FlutterError(code: "DATA_ERROR", message: "parameter is invalid", details: nil))
89 | }
90 |
91 | default:
92 | break
93 | }
94 | } else {
95 | print("This iOS version is not supported")
96 | result(nil)
97 | }
98 | }
99 |
100 | @available(iOS 16.1, *)
101 | func createActivity(data: [String: String], result: @escaping FlutterResult) {
102 | let attributes = FlutterLiveActivities()
103 | let contentState = FlutterLiveActivities.LiveData(data: data)
104 |
105 | do {
106 | let activity = try Activity.request(
107 | attributes: attributes,
108 | contentState: contentState,
109 | pushType: nil)
110 | result(activity.id)
111 | } catch {
112 | result(FlutterError(code: "LIVE_ACTIVITY_LAUNCH_ERROR", message: "launch live activity error", details: error.localizedDescription))
113 | }
114 | }
115 |
116 | @available(iOS 16.1, *)
117 | func updateActivity(liveId: String, data: [String: String], result: @escaping FlutterResult) {
118 | Task {
119 | for activity in Activity.activities {
120 | if liveId == activity.id {
121 | let updatedStatus: FlutterLiveActivities.LiveData = .init(data: data)
122 | await activity.update(using: updatedStatus)
123 | result(true)
124 | return
125 | }
126 | }
127 |
128 | result(false)
129 | }
130 | }
131 |
132 | @available(iOS 16.1, *)
133 | func endActivity(liveId: String, result: @escaping FlutterResult) {
134 | Task {
135 | for activity in Activity.activities {
136 | if liveId == activity.id {
137 | await activity.end(dismissalPolicy: .immediate)
138 | result(true)
139 | return
140 | }
141 | }
142 |
143 | result(false)
144 | }
145 | }
146 |
147 | @available(iOS 16.1, *)
148 | func getActivityState(liveId: String, result: @escaping FlutterResult) {
149 | Task {
150 | for activity in Activity.activities {
151 | if liveId == activity.id {
152 | switch activity.activityState {
153 | case .active:
154 | result(0)
155 | case .ended:
156 | result(1)
157 | case .dismissed:
158 | result(2)
159 | @unknown default:
160 | result(3)
161 | }
162 | break
163 | }
164 | }
165 | }
166 | }
167 |
168 | @available(iOS 16.1, *)
169 | func getAllActivities(result: @escaping FlutterResult) {
170 | var list: [String] = []
171 | for activity in Activity.activities {
172 | list.append(activity.id)
173 | }
174 | result(list.joined(separator: ","))
175 | }
176 |
177 | @available(iOS 16.1, *)
178 | func endAllActivities(result: @escaping FlutterResult) {
179 | Task {
180 | for activity in Activity.activities {
181 | await activity.end(dismissalPolicy: .immediate)
182 | }
183 |
184 | result(true)
185 | }
186 | }
187 |
188 | @available(iOS 16.1, *)
189 | func areActivitiesEnabled(result: @escaping FlutterResult) {
190 | var hasAuthorization = true
191 | let center = UNUserNotificationCenter.current()
192 |
193 | center.requestAuthorization(options: [.alert, .sound, .badge]) { _, error in
194 | if let error = error {
195 | hasAuthorization = false
196 | result(FlutterError(code: "AUTHORIZATION_ERROR", message: "authorization error", details: error.localizedDescription))
197 | }
198 | }
199 |
200 | result(ActivityAuthorizationInfo().areActivitiesEnabled && hasAuthorization)
201 | }
202 |
203 | @available(iOS 16.0, *)
204 | private func receiveImage(data: [String: String], result: @escaping FlutterResult) {
205 | guard var groupId = data["groupId"]
206 | else {
207 | result(FlutterError(code: "DATA_ERROR", message: "no groupId", details: nil))
208 | return
209 | }
210 |
211 | guard var destination = FileManager.default.containerURL(
212 | forSecurityApplicationGroupIdentifier: groupId)
213 | else {
214 | result(FlutterError(code: "DATA_ERROR", message: "no group", details: nil))
215 | return
216 | }
217 |
218 | do {
219 | if let id = data["id"], let path = data["filePath"] {
220 | destination = destination.appendingPathComponent(id)
221 |
222 | do {
223 | try FileManager.default.removeItem(at: destination)
224 | } catch {
225 | print(error.localizedDescription)
226 | }
227 |
228 | try FileManager.default.moveItem(at: URL(filePath: path), to: destination)
229 |
230 | result(true)
231 | }
232 | } catch {
233 | result(FlutterError(code: "OP_ERROR", message: "receiveImage error", details: error.localizedDescription))
234 | return
235 | }
236 | }
237 |
238 | public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
239 | eventSink = events
240 | return nil
241 | }
242 |
243 | public func onCancel(withArguments arguments: Any?) -> FlutterError? {
244 | eventSink = nil
245 | return nil
246 | }
247 |
248 | public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [AnyHashable: Any] = [:]) -> Bool {
249 | let launchUrl = (launchOptions[UIApplication.LaunchOptionsKey.url] as? NSURL)?.absoluteURL
250 |
251 | if launchUrl != nil {
252 | initialUrl = launchUrl?.absoluteURL
253 | }
254 |
255 | return true
256 | }
257 |
258 | public func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
259 | if isLiveActivitiesUrl(url: url) {
260 | eventSink?.self(url.absoluteString)
261 | return true
262 | }
263 | return false
264 | }
265 |
266 | private func isLiveActivitiesUrl(url: URL) -> Bool {
267 | let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
268 |
269 | if components?.scheme == nil { return false }
270 |
271 | return urlScheme == components?.scheme
272 | }
273 | }
274 |
--------------------------------------------------------------------------------
/ios/flutter_live_activities.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint flutter_live_activities.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'flutter_live_activities'
7 | s.version = '0.0.1'
8 | s.summary = 'A Flutter plugin for Live Activities.'
9 | s.description = <<-DESC
10 | A new Flutter project.
11 | DESC
12 | s.homepage = 'https://github.com/fluttercandies/flutter_live_activities'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'NONE' => 'l18281145312@gmail.com' }
15 | s.source = { :path => '.' }
16 | s.source_files = 'Classes/**/*'
17 | s.dependency 'Flutter'
18 | s.platform = :ios, '9.0'
19 |
20 | # Flutter.framework does not contain a i386 slice.
21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
22 | s.swift_version = '5.0'
23 | end
24 |
--------------------------------------------------------------------------------
/lib/flutter_live_activities.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'flutter_live_activities_platform_interface.dart';
4 |
5 | bool _isAndroid = Platform.isAndroid;
6 |
7 | class FlutterLiveActivities {
8 | FlutterLiveActivities({this.urlScheme = 'fla'}) {
9 | if (!_isAndroid) FlutterLiveActivitiesPlatform.instance.init(urlScheme);
10 | }
11 |
12 | /// The url scheme used to interact with the native platform.
13 | final String urlScheme;
14 |
15 | /// Get launch uri
16 | Future getInitUri() async {
17 | if (_isAndroid) return null;
18 |
19 | final Uri? url = await FlutterLiveActivitiesPlatform.instance.getInitUri();
20 | if (url?.isScheme(urlScheme) ?? false) return url;
21 | return null;
22 | }
23 |
24 | /// Get all activities id
25 | Future> getAllActivities() async {
26 | if (_isAndroid) return [];
27 |
28 | return FlutterLiveActivitiesPlatform.instance.getAllActivities();
29 | }
30 |
31 | /// Create an iOS 16.1+ live activity.
32 | /// When the activity is created, an activity id is returned.
33 | /// Data is a map of key/value pairs that will be transmitted to your iOS extension widget.
34 | /// Map is limited to String keys and values for now.
35 | Future createActivity(Map data) async {
36 | if (_isAndroid) return null;
37 |
38 | return FlutterLiveActivitiesPlatform.instance.createActivity(data);
39 | }
40 |
41 | /// Update an iOS 16.1+ live activity.
42 | /// You can get an activity id by calling [createActivity].
43 | /// Data is a map of key/value pairs that will be transmitted to your iOS extension widget.
44 | /// Map is limited to String keys and values for now.
45 | Future updateActivity(String liveId, Map data) async {
46 | if (_isAndroid) return false;
47 |
48 | return FlutterLiveActivitiesPlatform.instance.updateActivity(liveId, data);
49 | }
50 |
51 | /// End an iOS 16.1+ live activity.
52 | /// You can get an activity id by calling [createActivity].
53 | Future endActivity(String liveId) async {
54 | if (_isAndroid) return false;
55 |
56 | return FlutterLiveActivitiesPlatform.instance.endActivity(liveId);
57 | }
58 |
59 | /// End an iOS 16.1+ live activity.
60 | /// You can get an activity id by calling [createActivity].
61 | Future endAllActivities() async {
62 | if (_isAndroid) return false;
63 |
64 | return FlutterLiveActivitiesPlatform.instance.endAllActivities();
65 | }
66 |
67 | /// Check if iOS 16.1+ live activities are enabled.
68 | /// If they are not enabled, you will not be able to create activities.
69 | Future areActivitiesEnabled() async {
70 | if (_isAndroid) return false;
71 |
72 | return FlutterLiveActivitiesPlatform.instance.areActivitiesEnabled();
73 | }
74 |
75 | /// Get the state of an iOS 16.1+ live activity.
76 | Stream uriStream() {
77 | if (_isAndroid) return const Stream.empty();
78 |
79 | return FlutterLiveActivitiesPlatform.instance.uriStream();
80 | }
81 |
82 | /// Send to Group space
83 | Future sendImageToGroup({
84 | required String id,
85 | required String filePath,
86 | required String groupId,
87 | }) async {
88 | if (_isAndroid) return false;
89 |
90 | return FlutterLiveActivitiesPlatform.instance.sendImageToGroup(
91 | id: id,
92 | filePath: filePath,
93 | groupId: groupId,
94 | );
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/lib/flutter_live_activities_method_channel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/services.dart';
2 |
3 | import 'flutter_live_activities_platform_interface.dart';
4 | import 'src/live_activities_status.dart';
5 |
6 | /// An implementation of [FlutterLiveActivitiesPlatform] that uses method channels.
7 | class MethodChannelFlutterLiveActivities extends FlutterLiveActivitiesPlatform {
8 | /// The method channel used to interact with the native platform.
9 | final MethodChannel _methodChannel =
10 | const MethodChannel('flutter_live_activities');
11 | final EventChannel _eventChannel =
12 | const EventChannel('flutter_live_activities/event');
13 |
14 | @override
15 | void init(String urlScheme) {
16 | _methodChannel.invokeMethod('init', {
17 | 'urlScheme': urlScheme,
18 | });
19 | }
20 |
21 | @override
22 | Future getInitUri() async {
23 | try {
24 | return Uri.tryParse(
25 | await _methodChannel.invokeMethod('getInitUri') ?? '');
26 | } catch (e) {
27 | return null;
28 | }
29 | }
30 |
31 | @override
32 | Future> getAllActivities() async {
33 | try {
34 | final String? data =
35 | await _methodChannel.invokeMethod('getAllActivities');
36 | if (data == null) return [];
37 | return data.split(',');
38 | } catch (e) {
39 | return [];
40 | }
41 | }
42 |
43 | @override
44 | Future createActivity(Map data) async {
45 | return _methodChannel.invokeMethod(
46 | 'createActivity', {'data': data});
47 | }
48 |
49 | @override
50 | Future updateActivity(String liveId, Map data) async {
51 | return await _methodChannel.invokeMethod('updateActivity',
52 | {'liveId': liveId, 'data': data}) ??
53 | false;
54 | }
55 |
56 | @override
57 | Future endActivity(String liveId) async {
58 | return await _methodChannel
59 | .invokeMethod('endActivity', {
60 | 'liveId': liveId,
61 | }) ??
62 | false;
63 | }
64 |
65 | @override
66 | Future getActivityState(String liveId) async {
67 | try {
68 | final int? data = await _methodChannel
69 | .invokeMethod('getActivityState', {
70 | 'liveId': liveId,
71 | });
72 |
73 | return LiveActivitiesState.values[data ?? 3];
74 | } catch (e) {
75 | return LiveActivitiesState.unknown;
76 | }
77 | }
78 |
79 | @override
80 | Future endAllActivities() async {
81 | return await _methodChannel.invokeMethod('endAllActivities') ?? false;
82 | }
83 |
84 | @override
85 | Future areActivitiesEnabled() async {
86 | try {
87 | return (await _methodChannel
88 | .invokeMethod('areActivitiesEnabled')) ??
89 | false;
90 | } catch (e) {
91 | return false;
92 | }
93 | }
94 |
95 | @override
96 | Stream uriStream() {
97 | return _eventChannel.receiveBroadcastStream().map((dynamic eve) {
98 | return Uri.tryParse(eve.toString());
99 | });
100 | }
101 |
102 | @override
103 | Future sendImageToGroup({
104 | required String id,
105 | required String filePath,
106 | required String groupId,
107 | }) async {
108 | return await _methodChannel
109 | .invokeMethod('sendImageToGroup', {
110 | 'id': id,
111 | 'filePath': filePath,
112 | 'groupId': groupId,
113 | }) ??
114 | false;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/lib/flutter_live_activities_platform_interface.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_live_activities/src/live_activities_status.dart';
2 | import 'package:plugin_platform_interface/plugin_platform_interface.dart';
3 |
4 | import 'flutter_live_activities_method_channel.dart';
5 |
6 | abstract class FlutterLiveActivitiesPlatform extends PlatformInterface {
7 | /// Constructs a FlutterLiveActivitiesPlatform.
8 | FlutterLiveActivitiesPlatform() : super(token: _token);
9 |
10 | static final Object _token = Object();
11 |
12 | static FlutterLiveActivitiesPlatform _instance =
13 | MethodChannelFlutterLiveActivities();
14 |
15 | /// The default instance of [FlutterLiveActivitiesPlatform] to use.
16 | ///
17 | /// Defaults to [MethodChannelFlutterLiveActivities].
18 | static FlutterLiveActivitiesPlatform get instance => _instance;
19 |
20 | /// Platform-specific implementations should set this with their own
21 | /// platform-specific class that extends [FlutterLiveActivitiesPlatform] when
22 | /// they register themselves.
23 | static set instance(FlutterLiveActivitiesPlatform instance) {
24 | PlatformInterface.verifyToken(instance, _token);
25 | _instance = instance;
26 | }
27 |
28 | void init(String urlScheme) {
29 | throw UnimplementedError('init() has not been implemented.');
30 | }
31 |
32 | Future getInitUri() {
33 | throw UnimplementedError('getInitUri() has not been implemented.');
34 | }
35 |
36 | Future> getAllActivities() {
37 | throw UnimplementedError('getAllActivities() has not been implemented.');
38 | }
39 |
40 | Future createActivity(Map data) {
41 | throw UnimplementedError('createActivity() has not been implemented.');
42 | }
43 |
44 | Future updateActivity(String liveId, Map data) {
45 | throw UnimplementedError('updateActivity() has not been implemented.');
46 | }
47 |
48 | Future endActivity(String liveId) {
49 | throw UnimplementedError('endActivity() has not been implemented.');
50 | }
51 |
52 | Future getActivityState(String liveId) async {
53 | throw UnimplementedError('getActivityState() has not been implemented.');
54 | }
55 |
56 | Future endAllActivities() {
57 | throw UnimplementedError('endAllActivity() has not been implemented.');
58 | }
59 |
60 | Future areActivitiesEnabled() {
61 | throw UnimplementedError(
62 | 'areActivitiesEnabled() has not been implemented.');
63 | }
64 |
65 | Stream uriStream() {
66 | throw UnimplementedError('uriStream() has not been implemented.');
67 | }
68 |
69 | Future sendImageToGroup({
70 | required String id,
71 | required String filePath,
72 | required String groupId,
73 | }) {
74 | throw UnimplementedError('sendImageToGroup() has not been implemented.');
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/src/live_activities_status.dart:
--------------------------------------------------------------------------------
1 | /// LiveActivitiesState
2 | /// * [active] : The Live Activity is active, visible to the user, and can receive content updates.
3 | /// * [ended] : The Live Activity is visible, but the user, app, or system ended it, and it won't update its content anymore.
4 | /// * [dismissed] : The Live Activity ended and is no longer visible because the user or the system removed it.
5 | /// * [unknown]
6 | enum LiveActivitiesState { active, ended, dismissed, unknown }
7 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_live_activities
2 | description: Flutter plugin for Live Activities. Use to create, update and handling action for [DynamicIsland UI] and [Lock screen/banner UI]
3 | version: 0.0.5
4 | homepage: https://github.com/fluttercandies/flutter_live_activities
5 |
6 | environment:
7 | sdk: '>=2.18.2 <3.0.0'
8 | flutter: ">=2.5.0"
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | plugin_platform_interface: ^2.0.2
14 |
15 | dev_dependencies:
16 | flutter_test:
17 | sdk: flutter
18 | flutter_lints: ^2.0.0
19 |
20 | # For information on the generic Dart part of this file, see the
21 | # following page: https://dart.dev/tools/pub/pubspec
22 |
23 | # The following section is specific to Flutter packages.
24 | flutter:
25 | # This section identifies this Flutter project as a plugin project.
26 | # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
27 | # which should be registered in the plugin registry. This is required for
28 | # using method channels.
29 | # The Android 'package' specifies package in which the registered class is.
30 | # This is required for using method channels on Android.
31 | # The 'ffiPlugin' specifies that native code should be built and bundled.
32 | # This is required for using `dart:ffi`.
33 | # All these are used by the tooling to maintain consistency when
34 | # adding or updating assets for this project.
35 | plugin:
36 | platforms:
37 | ios:
38 | pluginClass: FlutterLiveActivitiesPlugin
39 |
40 | # To add assets to your plugin package, add an assets section, like this:
41 | # assets:
42 | # - images/a_dot_burr.jpeg
43 | # - images/a_dot_ham.jpeg
44 | #
45 | # For details regarding assets in packages, see
46 | # https://flutter.dev/assets-and-images/#from-packages
47 | #
48 | # An image asset can refer to one or more resolution-specific "variants", see
49 | # https://flutter.dev/assets-and-images/#resolution-aware
50 |
51 | # To add custom fonts to your plugin package, add a fonts section here,
52 | # in this "flutter" section. Each entry in this list should have a
53 | # "family" key with the font family name, and a "fonts" key with a
54 | # list giving the asset and other descriptors for the font. For
55 | # example:
56 | # fonts:
57 | # - family: Schyler
58 | # fonts:
59 | # - asset: fonts/Schyler-Regular.ttf
60 | # - asset: fonts/Schyler-Italic.ttf
61 | # style: italic
62 | # - family: Trajan Pro
63 | # fonts:
64 | # - asset: fonts/TrajanPro.ttf
65 | # - asset: fonts/TrajanPro_Bold.ttf
66 | # weight: 700
67 | #
68 | # For details regarding fonts in packages, see
69 | # https://flutter.dev/custom-fonts/#from-packages
70 |
--------------------------------------------------------------------------------