“尝试向 Flutter 发送平台消息,但 FlutterJNI 与原生 C++ 分离。”启动后台服务并关闭应用程序后

2024-01-25

我正在尝试构建一个使用某些包作为位置的应用程序(https://pub.dev/packages/location https://pub.dev/packages/location)和指南针(https://pub.dev/packages/flutter_compass https://pub.dev/packages/flutter_compass)并保持后台服务跟踪用户位置。 一切正常,直到我启动跟踪位置的服务。

当服务处于活动状态时,整个应用程序永远不会停止,例如,当我在没有服务的情况下关闭应用程序时,指南针也会停止,但随着服务运行,指南针也会继续运行。实际上它返回一个错误“尝试向 Flutter 发送平台消息,但 FlutterJNI 与本机 C++ 分离。无法发送。通道:hemanthraj/flutter_compass”。位置也会发生同样的情况:“尝试向 Flutter 发送平台消息,但 FlutterJNI 与本机 C++ 分离。无法发送。通道:lyokone/locationstream”。 在此之后,即使我再次打开该项目,它也不再工作了...... 我正在尝试使服务完全独立于项目的其余部分。

我将向您展示服务实现(Android)

public class CompassApplication extends FlutterApplication {

    @Override
    public void onCreate() {
        super.onCreate();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("messages", "Messages", NotificationManager.IMPORTANCE_LOW);
            NotificationManager manager = getSystemService(NotificationManager.class);
            if (manager != null) {
                manager.createNotificationChannel(channel);
            }
        }
    }
}
class MainActivity: FlutterActivity() {

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        val intent = Intent(this, LocationService::class.java)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForegroundService(intent)
        } else {
            startService(intent)
        }
    }
}
public class LocationService extends Service {

    static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10 * 60 * 1000; // 10 minutes
    static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;

    private LocationRequest mLocationRequest;
    private FusedLocationProviderClient mFusedLocationClient;
    private LocationCallback mLocationCallback;

    @Override
    public void onCreate() {
        super.onCreate();

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                onNewLocation(locationResult.getLastLocation());
            }
        };

        createLocationRequest();
        getLastLocation();
        requestLocationUpdates();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "messages")
                    .setSmallIcon(R.mipmap.ic_launcher_foreground);

            startForeground(101, builder.build());
        }
    }

    private void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    private void getLastLocation() {
        try {
            mFusedLocationClient.getLastLocation()
                    .addOnCompleteListener(task -> {
                        if (task.isSuccessful() && task.getResult() != null) {
                            onNewLocation(task.getResult());
                        }
                    });
        } catch (SecurityException ignored) {}
    }

    public void requestLocationUpdates() {
        Utils.setRequestingLocationUpdates(this, true);
        startService(new Intent(getApplicationContext(), LocationUpdatesService.class));
        try {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
        } catch (SecurityException unlikely) {
            Utils.setRequestingLocationUpdates(this, false);
        }
    }

    private void onNewLocation(Location location) {
        // TODO: deal with current location
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

另一个问题是,即使我不关闭应用程序,它也会消耗大量电池。 谢谢!


从插件包开发者的角度来看:

由于您使用的软件包导致了此问题,因此我会提到我在我的软件包中引起了同样的问题。

就我而言,我正在使用错误(或旧)方法通道。我在服务(广播接收器)运行时保存了方法通道的实例,并尝试使用它与正在运行的应用程序进行通信。

当清理服务(或广播接收器)时,我有被摧毁Flutter 引擎,因此将 Flutter JNI 从 C++ 引擎中分离出来。因此,当我使用该方法通道(它使用分离的 Flutter JNI)时,您会收到错误:

尝试向 Flutter 发送平台消息,但 FlutterJNI 与原生 C++ 分离。

我只需使用 FlutterActivity(或 FlutterFragment 或 Application)提供的 FlutterEngine 来获取新的 MethodChannel。

就我而言,我正在开发 Flutter 包插件(在 Android 上)。这意味着在插件代码内部,我不应该意外地缓存 methodChannels:

public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    final MethodChannel methodChannel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "example-method-channel-name");
}

你的问题

在您的依赖项的情况下,它们可能不支持在服务中使用:它们执行一些缓存/单例并重用不再附加的方法通道或 Flutter JNI。他们可能假设插件已实例化once,并且在服务运行时不会重新实例化(或者应用程序在服务已经运行时启动)。他们可能会注册回调以从操作系统接收数据,然后在创建具有新 Flutter 引擎的新插件时不会取消注册旧回调。

没有快速修复方法,必须构建包来支持这一点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

“尝试向 Flutter 发送平台消息,但 FlutterJNI 与原生 C++ 分离。”启动后台服务并关闭应用程序后 的相关文章

