Jun 13 | 8:55 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Dimitris K. | has entered the room |
Dimitris K. |
Hello Mark, good morning !
|
Mark M. |
hello, Dimitris!
|
Mark M. |
how can I help you today?
|
Dimitris K. |
Today I'm kinda interested in well structured code
|
Dimitris K. |
so basically I am reading some configuration files and in that files there are some set of rules
|
Dimitris K. |
the rules define when updates should happen (intervals), what time should updates occur, what the minimum inactivity time is and so on
|
Jun 13 | 9:00 AM |
Dimitris K. |
what would be a proper structure to save the parsed data
|
Dimitris K. |
and share it inside my apps components
|
Mark M. |
presumably, some set of POJOs that mirrors your configuration file structure
|
Mark M. |
with a singleton cache for those, based on how many possible configuration files your app needs to deal with at a time
|
Dimitris K. |
should I use shared prefs to save them read data to the device ?
|
Mark M. |
you already have a file; why create another?
|
Dimitris K. |
good point though that file will be updated and in case it somehow gets corrupted I would like to have a backup plan
|
Mark M. |
I'd back up the configuration file, rather than having two sets of disparate code for loading configurations
|
Mark M. |
in terms of the POJO structures themselves, for typical configuration files (XML, JSON, properties, etc.), usually there is a fairly canonical mapping from the file format to Java objects
|
Mark M. |
though that may be slightly different depending upon the parser that you choose to use
|
Jun 13 | 9:05 AM |
Mark M. |
(e.g., Jackson might want to populate POJOs slightly differently than does Gson)
|
Dimitris K. |
regarding the parsing of the config file would you use some kind of library to create java objects from the xml data?
|
Mark M. |
my default position is "yes"
|
Mark M. |
if you are at risk of going over the 64K DEX method reference limit (and therefore need multidex), then I might hand-roll something
|
Dimitris K. |
I wont get over the limit for sure
|
Mark M. |
or, if the XML is just plain weird (e.g., everything is in CDATA stanzas), I might hand-roll something, if SimpleXML or similar libraries won't handle it well
|
Mark M. |
or, if I am creating a library for somebody else to consume, I would hand-roll something (e.g., my work for the F-Droid "update channels" library)
|
Mark M. |
and personally, those scenarios cover most of my own circumstances, so I haven't actually used SimpleXML or anything similar
|
Dimitris K. |
should I show you a sample of what I have now ?
|
Mark M. |
well, these chats get archived, so only post stuff in here that you do not mind showing up on the Interwebs
|
Dimitris K. |
thats fine
|
Jun 13 | 9:10 AM |
Dimitris K. |
View paste
(48 more lines)
|
Dimitris K. |
something like that
|
Mark M. |
you are using the DOM; I would use an event-driven parser if the XML might be large
|
Dimitris K. |
what is considered large ?
|
Mark M. |
that depends a bit on your deployment environment
|
Mark M. |
1MB would certainly be large
|
Mark M. |
10KB would be not large
|
Mark M. |
rather than iterating over nodes, I'd retrieve them by name, for the names that you know about, but that's just a coding style issue
|
Mark M. |
and in your situation, I'm not sure that you just want to crash out on a parsing error (e.g., if Boolean.parseBoolean() does not like a value of "you betcha!")
|
Dimitris K. |
A friend suggested that it should also be somehow convenient to use annotations since the structure that I expect is known
|
Mark M. |
otherwise, what you have there seems reasonable
|
Mark M. |
only if you are using some XML parser that uses annotations
|
Mark M. |
otherwise, those would be akin to code comments, at best
|
Jun 13 | 9:15 AM |
Dimitris K. |
I guess this can be always changed later and as long as it works fine now maybe I should stick with it
|
Mark M. |
if there might be 10K lines of this code, you might worry about it more in the short term
|
Mark M. |
if it's only going to be a few short methods of the variety that you have here, "if it ain't broke, don't fix it"
|
Dimitris K. |
its going to be that short just different classes for different files
|
Dimitris K. |
and the files are probably always shorter than 1k lines
|
Mark M. |
you might consider a base parser class, to hold common utility code
|
Dimitris K. |
plus I am only parsing them once per session so performance doesnt really matter
|
Jun 13 | 9:20 AM |
Mark M. |
if there are dozens of different files, you might try to more aggressively implement some common rules-based engine, just to limit the amount of code that you need to maintain
|
Mark M. |
but otherwise, I wouldn't worry about it too much
|
Dimitris K. |
its something like 8 files
|
Dimitris K. |
not much
|
Mark M. |
in that case, just a base class to give you a spot to hang common code should suffice
|
Dimitris K. |
by the way I feel like we all have to really thank you for the wakelock, alarm manager and jobscheduler chapters of the book :D
|
Mark M. |
yeah, that stuff started confusing and has just gotten worse over the past couple of years
|
Dimitris K. |
that concentrated knowledge makes it so easy to work
|
Mark M. |
in your case, you have it somewhat easier, in that you always have power on a digital sign (right?)
|
Dimitris K. |
yes
|
Dimitris K. |
I will just use the wake lock and only reboot the device when I want to
|
Mark M. |
if and when you start supporting Android 6.0+, Doze mode and app standby should not be issues
|
Mark M. |
(as opposed to us poor schlubs having to write for phones and tablets, which have only intermittent power)
|
Dimitris K. |
the only mysterious parts left (and they really are mysterious) are regarding app monitoring and silent background installations
|
Jun 13 | 9:25 AM |
Mark M. |
silent background installations either requires root or a custom ROM
|
Mark M. |
and I'm not certain what "app monitoring" means in this context
|
Dimitris K. |
and ofc implementing my own nice kiosk mode
|
Dimitris K. |
All the devices I will work with have root access
|
Mark M. |
(silent installs might also be possible via device owner APIs -- I haven't checked there recently)
|
Dimitris K. |
I will have 2-3 apps installed
|
Mark M. |
I do not know the mechanics of doing silent installs on rooted devices; I'm just fairly certain that it is possible
|
Dimitris K. |
and the "controller" app should take care of the others
|
Dimitris K. |
I also need to gather some usage statistics
|
Dimitris K. |
sadly that will add some more logic to the presenter app since I dont think I can get much from a background app easily
|
Dimitris K. |
so probably my presenter app will have to send the data to the app that controls it and actually is connected to the server
|
Mark M. |
can you be more specific about what "usage statistics" means? also, what version of Android are the signs running?
|
Dimitris K. |
5.1
|
Dimitris K. |
and I will need to know when the device was used, for how long, what was clicked more often and general things like that
|
Jun 13 | 9:30 AM |
Mark M. |
well, you can use UsageStatsManager to get some of this
|
Dimitris K. |
I also followed your advice on the downloader and I am now using a class extending runnable in a thread from my service
|
Mark M. | |
Mark M. |
I have not covered UsageStatsManager in the book; I need to do that one of these days...
|
Dimitris K. |
nice ! I had no idea this existed
|
Dimitris K. |
im lucky my devices are running 5.1
|
Mark M. |
having a reasonably modern Android version is a double-edged sword
|
Mark M. |
on the one hand, you get APIs like this one
|
Mark M. |
on the other hand, older hacks for getting this stuff are partially gone, for privacy and security reasons
|
Mark M. |
while those concerns are less important in your deployment scenario, Android is Android, and so you are stuck with limits imposed for phones and tablets, to a large extent
|
Dimitris K. |
indeed !
|
Jun 13 | 9:35 AM |
Mark M. |
but I'd start with UsageStatsManager, then identify what you still need that is not covered by it, to see what else you might need to employ
|
Dimitris K. |
This is actually my first project that wont run on regular phones
|
Dimitris K. |
the most magical part in the digital signage part is that you know exactly the screen size and resolution you need to support so you can just use pixels
|
Dimitris K. |
and hardcode everything to perfection
|
Mark M. |
until the firm decides to switch to a different screen
|
Dimitris K. |
hehehe exactly
|
Dimitris K. |
but you only need to support a batch of devices each time
|
Dimitris K. |
so its fine for maybe even 2 years
|
Dimitris K. |
later the OS version for the devices will also change
|
Dimitris K. |
have you tried to use certificate pinning with okhttp ?
|
Mark M. |
only by way of my backport of network security configuration: https://github.com/commonsguy/cwac-netsecurity
|
Mark M. |
with that, it works fine back to Android 4.2
|
Jun 13 | 9:40 AM |
Dimitris K. |
awesome I guess I can use that
|
Mark M. |
your pin information goes into XML resources (e.g., res/xml/network_security.xml)
|
Mark M. |
and you tell the library to apply that configuration to your OkHttpClient via your Builder
|
Mark M. |
Google's and my code take care of the rest
|
Mark M. |
in the case of standard pinning, it's Google's code
|
Mark M. |
for soft pins/trust-on-first-use scenarios, it's my code
|
Dimitris K. |
sounds like that project is exactly what I need
|
Dimitris K. |
so it seems that the last complications I will have with the project is creating my own custom layout inflater
|
Dimitris K. |
and thats just cause I dont have enough experience on the matter
|
Dimitris K. |
plus there are is not much data online
|
Mark M. |
well, the basics are not that different than what you showed above for populating POJOs
|
Mark M. |
instead of creating instances of a Language, you are creating instances of a LinearLayout
|
Mark M. |
if you are trying to handle "real" layout XML syntax, with all the android: and app: attributes, *that's* going to be a pain
|
Jun 13 | 9:45 AM |
Dimitris K. |
will I be able to avoid that ?
|
Mark M. |
well, do you control the XML?
|
Mark M. |
if you want simpler XML, and you control the XML, create simpler XML
|
Dimitris K. |
thats already defined
|
Mark M. |
is it the same as Android's layout XML resources?
|
Dimitris K. |
its supported in another platform so as a new platform I should keep compatibility
|
Dimitris K. |
no the configuration files are custom structured
|
Dimitris K. |
they basically work like this
|
Dimitris K. |
main page has 3 things inside
|
Dimitris K. |
then explains what the 3 things are
|
Dimitris K. |
but each thing has a defined size
|
Mark M. |
OK, so, we're back to it being akin to your existing configuration XML parsing
|
Dimitris K. |
yep
|
Mark M. |
you have two ways of going about it:
|
Mark M. |
1. the XML parser is directly creating your view hierarchy
|
Mark M. |
2. the XML parser is building up a set of POJOs, akin to your configuration objects, and they create the view hierarchy
|
Mark M. |
personally, I'd lean towards the latter approach
|
Dimitris K. |
it will allow from some code to be reused so 2) makes more sense to me too
|
Mark M. |
to create the view hierarchy, you either are creating the views/viewgroups purely in Java, or you are inflating small focused layout resources for each and tailoring them in Java
|
Jun 13 | 9:50 AM |
Dimitris K. |
can I give you a small example
|
Mark M. |
go right ahead
|
Mark M. |
...bearing in mind that we only have a few minutes left in the chat...
|
Dimitris K. |
so I read from the config file that there is a main screen separated into 3 parts (half of the screen vertically separated and one part of it separated horizontally)
|
Dimitris K. |
sure no problem
|
Dimitris K. |
and it says that there is an image gallery on the top corner
|
Dimitris K. |
and a list next to it
|
Dimitris K. |
(ignore the 3rd window)
|
Dimitris K. |
how do you approach it
|
Mark M. |
have POJOs that mirror the XML
|
Mark M. |
have them implement some common interface with some common method for building the view hierarchy (e.g., assemble())
|
Mark M. |
tell the root POJO to build the view hierarchy
|
Mark M. |
whatever is in the XML for the rules (e.g., "there is an image gallery") maps to layout resources
|
Mark M. |
and, where needed, also applies some Java code to tailor non-static bits of those layout resources
|
Dimitris K. |
I see !
|
Mark M. |
the root POJO also tells its children to assemble(), passing along the partially-assembled view hierarchy, for them to chain on their own views/viewgroups
|
Dimitris K. |
this way I can add functionality slowly and step by step
|
Mark M. |
right
|
Jun 13 | 9:55 AM |
Mark M. |
testing the XML->POJO logic is very straightforward
|
Mark M. |
testing the POJO->view hierarchy is a bit more complicated but shouldn't be all that bad
|
Dimitris K. |
yep this sounds very realistic :D
|
Dimitris K. |
thank you once again for being the team member I need :D
|
Mark M. |
happy to be useful
|
Dimitris K. |
useful is an understatement !
|
Mark M. |
BTW, back on the certificate pinning... OkHttp 3 has its own certificate pinning code
|
Mark M. |
so, if all you need is certificate pinning, you could just use that
|
Mark M. |
use CWAC-NetSecurity if you need more of the power of the network security configuration stuff
|
Mark M. |
otherwise, it may be overkill
|
Mark M. | |
Dimitris K. |
I will check it out today !!
|
Dimitris K. |
So enjoy the rest of the day and thanks again !! :D
|
Mark M. |
you are very welcome
|
Jun 13 | 10:00 AM |
Mark M. |
the transcript will be posted to https://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is tomorrow at 7:30pm US Eastern
|
Mark M. |
the next chat in this time slot is 24 June
|
Mark M. |
have a pleasant day!
|
Dimitris K. |
:D
|
Dimitris K. | has left the room |
Mark M. | turned off guest access |