this is my MainActivity.kt :
import android.app.ActivityManager
import android.content.Context
import androidx.annotation.NonNull
import android.Manifest
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.net.Uri
import android.content.Intent
import android.app.AppOpsManager
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity : FlutterActivity() {
private val CHANNEL = "app_usage"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine);
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
call, result ->
if (call.method == "app_usage/printForegroundApp") {
val foregroundApp = printForegroundTask()
result.success(foregroundApp)
} else if (call.method == "needPermissionForBlocking") {
val needPermission = needPermissionForBlocking(context)
result.success(needPermission)
} else if (call.method == "openUsageAccessSettings") {
startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS))
} else {
result.notImplemented()
}
}
}
private fun needPermissionForBlocking(context: Context): Boolean {
return try {
val packageManager = context.packageManager
val applicationInfo = packageManager.getApplicationInfo(context.packageName, 0)
val appOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName)
mode != AppOpsManager.MODE_ALLOWED
} catch (e: PackageManager.NameNotFoundException) {
true
}
}
private fun printForegroundTask(): String {
var currentApp = "NULL"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val usm = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
val time = System.currentTimeMillis()
val usageEvents = usm.queryEvents(time - 1000, time)
var event: UsageEvents.Event = UsageEvents.Event()
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event)
if (event.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
currentApp = event.packageName
}
}
} else {
val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val tasks = am.runningAppProcesses
currentApp = tasks[0].processName
}
Log.e("adapter", "Current App in foreground is: $currentApp")
return currentApp
}
and this is implement on the dart code :
import 'package:flutter/services.dart';
import 'dart:async';
import 'package:logger/logger.dart';
class AppUsage {
static var logger = Logger();
static const MethodChannel _channel = MethodChannel("app_usage");
static Future<String> getForegroundApp() async {
try {
final String foregroundApp =
await _channel.invokeMethod("app_usage/printForegroundApp");
logger.d(foregroundApp);
return foregroundApp;
} catch (e) {
logger.e('Failed to get foreground app: $e');
return '';
}
}
static Future<bool> get needPermissionForBlocking async {
final bool needPermission =
await _channel.invokeMethod('needPermissionForBlocking');
return needPermission;
}
static void openUsageAccessSettings() {
_channel.invokeMethod('openUsageAccessSettings');
}
}
i always facing ⛔ Failed to get foreground app: MissingPluginException(No implementation found for method app_usage/printForegroundApp on channel app_usage)
I have tried various solutions, such as:
- flutter clean --> pub get --> run, but still doesn't work
- I have added super.configureFlutterEngine(flutterEngine); and GeneratedPluginRegistrant.registerWith(flutterEngine)
- I have tried to implement this: ‘In your invokeMethodCall, you have to include your channel name as a prefix to the name of the function you’re invoking, i.e., "_invokeMethodCall("$_channelName/register", args...)". Otherwise, it won’t recognize which method belonging to which channel you’re trying to call.’ (see my app_usage/printForegroundApp), but it’s still not working.
any idea what i missing here?
Soo I would recommend to change method name and leave out the „app_usage/” leading for
printForegroundAppbecause it’s clear what method channel you’re referring to anyway. Maybe that’s an issue. Remember to change it both on Flutter and native side.Also try running it on real device, Flutter docs say: