意图服务在打瞌睡模式下不工作

2023-12-12

我的一位同行开发人员写了一篇intent service进行 API 调用,然后休眠 2 分钟。醒来后,再次发送。

下面是代码:

public class GpsTrackingService extends IntentService {

....

@Override
    protected void onHandleIntent(Intent intent) {
      do{
        try{
          //make API call here

           //then go to sleep for 2 mins
          TimeUnit.SECONDS.sleep(120);
       
        } catch(InterruptedException ex){
            ex.printStackTrace();
        }
      } while (preferences.shouldSendGps()); //till the user can send gps.

    }

....

}


Manifest

<service android:name=".commons.GpsTrackingService" />

当手机处于活动状态时,此功能工作正常。但是,每当手机进入休眠模式时,它就无法唤醒。

将使用报警管理器WAKE permission解决这个问题吗?

我刚刚获得了代码库,需要在今天内修复这个问题。如果有人能帮忙那就太好了。


As the 文档 says:

在打瞌睡模式下,系统尝试通过限制 应用程序对网络和 CPU 密集型服务的访问。它还可以防止 应用程序访问网络并推迟其作业、同步和 标准警报。

系统会定期退出 Doze 状态一段时间,让应用程序 完成他们推迟的活动。在此维护窗口期间, 系统运行所有待处理的同步、作业和警报,并让应用程序 访问网络。

简而言之,在 Doze 模式下,系统暂停网络访问、忽略唤醒锁、停止从传感器获取数据、将 AlarmManager 作业推迟到下一个 Doze 维护时段(调用频率逐渐降低),并且 WiFi 扫描、JobScheduler 作业和同步适配器也不会运行.

对于每个应用程序,setAndAllowWhileIdle() 和 setExactAndAllowWhileIdle() 都不能每 9(?) 分钟多次触发警报。

看来前台服务也参与了这场“打瞌睡的戏剧”,至少在 MarshMellow (M) 中是这样。

为了在这种情况下生存,至少需要审查大量的申请。您能想象一个简单的 mp3 播放器在设备进入打瞌睡模式时停止播放音乐吗?

当设备拔掉电源并放在桌子上大约 1 小时左右时,或者甚至更早,当用户单击电源按钮关闭屏幕时,打瞌睡模式会自动启动,但我认为这可能取决于设备制造商也是如此。

我尝试了很多对策,其中一些真的很搞笑。

在测试结束时,我得出了一个可能的解决方案:

即使主机设备处于打瞌睡模式,也可以让应用程序运行的一种可能(也可能是唯一)的方法基本上是有一个前台服务(即使是假的,根本不做任何工作)运行另一个过程具有后天获得的部分唤醒锁定.

您需要做的基本上如下(您可以创建一个简单的项目来测试它):

  • 1 - 在您的新项目中,创建一个扩展应用程序 (myApp) 的新类,或使用 新项目的主要活动。
  • 2 - 在 myApp onCreate() 中启动一个服务 (myAntiDozeService)
  • 3 - 在 myAntiDozeService onStartCommand() 中,创建通知 需要将服务启动为前台服务,启动 使用 startForeground(id, notification) 的服务并获取 部分唤醒锁。

记住!这会起作用,但这只是一个起点,因为您必须小心此方法将产生的“副作用”:

  • 1 - 电池消耗:CPU 将永远为您的应用程序工作,如果您 不要使用某些策略并让 WakeLock 始终处于活动状态。

  • 2 - 即使在锁定屏幕中,也将始终显示一条通知, 而且这个通知不能通过简单地滑动来删除,它 将一直存在,直到您停止前台服务。

好的,让我们一起做。

myApp.java

    public class myApp extends Application {
    private static final String STARTFOREGROUND_ACTION = "STARTFOREGROUND_ACTION";
    private static final String STOPFOREGROUND_ACTION = "STOPFOREGROUND_ACTION";

        @Override
        public void onCreate() {

            super.onCreate();            

            // start foreground service
            startForeService();
    }

    private void stopForeService() {
        Intent service = new Intent(this, myAntiDozeService.class);
        service.setAction(STOPFOREGROUND_ACTION);
        stopService(service);
    }

    private void startForeService(){
        Intent service = new Intent(this, myAntiDozeService.class);
        service.setAction(STARTFOREGROUND_ACTION);
        startService(service);
    }

    @Override
    public void onTerminate() {
        stopForeService();
        super.onTerminate();
    }
}

myAntiDozeService.java

public class myAntiDozeService extends Service {