随机推荐

  • 尝试使用 C# 代码将数据输入到访问文件时出现无效的 Sql 语句错误[重复]

    这个问题在这里已经有答案了 我的错误是 System Data OleDb OleDbException 无效的 SQL 语句 应为 DELETE INSERT PROCEDURE SELECT 或 UPDATE 这是我的代码 我检查以确保
  • 在 Eclipse 中隐藏状态栏或进度栏

    如何隐藏 Eclipse 中的状态栏 我指的是底部的那个 其中还显示 进度 状态 它非常分散注意力 因为它一直在做某事 我看了一下这个问题 https stackoverflow com questions 5645495 how to h
  • 使用 Mockito 的 ArgumentCaptor 类来匹配子类

    下面的代码显示了我的问题 实际上 我尝试使用 Mockito 的 ArgumentCaptor 来验证某个具体类是否调用过一次方法 如果可能的话 我想在这里使用 ArgumentCaptor 但我开始怀疑我需要使用自定义 ArgumentM
  • 本机窗口queueBuffer函数不渲染来自Stagefright解码器的输出

    我将 SurfaceView 表面从 Java 传递到 JNI 在 JNI 中我从该表面获取本机窗口 Stagefright从 mp4 文件中解码 h264 帧 在解码过程中我调用ANativeWindow queueBuffer 为了发送
  • Rails 4:如何使用includes() 和where() 来检索关联对象

    我不知道如何使用 where 方法来检索关联的模型数据 在此示例中 项目属于用户 class Project lt ActiveRecord Base belongs to user has many videos end class Us
  • 为什么 GCC 的 -Wconversion 对于 char 和 unsigned char 的行为不同?

    Consider U8 foo U8 x U8 y return x y 如果 x 和 y 的类型 U8 是 char 或 unsigned char GCC 的 Wconversion 的行为会有所不同 gcc Wconversion c
  • 循环绘制子图

    z A 0 3618426 0 36146951 B 1 8908799 1 904695 C 2 1813462e 08 2 1833622e 08 D 0 89925492 0 89953589 E 2 6356747 2 631791
  • 如何使用 Excel VBA 单击网页上的链接?

    我正在编写 VBA 代码来从用户那里获取股票代码 导航到网站 输入股票代码并单击相应的链接 我研究了这个StackOverflow 问题和回复 https stackoverflow com questions 21002756 how t
  • Java:HashSet 与 HashMap

    我有一个程序正在处理巨大的数据集 对象最好存储在散列实现的容器中 因为程序不断在容器中寻找对象 第一个想法是使用HashMap 因为这个容器的get和remove方法更适合我需要的用途 但是 我发现 HashMap 的使用非常消耗内存 这是
  • 在运行时更改.dll

    我有一个巨大的应用程序 我的解决方案的一个项目在其中生成报告 我想添加新报告 更新报告 而不构建我的项目 只需添加 dll文件 我读到Assembly and AppDomain 但我不知道为新报告添加新的 dll 以及如何在运行时更新旧报
  • 我的图像处理项目的研究领域是什么?

    在我的最后一年项目中 我正在做一个车辆细节修改系统 系统应该能够完成以下任务 我使用的是从固定距离 例如 5m 拍摄的车辆尺寸图像 并存储不同的颜色和边缘图像我是我的应用程序 这是基本思想 检测车辆的轮胎和合金轮辋 检测并测量已安装轮辋的轮
  • Selenium - 如何获取窗口中打开的选项卡数量?

    我的测试用例 打开浏览器并访问 URL 单击主页上的链接 gt 这将打开一个新窗口 新选项卡 返回主页 单击另一个链接 确保步骤 2 中先前打开的子窗口 子选项卡上显示新内容 我可以通过获取窗口句柄的计数来检查打开的窗口数量 并断言它等于
  • Java中如何模拟文件IO?

    我怎样才能创建一个类MockFile模仿java io Filew r t 文件读写 我到处都用我自己的方法而不是new FileInputStream and new FileOutputStream 所以这部分没有问题 我总是委托给适当
  • 获取参数的调用变量名

    关于这个问题从调用方法中获取参数名称 https stackoverflow com questions 15205457 get the name of parameters from a calling method and 在 C 中
  • R 中没有重复的 Left_Join

    我想做一种vlookup 正如您所知 Excel vlookup 函数从数据中获取第一个值 另一方面 left join 函数的工作原理类似 但是 当第一个数据在查找值上不唯一时 left join 函数会重复 de 值 我想对 Excel
  • gradle 将外部插件的 jar 存储在哪里?

    我正在使用一个名为 jsonschema2pojo 的外部 gradle 插件 为此 我在 build gradle 文件中添加了以下代码 我可以成功使用该插件 但我找不到必须下载并存储在某处的 jar 在哪里可以找到为外部插件下载的 ja
  • 如何仅在 bash 中存在脚本时才执行该脚本?

    我想知道是否有一种更简单的方法可以仅在该脚本存在时才在 bash 中执行该脚本 我想要的相当于 if x name then name fi or x name name 我正在寻找的是类似的东西 exec if exist name 这消
  • Python-如何使用 re 来匹配整个字符串[重复]

    这个问题在这里已经有答案了 我正在验证用户输入的文本 以便它只接受字母而不接受数字 到目前为止 当我输入数字 例如 56 时 我的代码工作正常 它警告我应该只输入字母 而当我输入字母时 它不会返回任何内容 就像它应该做的那样 我的问题是 当
  • 使用YouTube Data API时如何避免视频信息获取的遗漏?

    假设 我想要实现的目标 我想使用YouTube Data API V3来无遗漏地获取视频ID 并找出问题的原因是在代码中还是在YouTube API端 的视频设置中 Problem 以下代码用于从YouTube Data API获取视频信息
  • “尝试向 Flutter 发送平台消息,但 FlutterJNI 与原生 C++ 分离。”启动后台服务并关闭应用程序后

    我正在尝试构建一个使用某些包作为位置的应用程序 https pub dev packages location https pub dev packages location 和指南针 https pub dev packages flut