Office Hours — Today, February 10

Yesterday, February 9

Feb 10
7:20 PM
Mark M.
has entered the room
7:25 PM
Mark M.
turned on guest access
7:30 PM
Jan v.
has entered the room
Jan v.
Hi Mark :)
7:35 PM
Mark M.
hello
sorry if there was a short delay there
they disabled the beeps on this chat
gonna drive me nuts 'til I write a replacement chat app
anyway, how can I help you today?
Jan v.
I'm going to paste in some framework and questions...
View paste (9 more lines)
An app with two primary, periodic functions:

1. Get GPS coordinates and Telephony info every ~10 seconds, log to a .csv file.

2. Http get and http put a file on a webserver every ~30 seconds, log up/down speed to a .csv file.

These logging tasks should be very robust - once started, logging must continue reliably.

Finally, a user interface:

a. Screen that shows latest results of loop 1, can start/stop loops.
b. Screen that shows latest results of loop 2, can start/stop loops.
c. Screen that shows map of current location.
d. Setup screen to adjust loop periods and server url.

...
Mark M.
oboy
Jan v.
Basically, I'm looking for some fundamental guidance on how to not mess it up totally.
Mark M.
first, is this an app for public distribution (e.g., Play Store), or for a more constrained audience (e.g., employees of a firm)?
Jan v.
No, very constrained, to say, a modern handset like a Nexus 5x
Mark M.
ok
with regards to 1+2, are you setting this up as some sort of kiosk app (i.e., your UI is guaranteed to always be in the foreground)?
Jan v.
I see where you coming from because Android itself is evolving fast
Mark M.
or is the user potentially switching between this app and other things (e.g., incoming calls)
?
7:40 PM
Jan v.
It's being envisioned as a "normal" app, i.e. it has to function around other potential apps.
Mark M.
Ok
in that case, you definitely need to use a service
Jan v.
Ok, check.
Mark M.
while the Application instance is around while your process is around, your process just won't be around all that long while your app is in the background, if you don't have a service
Jan v.
Will the service be essentially just to "keep the app open?"
Mark M.
it will be telling Android "hey, I'm workin' here!"
(delivered in a great Al Pacino impersonation)
more specifically, you probably want to use a foreground service, where you call startForeground() and put a Notification up
even then, your process will live for days, but probably not weeks
Jan v.
Ok, understood
Mark M.
#3, a ScheduledExecutorService seems like a reasonable choice, given your requirements
#4, um, use ViewPager
#5, use an in-process event bus (greenrobot's EventBus is my personal preference, though there's Square's Otto, plus LocalBroadcastManager)
#6 I don't understand, sorry
#7 hook the device up to a hydroelectric dam
because battery life is going to suck by definition
7:45 PM
Mark M.
a primary feature of this app appears to be to drain the battery as fast as possible
:-)
as it stands, you need the CPU to be powered on 100% of the time (e.g., WakeLock)
GPS every 10 seconds will keep the GPS radio powered on 100% of the time
doing network I/O every 30 seconds will keep some radio (WiFi or cellular) in a mid-to-high power state close to 100% of the time
maybe the screen turns off
but otherwise, you're hitting on all the big sources of battery drain, and there's not a lot you can do about that, given the stipulations of your app
Jan v.
Right.
Mark M.
BTW, on Android 6.0, you're going to need to add this app to the battery optimization whitelist in Settings
otherwise, Doze mode will shut you down, along with everything else, if the device is not moving
Jan v.
The AlarmManager would have been nice, but minimum duty cycle is 60s.
7:50 PM
Mark M.
yup
Jan v.
Ok I'm chewing on your responses a bit, questions coming up in a few :)
Mark M.
no worries
ordinarily, I time-slice between folks, but it's just you at the moment
Jan v.
So, given a ScheduledExecutorService, would I create the two looping threads inside the service?
Mark M.
I'm not sure what the two looping threads are
you have two tasks scheduled in the ScheduledExecutorService
the every-10-seconds one and the every-30-seconds one
they each do their work
they post messages on an event bus for consumption by the UI layer, if that UI layer is around
7:55 PM
Jan v.
is that the "greenrobot" thingy?
Mark M.
your control screen tells the service when to start, stop, and change polling periods
greenrobot's EventBus is one of three major event bus implementations for Android, yes
the other two are Square's Otto and LocalBroadcastManager
the latter is part of the Android Support libraries, but it's not nearly as nice as the other two
I cover the event bus pattern in the chapter on threads
Jan v.
does it use the standard intent messaging ?
Mark M.
and I have a later chapter comparing and contrasting these three implementations
LocalBroadcastManager uses Intents, but only to provide an API that feels like traditional system broadcasts
Jan v.
ah ok
Mark M.
the other two libraries do not use Intents, which gives them more flexibility
none of the three can start a component (e.g., start an activity, start a service)
they are for inter-component messaging within a running process
and they provide a fairly nice pattern for decoupled communications, such as from a service back to the activities/fragments/whatever that make up the UI
there are other approaches to solving that problem, but I usually steer people to an event bus
Jan v.
So let's say the user activity has started the service which started the 10s and the 30s logging thread.
8:00 PM
Jan v.
If that service gets killed somehow, i would have to insert code that reads the run state from say, sharedPrefs, so when it gets restarted, it can take off where it was, right?
Mark M.
first, it's not so much that the service alone gets "killed", as your process gets terminated
that can happen naturally on Android, to free up system RAM for other processes, though the foreground service will minimize the occurrences
but, if the user powers down the device, the battery runs out, the battery *falls* out, etc., you won't have a running process anymore
any state that you care about needs to be persisted
what's in RAM is purely a cache or transient stuff
whether you use SharedPreferences or a SQLite database or some other sort of file is up to you
Jan v.
Ok.
What class would you choose for the two primary threads?
Mark M.
I don't really understand
Jan v.
or is that forced by the ExecutorService
Mark M.
ScheduledExecutorService takes a Runnable or a Callable as the thing that is the embodiment of the periodic work
Jan v.
ok
8:05 PM
Mark M.
usually, for this sort of thing, I'd use Runnable
Jan v.
ok, check with what i thought
when you run out of work in your runnable, you just return, right? The scheduler will take care of the next run, right?
Mark M.
yup
automagically :-)
Jan v.
yiha!
is the System Nano timer the best timing resource for accurate timing of the up and download tasks?
Mark M.
um, probably
haven't done much of that
8:10 PM
Jan v.
A viewpager, are you forced to use fragments or can you use viewgroups
Mark M.
ViewPager uses a PagerAdapter
PagerAdapter itself deals with views
however, PagerAdapter is abstract
the two concrete implementations are FragmentPagerAdapter and FragmentStatePagerAdapter
as you might guess, those use fragments
however, you can create your own PagerAdapter implementation that avoids the fragments
I have at least one example of that in the book
Jan v.
yay
\0/
if you have a file open that you're writing to, and you get destroyed, do you get some extra time to close your files or do you have to assume the absolute worst? If so, how do you avoid indeterminate file writes?
Mark M.
that depends on how your process is being terminated
8:15 PM
Mark M.
normally, the out-of-memory killer will trigger onDestroy() on all running activities and services in your process
however, that's not guaranteed (e.g., user force-stops you from Settings, battery runs out)
Jan v.
is there a way in adb to simulate some of the rarer events?
Mark M.
um, I assume that there's an adb command that's the equivalent of killing the process from the IDE
yes, adb kill your.application.id.here
Jan v.
ok
Mark M.
though that might not kill you if you are still in the foreground -- you'll have to experiment with it
usually, I kill the process from the IDE (e.g., Android Monitor tool window in Android Studio)
Jan v.
how would you modularize the code? i'm thinking screen1, screen2, screen3, service, runnable_10s, runnable_30s, setup, application, and maybe test?
with better names, of course
Mark M.
um, that's well beyond what I can advise here, given that I don't know a lot about the app
8:20 PM
Jan v.
regarding gps, do you suggest rigging up a listener or get_ system call for lat/long
Mark M.
um, I do not know what "get_ system call for lat/long" would mean
if you are using LocationManager, you have no choice really but to use requestLocationUpdates()
otherwise, the GPS radio won't turn on
unless something else happens to be requesting location updates via GPS
Jan v.
i'm stretching, but like telephony you have a pre-implemented system implementation that you conjure up and cast to (TelephonyManager)
wait - i will look
Mark M.
that would be LocationManager for locations
it's a system service
however, then it's not "listener or get_ system call" -- it's "listener *and* get_ system call"
you call getSystemService() to get the LocationManager
you call requestLocationUpdates() on the LocationManager to register the listener
Jan v.
ah yes, that's it
ok check
8:25 PM
Jan v.
Mark, thanks for all the great insights. You probably saved us a few days!
Mark M.
happy to be useful
Jan v.
Enough from me for now, talk to you soon :)
Mark M.
OK, sounds good
note that the chat transcript will be posted to https://commonsware.com/office-hours/ shortly after the chat ends
Jan v.
Noted. Thanks!
8:30 PM
Jan v.
has left the room
Mark M.
turned off guest access

Yesterday, February 9

 

Office Hours

People in this transcript

  • Jan van Niekerk
  • Mark Murphy