    private static final String TAG = myAntiDozeService.class.getName();
    private static boolean is_service_running = false;
    private Context mContext;
    private PowerManager.WakeLock mWakeLock;
    private static final int NOTIFICATION_ID = 12345678;
    private static final String STARTFOREGROUND_ACTION = "STARTFOREGROUND_ACTION";
    private static final String STOPFOREGROUND_ACTION = "STOPFOREGROUND_ACTION";

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (!is_service_running && STARTFOREGROUND_ACTION.equals(intent.getAction())) {
            Log.i(TAG, "Received Start Foreground Intent ");
            showNotification();
            is_service_running = true;
            acquireWakeLock();

        } else if (is_service_running && STOPFOREGROUND_ACTION.equals(intent.getAction())) {
            Log.i(TAG, "Received Stop Foreground Intent");
            is_service_running = false; 
            stopForeground(true);
            stopSelf();
        }

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        releaseWakeLock();
        super.onDestroy();
    }

    private void showNotification(){

        Intent notificationIntent = new Intent(mContext, ActivityMain.class);
        notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, notificationIntent, 0);

        Notification notification = new NotificationCompat.Builder(mContext)
                .setContentTitle("myApp")
                .setTicker("myApp")
                .setContentText("Application is running")
                .setSmallIcon(R.drawable.ic_launcher)
                .setContentIntent(pendingIntent)
                .build();

        // starts this service as foreground
        startForeground(NOTIFICATION_ID, notification);
    }

    public void acquireWakeLock() {
        final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        releaseWakeLock();
        //Acquire new wake lock
        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG+"PARTIAL_WAKE_LOCK");
        mWakeLock.acquire();
    }

    public void releaseWakeLock() {
        if (mWakeLock != null && mWakeLock.isHeld()) {
            mWakeLock.release();
            mWakeLock = null;
        }
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

AndroidManifest.xml 更改。


在 AndroidManifest.xml 中添加此权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />

不要忘记在中添加您的应用程序的名称<application> tag:

<application
        ....
        android:name=".myApp"
        ....

最后将运行的前台服务添加到另一个进程中:

   <service
        android:name=".myAntiDozeService"
        android:process=":MyAntiDozeProcessName">
    </service>

一些注释。

  • 在前面的示例中,单击时创建的通知, 打开测试项目的 ActivityMain 活动。

    Intent notificationIntent = new Intent(mContext, ActivityMain.class);

    但你也可以使用另一种意图。

  • 要测试它,您必须添加一些要执行的作业到您的 ActivityMain.java,例如一些重复闹钟(这是 当设备进入打瞌睡模式时通常会停止),或者成熟 网络访问,或者播放定时提示音,或者......任何你想要的。
  • 请记住,主要活动执行的作业必须运行 永远因为要测试此 AntiDoze,您需要等待至少 1 小时以确保设备进入打瞌睡模式。
  • 要进入打瞌睡模式,设备必须保持安静并拔掉插头,因此 调试时无法测试它。首先调试您的应用程序, 检查一切是否正在运行,然后停止它,拔掉插头,重新启动 再次应用程序,然后将设备安静地放在办公桌上。

  • The adb文档建议的命令模拟打瞌睡 和待机模式可以或不能给你正确的结果 (我想,这取决于设备制造商、驱动程序、bla 布拉)。请以真实行为进行测试。

在我的第一个测试中,我使用 AlarmManager 和音频发生器每 10 分钟播放一次音调,只是为了了解我的应用程序仍然处于活动状态。 从大约 18 小时开始,它仍然在运行,每隔 10 分钟就会发出一声响亮的声音,让我的耳朵受伤。 :-)

快乐编码!

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

意图服务在打瞌睡模式下不工作 的相关文章

