Android 在设备睡眠时减慢前台服务速度

2023-11-21

几天来,我一直在努力解决以下问题:我想在屏幕关闭时使用 Android 设备上的重力传感器来计算运动模式。我正在使用在前台启动的绑定服务(带有 Android 8 的通知以使其保持运行),并且当屏幕打开时一切正常。即使应用程序没有在前台运行,一切也正常。

然而,一旦显示器关闭,非常奇怪的事情就开始发生:传感器数据仍在处理,并且在一定程度上对运动进行计数,但结果非常糟糕且不准确。此外,如果屏幕再次打开,该应用程序的行为会非常奇怪。有时应用程序按预期工作,但有时似乎旧的传感器事件被延迟处理并稍后计数。整个算法从这个时候开始就运行得不太顺利了。同样有趣的是:如果设备已插入,并且我通过 Android Studio 中的控制台观察到一切,那么即使屏幕关闭,一切也会完美运行。然而,如果设备被拔掉,结果又会变得错误。

我尝试了很多事情:在主线程上运行所有内容,在另一个线程上运行,使用 IntentService,将应用程序设置在白名单上Doze,在屏幕关闭时不向MainActivity发送数据,并遵循本指南(我正在 Galaxy J5 上进行开发) - 但没有任何效果。看来,要么Android系统的SensorFusion算法在待机状态下关闭,即使有注册的监听器,要么三星在后台运行了一些电池优化并限制了CPU操作。还有其他原因可能导致此行为吗?那么,如果应用程序处于活动状态、在后台运行,但在设备处于睡眠状态时则运行良好?

也许还值得一提的是:我正在为 Cordova 开发一个插件。

这是我的代码

主类

public class SensorPlugin extends CordovaPlugin implements ServiceClass.Delegate {

    public void initialize() {
      ...
      Intent serviceIntent = new Intent(applicationContext, ServiceClass.class);
      applicationContext.bindService(serviceIntent, serviceConnection, 
          Context.BIND_AUTO_CREATE);
    }

    public void start() {
        serviceClass.startMeasuring();
    }

    @Override
    public void updateMovementCount(int count) {
        ...
    };

}

服务等级

public class ServiceClass extends Service implements OtherClass.Delegate {

    private volatile boolean isMeasuring;
    private volatile double gravityX;
    private volatile double gravityY;
    private volatile double gravityZ;

    public IBinder onBind(Intent intent) {
        sensorManager = (SensorManager) getApplicationContext().
            getSystemService(Context.SENSOR_SERVICE);

        startForeground(1, buildNotification());
        return mBinder;
    }

    public void startMeasuring() {
        assert sensorManager != null;
        Sensor gravity = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
        sensorManager.registerListener(this, gravity, 
            SensorManager.SENSOR_DELAY_GAME);

        isTracking = true;

        SensorThread sensorThread = new SensorThread();
        sensorThread();
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        gravityX = event.values[0];
        gravityY = event.values[1];
        gravityZ = event.values[2];
    }

    // This is an interface method from another class that I wrote
    // (see below). For which I set this class as delegate and as soon
    // as the other class finds a pattern in the data it calls this method
    @Override
    public void movementPatternDidChange(int count) {
        // Usually I send this count to the main class with
        // the same delegation pattern
        delegate.updateMovementCount(count);
    }

    class SensorProcessingThread extends Thread {
        Handler handler = new Handler();

        // I use another runnable here, as I only want to process 10
        // sensor events per second. The sensor manager usually returns
        // way more which I don't need.
        private Runnable sensorProcessingRunnable = new Runnable() {
            public void run() {
                otherClass.processMotionData(gravityX, gravityY, gravityZ);
                if (isMeasuring) {
                    handler.postDelayed(this, 100);
                }
            }
        };

        @Override
        public void run() {
            if (!isMeasuring) {
                return;
            }

            handler.postDelayed(sensorProcessingRunnable, 100);
        }
    }

}

Edit

在此期间我进行了很多测试。我现在正在使用Apache Commons 基元集合为了更好的性能(而不是大型 FastUtil,这也会导致this过去的错误)。

