我是廣告,點擊一下吧!
標籤
#Flutter (15) 、 #PHP (9) 、 #Laravel (7) 、 #Dart (5) 、 #MySQL (5) 、 #Mac (4) 、 #VS Code (2) 、 #IDE (2) 、 #List (2) 、 #Android (2) 、 #Carbon (2) 、 #Linux (2) 、 #Shell Script (2) 、 #MySQL 效能 (1) 、 #Pagination (1) 、 #Cursor Pagination (1) 、 #LaTeX (1) 、 #個人空間 (1) 、 #Android Splash Screen (1) 、 #createFromTimestamp (1) 、 #資安 (1) 、 #Google Maps Static API (1) 、 #Mac M1 (1) 、 #floorMonth (1) 、 #subMonthNoOverflow (1) 、 #addMonthNoOverflow (1) 、 #subMonth (1) 、 #addMonth (1) 、 #keytool (1) 、 #Play App Signing (1)使用 https://pub.dev/packages/live_activities。
需要寫一些 Swift,這篇文章主要介紹我使用時遇到的問題跟要注意的事項。
1. 建立 Widget Extension 時不要勾選 Include Configuration App Intent
2. swift 的 LiveActivitiesAppAttributes 命名不可修改
Inside your extension ExtensionNameLiveActivity.swift file, you need to create an ActivityAttributes called EXACTLY LiveActivitiesAppAttributes (if you rename, activity will be created but not appear!)
3. Runner 與 Widget Extension 都要新增 NSSupportsLiveActivities
<key>NSSupportsLiveActivities</key>
<true></true>
4. 注意 Widget Extension 的 Minimum Deployments 要符合你的裝置,且要大於等於 16.1,否則完全不會有作用也不會有錯誤訊息!他預設是 17.1,這點我卡了最久,因為完全沒有訊息,點擊動態島又會正常回到 APP,所以一直以為是哪裡寫錯導致 UI 沒出來。
5. Cycle inside Runner
遇到 I have an issue when building my app on iOS: Error (Xcode): Cycle inside Runner; building could produce unreliable results.
調整 Runner 的 Build Phases:Copy Bundle Resources
> Embed Foundation Extensions
> Thin Binary
6. 程式更新與推播更新的資料取得方式不同
Flutter createActivity
跟 updateActivity
給的 data 要用 sharedDefault.string(forKey: context.attributes.prefixedKey("key_name"))
取得
推播的資料取得需實作 LiveActivitiesAppAttributes
的 ContentState
才有資料
struct LiveActivitiesAppAttributes: ActivityAttributes, Identifiable {
public typealias LiveDeliveryData = ContentState // don't forget to add this line, otherwise, live activity will not display it.
public struct ContentState: Codable, Hashable {
let heading: String?
}
var id = UUID()
}
extension LiveActivitiesAppAttributes {
func prefixedKey(_ key: String) -> String {
return "\(id)_\(key)"
}
}
let sharedDefault = UserDefaults(suiteName: "group.joymap.com")!
struct LiveWidgetLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
// Flutter createActivity 跟 updateActivity 用這個拿
let heading = sharedDefault.string(forKey: context.attributes.prefixedKey("heading"))!
// 取得目前的時間戳,方便查看是否有收到推播
let currentTimestamp = Date().timeIntervalSince1970
// Lock screen/banner UI goes here
VStack {
Text(context.state.heading ?? "")
Text("Update Timestamp: \(currentTimestamp)")
}
.activityBackgroundTint(Color.cyan)
.activitySystemActionForegroundColor(Color.black)
}
......
推播更新我是使用 FCM 不走原生 APNs,測試時可用https://developers.google.com/oauthplayground 產生 Google OAuth Access Token。
結構文件: https://firebase.google.com/docs/cloud-messaging/ios/live-activity?hl=zh-TW
FCM v1 messages:send Body
{
"message":{
"token": "<FCM_PUSH_TOKEN>",
"notification":{
"title":"test",
"body":"test test"
},
"data":{},
// Android
"android": {
"notification": {
"notification_count": 3
}
},
// iOS
"apns": {
"live_activity_token": "<https://pub.dev/packages/live_activities#update-live-activity-with-push-notification>",
"headers": {
"apns-priority": "5"
},
"payload": {
"aps": {
"timestamp": {{$timestamp}},
"event": "update",
"content-state": {
"heading": ""
},
"alert": {
"title": "test",
"body": "test test"
},
"badge":4
}
}
}
}
}
// 從 Flutter live_activity_token 取得方式
// 開發者不建議使用,可能會隨時更新
final activityToken = await _liveActivitiesPlugin.getPushToken(_activityId!);
// 或是
_liveActivitiesPlugin.activityUpdateStream.listen((event) {
event.map(
active: (activity) {
// Get the token
print(activity.activityToken);
},
stale: (activity) {},
ended: (activity) {},
unknown: (activity) {},
);
});