<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                在上一篇文章中,我與你分享了如何使用 Provider 去維護 Flutter 組件共用的數據狀態。在 Flutter 中狀態即數據,通過數據資源封裝、注入和讀寫這三步,我們不僅可以實現跨組件之間的數據共享,還能精確控制 UI 刷新粒度,避免無關組件的刷新。 其實,數據共享不僅存在于客戶端內部,同樣也存在于服務端與客戶端之間。比如,有新的微博評論,或者是發生了重大新聞,我們都需要在服務端把這些狀態變更的消息實時推送到客戶端,提醒用戶有新的內容。有時,我們還會針對特定的用戶畫像,通過推送實現精準的營銷信息觸達。 可以說,消息推送是增強用戶黏性,促進用戶量增長的重要手段。那么,消息推送的流程是什么樣的呢? ## 消息推送流程 手機推送每天那么多,導致在我們看來這很簡單啊。但其實,消息推送是一個橫跨業務服務器、第三方推送服務托管廠商、操作系統長連接推送服務、用戶終端、手機應用五方的復雜業務應用場景。 在 iOS 上,蘋果推送服務(APNs)接管了系統所有應用的消息通知需求;而 Android 原生,則提供了類似 Firebase 的云消息傳遞機制(FCM),可以實現統一的推送托管服務。 當某應用需要發送消息通知時,這則消息會由應用的服務器先發給蘋果或 Google,經由 APNs 或 FCM 被發送到設備,設備操作系統在完成解析后,最終把消息轉給所屬應用。這個流程的示意圖,如下所示。 :-: ![](https://img.kancloud.cn/91/6f/916f0ae684a20fbc87a15314cb8f2aea_904x462.png) 圖 1 原生消息推送流程 不過,Google 服務在大陸地區使用并不穩定,因此國行 Android 手機通常會把 Google 服務換成自己的服務,定制一套推送標準。而這對開發者來說,無疑是增大了適配負擔。所以針對 Android 端,我們通常會使用第三方推送服務,比如極光推送、友盟推送等。 雖然這些第三方推送服務使用自建的長連接,無法享受操作系統底層的優化,但它們會對所有使用推送服務的 App 共享推送通道,只要有一個使用第三方推送服務的應用沒被系統殺死,就可以讓消息及時送達。 而另一方面,這些第三方服務簡化了業務服務器與手機推送服務建立連接的操作,使得我們的業務服務器通過簡單的 API 調用就可以完成消息推送。 而為了保持 Android/iOS 方案的統一,在 iOS 上我們也會使用封裝了 APNs 通信的第三方推送服務。 第三方推送的服務流程,如下圖所示。 :-: ![](https://img.kancloud.cn/10/f4/10f46ae2b6ccb3753241dbf56f961223_1130x462.png) 圖 2 第三方推送服務流程 這些第三方推送服務廠商提供的能力和接入流程大都一致,考慮到極光的社區和生態相對活躍,所以今天我們就以極光為例,來看看在 Flutter 應用中如何才能引用原生的推送能力。 ## 原生推送接入流程 要想在 Flutter 中接收推送消息,我們需要把原生的推送能力暴露給 Flutter 應用,即在原生代碼宿主實現推送能力(極光 SDK)的接入,并通過方法通道提供給 Dart 層感知推送消息的機制。 ### 插件工程 在[第 26 篇](https://time.geekbang.org/column/article/127601)文章中,我們學習了如何在原生工程中的 Flutter 應用入口注冊原生代碼宿主回調,從而實現 Dart 層調用原生接口的方案。這種方案簡單直接,適用于 Dart 層與原生接口之間交互代碼量少、數據流動清晰的場景。 但對于推送這種涉及 Dart 與原生多方數據流轉、代碼量大的模塊,這種與工程耦合的方案就不利于獨立開發維護了。這時,我們需要使用 Flutter 提供的插件工程對其進行單獨封裝。 Flutter 的插件工程與普通的應用工程類似,都有 android 和 ios 目錄,這也是我們完成平臺相關邏輯代碼的地方,而 Flutter 工程插件的注冊,則仍會在應用的入口完成。除此之外,插件工程還內嵌了一個 example 工程,這是一個引用了插件代碼的普通 Flutter 應用工程。我們通過 example 工程,可以直接調試插件功能。 :-: ![](https://img.kancloud.cn/d6/08/d608c42b507e27a7456f37255d8a5b38_946x1244.png) 圖 3 插件工程目錄結構 在了解了整體工程的目錄結構之后,接下來我們需要去 Dart 插件代碼所在的 flutter\_push\_plugin.dart 文件,實現 Dart 層的推送接口封裝。 ### Dart 接口實現 為了實現消息的準確觸達,我們需要提供一個可以標識手機上 App 的地址,即 token 或 id。一旦完成地址的上報,我們就可以等待業務服務器給我們發消息了。 因為我們需要使用極光這樣的第三方推送服務,所以還得進行一些前置的應用信息關聯綁定,以及 SDK 的初始化工作。可以看到,對于一個應用而言,接入推送的過程可以拆解為以下三步: 1. 初始化極光 SDK; 2. 獲取地址 id; 3. 注冊消息通知。 這三步對應著在 Dart 層需要封裝的 3 個原生接口調用:setup、registrationID 和 setOpenNotificationHandler。 前兩個接口是在方法通道上調用原生代碼宿主提供的方法,而注冊消息通知的回調函數 setOpenNotificationHandler 則相反,是原生代碼宿主在方法通道上調用 Dart 層所提供的事件回調,因此我們需要在方法通道上為原生代碼宿主注冊反向回調方法,讓原生代碼宿主收到消息后可以直接通知它。 另外,考慮到推送是整個應用共享的能力,因此我們將 FlutterPushPlugin 這個類封裝成了單例: ~~~ //Flutter Push 插件 class FlutterPushPlugin { // 單例 static final FlutterPushPlugin _instance = new FlutterPushPlugin.private(const MethodChannel('flutter_push_plugin')); // 方法通道 final MethodChannel _channel; // 消息回調 EventHandler _onOpenNotification; // 構造方法 FlutterPushPlugin.private(MethodChannel channel) : _channel = channel { // 注冊原生反向回調方法,讓原生代碼宿主可以執行 onOpenNotification 方法 _channel.setMethodCallHandler(_handleMethod); } // 初始化極光 SDK setupWithAppID(String appID) { _channel.invokeMethod("setup", appID); } // 注冊消息通知 setOpenNotificationHandler(EventHandler onOpenNotification) { _onOpenNotification = onOpenNotification; } // 注冊原生反向回調方法,讓原生代碼宿主可以執行 onOpenNotification 方法 Future<Null> _handleMethod(MethodCall call) { switch (call.method) { case "onOpenNotification": return _onOpenNotification(call.arguments); default: throw new UnsupportedError("Unrecognized Event"); } } // 獲取地址 id Future<String> get registrationID async { final String regID = await _channel.invokeMethod('getRegistrationID'); return regID; } } ~~~ Dart 層是原生代碼宿主的代理,可以看到這一層的接口設計算是簡單。接下來,我們分別去接管推送的 Android 和 iOS 平臺上完成相應的實現。 ### Android 接口實現 考慮到 Android 平臺的推送配置工作相對較少,因此我們先用 Android Studio 打開 example 下的 android 工程進行插件開發工作。需要注意的是,由于 android 子工程的運行依賴于 Flutter 工程編譯構建產物,所以在打開 android 工程進行開發前,你需要確保整個工程代碼至少 build 過一次,否則 IDE 會報錯。 > 備注:以下操作步驟參考[極光 Android SDK 集成指南](https://docs.jiguang.cn//jpush/client/Android/android_guide/)。 首先,我們需要在插件工程下的 build.gradle 引入極光 SDK,即 jpush 與 jcore: ~~~ dependencies { implementation 'cn.jiguang.sdk:jpush:3.3.4' implementation 'cn.jiguang.sdk:jcore:2.1.2' } ~~~ 然后,在原生接口 FlutterPushPlugin 類中,依次把 Dart 層封裝的 3 個接口調用,即 setup、getRegistrationID 與 onOpenNotification,提供極光 Android SDK 的實現版本。 需要注意的是,由于極光 Android SDK 的信息綁定是在應用的打包配置里設置,并不需要通過代碼完成(iOS 才需要),因此 setup 方法的 Android 版本是一個空實現: ~~~ public class FlutterPushPlugin implements MethodCallHandler { // 注冊器,通常為 MainActivity public final Registrar registrar; // 方法通道 private final MethodChannel channel; // 插件實例 public static FlutterPushPlugin instance; // 注冊插件 public static void registerWith(Registrar registrar) { // 注冊方法通道 final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_push_plugin"); instance = new FlutterPushPlugin(registrar, channel); channel.setMethodCallHandler(instance); // 把初始化極光 SDK 提前至插件注冊時 JPushInterface.setDebugMode(true); JPushInterface.init(registrar.activity().getApplicationContext()); } // 私有構造方法 private FlutterPushPlugin(Registrar registrar, MethodChannel channel) { this.registrar = registrar; this.channel = channel; } // 方法回調 @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.equals("setup")) { // 極光 Android SDK 的初始化工作需要在 App 工程中配置,因此不需要代碼實現 result.success(0); } else if (call.method.equals("getRegistrationID")) { // 獲取極光推送地址標識符 result.success(JPushInterface.getRegistrationID(registrar.context())); } else { result.notImplemented(); } } public void callbackNotificationOpened(NotificationMessage message) { // 將推送消息回調給 Dart 層 channel.invokeMethod("onOpenNotification",message.notificationContent); } } ~~~ 可以看到,我們的 FlutterPushPlugin 類中,僅提供了 callbackNotificationOpened 這個工具方法,用于推送消息參數回調給 Dart,但這個類本身并沒有去監聽極光 SDK 的推送消息。 為了獲取推送消息,我們分別需要繼承極光 SDK 提供的兩個類:JCommonService 和 JPushMessageReceiver。 * JCommonService 是一個后臺 Service,實際上是極光共享長連通道的核心,可以在多手機平臺上使得推送通道更穩定。 * JPushMessageReceiver 則是一個 BroadcastReceiver,推送消息的獲取都是通過它實現的。我們可以通過覆蓋其 onNotifyMessageOpened 方法,從而在用戶點擊系統推送消息時獲取到通知。 作為 BroadcastReceiver 的 JPushMessageReceiver,可以長期在后臺存活,監聽遠端推送消息,但 Flutter 可就不行了,操作系統會隨時釋放掉后臺應用所占用的資源。因此,**在用戶點擊推送時,我們在收到相應的消息回調后,需要做的第一件事情不是立刻通知 Flutter,而是應該啟動應用的 MainActivity。**在確保 Flutter 已經完全初始化后,才能通知 Flutter 有新的推送消息。 因此在下面的代碼中,我們在打開 MainActivity 后,等待了 1 秒,才執行相應的 Flutter 回調通知: ~~~ //JPushXCustomService.java // 長連通道核心,可以使推送通道更穩定 public class JPushXCustomService extends JCommonService { } //JPushXMessageReceiver.java // 獲取推送消息的 Receiver public class JPushXMessageReceiver extends JPushMessageReceiver { // 用戶點擊推送消息回調 @Override public void onNotifyMessageOpened(Context context, final NotificationMessage message) { try { // 找到 MainActivity String mainClassName = context.getApplicationContext().getPackageName() + ".MainActivity"; Intent i = new Intent(context, Class.forName(mainClassName)); i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); // 啟動主 Activity context.startActivity(i); } catch (Exception e) { Log.e("tag"," 找不到 MainActivity"); } new Timer().schedule(new TimerTask() { @Override public void run() { FlutterPushPlugin.instance.callbackNotificationOpened(message); } },1000); // 延遲 1 秒通知 Dart } } ~~~ 最后,我們還需要在插件工程的 AndroidManifest.xml 中,分別聲明 receiver JPushXMessageReceiver 和 service JPushXCustomService,完成對系統的注冊: ~~~ ... <application> <!-- 注冊推送消息接收類 --> <receiver android:name=".JPushXMessageReceiver"> <intent-filter> <action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" /> <category android:name="${applicationId}" /> </intent-filter> </receiver> <!-- 注冊長連通道 Service --> <service android:name=".JPushXCustomService" android:enabled="true" android:exported="false" android:process=":pushcore"> <intent-filter> <action android:name="cn.jiguang.user.service.action" /> </intent-filter> </service> </application> ... ~~~ 接收消息和回調消息的功能完成后,FlutterPushPlugin 插件的 Android 部分就搞定了。接下來,我們去開發插件的 iOS 部分。 ### iOS 接口實現 與 Android 類似,我們需要使用 Xcode 打開 example 下的 ios 工程進行插件開發工作。同樣,在打開 ios 工程前,你需要確保整個工程代碼至少 build 過一次,否則 IDE 會報錯。 > 備注:以下操作步驟參考[極光 iOS SDK 集成指南](https://docs.jiguang.cn//jpush/client/iOS/ios_guide_new/) 首先,我們需要在插件工程下的 flutter\_push\_plugin.podspec 文件中引入極光 SDK,即 jpush。這里,我們選用了不使用廣告 id 的版本: ~~~ Pod::Spec.new do |s| ... s.dependency 'JPush', '3.2.2-noidfa' end ~~~ 然后,在原生接口 FlutterPushPlugin 類中,同樣依次為 setup、getRegistrationID 與 onOpenNotification,提供極光 iOS SDK 的實現版本。 需要注意的是,APNs 的推送消息是在 ApplicationDelegate 中回調的,所以我們需要在注冊插件時,為插件提供同名的回調函數,讓極光 SDK 把推送消息轉發到插件的回調函數中。 與 Android 類似,在極光 SDK 收到推送消息時,我們的應用可能處于后臺,因此在用戶點擊了推送消息,把 Flutter 應用喚醒時,我們應該在確保 Flutter 已經完全初始化后,才能通知 Flutter 有新的推送消息。 因此在下面的代碼中,我們在用戶點擊了推送消息后也等待了 1 秒,才執行相應的 Flutter 回調通知: ~~~ @implementation FlutterPushPlugin // 注冊插件 + (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { // 注冊方法通道 FlutterMethodChannel* channel = [FlutterMethodChannel methodChannelWithName:@"flutter_push_plugin" binaryMessenger:[registrar messenger]]; // 初始化插件實例,綁定方法通道 FlutterPushPlugin* instance = [[FlutterPushPlugin alloc] init]; instance.channel = channel; // 為插件提供 ApplicationDelegate 回調方法 [registrar addApplicationDelegate:instance]; // 注冊方法通道回調函數 [registrar addMethodCallDelegate:instance channel:channel]; } // 處理方法調用 - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if([@"setup" isEqualToString:call.method]) { // 極光 SDK 初始化方法 [JPUSHService setupWithOption:self.launchOptions appKey:call.arguments channel:@"App Store" apsForProduction:YES advertisingIdentifier:nil]; } else if ([@"getRegistrationID" isEqualToString:call.method]) { // 獲取極光推送地址標識符 [JPUSHService registrationIDCompletionHandler:^(int resCode, NSString *registrationID) { result(registrationID); }]; } else { // 方法未實現 result(FlutterMethodNotImplemented); } } // 應用程序啟動回調 -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化極光推送服務 JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init]; // 設置推送權限 entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound; // 請求推送服務 [JPUSHService registerForRemoteNotificationConfig:entity delegate:self]; // 存儲 App 啟動狀態,用于后續初始化調用 self.launchOptions = launchOptions; return YES; } // 推送 token 回調 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { /// 注冊 DeviceToken,換取極光推送地址標識符 [JPUSHService registerDeviceToken:deviceToken]; } // 推送被點擊回調 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler { // 獲取推送消息 NSDictionary * userInfo = response.notification.request.content.userInfo; NSString *content = userInfo[@"aps"][@"alert"]; if ([content isKindOfClass:[NSDictionary class]]) { content = userInfo[@"aps"][@"alert"][@"body"]; } // 延遲 1 秒通知 Flutter,確保 Flutter 應用已完成初始化 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.channel invokeMethod:@"onOpenNotification" arguments:content]; }); // 清除應用的小紅點 UIApplication.sharedApplication.applicationIconBadgeNumber = 0; // 通知系統,推送回調處理完畢 completionHandler(); } // 前臺應用收到了推送消息 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger options))completionHandler { // 通知系統展示推送消息提示 completionHandler(UNNotificationPresentationOptionAlert); } @end ~~~ 至此,在完成了極光 iOS SDK 的接口封裝之后,FlutterPushPlugin 插件的 iOS 部分也搞定了。 FlutterPushPlugin 插件為 Flutter 應用提供了原生推送的封裝,不過要想 example 工程能夠真正地接收到推送消息,我們還需要對 exmaple 工程進行最后的配置,即:為它提供應用推送證書,并關聯極光應用配置。 ### 應用工程配置 在單獨為 Android/iOS 應用進行推送配置之前,我們首先需要去[極光的官方網站](https://www.jiguang.cn/dev2/#/overview/appCardList),為 example 應用注冊一個唯一標識符(即 AppKey): :-: ![](https://img.kancloud.cn/14/74/1474a599fc1c2bd34d2e12cd6dbfb46a_708x544.png) 圖 4 極光應用注冊 在得到了 AppKey 之后,我們需要**依次進行 Android 與 iOS 的配置工作**。 Android 的配置工作相對簡單,整個配置過程完全是應用與極光 SDK 的關聯工作。 首先,根據 example 的 Android 工程包名,完成 Android 工程的推送注冊: :-: ![](https://img.kancloud.cn/3d/e9/3de9b139d409f669fa23a94cb2cdcdb9_1392x648.png) 圖 5 example Android 推送注冊 然后,通過 AppKey,在 app 的 build.gradle 文件中實現極光信息的綁定: ~~~ defaultConfig { ... //ndk 支持架構 ndk { abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' } manifestPlaceholders = [ JPUSH_PKGNAME : applicationId, // 包名 JPUSH_APPKEY : "f861910af12a509b34e266c2", //JPush 上注冊的包名對應的 Appkey JPUSH_CHANNEL : "developer-default", // 填寫默認值即可 ] } ~~~ 至此,Android 部分的所有配置工作和接口實現都已經搞定了。接下來,我們再來看看 iOS 的配置實現。 **iOS 的應用配置相對 Android 會繁瑣一些**,因為整個配置過程涉及應用、蘋果 APNs 服務、極光三方之間的信息關聯。 除了需要在應用內綁定極光信息之外(即 handleMethodCall 中的 setup 方法),還需要在[蘋果的開發者官網](https://developer.apple.com/)提前申請蘋果的推送證書。關于申請證書,蘋果提供了.p12 證書和 APNs Auth Key 兩種鑒權方式。 這里,我推薦使用更為簡單的 Auth Key 方式。申請推送證書的過程,極光官網提供了詳細的[注冊步驟](https://docs.jiguang.cn//jpush/client/iOS/ios_cer_guide/),這里我就不再贅述了。需要注意的是,申請 iOS 的推送證書時,你只能使用付費的蘋果開發者賬號。 在拿到了 APNs Auth Key 之后,我們同樣需要去極光官網,根據 Bundle ID 進行推送設置,并把 Auth Key 上傳至極光進行托管,由它完成與蘋果的鑒權工作: :-: ![](https://img.kancloud.cn/31/fd/31fd3119256c8d54f216b8922bf7da57_1550x736.png) 圖 6 example iOS 推送注冊 通過上面的步驟,我們已經完成了將推送證書與極光信息綁定的操作,接下來,我們**回到 Xcode 打開的 example 工程,進行最后的配置工作**。 首先,我們需要為 example 工程開啟 Application Target 的 Capabilities->Push Notifications 選項,啟動應用的推送能力支持,如下圖所示: :-: ![](https://img.kancloud.cn/c8/66/c866e1a8662b8220ad20f12560dc70f9_1370x522.png) 圖 7 example iOS 推送配置 然后,我們需要切換到 Application Target 的 Info 面板,手動配置 NSAppTransportSecurity 鍵值對,以支持極光 SDK 非 https 域名服務: :-: ![](https://img.kancloud.cn/64/d2/64d21293e30b316b1e88d79c954df4a2_1526x254.png) 圖 8 example iOS 支持 Http 配置 最后,在 Info tab 下的 Bundle identifier 項,把我們剛剛在極光官網注冊的 Bundle ID 顯式地更新進去: :-: ![](https://img.kancloud.cn/a3/0a/a30ae94430ce022c1aec423c6c9ea606_1730x332.png) 圖 9 Bundle ID 配置 至此,example 工程運行所需的所有原生配置工作和接口實現都已經搞定了。接下來,我們就可以在 example 工程中的 main.dart 文件中,使用 FlutterPushPlugin 插件來實現原生推送能力了。 在下面的代碼中,我們在 main 函數的入口,使用插件單例注冊了極光推送服務,隨后在應用 State 初始化時,獲取了極光推送地址,并設置了消息推送回調: ~~~ // 獲取推送插件單例 FlutterPushPlugin fpush = FlutterPushPlugin(); void main() { // 使用 AppID 注冊極光推送服務 (僅針對 iOS 平臺) fpush.setupWithAppID("f861910af12a509b34e266c2"); runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 極光推送地址 regID String _regID = 'Unknown'; // 接收到的推送消息 String _notification = ""; @override initState() { super.initState(); // 注冊推送消息回調 fpush.setOpenNotificationHandler((String message) async { // 刷新界面狀態,展示推送消息 setState(() { _notification = message; }); }); // 獲取推送地址 regID initPlatformState(); } initPlatformState() async { // 調用插件封裝的 regID String regID = await fpush.registrationID; // 刷新界面狀態,展示 regID setState(() { _regID = regID; }); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: Column( children: <Widget>[ // 展示 regID,以及收到的消息 Text('Running on: $_regID\n'), Text('Notification Received: $_notification') ], ), ), ), ); } } ~~~ 點擊運行,可以看到,我們的應用已經可以獲取到極光推送地址了: :-: ![](https://img.kancloud.cn/40/ba/40bacc76342c21ef43681a625709a4bf_1125x2436.png) 圖 10 iOS 運行示例 :-: ![](https://img.kancloud.cn/54/2d/542d1eda3e40c50b3c4a3495bb682a53_1080x2244.jpg) 圖 11 Android 運行示例 接下來,我們再去[極光開發者服務后臺](https://www.jiguang.cn/dev2/#/overview/appCardList)發一條真實的推送消息。在服務后臺選擇我們的 App,隨后進入極光推送控制臺。這時,我們就可以進行消息推送測試了。 在發送通知一欄,我們把通知標題改為“測試”,通知內容設置為“極光推送測試”;在目標人群一欄,由于是測試賬號,我們可以直接選擇“廣播所有人”,如果你希望精確定位到接收方,也可以提供在應用中獲取到的極光推送地址(即 Registration ID): :-: ![](https://img.kancloud.cn/a5/c3/a5c3aaf126d59561ee078dc5987ca8b6_2692x1852.png) 圖 12 極光推送后臺 點擊發送預覽并確認,可以看到,我們的應用不僅可以被來自極光的推送消息喚醒,還可以在 Flutter 應用內收到來自原生宿主轉發的消息內容: :-: 圖13 iOS 推送消息 :-: ![](https://img.kancloud.cn/b5/9f/b59ff183027f50df9fed14c4abfe9fd8_464x960.gif) 圖 14 Android 推送消息 ## 總結 好了,今天的分享就到這里。我們一起來小結一下吧。 我們以 Flutter 插件工程的方式,為極光 SDK 提供了一個 Dart 層的封裝。插件工程同時提供了 iOS 和 Android 目錄,我們可以在這兩個目錄下完成原生代碼宿主封裝,不僅可以為 Dart 層提供接口正向回調(比如,初始化、獲取極光推送地址),還可以通過方法通道以反向回調的方式將推送消息轉發給 Dart。 今天,我和你分享了很多原生代碼宿主的配置、綁定、注冊的邏輯。不難發現,推送過程鏈路長、涉眾多、配置復雜,要想在 Flutter 完全實現原生推送能力,工作量主要集中在原生代碼宿主,Dart 層能做的事情并不多。 我把今天分享所改造的[Flutter\_Push\_Plugin](https://github.com/cyndibaby905/31_flutter_push_plugin)放到了 GitHub 中,你可以把插件工程下載下來,多運行幾次,體會插件工程與普通 Flutter 工程的異同,并加深對消息推送全流程的認識。其中,Flutter\_Push\_Plugin 提供了實現原生推送功能的最小集合,你可以根據實際需求完善這個插件。 需要注意的是,我們今天的實際工程演示是通過內嵌的 example 工程示例所完成的,如果你有一個獨立的 Flutter 工程(比如[Flutter\_Push\_Demo](https://github.com/cyndibaby905/31_flutter_push_demo))需要接入 Flutter\_Push\_Plugin,其配置方式與 example 工程并無不同,唯一的區別是,需要在 pubspec.yaml 文件中將對插件的依賴顯示地聲明出來而已: ~~~ dependencies: flutter_push_plugin: git: url: https://github.com/cyndibaby905/31_flutter_push_plugin.git ~~~ ## 思考題 在 Flutter\_Push\_Plugin 的原生實現中,用戶點擊了推送消息把 Flutter 應用喚醒時,為了確保 Flutter 完成初始化,我們等待了 1 秒才執行相應的 Flutter 回調通知。這段邏輯有需要優化的地方嗎?為了讓 Flutter 代碼能夠更快地收到推送消息,你會如何優化呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看