Firebase messagingバックグラウンドタスク制御android,第2部



実際のパッケージのコードを分析するのに長い時間がかかり、このようなプロセスを経験することを知りました.今しなければならないのはパッケージを修正することです.fork firebase messagingパッケージをgithubにインポートして修正します.

fork


flutterfireというgithubリポジトリがあり、flutが使用するfirebaseに関連するパッケージが集約されています.これまでforkを使った経験はなく、検索した方法は単一のパッケージの方法しかなく、複数のリポジトリからどのようにインポートするかも考慮する必要があります.

flutterfire githubリポジトリに移動し、Forkボタンを押してリポジトリにインポートします.

そして私のプロジェクトのpubspecです.yamlファイルの依存項目で画像のように変更します.
urlはコピーボタンを押して赤いボックスに貼り付けるだけで、pathはリポジトリにfirebase messagingフォルダ(pubspec.yamlファイル付き)を指定するだけです.
このようにインポートされたパッケージは使用できますが、firebase messaging interfaceパッケージはfirebase messagingの複数の論理を使用できます.2つのパッケージ、firebase messagingのpubspecを変更する必要がある可能性があります.yamlのfirebase messaging interfaceパッケージのパスも変更する必要があります.
//firebase_messaging_platform_interface의 pubspec.yaml
name: firebase_messaging

...

dependencies:
  firebase_core: ^1.10.0
  firebase_core_platform_interface: ^4.2.3
  firebase_messaging_platform_interface:
    git:
      url: https://github.com/shawn-flunge/flutterfire.git
      path: packages/firebase_messaging/firebase_messaging_platform_interface
      ref: master

  # firebase_messaging_web: ^2.2.5
  firebase_messaging_web:
    git:
      url: https://github.com/shawn-flunge/flutterfire.git
      path: packages/firebase_messaging/firebase_messaging_web
      ref: master

  ...
上に示すようにfirebase messaging platform interfaceのパスを「マイリポジトリ」に変更します.

ポリシーの変更



Background IsolateはIsolatespawnやcomputeで生成されたわけではなく、Isolate間のコミュニケーション方法が思いつかなかったので、戦略は中間メディアAndroid側のMethodCallHandlerを通じて間接的にコミュニケーションすることです.
  • バックグラウンドHandlerのループにおいて、isSelectedの状態は、方法チャネルによって継続的にチェックされる.
  • ループを終了させたいタイミングで、同様にメソッドチャネルを介してisSelectedの状態を変更する.

  • Androidエンドコードが存在するパス

    このパスのファイルのうち,バックグラウンドサービスロジックが存在するファイルはレッドブロックの3つであり,一番下のファイルは今回修正するファイルである.

    firebase_messaging : Native

    public class FlutterFirebaseMessagingPlugin extends BroadcastReceiver
        implements FlutterFirebasePlugin,
            MethodCallHandler,
            NewIntentListener,
            FlutterPlugin,
            ActivityAware {
    
      private final HashMap<String, Boolean> consumedInitialMessages = new HashMap<>();
      private MethodChannel channel;
      private Activity mainActivity;
      private RemoteMessage initialMessage;
      private static final String TAG = "FLTFireMsgPlugin";
      private static boolean isSelected = false;
    一番下にあるようにisSelected変数を作成します.ちなみにJavaコードなのでboolではなくbooleanです.
    @Override
      public void onMethodCall(final MethodCall call, @NonNull final Result result) {
        Task<?> methodCallTask;
    
        switch (call.method) {
            
          ...
          
          case "Messaging#askIsSelected":
            Log.i(TAG, "askIsSelected");
            // result.success(isSelected);
            channel.invokeMethod("Messaging#answerIsSelected", isSelected);
            methodCallTask = Tasks.forResult(null);
            break;
          case "Messaging#setIsSelectedFalse":
            Log.i(TAG, "setIsSelectedFalse");
            isSelected = false;
            methodCallTask = Tasks.forResult(null);
            break;
          case "Messaging#setIsSelectedTrue":
            Log.i(TAG, "setIsSelectedTrue");
            isSelected = true;
            methodCallTask = Tasks.forResult(null);
            break;
          default:
            result.notImplemented();
            return;
        }
    
        ...
        
      }
    クラスのonMethodCallメソッドの実装部分.caseを3つ追加しました.現在の状態を回答した症例と変化した状態を回答した2例があった.

    firebase_messaging : Flutter




    処理するファイルのパス
    この中の
    platform_interface_messaging.dart,
    method_channel_messaging.省道にはそれぞれの位置がある.
    platform_interface_messaging.dartをメソッドchannel messagingとする.dartは継承構造であり,メソッドchannel messagingである.メソッドチャネルを使用する論理をdartで実現する.

    platform_interface_messaging.dart


    クラスで2つのメソッドを実装します.
      void setIsSelectedTrue(){
        throw UnimplementedError('setIsSelectedTrue() is not implemented');
      }
    
      void setIsSelectedFalse(){
        throw UnimplementedError('setIsSelectedTrue() is not implemented');
      }

    method_channel_messaging.dart


    クラスで上記の2つのメソッドを再定義します.
      @override
      void setIsSelectedTrue() {
        channel.invokeMethod('Messaging#setIsSelectedTrue');    
      }
    
      @override
      void setIsSelectedFalse(){
        channel.invokeMethod('Messaging#setIsSelectedFalse');
      }

    マイプロジェクトのバックグラウンドプロセッサ

    Future<void> onBackgroundHandler(RemoteMessage message) async {
      const MethodChannel methodChannel = MethodChannel('plugins.flutter.io/firebase_messaging');
    
      bool isSelected = false;
    
      methodChannel.setMethodCallHandler((call){
    
        if(call.method == 'Messaging#answerIsSelected'){
          isSelected = call.arguments as bool;
        }
        return Future.value();
      });
      
      
      Timer.periodic(const Duration(seconds: 5), (timer) {
        methodChannel.invokeMethod('Messaging#askIsSelected');
    
        if(isSelected) timer.cancel();
        NotificationController().showNotification();
      });
    
      return Future.value();
    }
    メソッドチャネルオブジェクトを生成し、メソッドを受信するときに処理のための論理を登録するsetMethodCallHandlerメソッドでMessage#AnswerIsSelectedが受信された場合、isSelected変数にパラメータ値を格納する必要があります.
    これにより,isSeeledの値を次の繰返しサイクルで認知することができる.
    しかし、コード分析やテストに比べて、実際に追加されたコードは少ないようです.

    結果



    もともと、アプリのモバイル画面を開いても、ずっと通知が生成されていましたが、今はそうではありません.しかし疑問なのは、サイクルの時間にかかわらず、2回繰り返して、サイクルを離れることです.予想できるのはお互いに情報を伝える時間があるから
    githubで完全なコードを表示できます.
    変更されたパッケージリンク
    現在進行中のプロジェクトリンク

    の最後の部分


    今回のプロジェクトを行った時は、最初はあまり難しくないと思っていたのですが、最初から今まで使ったことのないCustomPaintを使い、今回はMethodChannelのNative Codeも使いました.もちろん、私は多くのことを学び、それができる自信も生まれましたが、逆境がこれで終わることを望んでいます.