0

When the activitiy is in the foreground, my app is doing things at night even though the phone should be sleeping. Wake log permission is NOT set.

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

But in the server log, I can see the app has accessed the server multiple times, depsite wake lock being off.

2014-12-02 20:58:15.755 200 2.56 KB 70ms /StorageEndpoint.getSignedUrls
2014-12-02 22:57:30.111 200 2.57 KB 150ms /StorageEndpoint.getSignedUrls
2014-12-03 00:57:04.359 200 2.56 KB 65ms /StorageEndpoint.getSignedUrls
2014-12-03 02:57:05.138 200 2.56 KB 154ms /StorageEndpoint.getSignedUrls
2014-12-03 04:56:14.456 200 2.56 KB 72ms /StorageEndpoint.getSignedUrls
2014-12-03 05:46:02.137 200 3.62 KB 551ms /SessionEndpoint.signinUser
2014-12-03 05:56:03.048 200 3.64 KB 269ms /SessionEndpoint.signinUser
2014-12-03 06:06:01.658 200 3.6 KB 209ms /SessionEndpoint.signinUser
2014-12-03 06:16:02.138 200 3.62 KB 309ms /SessionEndpoint.signinUser
2014-12-03 06:26:02.253 200 3.62 KB 274ms /SessionEndpoint.signinUser

In this post When will android stop its cpu without wake lock? @AksharPrabhuDesai explains that some other process may wake up the device, which explains why my app accessed the server in 10-minute intervals during the morning hours when the alarm came off.

But why did it access the server in 2-hour intervals at night? The two-hour interval is the time after which signed urls expire, and my app wants to renew them. But how come the device is awake precisely at the time due? Either my own app must keep it awake, or some other app. Is there a way to debug this, and is there a way to detect if a user is actually using my app or if the phone was woken up by some other activity?

--

Here is the code which makes the client connect to the server [I know it is not efficient and it hasn't been optimized yet]:

private static Subscription maintainSignedUrlsSubscription = Observable.timer(0, Constants.SIGNED_URL_MAINTENANCE_EVERY_SECONDS, TimeUnit.SECONDS)
        .flatMap(new Func1<Long, Observable<UploadItem>>() {

            @Override public Observable<UploadItem> call(Long aLong) {
                try {
                    // count URLs
                    List<SignedUrl> expiringUrls = new ArrayList<SignedUrl>(); // find urls which will expire soon
                    List<SignedUrl> expiredUrls = new ArrayList<SignedUrl>(); // find expired urls
                    for (SignedUrl url : Session.getSession().getApiSession().getSignedUrls()) {
                        if (System.currentTimeMillis() > url.getExpires() - 1000 * Constants.SIGNED_URL_EXPIRED_TOLERANCE_SECONDS) {
                            expiredUrls.add(url);
                        } else if (System.currentTimeMillis() > url.getExpires() - 1000 * Constants.SIGNED_URL_EXPIRING_TOLERANCE_SECONDS) {
                            expiringUrls.add(url);
                        }
                    }
                    Session.getSession().getApiSession().getSignedUrls().removeAll(expiredUrls);

                    int reserve_IMAGE_JPEG = 0;
                    int reserve_VIDEO_MP4 = 0;
                    for (SignedUrl url : Session.getSession().getApiSession().getSignedUrls()) {
                        switch (ContentType.valueOf(url.getContentType())) {
                            case IMAGE_JPEG: reserve_IMAGE_JPEG++; break;
                            case VIDEO_MP4: reserve_VIDEO_MP4++; break;
                        }
                    }
                    for (SignedUrl url : expiringUrls) {
                        switch (ContentType.valueOf(url.getContentType())) {
                            case IMAGE_JPEG: reserve_IMAGE_JPEG--; break;
                            case VIDEO_MP4: reserve_VIDEO_MP4--; break;
                        }
                    }

                    System.out.println("**** Uploader: stats: signed urls = " + reserve_IMAGE_JPEG + "/" + reserve_VIDEO_MP4 + " (jpeg/mp4), queue items = " + uploadItemsQueue.size() + "/" + delayedItemsQueue.size() + " (upload/delayed), queued files = "  + uploadFilesQueue.size() + "/" + delayedFilesQueue.size() + " (upload/delayed)"); // report all uploader stats here

                    List<SignedUrl> newUrls = new ArrayList<SignedUrl>();
                    if (reserve_IMAGE_JPEG < Constants.SIGNED_URL_MINIMUM_RESERVE_IMAGE_JPEG) {
                        System.out.println("**** Uploader: signed urls: requesting IMAGE_JPEG pack");

                        newUrls.addAll(StorageEndpoint.getSignedUrls(Session.getUser().getId(), ContentType.IMAGE_JPEG));
                    }
                    if (reserve_VIDEO_MP4 < Constants.SIGNED_URL_MINIMUM_RESERVE_VIDEO_MP4) {
                        System.out.println("**** Uploader: signed urls: requesting VIDEO_MP4 pack");

                        newUrls.addAll(StorageEndpoint.getSignedUrls(Session.getUser().getId(), ContentType.VIDEO_MP4));
                    }

                    Session.getSession().getApiSession().getSignedUrls().addAll(newUrls); // add new urls
                } catch (Exception e) { // can be IOException, ConcurrentModificationException
                    // fail silently
                }
                return Observable.just(null);
            }

        }).subscribeOn(Schedulers.newThread()).observeOn(Schedulers.newThread())
        .subscribe();

Can any of the rxjava people tell me how an Observable behaves - which emits in regular intervals - while Android should be sleeping? Do I need to put the Observable asleep explicitly?

Community
  • 1
  • 1
Oliver Hausler
  • 4,900
  • 4
  • 35
  • 70
  • You know it would really help to see some code. Are you using a `SyncAdapter` or `AlarmManager` or something like that? Are you preforming periodic updates to or from the server? – Xaver Kapeller Dec 03 '14 at 16:23
  • No alarm managers or anything the like. The code is in an rxjava Observable which fires every few seconds to do maintenance. The code is meant to run while the device is awake and I have no intention to run it while the device is asleep. In the code, the client checks if it needs anything from the server and calls a rest endpoint in case it does. So this is purely a pull operation which is initiated by the app. – Oliver Hausler Dec 03 '14 at 17:44
  • 1
    You need to do `unsubscribe` when the device becomes asleep. RxJava will use some background threads for timer. Looks they cannot be suspended by Android. – zsxwing Dec 04 '14 at 03:40

0 Answers0