ap_common_plugin 1.0.1-dev.5 copy "ap_common_plugin: ^1.0.1-dev.5" to clipboard
ap_common_plugin: ^1.0.1-dev.5 copied to clipboard

ap_common Native Plugin

ap_common_plugin #

pub.dev melos

校務通系列 Native Plugin,提供課表桌面小工具(App Widget)功能。

支援平台 #

功能 Android iOS macOS Web
課表小工具

安裝 #

dependencies:
  ap_common_plugin: ^1.0.1-dev.3

使用方式 #

1. 初始化(iOS 必要) #

在 app 啟動時呼叫 configure,設定 App Group ID 以供 WidgetKit extension 讀取資料。Android 會忽略此設定。

import 'package:ap_common_plugin/ap_common_plugin.dart';

// 在 main() 或 app 初始化時
if (!kIsWeb && (Platform.isIOS || Platform.isMacOS)) {
  await ApCommonPlugin.configure(appGroupId: 'group.com.yourapp.id');
}

2. 更新課表小工具 #

取得課表資料後,呼叫 updateCourseWidget 推送至原生小工具:

final CourseData courseData = await fetchCourseData();
await ApCommonPlugin.updateCourseWidget(courseData);
  • Android:寫入 SharedPreferences,觸發 AppWidgetManager 更新
  • iOS:寫入 App Group UserDefaults,觸發 WidgetCenter.reloadAllTimelines()

3. 清除課表小工具 #

登出或需要清除小工具資料時:

await ApCommonPlugin.clearCourseWidget();

4. 測試用假資料(Debug) #

注入假課程資料以測試小工具顯示,會建立兩筆課程(30 分鐘後、90 分鐘後):

if (kDebugMode) {
  await ApCommonPlugin.setFakeCourseWidget();
}

原生端整合 #

Android #

Plugin 已包含完整的 CourseAppWidgetProvider 實作與 AndroidManifest.xml 註冊,App 端不需要額外修改 manifest。建置時會自動合併。

iOS #

iOS 需要在 Xcode 專案中建立 WidgetKit extension,步驟如下:

1. 建立 Widget Extension

在 Xcode 中 File → New → Target → Widget Extension,命名為 CourseAppWidget

2. 設定 App Group

在主 App 和 Widget Extension 的 Signing & Capabilities 中加入相同的 App Group(例如 group.com.yourapp.id)。

3. 建立資料模型

在 Widget Extension 中建立 CourseData.swift

import Foundation

struct CourseData: Codable {
    let courses: [Course]
    let timeCodes: [TimeCode]
}

struct Course: Codable {
    let code: String
    let title: String
    let className: String?
    let group: String?
    let units: String?
    let hours: String?
    let required: String?
    let at: String?
    let sectionTimes: [SectionTime]
    let location: Location?
    let instructors: [String]

    enum CodingKeys: String, CodingKey {
        case code, title, className, group, units, hours
        case required, at
        case sectionTimes, location, instructors
    }
}

struct Location: Codable {
    let building: String?
    let room: String?
}

struct SectionTime: Codable {
    let weekday: Int
    let index: Int
}

struct TimeCode: Codable {
    let title: String
    let startTime: String
    let endTime: String
}

4. 實作 Timeline Provider

在 Widget Extension 中讀取 App Group UserDefaults 的課程資料:

let defaults = UserDefaults(suiteName: "group.com.yourapp.id")
let json = defaults?.string(forKey: "course_notify")
let courseData = try? JSONDecoder().decode(
    CourseData.self,
    from: Data(json!.utf8)
)

完整的 iOS Widget 範例程式碼請參考 ios/CourseAppWidget/ 目錄。

API 參考 #

方法 說明
ApCommonPlugin.configure({required String appGroupId}) 設定 iOS App Group ID
ApCommonPlugin.updateCourseWidget(CourseData courseData) 更新課表小工具資料
ApCommonPlugin.clearCourseWidget() 清除課表小工具資料
ApCommonPlugin.setFakeCourseWidget() 注入假資料供測試
ApCommonPlugin.platformVersion 取得平台版本字串

資料流程 #

Dart (CourseData)
  │
  ▼ jsonEncode → MethodChannel
  │
  ├─ Android: SharedPreferences("ap_common_plugin", "course_notify")
  │           → AppWidgetManager.notifyAppWidgetViewDataChanged()
  │
  └─ iOS:     UserDefaults(suiteName: appGroupId)["course_notify"]
              → WidgetCenter.shared.reloadAllTimelines()

相關連結 #