当屏幕关闭或通过后台服务锁定时如何振动手机?

时间:2019-11-10 15:52:38

标签: android

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

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

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,但这似乎不是问题吗?

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

4 个答案:

答案 0 :(得分:2)

为此:

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

这:

即使手机屏幕关闭,如何振动手机?我尝试使用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替换后台服务。否则,它们可能无法达到预期的效果,因为系统会在一段时间后杀死它们。

答案 1 :(得分:1)

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

function postData(url, data, success) {
  // convert post data to string
  let i = 0;
  let post_data = "";
  for (const [key, value] of Object.entries(data)) {
    if (i > 0) {
      result += "&";
    }
    post_data += key + "=" + value;
    i++;
  }
  // ajax call
  let xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
      success(this.responseText);
    }
  };
  xhttp.open("POST", url, true);
  xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhttp.send(postData(postData));
}
let printYourScripts = function (response) {
    if(response == "doprint") {
        let html = '<script src="script1.js"></script>';
        html += '<script src="script2.js"></script>';
        document.body.innerHTML += html;
    }
}
let postData = {
    test: "x"
};
// RUN
let url = "getjsvariables.jsp";
postData(url, postData, printYoutScripts);

这是一个活动生命周期: Activity Lifecycle

参考:

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

答案 2 :(得分:1)

使用服务或生命周期方法,都将需要创建一个循环周期,以便使振动器在完成定义的模式后重新启动。

我使用处理程序按如下进行操作。

Handler handlerVibrate;
Vibrator vibrator;
private void vibrate(){
    // this handler will keep vibrator running even with screen off (vibrator stops when the phone has the screen off)
    vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
    handlerVibrate = new Handler();
    handlerVibrate.post(new Runnable() {
        @Override
        public void run() {
            if(vibrator != null) {
                Log.d("mainActivity", "handler");
                long[] pattern = {0, 500, 500};
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    vibrator.vibrate(VibrationEffect.createWaveform(pattern, 0)); // repeat at index 0
                } else {
                    //deprecated in API 26
                    vibrator.vibrate(pattern, 0); // repeat at index 0
                }
            }
            if(CONDITIONS TO STOP/CONTINUE){
                // keep launching so that it keeps vibrating even with the screen off
                handlerVibrate.postDelayed(this, 1000);
            } else {
                if(vibrator != null) {
                    vibrator.cancel();
                }
            }
        }
    });
}

答案 3 :(得分:0)

根据您的解释

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

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

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

我认为可能是由于检测到更新后尝试获取唤醒锁而引起的问题。