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"