Flutter : MainIsolate is unable to contact background service isolate in release version

In my flutter app, I am using the flutter background service plugin.

I share data among isolates using ports. There is a mainIsolate present in the homepage‘s code. Then a bgIsolate of the background_service. When the background_service isolate does not hold data and needs to close, I check if the application is open or not, and do not close the background_service isolate and the process when the application is open in case the application sends more data to it. I close it when the application is in terminated state (closed) and it automatically turns on again when the application is opened again.

Now, from the background_service isolate, to check if the app is on or not, I send a ping message to mainIsolate for which it null-checks the bgIsolate‘s sendPort and sends back a pong message for which I wait for 5 seconds.

In debug mode, there are no issues. The conversations between the isolate are as expected. The issues comes in release mode. bgIsolate is able to send the ping message to the mainIsolate but when mainIsolate null-checks the bgIsolate‘s sendPort, it returns false.

But when I try to send messages from other parts of the app. Like the database section which sends updates to the bgIsolate, I can see that the updates are still being sent without issues, even in the release mode. The database is not in any other isolate though, it is still in the mainIsolate the difference is only in the file from where the data is being sent. The pong message is being sent from the homepage while the data updates are being sent from the database file.

The problem is only with sending messages from the mainIsolate code present in homepage.

Now I would share some code with you:

Note: The bg_isolate_name is a variable stored in a different file which contains the name of the bgIsolate.

This is the background_service file. I removed parts unrelated to this matter.

// imports

@pragma('vm:entry-point')
bool mainIsActive = false;
Map<int, Reminder> reminders = {};
final List<Reminder> activeStatusReminders = [];   
final Map<int, int> repeatNumbers = {};
final ReceivePort receivePort = ReceivePort();

Future<void> initializeService() async {
  final service = FlutterBackgroundService();

  await service.configure(
    iosConfiguration: IosConfiguration(), 
    androidConfiguration: AndroidConfiguration(
      autoStart: true,
      onStart: onStart, 
      isForegroundMode: true
    )
  );

  service.startService();
}

@pragma('vm:entry-point')
void onStop(ServiceInstance service) async {
  debugPrint("[BGS onStop] called | ${service.runtimeType}");
  receivePort.close();
  IsolateNameServer.removePortNameMapping(bg_isolate_name);
  await service.stopSelf();
  debugPrint("[BGS onStop] service stopped");
}

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {

  // Control Section
  if (service is AndroidServiceInstance) {
    service.on('setAsForeground').listen((event) {
      service.setAsForegroundService();
    });

    service.on('setAsBackground').listen((event) {
      service.setAsBackgroundService();
    });
  }

  service.on('stopService').listen((event) {
    onStop(service);
  });

  // 
  if (service is AndroidServiceInstance)
  {
    service.setForegroundNotificationInfo(
      title: "On Standby",
      content: "Will disappear automatically if not needed."
    );
  }
  
  startListners(service);

  // Life Section
  final now = DateTime.now();
  final Duration delay = DateTime(now.year, now.month, now.day, now.hour, now.minute + 1)
      .difference(now);
  debugPrint("[BBGGSS] delay: ${delay.inSeconds}");
  Timer.periodic(Duration(seconds: delay.inSeconds), (timerFirst) async { // Double Timers are used to sync the Timer with 00 seconds. Like, run only on 5min 0 seconds and not on 5 min 5 seconds.
    bgServicePeriodicWork(service);
    Timer.periodic(Duration(minutes: 1), (timer) {
      bgServicePeriodicWork(service);
    });
    timerFirst.cancel();
  });
}

Future<void> bgServicePeriodicWork(ServiceInstance service) async {
  // More code. Not related to issue.
  // This holds the things which the background service repeatedly does.
}

