屏幕关闭/锁定后手机振动停止工作

问题描述 投票:7回答:3

[我有一项服务可以检查我的网站上的更新,并且即使屏幕关闭或锁定,我希望它能够在发现更新时引起振动。

当前仅在屏幕未关闭/锁定的情况下,振动才起作用。即使屏幕处于关闭/锁定状态,所有其他功能都可以使用。

Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
   long[] pattern = new long[]{0, 400, 200, 400};
   if (Build.VERSION.SDK_INT >= 26) { // New API
     vibrator.vibrate(VibrationEffect.createWaveform(pattern,0));
   } else { // Old API
     vibrator.vibrate(pattern, 0);
}

即使手机的屏幕关闭,如何振动手机?我尝试使用WakeLock,但这似乎不是问题吗?

我已设置所有权限,因为它在屏幕打开时可以正常工作。

java android android-service android-vibration
3个回答
1
投票

您可以尝试添加一个接收器来控制屏幕逻辑的开/关:

public class ScreenReceiver extends BroadcastReceiver {

    public static boolean wasScreenOn = true;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // DO WHATEVER YOU NEED TO DO HERE
            Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            long[] pattern = new long[]{0, 400, 200, 400};
            // Only perform this pattern one time (-1 means "do not repeat")
            v.vibrate(pattern, -1);
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // AND DO WHATEVER YOU NEED TO DO HERE
            wasScreenOn = true;
        }
    }

}

public class ExampleActivity extends Activity {

   @Override
    protected void onCreate() {
        // INITIALIZE RECEIVER
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        BroadcastReceiver mReceiver = new ScreenReceiver();
        registerReceiver(mReceiver, filter);
        // YOUR CODE
    }

    @Override
    protected void onPause() {
        // WHEN THE SCREEN IS ABOUT TO TURN OFF
        if (ScreenReceiver.wasScreenOn) {
            // THIS IS THE CASE WHEN ONPAUSE() IS CALLED BY THE SYSTEM DUE TO A SCREEN STATE CHANGE
            System.out.println("SCREEN TURNED OFF");
        } else {
            // THIS IS WHEN ONPAUSE() IS CALLED WHEN THE SCREEN STATE HAS NOT CHANGED
        }
        super.onPause();
    }

    @Override
    protected void onResume() {
        // ONLY WHEN SCREEN TURNS ON
        if (!ScreenReceiver.wasScreenOn) {
            // THIS IS WHEN ONRESUME() IS CALLED DUE TO A SCREEN STATE CHANGE
            System.out.println("SCREEN TURNED ON");
        } else {
            // THIS IS WHEN ONRESUME() IS CALLED WHEN THE SCREEN STATE HAS NOT CHANGED
        }
        super.onResume();
    }

}

以下是活动生命周期:Activity Lifecycle

参考:

https://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/


1
投票

给出此:

[我有一项服务可以检查我的网站上的更新,并且即使屏幕关闭或锁定,我希望它能够在发现更新时引起振动。

还有这个:

即使手机的屏幕关闭,如何振动手机?我尝试使用WakeLock,但这似乎不是问题吗?

我得出一个结论,当您的应用程序位于前台时,您的服务正常运行,而当其后台运行时,则没有问题。因此,您的目标Android API最有可能是26及更高版本。

在这种情况下,由于操作系统施加的背景限制,您的更新服务将在一段时间后停止工作。显然,由于更新服务不再运行,因此它无法启动任何振动。

API的背景执行限制> = 26

[从Android 8.0开始,在后台运行哪些应用程序受到限制。因此,您的服务将工作一段时间,然后将被文档中所述的系统杀死(请阅读更多here):

[当应用进入后台时,它会显示多个窗口在几分钟之内仍然可以创建和使用服务。在在该窗口的末尾,该应用程序被视为处于空闲状态。在这时间,系统会停止应用程序的后台服务,就像应用程序调用了服务的Service.stopSelf()方法。

因此,如果您希望服务在后台运行时继续运行,您仍然可以选择。其中一些如下

WorkManager

WorkManager API使计划可延期的,异步的计划变得容易即使应用程序退出或设备仍有望运行的任务重新启动。

WorkManager替换服务,该服务会定期运行以查询服务器。

JobScheduler

嗯,如果您使用WorkManager,则实际上并不需要它。如果您的设备API为WorkManager及更高版本,它将由23内部使用。

前台服务

将您的服务转换为前台服务,以便在执行该应用程序时将其视为前台。但是在这种情况下,它必须在您执行更新检查的整个过程中都处于活动状态,因此,它并不是最佳解决方案。请阅读更多here

结论

请记住,应该从API WorkManager开始用Foreground Service26替换后台服务。否则,它们可能无法按预期运行,因为系统会在一段时间后将其杀死。


0
投票

根据您的解释

我有一项服务可以检查我的网站上的更新

您会定期检查网站更新。在尝试连接到服务器之前,请确保获取唤醒锁,否则应用程序将无法连接,否则应用程序将无法连接到Internet。

[如果在屏幕关闭时无法获取唤醒锁的情况下,也可以通过显示通知或按照this answer来尝试以编程方式打开屏幕。

我相信可能是由于检测到更新后您试图获取唤醒锁而引起的问题。

© www.soinside.com 2019 - 2024. All rights reserved.