"FlutterJNI was detached" error when invoking MethodChannel after returning from background

48 views Asked by At

MainActivity.java

public class MainActivity extends FlutterActivity {
    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        FlutterEngineCache.getInstance().put("my_engine_id", flutterEngine);
        System.out.println("configure flutter engine nethod in MainActivity.java");
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "Widget_ForeGroundChannel").setMethodCallHandler(
                new MethodChannel.MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
                        if (call.method.equals("registerMethods")) {
                            Context context = getApplicationContext();
                            SharedPreferences sharedPreferences = context.getSharedPreferences("MySharedPref",Context.MODE_PRIVATE);
                            Object arguments = call.arguments;
                            Long l = 555419204045280687L;
                            Long p = 555419204045280687L;
                            if (arguments instanceof Map) {
                                Map<String, Long> arguments1 = (Map<String, Long>) arguments;
                                l=arguments1.get("callbackDispatcher");
                                p=arguments1.get("callBackFunction");
                            } else {
                                System.out.print("wrong instanve");
                            }
                            SharedPreferences.Editor myEdit = sharedPreferences.edit();
                            myEdit.putLong("callbackdisptacher", l);
                            myEdit.putLong("callbackFunction",p);
                            myEdit.commit();
                        } else {
                            result.notImplemented();
                        }
                    }
                }
        );
    }
}

MyService.java

public class MyService extends Service{
    FlutterEngine flutterEngine;
    public MyService() {
    }
    @Override
    public  int onStartCommand(Intent intent, int flags, int startId) {
        System.out.print("Android Service started");
        String bg_channel_name = "android_back_ground_channel";
            if(flutterEngine==null){
                System.out.print("flutter got from cache");
                flutterEngine = FlutterEngineCache.getInstance().get("my_engine_id");
            }
        assert flutterEngine != null;
        MethodChannel bg_channel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(),bg_channel_name);
        Context context = getApplicationContext();
        SharedPreferences sh = context.getSharedPreferences("MySharedPref", context.MODE_PRIVATE);
        SharedPreferences.Editor myEdit = sh.edit();
        Long n = sh.getLong("callbackdisptacher",213123123123L);
        Long pl = sh.getLong("callbackFunction",421412412442L);
        final ArrayList<Object> l = new ArrayList<>();
        l.add(n);
        l.add(pl);
        bg_channel.invokeMethod("", l);
        Toast.makeText(getApplicationContext(), "Service started", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        System.out.print("onCreate of service");
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        System.out.print("onBind of service");
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

NewAppWidget.java

public class NewAppWidget extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int appWidgetId : appWidgetIds) {
            updateAppWidget(context, appWidgetManager, appWidgetId);
        }
    }

    static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

        // Intent for the refresh button
        Intent refreshIntent = new Intent(context, NewAppWidget.class);
        refreshIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]{appWidgetId});
        PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0, refreshIntent, PendingIntent.FLAG_IMMUTABLE);

        // Intent for the service
        Intent serviceIntent = new Intent(context, MyService.class);
        serviceIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        PendingIntent servicePendingIntent = PendingIntent.getService(context, 0, serviceIntent, PendingIntent.FLAG_IMMUTABLE);

        // Construct the RemoteViews object
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
        views.setOnClickPendingIntent(R.id.refresh_button, refreshPendingIntent);
        views.setOnClickPendingIntent(R.id.refresh_button, servicePendingIntent);


        String currentTime = DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date());
        String currentDate = DateFormat.getDateInstance(DateFormat.SHORT).format(new Date());
        views.setTextViewText(R.id.text_time, currentTime);
        views.setTextViewText(R.id.text_date, currentDate);


        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);

        if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(intent.getAction())) {
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
            if (appWidgetIds != null) {
                for (int appWidgetId : appWidgetIds) {
                    updateAppWidget(context, appWidgetManager, appWidgetId);
                }
            }
        }
    }
}

Dart Code

  static Future<bool> registerMethods(Function callBackFunction) async {
    print("registerMethods method from main.dart");
    final callBackDispatcher = PluginUtilities.getCallbackHandle(callbackDispatcher);
    final callBack = PluginUtilities.getCallbackHandle(callBackFunction);
    await _channel.invokeMethod("registerMethods", {
      'callbackDispatcher': callBackDispatcher!.toRawHandle(),
      'callBackFunction': callBack!.toRawHandle(),
    });
    return true;
  }



@pragma('vm:entry-point')
void callbackDispatcher() {
  print("callbackDispatcher from main.dart creating background method Channels");
  const MethodChannel _backgroundChannel = const MethodChannel("android_back_ground_channel");
  WidgetsFlutterBinding.ensureInitialized();
  _backgroundChannel.setMethodCallHandler((MethodCall call) async {
    final args = call.arguments;
    print("Method handler of background channel");
    final Function callback = PluginUtilities.getCallbackFromHandle(CallbackHandle.fromRawHandle(args[1]))!;
    callback();
  });
}

When Android widget button is clicked, Android Service is created and then it should be making an method call(Dart code) throught methodchannel, If the app is in background, Its working fine, but When app is not in background, it was throwing ""FlutterJNI was detached" error when invoking MethodChannel after returning from background"

0

There are 0 answers