我还在两台设备上测试了该应用程序,一台相当旧的 LG G2 和 Galaxy J5。两者的问题都是一样的。所以可能不是制造商特定的。 Android Studio Profiler 报告两台设备上的 CPU 使用率平均为 1-3%,因此我认为过载可能不是原因。我还测试了 TimerTask 和 Timer,而不是 Runnable 和 Handler,但效果不佳。

也很有趣的是:我尝试通过 Wifi 调试应用程序正如这里所解释的,即使设备处于睡眠状态并且屏幕关闭,该应用程序也可以正常工作。调试这个问题非常困难,因为即使没有连接电缆,只要我调试它,应用程序就表现良好。我不知道我还能做什么。


对于有类似问题的每个人:我终于找到了解决方案。

我认为Android文档中没有很好地解释,也不是很直观,但仍然有必要设置部分唤醒锁以防止CPU休眠。This解释如何设置唤醒锁。单独的前台服务不足以保持时间关键的进程运行。

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

Android 在设备睡眠时减慢前台服务速度 的相关文章

  • android - EditText 打字速度很慢

    我的 EditText 在打字时响应速度很慢 这种滞后现象足以让我找到解决方案 我做了一些研究 发现了一个 SO 线程输入文本时 EditText 滞后 https stackoverflow com questions 6173591 a
  • 任务“:app:dexDebug”执行失败

    我目前正在处理我的项目 我决定将我的 Android Studio 更新到新版本 但在我导入项目后 它显示如下错误 Information Gradle tasks app assembleDebug app preBuild UP TO
  • 未找到 Gradle DSL 方法:“versionCode()”

    构建我的 Android 项目时遇到问题 我使用Grgit https github com ajoberstar grgit填写versionCode and versionName在 gradle 中 一切工作正常 直到我将 Andro
  • 为什么 Kotlin 数据类可以在 Gson 的不可空字段中包含空值?

    在 Kotlin 中你可以创建一个data class data class CountriesResponse val count Int val countries List
  • 查找回收器视图中的第一个可见项目是否是列表的第一项

    我有一个包含 13 个数据项的回收器视图 我想知道列表中的第一项是否可见 我知道像这样的方法findFirstVisibleItemPosition and findLastVisibleItemPosition但他们没有说明第一个可见项目
  • Android studio 在日志猫中“清除全部”,更改日志级别过滤器时日志仍然会回来

    在 LogCat 中 当我单击 全部清除 按钮时 它似乎清除了所有日志 但是 如果我更改日志级别并返回到之前的日志级别 则所有日志都会返回 例如 我正在查看 Verbose 我选择 全部清除 日志清除 我切换到 调试 我切换回 详细 现在所
  • 在 Android 中的活动、服务和应用程序之间传递变量

    有人可以给我提供以下活动 服务 应用程序组合的示例吗 我拥有这三个 但我已经把我的应用程序弄得一团糟 试图在这个地方传递一堆变量 现在我不知道发生了什么 请注意 我是 Android 新手 最近我一直在努力解决这个问题 因为有很多方法可以实
  • 更改工具栏中汉堡图标的大小?

    我有两个问题 可能很奇怪 但无论如何 我有带有应用程序标题的工具栏 如何将其更改为非徽标的图片 下一个问题 是否可以设置 更改工具栏中汉堡图标的大小 我在下面的下一个代码的帮助下制作了经典的导航抽屉 我也使用了 ActionBarDrawe
  • Google Inbox 类似 RecyclerView 项目打开动画

    目前 我正在尝试实现 Google Inbox 例如RecyclerView行为 我对电子邮件打开动画很好奇 我的问题是 该怎么做 我的意思是 他们使用了哪种方法 他们用过吗ItemAnimator dispatchChangeStarti
  • layout.xml 的用途是什么?

    人们为什么使用layout xml在他们的resources like
  • 下载图像并显示它

    应用程序的主要目的是下载和显示图像 但是当我尝试启动应用程序时它崩溃了 这是我的代码 private DownloadImageTask task protected void onCreate Bundle savedInstanceSt
  • Android 手机应用意图

    我想在手机上启动手机应用程序作为意图 我正在使用这个代码 startActivity getPackageManager getLaunchIntentForPackage com android phone 但该函数抛出一个空指针异常 因
  • Facebook LoginActivity 未正确显示

    我有一个使用 Facebook 登录的应用程序 我有 FacebookSDK 并且使用 com facebook LoginActivity 问题是 在 10 英寸平板电脑上 当显示软键盘时 活动无法正确显示 我使用的是 Samsung G
  • 手动启用时 Firebase Crashlytics 不报告崩溃

    Crashlytics 在没有选择加入报告的情况下也能正常工作 但一旦我根据规定设置了选择加入报告 它就会停止报告任何内容tutorial https firebase google com docs crashlytics customi
  • onTouchEvent()中如何区分移动和点击?

    在我的应用程序中 我需要处理移动和单击事件 一次点击是由一个 ACTION DOWN 操作 多个 ACTION MOVE 操作和一个 ACTION UP 操作组成的序列 理论上 如果您收到 ACTION DOWN 事件 然后收到 ACTIO
  • 如何在android中录制音频时暂停背景音乐

    我正在 Android 中开发一个音频记录应用程序 因此 如果设备音乐播放器中已播放任何背景音乐 则应在开始录制之前暂停该背景音乐 并且每当录制停止或暂停时 背景音乐都应恢复 播放录制的音频时也应该如此 有人可以帮我解决这个问题吗 提前致谢
  • 带有空白白屏的 WebView

    我在 DialogFragment 中有一个 webview 它使用以下方式显示文档和 PDF它可以进行几次尝试 但如果用户尝试频繁打开和关闭对话框 webview 将显示空白屏幕 我已经尝试了所有的线程link1 https stacko
  • Google Android Drive api 在已安装版本上登录失败

    我开发了一个使用 GoogleDrive api 的 Android 应用程序 当处于调试状态或运行调试版本时 应用程序 工作正常 并正确验证附加的谷歌帐户 等 当我构建发行版本时 使用我的签名密钥 并且 安装apk文件 当我运行时 Goo
  • Android应用程序kill事件捕获

    我想在我的应用程序被终止时执行一些操作 可以使用哪种方法来实现此目的 我正在开发 Android 5 0 这个问题的关键在于 您必须了解您的申请是否可以收到任何 当您的应用程序在任何情况下被终止时的额外回调 下面的答案是由德文连线 http
  • Amazon IAP 不会调用 onPurchaseResponse

    我有一个 Android 应用程序 它使用 IAP 我正在发送PurchasingManager initiateGetUserIdRequest 并得到用户识别成功 in onGetUserIdResponse 得到回复后Purchasi