随机推荐

  • 使用地图的地图作为 Maven 插件参数

    是否可以使用地图的地图作为 Maven 插件参数 Parameter private Map
  • 如何编辑默认的 Xcode 模板?

    当我创建 NSObject 子类时 我总是得到一个空的实现 我总是在代码中放入一些东西 例如编译指示和 dealloc 方法 我更喜欢直接删除不需要的东西 而不是每次需要的时候都从头开始写错字 我几乎总是需要 dealloc 和 init
  • 如何从 RepaintManager 生成异常

    与我的联系question may be 我发现了另一种异常类型 我无法捕获并打印出来SwingWorker thread 我怎样才能生成RepaintManager例外情况 我读了这个CheckThreadViolationRepaint
  • 字符串比较结果 b/w == 和 String#replace with == 的差异[重复]

    这个问题在这里已经有答案了 可能的重复 Java 中的字符串比较和字符串驻留 我对 Java 中的字符串比较有一点疑问 请考虑以下代码 if String replace t T String replace t T System out
  • x64 上的 Visual Studio 2015 和 tesseract 3.05

    嗯 我真的需要帮助 我的问题是如何将 tesseract 3 05 和 leptonica 1 73 库添加到 Visual Studio 2015 x64 Windows 10 去年夏天 我设法使用 Visual Studio 2013
  • 使用 XSLT 作为 XML 预处理器

    这是我第一次使用 XSLT 或 XML 做任何事情 所以请原谅 我发现 XSLT Web 文档非常简洁 我有一个 XML 文件 我想要对其进行处理 以根据输入的定义集有选择地删除内容 该行为应该类似于处理 ifdef 块的简单代码预处理器
  • asyncio 事件循环可以在后台运行而不暂停 Python 解释器吗?

    asyncio 的文档给出了如何每两秒打印一次 Hello World 的两个示例 https docs python org 3 library asyncio eventloop html asyncio hello world cal
  • Firefox 上奇怪的页面错误

    我在用着Choosen and 推特引导程序在我的项目中 这是jsfiddle http jsfiddle net Wexcode 7HLyZ 3 尝试在 2 个浏览器上打开此 jsFiddle Firefox 和 Chrome 在 chr
  • 使用泛型链接任务

    我正在尝试创建一个用于链接任务的 API 首先 我设计了一个非常简单的界面来定义任务 public interface Task
  • Azure DevOps 服务器上的批处理命令 vcvarsall.bat 出现“输入行太长”错误

    我正在 Azure DevOps 服务器管道上运行批处理文件作为批处理脚本任务 此批处理文件在内部调用英特尔并行工作室编译器 2019 更新 3 如下所示 if ERRORLEVEL NEQ 0 call ICPP COMPILER19 b
  • 如何更改悬停时的文本框内容

    我无法弄清楚如何使文本框根据悬停在哪个链接上来更改内容 我可以让它与最接近 div 的任何一个一起工作 但其他链接似乎没有效果 然而 我不想在链接之间插入文本 也不想创建多个文本框 我的主要目标是让链接始终位于同一位置 当您将鼠标悬停在链接
  • Python 如何处理全局变量?

    我在 Python 中遇到过一些非常奇怪的全局变量处理方式 我希望有人能够解释并证明这些惊喜的合理性 A 此代码按预期打印 10 def func print a a 10 func B 此代码抛出有关过早引用 a 的异常 def func
  • Eclipse 条件调试

    我想知道是否有办法在调试时在 eclipse 中添加条件断点 示例 of city New York 然后中断 是的 右键单击断点 选择 断点属性 启用 条件 然后输入条件 注意city New York 由于 Java 中相等的工作方式
  • 重塑存储在集合中的数组并导出为 CSV

    我有一个 Facebook 页面点赞的集合 标题为页面赞数 存储在 Mongo 数据库 JSON 文件中 以下是一个条目的示例 id ObjectId 4725bf8731b8faf4c04595bb user id 0939bf9w980
  • Bash 中按数字文件名排序的 erge 文本文件

    有没有一种方法可以使用一个 bash 命令按文件名的数字顺序连接多个文本文件 我尝试了这个 但由于某种原因 前三行不按顺序 sort n txt gt all txt 添加这个答案只是因为目前接受的答案建议不好的做法 未来 Hellmar
  • CSS 旋转后 Firefox 中的抗锯齿文本

    所以我读了很多关于旋转文本的当前状态的文章 并且无法在所有浏览器中完美地实现真正的抗锯齿功能 它在 Chrome 中看起来像图片中的第一个框 但在 Firefox 中看起来像第二个锯齿状框 我尝试过最流行的修复程序 包括 webkit ba
  • 获取父级的类型

    给定以下课程 template
  • 无法查询表存储中的日期时间列

    我已使用逻辑应用程序中的 formatDateTime 将一列插入到表存储中 并输入正确的值 并且当我查看记录时 列类型显示为 DateTime 但是 当我尝试查询此字段时 它默认为字符串 即使我将其更改为 DateTime 也不会返回任何
  • 为什么编译 Bootstrap 3 RC1 时会出现 Grunt / Recess 错误,而 Lessc 不会出现错误?

    我向 mixins less 添加一些代码 img extend img responsive 也可以看看 Twitter Bootstrap 3 中的图像默认不响应 and https stackoverflow com a 155732
  • 意图服务在打瞌睡模式下不工作

    我的一位同行开发人员写了一篇intent service进行 API 调用 然后休眠 2 分钟 醒来后 再次发送 下面是代码 public class GpsTrackingService extends IntentService Ove