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?

1

There are 1 best solutions below

0
Maciej Bastian On

Soo I would recommend to change method name and leave out the „app_usage/” leading for printForegroundApp because 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:

The call might fail—for example, if the platform doesn’t support the platform API (such as when running in a simulator), so wrap the invokeMethod call in a try-catch statement.