@pragma('vm:entry-point')
Future<bool> stopBackgroundService(
  AndroidServiceInstance service
) async {
  debugPrint("[BGS] Attempting to stop background service");
  final SendPort? mainIsolate = IsolateNameServer.lookupPortByName('main');
  if (mainIsolate == null) {
    debugPrint("[BGS] mainIsolate is null");
    onStop(service);
    return true;
  } else {
    debugPrint("[BGS] mainIsolate found");
    mainIsActive = false;
    mainIsolate.send('ping_from_bgIsolate');
    // send message and wait. The listener handles received message and changes value of mainIsActive variable.

    debugPrint("[BGS] sent ping_from_bgIsolate");

    await Future.delayed(Duration(seconds: 5));
    if (mainIsActive)
    {
      debugPrint("[BGS] mainIsolate is active");
      return false;
    }
    else
    {
      debugPrint("[BGS] mainIsolate is not active");
      onStop(service);
      return true;
    }
  }
}

@pragma('vm:entry-point')
void updateNotification(AndroidServiceInstance service) async{
  // Function reads the data and updates the notification. It also calls for the service  to stop in a certain scenario.
}

@pragma('vm:entry-point')
void startListners(
  ServiceInstance service
) {
  IsolateNameServer.registerPortWithName(receivePort.sendPort, bg_isolate_name);

  // Listening for reminders
  receivePort.listen((dynamic message) {
    debugPrint("[BGS] Message nnnnnReceived $message");
    if (message is Map<int, Map<String, dynamic>>) { // Received Reminders from Hive DB

      handleReceivedRemindersData(message);
      if (service is AndroidServiceInstance) updateNotification(service);
    } 
    else if (message is Map<String, String>) // Received update after button click on notification. id and action.
    {
      handleNotificationButtonClickUpdate(message);
      if (service is AndroidServiceInstance) updateNotification(service);
    }
    else if (message is String) // String messages, ping, pong.
    {
      debugPrint("[BGS] Message: $message");
      if (message == 'pong') 
      {
        mainIsActive = true;
        debugPrint("[BGS Listener] mainIsActive: $mainIsActive");
      }
      // else debugPrint("[BGS] Unknown Content $message");
    }
    else {
      // debugPrint("[BGS] Unknown Content $message");
    }
  });
}

@pragma('vm:entry-point')
void handleReceivedRemindersData(Map<int, Map<String, dynamic>> message) {
  // Handles the data received from the database file.
}

@pragma('vm:entry-point')
void handleNotificationButtonClickUpdate(Map<String, String> message) {
  // Handles when a notification button is clicked. Not the notification of background_service, but of apps. The application is focused around notification and the background_service helps with it.
}

Here is the homepage code related to isolate transaction,

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  final ReceivePort receivePort = ReceivePort();
  final bgIsolate = IsolateNameServer.lookupPortByName(bg_isolate_name);

  @override
  void initState() {

    super.initState();

    if (bgIsolate != null)
    {
      bgIsolate!.send("main_is_active");
    }
    else debugPrint("[homepageInit] bgIsolate is down");
    
    // Listening for reloading orderers
    IsolateNameServer.registerPortWithName(receivePort.sendPort, 'main');
    receivePort.listen((dynamic message) {
      if (message == 'ping_from_bgIsolate')
        {
          debugPrint("[homepageListener] received ping_from_bgIsolate");
          if (bgIsolate != null) // Initialized on top
          {
            bgIsolate!.send("pong");
          }
          else debugPrint("[homePageListener] bgIsolate is null");
          debugPrint("[homepageListener] sent back pong to bgIsolate");
        }
        else 
        {
          debugPrint("[homepageListener] Unknown string received");
        }
      }
      else 
      {
        debugPrint("[homepageListener] Unknown message received $message");
      }
    });
  } 
.
.
// More code
.
.
}

Here is code from the database file which is always working unlike the homepage file.

static void updateReminders() async 
    // more code

    final SendPort? backgroundIsolate = IsolateNameServer.lookupPortByName(bg_isolate_name);
    if (backgroundIsolate != null) 
    {
      debugPrint("[updateReminders] message sending");
      final message = RemindersDatabaseController.getRemindersAsMaps();

      backgroundIsolate.send(message);
    }
    else
    {
      debugPrint("[updateReminders] background Isolate is null");
    }
  }

I haven’t tried much in this issue because I just don’t know what to do. A general idea of what might be causing this could help me.

I know this much that something is getting wrong in the release mode optimisations. But not how I could fix this or even what is getting wrong.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật