【问题标题】:Android Wear sleeps when launching Activity from WearableListenerService从 WearableListenerService 启动 Activity 时,Android Wear 休眠
【发布时间】:2014-08-22 15:37:13
【问题描述】:

我有一个向 Wear 发送消息的手持应用程序。当 Wear 应用收到消息时,它会启动一个 Activity。 Activity 会在启动后不久根据其他因素自行更新。

如果 Wear 设备在收到消息时完全处于唤醒状态,这一切都没有问题。

但是,如果 Wear 设备在收到传入消息时处于睡眠状态,则会发生以下三种情况之一:

  1. 根据我在日志中看到的内容,Activity 正在启动,但在 Wear 设备屏幕上不可见
  2. Activity 启动并且可见 - 但启动后更新没有发生
  3. 发布后更新仅部分发生

最常见的结果是#3。例如,如果 XML 有一个开始显示“msg”的文本字段,并且发布后更新将此文本更改为“收到的消息” - 实际显示的是“mess”。在这种情况下,触摸屏幕会唤醒设备,然后才会完成 UI 更新。

这一切的实现包括一个 WearableListenerService 子类:

public class ListenerService extends WearableListenerService {
    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        Intent i = new Intent(this, MessageReceivedActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(i);
    }
}

出于这个(简化)示例的目的,我让 Activity 启动一个线程,等待 1 秒,然后进行 UI 更新:

public class MessageReceivedActivity extends Activity {
    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_message_received);
        final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
        stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
            @Override
            public void onLayoutInflated(WatchViewStub stub) {
                mTextView = (TextView) stub.findViewById(R.id.text);
                new UpdateTask().execute();
            }
        });
    }

    private class UpdateTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... params) {
            try {
                Thread.sleep(1000);
            }
            catch (Exception ex) {
                Log.e(TAG, "UpdateTask.doInBackground: error sleeping", ex);
            }
            return null;
        }

        protected void onPostExecute(Void result) {
            mTextView.setText("something else");
        }
    }
}

我试过以下,都没有效果:

  • 在 Activity 的布局 XML 中添加了 android:keepScreenOn="true"
  • 在Activity的onCreate中添加了getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  • 在 ListenerService.onMessageReceived 中获得了 WakeLock(出于测试目的,直到 MessageReceivedActivity.onDestroy 才发布)

似乎因为 Wear 仅因传入消息而唤醒,所以它会在 UI 线程空闲的那一刻重新进入睡眠状态 - 即使有 WakeLock。还有其他方法可以让 Wear 保持清醒吗?

【问题讨论】:

  • android:keepScreenOn="true" 对我来说非常有效,但与您的设置不同的是,我没有从服务启动 Activity。在我的应用中,Service 会发布一个通知,当用户点击通知中的某个操作时,会启动一个布局中包含 android:keepScreenOn="true" 的 Activity。

标签: android wear-os android-wake-lock


【解决方案1】:

您所描述的情况是您的服务启动,这会唤醒 CPU,但在您有时间完成所有操作之前,CPU 会重新进入睡眠状态。

解决方案是使用唤醒锁来防止 CPU 在您的操作完成之前休眠。您可以发布您的唤醒锁代码吗?

还要确保您有权限。 ;)

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

【讨论】:

  • 感谢您的建议。我最终不得不放弃这种方法。不是让服务直接启动活动,而是服务生成通知。然后可以从通知中启动 Activity。所以我不再有原始代码可以在这里发布。然而,一般的想法是我在收到消息后立即获取唤醒锁,然后(至少只是为了测试目的)在启动的 Activity 被销毁时释放它。我确实在清单中有许可行。不幸的是,它仍然没有工作。
  • 很高兴你让它工作了,但是下一次要注意几个小时。wakelock 将保持唤醒状态以运行当前线程中的任何代码。但是,如果您随后从唤醒锁发布任何非同步后台任务,则不能保证在唤醒锁释放之前完成。
  • 如果您只需要在后台更新一些数据并且不需要用户与应用程序/活动交互,则部分唤醒锁可能特别有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2014-06-16
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多