随机推荐

  • 在 Laravel 中访问 $_GET 值的最佳实践是什么?

    有没有更好的访问方式 GET而不是 Laravel 中的变量本身 或者就是这样 我需要 API 的多个参数 例如 users q keyword order desc limit 5 是否有更干净 更安全且类似 Laravel 的方式来访问
  • 使用 Azure Functions 在本地存储状态

    Azure Functions 是否提供本地 状态 存储来消除调用其他服务 例如存储 docDB 等 的需要 功能基于 Azure 应用服务构建 提供存储持久文件的功能 例如您可以将文件存储在 HOME data SomeFolderOfY
  • 在 Equinox 中,是否可以将 OSGi 包标记为从其包含功能的 p2.inf 开始?

    我有一个 Eclipse 功能 其中包含多个捆绑包 我想告诉 p2 在安装该功能时将其中一个捆绑包标记为已启动 这可以使用捆绑包自己的 META INF p2 inf 来实现 如下所示 instructions configure mark
  • Json.NET:反序列化嵌套 Json

    如何反序列化此 Json 字符串上的 Items 类部分 Buddies count 1 items id 5099207ee4b0cfbb6a2bd4ec firstName Foo lastName Bar image url size
  • Buildozer 未能执行最后一个命令

    当我尝试在我的设备上构建 推送并自动运行 apk 时 使用buildozer android debug deploy run它显示这些错误 Check configuration tokens Ensure build layout Ch
  • notify可以多次唤醒同一个线程吗?

    想象一下 Java 中有一个典型的生产者 消费者模式 为了提高效率 你想使用notify 并不是notifyAll 当一个新元素被添加到队列中时 如果两个生产者线程调用notify 是否可以保证两个不同的等待消费者线程会被唤醒 或者可以是两
  • Windows 中相当于命令“date+%s”的是什么

    我正在编写一个批处理脚本 我需要 unix 时间 在linux下很容易 但我不知道如何在windows下做到这一点 这是一个适用于任何区域设置的本机批处理解决方案 它使用 WMIC 以与区域设置无关的方式获取当前本地时间 其他一切都是字符串
  • CSS中的蛇形对齐

    我一直在努力解决 CSS 中的以下问题 我有任意数量的项目 跨度或 div 我想将它们以蛇状图案包装在容器内 我的意思是 如果我有 10 个项目 每个项目的宽度为 20 像素 我希望它们在 60 像素宽的容器中显示如下 0 1 2 5 4
  • setNeedsDisplay并不总是调用drawRect

    我在自定义表格单元格中有一个自定义视图 每次更改自定义视图上的特定属性时 我都会调用 self setNeedsDisplay 这会重绘视图 void drawRect CGRect rect 该属性在表视图委托中设置tableView c
  • 如何在 dart 中创建多个构造函数?

    我想通过调用具有不同数量参数的构造函数来创建不同的对象 我怎样才能在 Dart 中实现这一目标 class A String b c d A this b this c A this b this c this d See 构造函数部分飞镖
  • 如何将 ctrl+c 发送到 C# 中的进程?

    我正在为命令行可执行文件编写一个包装类 该exe接受来自的输入stdin直到我击中Ctrl C在命令提示符 shell 中 在这种情况下 它将输出打印到stdout基于输入 我想模拟一下Ctrl C按 C 代码 将终止命令发送到 NETPr
  • 检测范围大小的编译时常数

    请注意 在提出此问题后 缺陷报告更改了下面提到的行为 见问题末尾 编译器资源管理器链接 考虑以下 Variant 1 template
  • 在 C# 中缓存 FileInfo 属性

    来自MSDN 文档为了FileInfo Name属性 我看到该属性的数据在第一次调用时被缓存 并且仅在随后使用Refresh method 我有以下问题 但在文档中找不到或不太清楚 所有属性的数据是否同时缓存 Is the Refresh创
  • 将部分视图渲染为字符串 MVC4

    我正在使用以下内容来呈现字符串的部分视图 protected string RenderPartialViewToString string viewName object model if string IsNullOrEmpty vie
  • 告知作业何时完成

    我正在寻找一种方法 从脚本内 判断 Kubernetes 作业何时完成 然后我想从容器中取出日志并执行清理 这样做的好方法是什么 最好的方法是跑步kubectl describe job
  • 如何检查对象中的对象是否存在

    似乎以下用于检查对象成员是否存在的技术会产生错误 因为在检查之前尚未声明 bar 父对象 这意味着我要么必须在检查之前声明它 要么使用两个 typeof 表达式 其中任何一个都是多余的代码 var foo newVal typeof foo
  • 如何为 Google Apps 脚本网络应用程序上的并发用户提供便利?

    我目前正在创建一个可以读取和写入 Google 表格的网络应用程序 它本质上是一个表单应用程序 它从 HTML 表单中获取输入 然后使用appendRow 以及随后使用getRange and setValue 将更多数据附加到该行 每行代
  • Application.DoEvents() 的替代方法

    我正在开发一个基于 webBrowser 控件的消息传递系统 以便我可以随心所欲地格式化文本 当用户离线并收到消息时 消息将被存储 并在用户重新登录时为每条消息发送一个事件 当我为网站设置默认 html 等时 我通常使用 while thi
  • Mongodb:查找不带点符号的子文档

    例如我们有集合 field subfield name field subfield phone 我可以找到没有点符号的文档吗 像这样 db test find field subfield regex 或者也许像这样 db test fi
  • Android 在设备睡眠时减慢前台服务速度

    几天来 我一直在努力解决以下问题 我想在屏幕关闭时使用 Android 设备上的重力传感器来计算运动模式 我正在使用在前台启动的绑定服务 带有 Android 8 的通知以使其保持运行 并且当屏幕打开时一切正常 即使应用程序没有在前台运行