Office Hours — Today, March 1

Saturday, February 25

Mar 1
7:20 PM
Mark M.
has entered the room
Mark M.
turned on guest access
7:25 PM
the_new_mr
has entered the room
Mark M.
hello!
how can I help you today?
the_new_mr
hi Mark :)
how are things?
Mark M.
Android Things is somewhat interesting, though it's pretty rough right now
oh, no, wait... that's probably not what you meant...
:-)
the_new_mr
:)
haha. it's not... but good answer :)
how are things with *you*? ;)
Mark M.
busy as usual -- and you?
the_new_mr
hectic as usual :)
H_Walter
has entered the room
Mark M.
(BTW, hello, H_Walter -- I will be with you shortly!)
the_new_mr
speaking of hectic... i'm here to ask something related to work
do you remember before when i asked about the situation we were having with the null pointer exception on the context?
going back into last year here
Mark M.
ummm... vaguely
the_new_mr
i know you do a lot of chats so you may not remember
Mark M.
that rounds down to "no" :-)
the_new_mr
lol
well, basically, we were getting NPEs when trying to do context.getApplicationContext()
Mark M.
the_new_mr
so the context itself is null
Paul R.
has entered the room
the_new_mr
that's the one :)
Mark M.
(BTW, hello, Paul -- I will be with you after the_new_mr and H_Walter!)
7:30 PM
the_new_mr
so... the problem is the context
Mark M.
OK, what's your question?
Paul R.
Evening. I cam prepared with questions about services. And will wait patiently to get my turn.
the_new_mr
for some bizarre reason, it's null
just a plain old context
Mark M.
right, and I thought it might be a timing thing due to configuration changes
the_new_mr
right
so you said to get the context and pass it to the constructor of the async task
which i did
but we're still getting the NPE
so it must be something else we're doing wrong
Mark M.
with the same basic stack trace?
the_new_mr
we actually have loads of different strack traces all over the code
all related to this
perhaps it's a general context thing...
Mark M.
"all over the code" -- you mean, from more than just the one fragment you cited from the earlier chat?
the_new_mr
yes
i was under the impression that we should always use the application context when passing it outside of the activity/fragment
but this seems to yield the NPE
is that understanding incorrect?
to prevent memory leaks
Mark M.
I am not certain what "passing it outside the activity/fragment" means
if you mean "stuffing something in a static field", then, yes, that needs to be the Application context
the_new_mr
like, say, to the preference manager
yes
in case it gets held in a reference somewhere
Mark M.
then perhaps you are not initializing the static fields lazily
the_new_mr
particularly a static reference
Mark M.
if your process gets terminated, your new process will not have the old values for those fields
7:35 PM
the_new_mr
well yes. but that doesn't seem to be the problem
today, a user demoed the app crashing while they were using it
Mark M.
um, well, no offense, but you aren't really giving me a lot to go on
the_new_mr
and i can't for the life of me think why the context would be null in this situation
ok. tell you what. chat to Walter and i'll try and get you some specific stuff
Mark M.
that's just what I was going to ask for -- I'll be with you in a bit
the_new_mr
i didn't get the chance to prepare before the chat like i had planned
Mark M.
H_Walter: your turn! do you have a question?
the_new_mr
ok
H_Walter
View paste
Hi Mark. First time here.
I have a personal (not published on the app store) app and can build both debug and release build types. I would like to have both versions present on my Pixel XL at the same time with different names. Is there an easy Android Studio configuration that will do this?
Mark M.
sure: use applicationId
assuming that by "different names" you mean "different package names", so they can be installed at the same time
H_Walter
Yes. Thanks. I'll look into it.
Mark M.
or, for debug/release, use applicationIdSuffix
drop it in buildTypes { debug { } } and your chosen suffix will be appended to your regular applicationId for the debug builds
that was a nice and easy question, with the downside being that I now get to take questions from the others :-)
I'll be back with you in a bit
Paul: your turn! you had a question?
Paul R.
I do. The info is in the clipboard so I'll paste it...
View paste
Overview: My application is a gaming/chat application for teaching simple games remotely, generally to young children, games like tic-tac-toe, checkers, chess, etc.  It uses Firebase to provide realtime chat and game data to multiple devices simultaneously.  It is now time to add a notifications feature to the app where the device User will receive notifications about new messages or game moves in the status bar iff the User is not "in" the room showing the game or messages. It is pretty clear that a service should provide this feature.  Now come the questions:

Notification Icons: Mostly, a device will support a single User, but there will be cases where a tablet or ChromeBook (supporting Android) will have multiple Users, a handful at most.  Should the status bar notifications be wrapped under a single icon for all Users or an icon per User?

Service Instances: Similarly, should there be one service supporting all Users or a service instance per User.  Unless I am mistaken, I think the framework has decided this already, only one service instance per class.

Process Model: In order to process notifications, the service needs to see every message change and game change event that 
...
7:40 PM
Mark M.
wow, that was epic :-)
Paul R.
The end got truncated. I'll post that after we deal with the first two questions.
Thamks. :-)
Mark M.
actually, I think I have it all, via the "View paste" link
Paul R.
cool
Mark M.
with regards to service instances, services are natural singletons, so you don't have many choices there
with regards to the process model, you could use android:process in the manifest to have one of the components (e.g., the service) be in a separate process
Paul R.
Good, I understand that correctly.
Mark M.
IMHO, having some long-running durable process for a game may not go over all that well, but that's just me
Paul R.
That opens up a question: is this a good idea or bad to have separate processes.
Mark M.
you take up more memory, and you now incur IPC overhead and limitations for communications to the service
OTOH, Android can terminate the non-service process, freeing up that system RAM sooner
H_Walter
has left the room
Mark M.
a very well-written app, using onLowMemory() and kin, can get much of the same memory savings with a single process, but that's hard
Paul R.
Sounds like one process for both activity and service is not a good idea.
Mark M.
it is the simplest way to jettison the UI memory
I am a bit of a curmudgeon on the subject, as I remember the old days with low-RAM devices
and, if your app might be distributed to Android One markets, you have low-RAM devices there too
7:45 PM
Mark M.
with regards to the notifications... is a User something independent from Android's concept of user accounts?
Paul R.
My app User is essentially an Android account User.
Mark M.
I haven't played with notifications in a multi-user scenario, but I would be surprised if one user can see another user's notifications
privacy, and all that
so I suspect that you have no choice but one notification per user
Paul R.
I'll check that out with Hangouts. I use multiple accounts with hangouts.
Mark M.
assuming that "is essentially" really means "is", as you either are or are not relying on Android's multi-user support, AFAIK
Paul R.
I am relying on the fact that there will be multiple accounts on the device.
Mark M.
yeah, I haven't done much work with that in general, let alone with notifications
Paul R.
They can be facebook, twitter, etc.
Mark M.
um, no, that's not what I meant
Settings > Users
7:50 PM
Mark M.
(on Android 4.2+ tablets and Android 5.0+ devices)
that's what I am referring to
Paul R.
In that case, I have in mind only a single User.
Mark M.
then you could go either way on the notifications, assuming that the small icons would differ by User
if the small icons would be identical per User, you are better off grouping them, IMHO
but, that's more of a design/UX opinion, more so than a hard-and-fast rule or anything
let me take another question from the_new_mr, and I'll swing back to you in a bit
Paul R.
Grouping would be my preference.
Mark M.
the_new_mr: back to you!
Paul R.
OK
Mark M.
the_new_mr: are you there?
the_new_mr: when you return, chime in and let me know that you are around
Paul: back to you in the meantime
Paul R.
ok, a question about data sizes
7:55 PM
Paul R.
My estimate is that on average, over many days, the data size will be constant and in the ballpark of tens of KBytes. I think that is tiny, even for Android One. Would I be wrong?
the_new_mr
back when ready
Mark M.
(the_new_mr: OK, one moment)
the_new_mr
sure
Mark M.
Paul: data size... in memory? on disk? something else?
Paul R.
in memory
Mark M.
well, there should be a second copy of all your classes
or at least the ones that you touch
I'm hazy as to how the AOT compilation on Android 5.0+ affects that sort of thing
so, the second process is definitely more heavyweight than just the objects that you instantiate
Paul R.
btw, classes.dex is tiny too.
the size is in resources, all in the activity.
Mark M.
:: shrug :: adding android:process takes less time than it does to type in a chat entry :-)
try it, and see what the system reports for your RAM usage
now, if it will break your activity <-> service communication, that may be a longer test
Paul R.
Good enough. Just wanted to check to see if my thinking was brain-dead. :-)
Mark M.
let me switch back to the_new_mr for realz, and I'll be back with you in a bit
the_new_mr: OK, back to you!
the_new_mr
ok
8:00 PM
the_new_mr
so.... let me ask a few general questions first if you don't mind
Mark M.
go ahead
the_new_mr
when passing context, say to an async task or to the preference manager (or to something that might pass it to the preference manager or similar), it's generally better to pass the application context, right?
Mark M.
I would phrase it as: you want the lifespan of the use of the Context to match the lifespan of the Context
the_new_mr
right...
so application context where its lifespan may outlive the thing you're passing it from
Mark M.
so, for example, PreferenceManager.getDefaultSharedPreferences() should be safe to call with just the activity as the context
the_new_mr
ok...
and, is there an advantage to doing so?
Mark M.
in that specific case? no
the_new_mr
i mean, using the activity?
ok. in other cases?
Mark M.
the activity as a context is important for UI work
the_new_mr
right
Mark M.
the_new_mr
so that you don't have to traverse the whole app
Mark M.
no, it's more so that your styles and themes work
the_new_mr
ok... that looks like a good read
Mark M.
yes, it's my go-to resource for "when to use what context"
the_new_mr
i see. ok
thanks for that
still learning android by the way... as you can probably tell :)
Mark M.
this is a funky area
the_new_mr
tell me about it!
ok...
Mark M.
so, let's take your AsyncTask scenario
the_new_mr
another general question...
Mark M.
OK
8:05 PM
Mark M.
sorry, go ahead with your next question
the_new_mr
storing the context as a static reference is a bad idea because of memory leaks, right? but is this a bad idea when it comes to storing the application context as a static member in the application class (or rather, a class that extends the application class)
Mark M.
storing a context other than Application represents a leak
the_new_mr
because the application class is over-arching
Mark M.
Application is a process-wide singleton
the_new_mr
yes, that's what i was thinking
Mark M.
or, as I like to describe it, Application is pre-leaked
you cannot leak it further
the_new_mr
it exists as long as everything else exists
ha, right
Mark M.
for 99.99% of the life of your process, yes
the_new_mr
ok. so that answers that one. so far, my understanding seems correct
what about the 0.01%? :)
Mark M.
(it's a bit weird right when the process is starting up, if you also have ContentProviders, but that usually isn't an issue for most people)
the_new_mr
ah ok
now. part of our problems seems to be that getContext() itself returns null
Mark M.
getContext() called on what?
the_new_mr
not sure why. maybe because the fragment is detached from the activity or something
inside a fragment
Mark M.
that method was added in API Level 23
are you sure that you are using it? or is your minSdkVersion that high?
or are you using the fragment backport?
the_new_mr
backport
support v4
Mark M.
OK, I'll assume for the moment that it just returns the same thing as getActivity() does
the_new_mr
ok
anyway...
Mark M.
getActivity() will return null when your fragment is not attached to an activity
8:10 PM
the_new_mr
we have a static method in the application class that returns the static reference to the application context
i'm inclined to use this where we are having these NPE problems. is this a bad way to go?
i'll read that article obviously
Mark M.
it depends on what the context is used for
the_new_mr
yeah
i guess the article will help with that
say to get values from shared preferences
Mark M.
in the previous chat, you were trying to access SharedPreferences from doInBackground() of an AsyncTask kicked off by the fragment
the_new_mr
yes. actually, looking at the crashes, it seems your solution did help after all so apologies for that
Mark M.
OK, that's good
the_new_mr
but, as i was saying, we're having context issues elsewhere
Mark M.
while you can paper over the problem by using the Application context, you have deeper issues
the_new_mr
i think so at least... we're using splunk mint for crash reporting and it's not the best
not bad but not amazing
hmmm... yeah
true for sure
Mark M.
I am worried about what you are doing, and when, that is trying to use getContext() on a fragment and you are getting null
the_new_mr
don't i know it!
yes
Mark M.
this is one of the reasons I don't like the "use a static Application reference" solutions
IMHO, you're kicking the can down the road
and you'll eventually get bitten by the problem in some other fashion
the_new_mr
honestly, dealing with legacy code, fire fighting, trying to get crash count down... i'm just trying to sort out the big fish at the moment and then get to the little fish when i can get the time!
yes, i know what you mean
clearly, the getContext returning null is an issue
Mark M.
what you might consider doing is making your change to Application, but making very careful notes about where and why you are doing it
the_new_mr
let me check the API reference... maybe the API level 23 thing you mentioned is part of the problem
Mark M.
so when you can devote the time, you can try to figure out the underlying issue
the_new_mr
yeah
8:15 PM
the_new_mr
some comment with a codeword. that's a good idea
Mark M.
and with that, let me give Paul another shot -- with luck, I'll be back with you before the chat ends
Paul: do you have another question?
Paul R.
The approach seems ok: app starts service in a separate process and binds to the service. Service forwards data until bind is broken. Then service collects data while app is dead (unbound) to provide notifications. When the app is running in the foreground again, service dumps the data to the app. Seems clean. You agree?
the_new_mr
ok
Mark M.
you'll need to both start and bind to the service to get that effect, but you're presumably doing that already
the_new_mr
that's the getContext reference when you're finished with Paul
Mark M.
and you'll need to think through the triggers for clearing those notifications, when they are no longer needed
otherwise, that seems reasonable
Paul R.
Yup. What constitutes a "large" amount of data that should give me pause to reconsider the approach?
Mark M.
reconsider what aspect of the approach? using two processes?
having a long-running service in general?
Paul R.
Holding data in the service.
for a long time.
Mark M.
well, that data would have to just be a cache, as you cannot guarantee that the service will be around for a long time
your clear upper bound is your heap limit
personally, I'd want that process to be leaner than that
a few MB, tops
but, that's me, not a system requirement
Paul R.
That's a fair answer. And much appreciated.
8:20 PM
Mark M.
the heap limit is the system's way of trying to ensure that all apps "play fair" with respect to sharing system RAM
the longer your process might be around, the greater the need to tighten the proverbial belt
consider overriding onTrimMemory() in the service and using that to prune back the cache
Paul R.
The process can be around forever. The key is to make sure the cache gets drained from time to time.
Mark M.
yup, that's what onTrimMemory() is for, plus any other internal triggers that you want (e.g., time-based)
Paul R.
Setting an upper bound on the cache is reasonable.
Mark M.
LruCache helps with that
Paul R.
I'll look into the method.
Is that a class?
Mark M.
LruCache is, yes
pretty much what it says on the box: it's a least-recently-used cache implementation
Paul R.
Perfect.
Mark M.
either by # of objects or their size, depending on your implementation
Paul R.
Thanks for your help. Talk to you soon I'm sure.
Mark M.
OK, sounds good
the_new_mr: back to you!
Paul R.
has left the room
the_new_mr
just reading that article
quality stuff!
Mark M.
Dave Smith is awesome
the_new_mr
really wish i'd known about it about two years ago :)
clearly
8:25 PM
the_new_mr
you're not bad yourself. i'd hire ya ;)
you have potential :p
Mark M.
I try
the_new_mr
:)
ok... so i checked that getContext for the v4 fragment
seems ok. no mention of api level 23. and i noticed crashes on marshmallow and above phones
so no issues there
so just must be that the fragment is somehow being detached
can't imagine why but that's for another day some day
i guess
Mark M.
it'll be detached on a configuration change
if the fragment is retained, it will be attached to a new activity instance shortly thereafter
the_new_mr
i have a feeling the fragments are not being handled properly in our app
i've noticed multiple calls to the lifecycle methods
legacy code with some serious issues
Mark M.
*to* the lifecycle methods?
the_new_mr
trying to make it better as much as we can
yes
Mark M.
other than chaining to the superclass, *calling* a lifecycle method is just plain evil
the_new_mr
oh.. not explicit calls
Mark M.
oh, whew
the_new_mr
yes, that is evil. nothing like that thankfully
Mark M.
you had me scared there for a bit
the_new_mr
:)
:)
i meant that they are getting calle
d
Mark M.
another thing that you might try doing is switching from getContext() to getActivity()
the_new_mr
which implies bad fragment management i guess, right?
8:30 PM
the_new_mr
i see...
ok. that might be worth a try
Mark M.
looking at the code for the backport, getContext() and getActivity()are independent
the_new_mr
ok. i might give that a go
thanks Mark. you've been very helpful as always
Mark M.
most of the "institutional knowledge" on this stuff is tied to fragments being hosted by activities, and using getActivity()
the_new_mr
greetings from the mother land btw ;)
Mark M.
pardon?
the_new_mr
Ireland
Mark M.
yeesh, it's late for you there
the_new_mr
it is
but this was the only time that suited this week
Mark M.
which means it's a fine time to note that we have run out of time for the chat
er, that wasn't really tied to your last comment
the_new_mr
ha. yes :)
Mark M.
more the "you should get some sleep" angle
the_new_mr
yeah, i got that
Mark M.
the next chat is tomorrow at 9am US Eastern
which is a more Ireland-friendly hour, at least
the_new_mr
yeah. had a meeting clash
Mark M.
ah
the_new_mr
then friday's i'm otherwise engaged
so had to be now
Mark M.
OK
the_new_mr
plus kinda wanted to get to the bottom of this
Mark M.
sorry if my switch of the chat time yesterday -> Friday messed things up for you
my site was suffering from S3 issues, like lots of others
the_new_mr
anyway... thanks and good evening/night :)
Mark M.
and I wasn't sure that was going to get cleared up in time
the_new_mr
no worries at all ;)
i didn't even notice
didn't check office hours till today :)
Mark M.
OK, well, have a pleasant rest of your evening!
the_new_mr
thanks. you too!
good night!!
the_new_mr
has left the room
Mark M.
turned off guest access

Saturday, February 25

 

Office Hours

People in this transcript

  • H_Walter
  • Mark Murphy
  • Paul Reilly
  • the_new_mr