Sep 4 | 8:50 AM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Sep 4 | 8:55 AM |
Ray B. | has entered the room |
Mark M. |
hello, Ray
|
Ray B. |
Hello
|
Mark M. |
how can I help you today?
|
Ray B. |
I was wondering if you had an opinion on the best way to show/hide a notification when an app is swapped between foregound and background. Like with Google Music, if you've used it
|
Ales N. | has entered the room |
Ales N. |
Hello
|
Mark M. |
(BTW, hello, Ales -- I will be with you shortly!)
|
Mark M. |
Ray: I guess I don't really understand the question
|
Ray B. |
We'd like to show a notification when the app is closed and hide it if the app is opened
|
Mark M. |
no, I got that part
|
Ray B. |
We've considered using the package manager to check if the app is in front, using a counter/flag in onstart and onstop and the trim memory but these seem like hacky approaches
|
Mark M. |
yeah, well, you'll wind up with one of them
|
Mark M. |
there really is no "the app is moved to the background" event
|
Mark M. |
there is onUserLeaveHint(), but it will not cover all cases
|
Sep 4 | 9:00 AM |
Mark M. |
onTrimMemory() is the closest literal match, when you get the TRIM_MEMORY_BACKGROUND flag (or whatever that value is)
|
Ray B. |
Yes, I saw your answer on SO but unfortunately onUserLeaveHint() wouldn't be suitable
|
Ray B. |
Ok, just making sure we hadn't missed anything, thanks
|
Mark M. |
Android's "basket of loosely-coupled components" architecture has its pros and cons, and you're tripping over a con
|
Mark M. |
if the service will be running in either case (e.g., Google Music playing music), I'd go with onTrimMemory() in the service itself
|
Ray B. |
Ah ok, thanks, I'll recommend it
|
Mark M. |
otherwise, onTrimMemory() in a custom Application class would be a central spot
|
Mark M. |
the only thing I have not experimented with is timing on when onTrimMemory() is called, as to how quickly it is invoked once you move to the background
|
Mark M. |
let me take a question from Ales, and I'll be aback with you in a bit
|
Mark M. |
Ales: your turn! do you have a question?
|
Ray B. |
In our tests it seems to be near instant, however it was occasionally called while the app was open but this wasn't a problem for us
|
Mark M. |
(Ray: onTrimMemory() will be called, but I would not expect the _BACKGROUND flag to be passed in while you are in the foreground)
|
Mark M. |
Ales: do you have a question?
|
Sep 4 | 9:05 AM |
Ales N. |
Hi again :) so my question is somewhat more general. I use Parse.com for notification and data storage. I'm quite ok with the library. However recently I got stuck with some issue on the service implementation.
|
Mark M. |
I can try to help with general stuff, but I have never used Parse personally
|
Mark M. |
so I won't know much about any particular APIs, etc. of theirs
|
Ales N. |
doesn't matter
|
Ales N. |
as I need custom notification, I use Broadcast receiver and want to start wakeful service
|
Mark M. |
this is on some sort of push message?
|
Ales N. |
but I somehow come into a problem, that bindService call won't call any of the method of the callback
|
Mark M. |
well, WakefulIntentService is not designed to be use with bindService()
|
Mark M. |
IntentService in general is not designed to be used with bindService()
|
Ales N. |
yeah, I was afraid of that :)
|
Ales N. |
the thing is I really would like to have Service with certain data access methods filled by Parse queries and so on
|
Ales N. |
have it on single longer living object, I would guess that service is ok
|
Mark M. |
well, IntentService is designed for transactional work: do something, then shut down
|
Ales N. |
but there are two user cases... one is on notification I would like to delegate from the broadcast receiver to wakeful service
|
Ales N. |
that is as you pointed out probably correct approach
|
Mark M. |
yes, that's a typical model for push-style notifications
|
Ales N. |
but for data access I would rather have bound service
|
Mark M. |
then perhaps you have two services
|
Ales N. |
but I don't understand how to avoid duplication of code in such case
|
Sep 4 | 9:10 AM |
Mark M. |
well, inheritance would be out, so composition would be a better design pattern
|
Ales N. |
I need to access data even from the wakeful service :(
|
Ales N. |
yeah
|
Mark M. |
have the common stuff implemented in a general class
|
Mark M. |
have each service use an instance of the common-stuff class
|
Ales N. |
sure. Sounds great. I like that you clear up that Wakeful service is not intened for such use
|
Ales N. |
so that I don't need to burn time on this dead end
|
Mark M. |
yes, that end is pretty dead :-)
|
Ales N. |
:)
|
Mark M. |
let me take a question from Ray, and I'll be back with you in a bit
|
Ales N. |
sure
|
Mark M. |
Ray: your turn! do you have another question?
|
Ray B. |
Yes, just one, do you have a copy of the slides from yesterdays security presentation please. My computer rebooted when I tried to open them
|
Mark M. | |
Mark M. |
it's just a PDF, so I would hope that the slides themselves did not cause the reboot
|
Ray B. |
No, it's the computer, it's old
|
Ray B. |
Thank you, regarding the _BACKGROUND flag comment, yes you're probably right. We were using the UI_TRIMMED flag which is caused on every onStop.
|
Sep 4 | 9:15 AM |
Mark M. |
yeah if you got BACKGROUND when not in the background, I'd consider that a bug
|
Mark M. |
which isn't out of the question, of course
|
Ray B. |
True
|
Mark M. |
Ales: back to you, then -- do you have another question?
|
Ales N. |
Can you please recommend me from your experience some ORM that is suitable for Android and also can be used to build ContentProvider?
|
Mark M. |
I have not used any ORM personally
|
Mark M. |
the ContentProvider generators that I have seen have been focused on the ContentProvider itself, not using an ORM with one
|
Mark M. |
having a ContentProvider implemented using an ORM is probably inefficient, as you need to be handing back Cursor objects anyway
|
Mark M. |
having a ContentProvider be consumed ORM-style might be interesting, but I don't know of any ORMs that do that
|
Mark M. |
but, then again, I have not looked
|
Sep 4 | 9:20 AM |
Ales N. |
yes, I think that's the root for my question
|
Ales N. |
I think ORMs are good for querying, but they generally don't play well with CP
|
Mark M. |
it's more that CP is probably out of scope in the eyes of the ORM authors
|
Ales N. |
What other options are interesting for storing unstructured data?
|
Mark M. |
I have been intrigued by Couchbase Mobile
|
Mark M. |
which is a JSON document store
|
Mark M. |
there are a few other NoSQL options out there for Android
|
Mark M. |
and for smaller data sets, it may be just as easy to use them fully in RAM, serializing them as needed to something (JSON, XML, whatever)
|
Ales N. |
I've seen MapDB, which is basically persistent variant of NavigableMap
|
Ales N. |
but it's quite low-level
|
Sep 4 | 9:25 AM |
Mark M. |
yes, there are a few of those key-value stores floating around as well
|
Ales N. |
one more thing related to storage, is there any option to use encrypted data?
|
Ales N. |
and does it worth it?
|
Mark M. |
if you're using SQLite today, SQLCipher for Android is an easy migration
|
Mark M. |
as to whether or not it is "worth it", it depends on who you are trying to defend against
|
Mark M. |
encryption solutions like SQLCipher are designed to defend the user's data against those who might try to steal that data
|
Ales N. |
I would need to protect some sort of private keys
|
Ales N. |
so something itself is participating in secure operations :)
|
Mark M. |
who owns the keys? are they the user's keys? are they your keys to some back-end service?
|
Ales N. |
in this particular case it's bitcoin `wallet` private key
|
Mark M. |
so, it's the user's key
|
Ales N. |
yeah
|
Mark M. |
because presumably it is their wallet
|
Ales N. |
yes
|
Mark M. |
SQLCipher could work, though it's a bit of overkill
|
Mark M. |
I think there are encrypted versions of SharedPreferences available
|
Mark M. |
I have one, which is backed by SQLCipher, but that doesn't solve the size issue (SQLCipher is kinda big)
|
Sep 4 | 9:30 AM |
Mark M. |
I think that there are others that just use javax.crypto
|
Ales N. |
yeah
|
Ales N. |
mapdb supports xtea encryption
|
Mark M. |
the challenge with javax.crypto is getting everything right (e.g., key stretching), as it's rather low-level
|
Ales N. |
so I can give it a try
|
Mark M. |
I'm not familiar with xtea
|
Mark M. |
(BTW, Ray, if you have another question, just chime in)
|
Ales N. |
sure, Ray go ahead
|
Ray B. |
Don't worry, I don't have any more questions. Thanks for your time
|
Ray B. | has left the room |
Ales N. |
I would like to thank you a lot for your book
|
Ales N. |
and also the examples
|
Mark M. |
you are very welcome
|
Ales N. |
great job
|
Mark M. |
thanks!
|
Mark M. |
BTW, if you did not catch yesterday's announcement, Version 6.0 is ready for download
|
Ales N. |
I've seen right before I joined chatroom :)
|
Ales N. |
I'm from Europe so there is time shift few hours I guess. You've morning right?
|
Mark M. |
yes
|
Ales N. |
Can you share please some general opinions about Android and robustness of the platform?
|
Ales N. |
I mean, I quite fight it :)
|
Mark M. |
fighting the platform isn't unique to Android
|
Sep 4 | 9:35 AM |
Mark M. |
I have been fighting platforms for ~3 decades
|
Mark M. |
beyond that, this chat is really more for problem-solving
|
Mark M. |
if you have any other concrete questions, go right ahead
|
Sep 4 | 9:40 AM |
Ales N. |
Maybe one, on one of my prototype I tried to use Navigation drawer, however I found it quite clumsy and state was spreading throughout the application quite a lot. Is there some general pattern which allows me to manage complexity of state in action bar, navigation drawer and fragments?
|
Mark M. |
that is difficult to answer in the abstract
|
Mark M. |
you may wind up having some dedicated Parcelable state object that everyone participates with, and that is used with onSaveInstanceState()
|
Sep 4 | 9:45 AM |
Mark M. |
things that cannot really be put in a Parcel (e.g., large bitmaps) wind up being managed by a retained fragment to handle configuration changes, but then will need to get reloaded if the process is terminated (e.g., user returns to you through recent-tasks list)
|
Ales N. |
interesting, I'll take a look at this approach.
|
Ales N. |
I think it's all from me, thank you very much for your time. See you next time Mark.
|
Mark M. |
note that the chat transcript will be posted to http://commonsware.com/office-hours/ shortly after the chat ends
|
Ales N. | has left the room |
Sep 4 | 10:00 AM |
Mark M. | turned off guest access |