1

I'm trying to launch briefly a flutter engine from a notification service extension in order to run some dart code. I created a new flutter module that I compiled as a framework and added to the extension target in xCode.

The code works well and the data is sent to the flutter part from which I have a log. Yet the data never comes back. I also tried doing an invokeMethod instead of return but it didn't work either.

Everything works fine when I add the module to a pure ios app and call it from AppDelegate (tho when trying to bring back the data on native side using shared_preferences I had an error stating the channel was unavailble). Yet once added to the flutter app it doesn't work at all even using only the method channel. Running the engine and sending the data to the flutter side is never an issue.

Could this be caused by a "persistance" issue since the notificatione extension is not an app but only a callback ? Or did I miss to properly register the engine or channel somewhere ?

NotificationService.swift :


import Flutter
import UserNotifications


let flutterEngine = FlutterEngine(name: "The engine")
let flutterDataChannel = FlutterMethodChannel(name: "com.test.shouldwork/ios", binaryMessenger: flutterEngine.binaryMessenger)

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?
    
    
    

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            
            //init part
             flutterEngine.run()
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            struct Content:Codable{
                var title:String
                    var body:String
                
            }
                
                let content = Content(title:bestAttemptContent.title,body: bestAttemptContent.body)
                var data:Data
                do{
                    data = try JSONEncoder().encode(content)
                    let convertedString = String(data: data, encoding: .utf8)!
                    flutterDataChannel.invokeMethod("dataToFlutter", arguments: convertedString, result:{(result) -> () in
                        var request = URLRequest(url: URL(string: "https://us-central1-wellenbrecher-3c570.cloudfunctions.net/debug?data=isback")!)
                        let task = URLSession.shared.dataTask(with: request)
                        task.resume()
                      
                        let result = result as! NSDictionary
                        //bestAttemptContent.title = result["title"] as! String
                        //bestAttemptContent.body = result["body"] as! String$
                        bestAttemptContent.title = "was mutated !"
                        contentHandler(bestAttemptContent)
                        
                        
                    })
               
                }
                catch{
                   print("error")
                }
             }

        }
        
        
    }
    
               
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
    

}


main.dart :


import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;


final platform = const MethodChannel('com.test.shouldwork/ios');

notification_extension(data){

data['title']= "Hello world !";


  return data;
}


Future<void> _receiveFromNative(MethodCall call) async {
  
 
   try {
 
     if (call.method == "dataToFlutter") {
       final String data = call.arguments;
       http.get(Uri.parse('https://us-central1-wellenbrecher-3c570.cloudfunctions.net/debug?data=$data'));
      
       var jData = await jsonDecode(data);
      var jResult = notification_extension(jData);
      
       return jResult;
     }
     
   } on PlatformException catch (error) {
     print(error);
   }

 }



main() async {
   
    WidgetsFlutterBinding.ensureInitialized();
   http.get(Uri.parse('https://us-central1-wellenbrecher-3c570.cloudfunctions.net/debug?flutter=true'));
  
    try{
    platform.setMethodCallHandler(_receiveFromNative);
      
  
    }
    catch (e){
      http.get(Uri.parse('https://us-central1-wellenbrecher-3c570.cloudfunctions.net/debug?isReady_error=$e'));
  
    }
}

Thanks

aloys-c
  • 51
  • 5

0 Answers0