简体   繁体   中英

Android Wear sleeps when launching Activity from WearableListenerService

I have a handheld application that sends a message to Wear. When the Wear app receives the message, it launches an Activity. The Activity then updates itself shortly after launch based on other factors.

If the Wear device is fully awake when it receives the message, this all works with no problem.

However, if the Wear device is asleep when it receives the incoming message, then one of three things happens:

  1. Based on what I see in the log, the Activity is being launched, but isn't visible on the Wear device screen
  2. The Activity launches and is visible - but the after-launch update doesn't happen
  3. The after-launch update only partially happens

The most common outcome is #3. For example, if the XML has a text field that starts off showing "msg" and the after-launch update changes this text to "message received" - what is actually shown is "mes". In this case, touching the screen wakes up the device and only then does it finish updating the UI.

The implementation of all this includes a WearableListenerService subclass:

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);
    }
}

For the purpose of this (simplified) example, I have the Activity starting a thread, waiting 1 second, then making a UI update:

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");
        }
    }
}

I have tried the following, all with no effect:

  • added android:keepScreenOn="true" to the Activity's layout XML
  • added getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) in the Activity's onCreate
  • acquired a WakeLock in ListenerService.onMessageReceived (for testing purposes, not released until MessageReceivedActivity.onDestroy)

It appears that because Wear only woke up due to the incoming message, it goes back to sleep the instant the UI thread becomes idle - even in spite of a WakeLock. Is there some other way to tell Wear to stay awake?

The situation you are describing is that your service launches, which wakes up the CPU, but then the CPU goes back to sleep before you have time to complete all your operations.

The solution to this is to use a Wakelock to keep the CPU from sleeping before your operation completes. Can you post your Wakelock code?

Also make sure you have permission. ;)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM