Mar 15 | 3:50 PM |
Mark M. | has entered the room |
Mar 15 | 3:55 PM |
Mark M. | turned on guest access |
Janice | has entered the room |
Mark M. |
hello, Janice!
|
Mark M. |
how can I help you today?
|
Janice |
Hi Mark. Have to start off with a message of thanks for your books
|
Mark M. |
you're welcome!
|
Janice |
I received a Grow with Google Udacity scholarship, and I have been talking them up all over the Slack group
|
Janice |
I have a question more about how to think about an Android problem rather than how to actually code it.
|
Janice |
I'm working on an app for a local non-profit. The users will have very limited data plans so I need to take that into account.
|
Janice |
They want to display a list of contacts of staff members (list and detail view) as well as events (also list-detail view).
|
Janice |
I'll be grabbing those resources from a Google Calendar and a Google Sheet (easiest way for someone non-technical to update information)
|
Janice |
I'm using Room architectural component and I've gotten to the Repository.
|
Mar 15 | 4:00 PM |
Janice |
I know this is where I need to coordinate both retrieving this information from the cloud and persisting it to the db
|
Mark M. |
so far, so good
|
Janice |
View paste
|
Mark M. |
you would have to ask your users what a good profile would be
|
Janice |
2. the contacts are unlikely to change very often, so I'm not terribly worried about how to merge any new information in with old information. The calendar events, though, are a different matter.
|
Mark M. |
with regards to polling frequency: for example, if they will only be updating the data during business hours on weekdays, there's no sense in checking for updates much outside of that window
|
Mark M. |
how frequently you check within that window may be up to the OS as much as you, given Doze mode on Android 6.0+
|
Janice |
Makes perfect sense.
|
Janice |
this is where my newbie kicks in (I've been learning Android for 2+ years, but this is the first time I'm combining cloud data with a SQLite db)
|
Mark M. |
so, maybe check once an hour, bearing in mind that it might wind up being less frequent, and perhaps giving users control via manual refresh or a settings screen to change the polling frequency
|
Janice |
Also makes sense.
|
Mark M. |
in terms of the calendar events, are you directly accessing the online calendar, or is it syncing with the local device calendar and you're using CalendarContract for accessing the local copy?
|
Mar 15 | 4:05 PM |
Janice |
Sorry. I'm formulating question and It's taking longer than I would like.
|
Janice |
Directly accessing the online calendar
|
Janice |
The non-profit keeps a Google calendar which is available for anyone to see
|
Janice |
Not CalendarContract. I was going to use the Calendar API.
|
Janice |
Then store those events in the local db.
|
Mark M. |
is the calendar data read-only on the device, or are you accepting local changes and pushing them to the calendar?
|
Janice |
Yes, on the device it will be read only. No local changes.
|
Mark M. |
if there aren't a ton of entries, you could take the brute-force approach of completely overwriting the local copy on every update
|
Janice |
Keeping in mind the data saving aspects, and sorry if this is a stupid question, is it wiser to . . . .
|
Janice |
Yes, that was the question I was about to ask. Exactly it.
|
Mark M. |
I don't know the Google Calendar API, so I don't know if they offer some sort of per-event last-updated timestamp or something
|
Janice |
I'm nervous about having to update changed events.
|
Mark M. |
at the level of an individual event, I'd just delete the local copy and replace it with what you download
|
Janice |
Again, you anticipated my question.
|
Mark M. |
in terms of bandwidth, ideally you could ask the Calendar API "what events have changed since such-and-so time", or the equivalent
|
Janice |
Never thought about this, but I wonder how much data per event (on average)
|
Mark M. |
but, again, I don't know that API, so I don't know what the options are there
|
Mark M. |
usually a calendar entry is small (e.g., vCalendar/iCalendar specs), though Google could have additional stuff that could be large
|
Mark M. |
for example, if you can attach a photo or something to an event
|
Janice |
No, no worries about not knowing the API. I can figure that out. Mostly the problem is that I'm coding in a vacuum (by myself) and sometimes I get stuck in a mental loop
|
Mar 15 | 4:10 PM |
Janice |
So if I limit my query to only specific fields (excluding photos) I limit the size of the event. Makes sense.
|
Mark M. |
if they offer that, and you don't need the larger data, that's one way to help ensure low bandwidth
|
Janice |
The calendar API does offer that.
|
Janice |
One last question, please?
|
Mark M. |
sure!
|
Janice |
So with the repository we no longer have to worry about AsyncTask and lifecycle events.
|
Janice |
But. Is an Asynctask long enough in duration to do such a task, or should a service be used?
|
Janice |
Best practices wise?
|
Janice |
I've seen AsyncTask used this way, but that could result in an ANR, yes?
|
Mark M. |
a repository shouldn't need AsyncTask, as a repository shouldn't need to do work on the main application thread
|
Mark M. |
the repository should use other stuff (plain threads, SchedueledExecutorService, RxJava, etc.) for background I/O
|
Janice |
But Asynctask has a separate thread built in ..
|
Janice |
Oh.
|
Mark M. |
the point of AsyncTask is to do work on the main application thread after the background work is done
|
Janice |
Huh. Didn't occur. But it should have
|
Mark M. |
with the repository, those things are more decoupled
|
Janice |
Yes, it is, and I feel stupid now.
|
Mark M. |
so the repository can be pure background, and you use other stuff (e.g., LiveData) to get the data to the main application thread when needed
|
Mark M. |
anyway, in terms of whether you need a service... that depends
|
Janice |
Yes, I'm using LiveData and Observers
|
Janice |
depends on?
|
Mark M. |
if the work is likely to take more than a few seconds, a service is probably a good idea
|
Mark M. |
if the work is likely to be much shorter than that, a service is probably unnecessary
|
Mar 15 | 4:15 PM |
Mark M. |
the risk is if you kick off the background work, the user switches to some other app, and Android decides to terminate your process to free up system RAM
|
Janice |
So, again, taking into account the users (low income teens) will have "starter" phones, an assuming a possible connection speed, a service could be warranted?
|
Mark M. |
the longer the user is away, the more likely it is that your process gets terminated
|
Lynn Z. | has entered the room |
Lynn Z. |
Hello!
|
Janice |
Isn't there a way to prioritize the app while the service is out doing work? I thought there was, but my memory fails
|
Mark M. |
hello, Lynn! I will be with you shortly!
|
Janice |
Sorry. Prioritize the app's outstanding service
|
Mark M. |
Janice: well, a service helps keep your process around
|
Mark M. |
which is why if the work may take more than a few seconds, a service may be a good idea
|
Ed T. | has entered the room |
Mark M. |
but, it depends on the work as much as anything
|
Janice |
Thank you.
|
Mark M. |
(BTW, hello, Ed! I'll be with you shortly, after Lynn!)
|
Janice |
You have helped immensely.
|
Mark M. |
Janice: great! let me take questions from the others, and I'll return to you in a bit
|
Lynn Z. |
here it comes:
|
Janice |
All done. Thank you so much Mark!
|
Lynn Z. |
View paste
|
Mark M. |
Lynn: your turn! do you have a question!
|
Lynn Z. |
hmm pasting it is not very friendly to others viewing
|
Mark M. |
Lynn: if you return and have a question, chime in
|
Mark M. |
Ed: do you have a question?
|
Mar 15 | 4:20 PM |
Ed T. |
I do, thanks Mark
|
Janice | has left the room |
Lynn Z. |
Hmm, i pasted my pretyped question. you don't see it? I'll type instead
|
Ed T. |
I see it after a 'refresh'. fyi
|
Mark M. |
OK, if *anyone* has a question, go right ahead
|
Lynn Z. |
I have delivered a signed APK to a client who uses and MDM to wrap the app for enterprise deployment. The wrapping tool has a known 'limitation' (bug?) where it blacklists certain characters
|
Lynn Z. |
from filenames in the APK so fails to wrap it
|
Lynn Z. |
THere are filenames in my APK that start with a '$' and are the culprit
|
Mark M. |
wow, sorry -- having update problems here
|
Lynn Z. |
1 is from my adaptive icon file $ic_launcher_background__0.xml and the other 6 are from the design library $avd_show/hide_password__0/1/2.xml
|
Lynn Z. |
how can i remove these? should I? why are they there?
|
Lynn Z. |
(it's ok, i'm getting a typing exercise)
|
Ed T. |
lol
|
Lynn Z. |
thanks for patience Ed!
|
Mark M. |
that's a strange filename
|
Mark M. |
or, more accurately, a strange directoy
|
Mark M. |
er, directory
|
Lynn Z. |
Can I remove files during the build process come from a 3rd party library? do these files event belong there?
|
Lynn Z. |
these are files
|
Mark M. |
beats me -- they don't look familiar, but I haven't rummaged through an APK looking for something like that recently either
|
Mark M. |
is $avd_show directly in the APK root, or in some subdirectory?
|
Mar 15 | 4:25 PM |
Lynn Z. |
in the res/drawable-v21 directory
|
Mark M. |
what version of the Support Libraries are you using?
|
Lynn Z. |
ugh, i am now having refresh problems and cant see anything I just typed...
|
Mark M. |
yeah, Campfire isn't having a good day -- which is odd, as they are fairly reliable
|
Lynn Z. |
they are in the res/drawable-v21 folder
|
Mark M. |
what version of the Support Libraries are you using?
|
Lynn Z. |
View paste
|
Lynn Z. |
can you see this pasted ^
|
Mark M. |
yes
|
Lynn Z. |
27.0.1
|
Lynn Z. |
and presumably my apps file: /res/drawable/$ic_launcher_background__0.xml
|
Lynn Z. |
sorry, 27.0.2
|
Mark M. |
they are vector drawables and animation resources, it appears
|
Lynn Z. | |
Lynn Z. |
right, but what of the $xxx __0.xml versions?
|
Mark M. |
again, they are vector drawables and animation resources
|
Mark M. |
the design library itself does not have those resources
|
Mark M. |
so the $ stuff must be added by AAPT2 or something
|
Mark M. |
this probably isn't going to be unique for you
|
Lynn Z. |
where do they come from and why would they be in the APK ?
|
Mark M. |
most likely, they are derived from other resources
|
Lynn Z. |
google has proved to be not helpful to me...
|
Mark M. |
for example, the design library has res/drawable-v21/avd_hide_password.xml
|
Mar 15 | 4:30 PM |
Ed T. |
that t-shirt would sell well :-)
|
Lynn Z. |
right, i've located it (ha! good idea Ed)
|
Mark M. |
that appears to be converted into three resources in the APK, two of which have the $ prefix
|
Mark M. |
looks like perhaps it's one file per frame of an animated vector
|
Mark M. |
regardless, it's not going to be unique for you
|
Lynn Z. |
I know the real fix is to get Citrix to fix their MDM wrapping tool, but that's not happening anytime soon probably
|
Mark M. |
so the MDM folk eventually have to fix their stuff
|
Lynn Z. |
hmm so, when would those 'frames' be generated?
|
Mark M. |
at build time, presumably
|
Mark M. |
you might try researching what specific class in the design library uses those
|
Mark M. |
then, see if you are using that class
|
Lynn Z. |
plus, with a name like avd_*** I would think it would be emulator resources
|
Mark M. |
if not, try more aggressively minifying your resources to see if you can get rid of it
|
Mark M. |
but, if you're using the class that needs the resources... you're probably stuck
|
Mark M. |
I think that's "animated vector drawable"
|
Lynn Z. |
no way for me to exclude resources that come from 3rd party lib right?
|
Mark M. |
= avd
|
Mark M. |
not directly, but the minification process might remove them if you do not need them
|
Mark M. |
frankly, I haven't fussed with that much, so I don't know its limits
|
Lynn Z. |
ohhhh there just aren't enough acronyms! they should have called it $avd to fix collision haha wait, they did haha
|
Mark M. |
let me take a question from Ed, and I will return to you shortly
|
Lynn Z. |
no problem!
|
Mark M. |
Ed: sorry for all the delays! do you have a question?
|
Ed T. |
no worries
|
Ed T. |
question is around a RecyclerView
|
Ed T. |
I get how it works and I've done a few of the 'plain' items
|
Mar 15 | 4:35 PM |
Ed T. |
my approach has been to have a 'list' layout
|
Ed T. |
and an 'item' layout
|
Ed T. |
Recycler is the only thing in the List layout
|
Ed T. |
and then my 'row' is in the item and I 'bind' that with the Adapter / Holder
|
Ed T. |
did I describe it well enough?
|
Mark M. |
so far, so good
|
Ed T. |
my question is next
|
Ed T. |
so I need a 'floating' header
|
Ed T. |
so if I had a list of animals
|
Ed T. |
I need a header for 'Reptile'
|
Ed T. |
'Mammal'
|
Ed T. |
things like that
|
Ed T. |
and that header needs a click even that describes that 'group'
|
Ed T. |
am I on the right path and is this doable ?
|
Ed T. |
I'm not sure how I bind something that isn't always 'there'
|
Mark M. |
well, there are a number of libraries that offer header support within RecyclerView
|
Mark M. | |
Ed T. |
thanks Mark!
|
Mark M. | |
Mark M. |
and probably others, pulling from https://android-arsenal.com/tag/199
|
Mark M. |
I also demonstrate headers in the book
|
Mark M. |
though mine might not be "floating"
|
Ed T. |
the book is so large... it doesn't play well with my reader. :(
|
Mark M. |
what reader?
|
Ed T. |
it doesn't need to float, so say...
|
Ed T. |
'Preview'
|
Ed T. |
on OSX
|
Mark M. |
try real Adobe Reader
|
Mar 15 | 4:40 PM |
Ed T. |
thanks Mark! I'm good. Appreciate the help
|
Ed T. |
will do on the reader item
|
Mark M. |
FWIW, my header example is: https://github.com/commonsguy/cw-omnibus/tree/v...
|
Mark M. |
the headers are just additional views, nothing special
|
Mark M. |
let me switch back to Lynn, and I'll return to you in a bit
|
Mark M. |
Lynn: back to you! do you have another question?
|
Lynn Z. |
well, how would I go about trying to find which class is causing that resource to get pulled in?
|
Mark M. |
look at the source code
|
Mark M. |
we know it has something to do with passwords
|
Lynn Z. |
right, so I know I'm not ever using that eyeball that is used for show/hide password
|
Mark M. |
are you using TextInputLayout?
|
Lynn Z. |
checking...
|
Mar 15 | 4:45 PM |
Lynn Z. |
I am
|
Mar 15 | 4:45 PM |
Lynn Z. |
yes, sir
|
Mark M. |
my guess is that TextInputLayout indirectly uses those resources
|
Ed T. |
most Enterprise systems scrub files for 'clear text' passwords. You could easily do a hash via Java but you would need to bundle a key to decrypt it. Not ideal but it would keep a simple 'sniff' test from failing....
|
Ed T. |
not sure if that is your issue... and Mark is the Android guru. ;-)
|
Mark M. |
since this isn't their own resource, but one from a library, I don't think it's that easy to change
|
Lynn Z. |
I can't very well not use it... also, lets say I could get rid of the $avd_show/hide_password files, that still leaves the $ic_launcher_background__0.xml file in my drawable directory
|
Mark M. |
that might be tied to adaptive icons
|
Mark M. |
though I'm not seeing that resource file in the projects that I'm looking at
|
Lynn Z. |
right, i'm sure it is because I created it in order to support adaptive icons (not the $ file version, the 'normal' version)
|
Mark M. |
again, the build tools are what are creating these files
|
Lynn Z. |
do you see it when you analyze an apk?
|
Lynn Z. |
it's not there until you create an apk
|
Mark M. |
not in the couple of projects that I looked at
|
Mark M. |
but my launcher icon might be set up differently
|
Lynn Z. |
er, in apk, not in source directory. (i may have created it incorrectly too)
|
Lynn Z. |
workaround has been to create unsigned apk, decompress, remove offending files, recompress and then sign APK ugh
|
Mar 15 | 4:50 PM |
Mark M. |
does the resulting app run?
|
Lynn Z. |
not maintainable as a workflow and unknown consequences of removing those files. I'm still waiting to hear if they can run it. I can install it on a device, but I need to see if they can wrap and deploy
|
Mark M. |
I mean, I doubt that those files are there for grins
|
Lynn Z. |
exaaactly
|
Mark M. |
something expects them to exist
|
Mark M. |
so while physically removing them might be possible... I can't imagine that being a viable approach
|
Lynn Z. |
yeah.. I know... which is why I bought my subscription yesterday :)
|
Mark M. |
so... I really don't know what to tell you
|
Mark M. |
I mean, other than unwinding the adaptive icon and trying to avoid TextInputLayout
|
Lynn Z. |
I'll try the optimizations suggested and breathe on the client to breathe on the MDM folks
|
Lynn Z. |
thank you
|
Mark M. |
sorry I didn't have a magic bullet for this one
|
Mark M. |
Ed: back to you! do you have another question?
|
Lynn Z. |
no worries. You've made me feel better about how much time I've spent on it. how soon are the chat file archives available? (today's chat)
|
Mark M. |
within a few minutes of the end of the chat -- it's a manual thing that I do when the chat ends
|
Lynn Z. |
gotchya
|
Mar 15 | 4:55 PM |
Lynn Z. |
Thanks again for some clues (and sanity verifications). Until next time...
|
Mark M. |
you're welcome!
|
Lynn Z. | has left the room |
Mark M. |
Ed: any other questions?
|
Mar 15 | 5:00 PM |
Mark M. |
that's a wrap for today's chat
|
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is Saturday, 7:30pm US Eastern
|
Mark M. |
have a pleasant day!
|
Ed T. | has left the room |
Mark M. | turned off guest access |