Office Hours — Today, January 28

Thursday, January 23

Jan 28
7:15 PM
Mark M.
has entered the room
7:25 PM
Mark M.
turned on guest access
Adam F.
has entered the room
Mark M.
hello, Adam!
how can I help you today?
Caldwell S.
has entered the room
Adam F.
good evening
Caldwell S.
Hola.
EGHDK
has entered the room
Mark M.
hello, Caldwell! Adam arrived just before you, so he gets the first shot, followed by you, then EGHDK (hi!)
Adam F.
I have a situation i would like to describe and see if you have any suggestions
Mark M.
Adam: do you have a question?
Caldwell S.
heh heh Adam and I are from the same team. Love it.
Adam F.
Yes
Caldwell S.
Thanks for seeing us, Mark.
Adam, do you want me to post the question?
7:30 PM
Adam F.
were using your piped content provider and we are having issues with some apps and mime types not loading correctly in third party apps ?
Mark M.
OK
Adam F.
Have you seen this behavior in the past?
Mark M.
one known limitation is if the client needs to be able to rewind the stream, the stream from a ParcelFileDescriptor will not work
(or, at least, from one created by createPipe())
so, for example, you can't stream a video using the streaming provider approach
Adam F.
I think thats the case as I know video content does.
Would that entail writing the file out to disk?
Mark M.
that's the only definitive case I know of that does not work
would what entail writing what file out to what disk?
Caldwell S.
Adam, may I post the full context of the question?
Adam F.
Yes
Caldwell S.
View paste (18 more lines)
We're attempting to solve a problem.  We need to download files via the internet from a remote server and then save the files to the Android file system.  The files will be encrypted.  The user will be able to see a list of these files.  When the user taps a file in the list, such as a PDF, we need to un-encrypt the file before we allow the Android operating system to attempt to open the file.  

However, the problem is that the customer doesn't want us to un-encrypt the file and write the un-encrypted file to the file system before an app attempts to open the file.  The customer would prefer that we keep the file encrypted.  

Is it possible to use a content provider that can un-encrypt the file so that an app, such as Adobe Acrobat, can use this content provider to receive the unencrypted state of the file and thus open the file?

From your latest book (Android-5.5.pdf), we looked at your examples on page 1409 (the local-file content provider) and on page 1416 (i.e. the stream provider).  

The problem is that using the stream provider, not all apps function that attempt to read files.  

PDF
Adobe reader - works
PDF Viewer - works
EBook Reader - works
PDF Reader - works
...
View paste (3 more lines)
PDF Viewer - works
Quick Office - crashes
Easy PDF Reader - crashes

TXT
HTMLViewer - works
File Manager - works

PNG
G+ Photos - Works
File Manager Image Gallery - Works
Gallery - Black screen

MP4
G+ Photos - Error
...
Mark M.
OK, give me a moment to read this...
Caldwell S.
Roger that.
Mark M.
other than the Gallery one, the rest would seem to fit the rewindable-stream issue
not sure why Gallery would need that for an image, but I suppose I can't rule that out
the only way I know of to get past the rewindable-stream issue is to use a ParcelFileDescriptor backed by an actual file
7:35 PM
Mark M.
which would imply writing the decrypted content out to disk, at least to internal storage
Caldwell S.
We can remove the requirement of having to handle video files, for example, for v1.0.0.
I think we're trying to determine if you think we're on the correct path by attempting to unencrypt the file on the fly by using a content provider.
Mark M.
for arbitrary content, that's risky, as you're seeing
Adam F.
My concern is that we cannot guaranty other interactions won't also cause issues.
Mark M.
Adam: agreed
in more controlled scenarios, it would be fine
you can try the old "write a micro Web server and serve the content via HTTP" approach
using some sort of dynamically-generated URL to prevent other apps from being able to hit your server
Adam F.
Tried that and the browser takes control of every interaction
Mark M.
(and only listening to localhost, of course)
Caldwell S.
heh heh I think Adam attempted something like that.
Mark M.
that too is not terribly shocking
off the top of my head, I don't have a great answer
though it's something I need to work on myself, for other reasons, in the not too distant future
(by which I mean "2014" :-)
Caldwell S.
We've certainly noticed an increase in requests from customers to further secure their content.
Mark M.
completely understandable
OTOH, bear in mind that once the data is in the hands of a third-party app, security goes out the window
for example, the third-party app could off "Save As", its own "Share", etc.
Caldwell S.
Agreed - and we've explained this scenario to the customer.
Mark M.
/s/off/offer/
7:40 PM
Caldwell S.
Right. The third-party app could potentially write the stream to the disc.
Mark M.
but right now, I don't have great answers for you
Caldwell S.
No worries. We'll keep working at it, Mark. We may need to explain to them that when the user attempts to open a file, it may fail for certain apps; this is something that we can attempt to improve in the future.
Security is very important to them. So, unless they want to change their point of view on this requirement, I don't know how we can make what we have any better at this time.
Adam F.
Thanks for hearing us out
Mark M.
conversely, keep tabs on my book, blog, and the StreamProvider project, as that's all where I'll be working on this stuff
Caldwell S.
OK. Thank you, Mark. Have a nice evening.
Adam F.
No worries we are.
Mark M.
EGHDK: your turn! do you have a question?
EGHDK
Yeah. Two of them.
First one is something that I wrote down, but I don't remember from where. Could've been from you on SO, or Raomain from a GOogle i/o video. The quote is "getView returns a new view. New view is very expensive, especially if it comes from an xml file, which inflates it, which involves reflection."
My question is reflection, and what does it have to do with this?
Mark M.
all the *Inflater classes (LayoutInflater, MenuInflater, etc.) use reflection as part of converting the XML into Java objects
for example, suppose you have a layout XML file
the root element is <RelativeLayout>
LayoutInflater, when it encounters that element, will use methods like Class.forName() to go find android.widget.RelativeLayout, then use methods like newInstance() on the Class object to create an instance of RelativeLayout
7:45 PM
Mark M.
reflection isn't the cheapest thing out there
now, one could argue that LayoutInflater should just have some massive lookup table and avoid the reflection
but then it could not handle <com.commonsware.android.MyCustomView>
EGHDK
Gotcha.
So which part of it is reflection... when you said "will use methods like Class.forName() to go find android.widget.RelativeLayout"
Mark M.
Class.forName(), and using Java classes like Class and Method, are all considered part of the reflection API
EGHDK
There are java classes called Class? and Method?
Mark M.
yes
EGHDK
Interesting.
Mark M.
Java gets meta :-)
EGHDK
Okay cool. Thanks for clearing that up.
Mark M.
Adam: do you have another question?
Adam F.
no I'm out and thanks for the assistance
Mark M.
you're very welcome
Caldwell: do you have another question?
Adam F.
has left the room
7:50 PM
Mark M.
OK, EGHDK: do you have another question?
EGHDK
Okay, so my second question is that I'm trying to build a sample messaging application like snapchat, but just for text messages.
I'm sure you know, but snap chat basically has timers that will make a message dissapear.
Mark M.
theoretically
EGHDK
yep =)
My app is super simple, I open up my activity and it reads a database that I populate myself, the database has a table of messages with three columns.
_id, text, and seconds_remaining
I load up the messages into a listView, and I show the text and seconds remaining in simple_list_items_2
so that's super easy and it works fine.
but now, I want to make the text View that holds the seconds remaining to tick.
so each text view would update and incrementally go down every second.
What would be the best way to do this? Do I have to call getView every second?
Mark M.
you open up your favorite (::cough::) Android development book and search for ReverseChronometer
7:55 PM
EGHDK
Forget about the database or anything, I just want the seconds to count down in front of the users eyes.
Oh! I learned about chonometer when I made a stop watch app. hahaha
Reversechronometer makes sense.
Mark M.
in version 5.5 of the book, ReverseChronometer is explained on pages 1131-1136
as an example of a custom View
EGHDK
Thanks.
Mark M.
(BTW, those were PDF page numbers)
EGHDK
got it
Tom
has entered the room
Mark M.
hello, Tom!
Tom
Hello
Mark M.
Tom: the others have all had a shot at questions so -- do you have a question?
Tom
I have a question - it is about whether sync adapters are the right solution for my situation.
My app has a custom log framework. If it encounters an error or exception then it dumps log info into a file. The issue is how/when to send those files to my server.
Mark M.
I have not messed with SyncAdapter
last I knew, it was difficult to use it outside of the whole Authenticator framework
Tom
Ok, that's useful input.
Mark M.
which means if this is the *only* thing you need to sync, I'd skip SyncAdapter, as that would be a headache for you and the user
if, OTOH, this is one piece of a larger sync puzzle, and the Authenticator framework would be useful, then SyncAdapter may be a fine choice
Tom
I think that answers my question - I should not use sync adapters.
8:00 PM
Mark M.
one of my 2014 projects is to get into SyncAdapter and figure out the leanest possible implementation, in terms of code, permissions, and user headache
Tom
But I am still not quite certain when to schedule (launch) the service that sends my log files to the server.
I wish there were a way to tell Android to schedule something when it will cost the user the least (e.g. middle of the night, when plugged in).
Caldwell S.
has left the room
Mark M.
well, you know when the middle of the night is for most ordinary users
so, you could use AlarmManager to do something at, say, 4am
unless this is one hella big file, I wouldn't worry about the device being plugged in, though
Tom
Yes, so my current plan is to use AlarmManager and a pendingintent to launch my 'sync' service in the middle of the night.
It shouldn't be too big - its a log file. Hopefully this will happen extremely rarely - only if there is an error or exception in the app.
Mark M.
yeah, worrying about the power is definitely overkill
and you might not even want to wait for the middle-of-the-night bit, if this is only a handful of KB
Tom
Ok - maybe I'm over-thinking this one.
Mark M.
the user is unlikely to notice a small power/bandwidth hit, and it may be important for the user, and you, to get the crashes faster than that
for example, I don't think that the major crash-reporting solutions do aggressive batching like this
leastways, ACRA doesn't
and I'm not aware of others that do
EGHDK: do you have another question?
8:05 PM
Tom
Yeah, you're right. Ok, thanks for the help.
Mark M.
OK, if either of you have a question, go ahead
EGHDK
Yeah, this one is about me having an app that has lets say 20 "important messages". These messages are loaded up into the database at the start of the app the first time you launch it. Then the application see if todays date matches the date associated with the important message, and then it displays that message in the app. What would I do if I also wanted to send a notification to the user, so that they don't have to open up the app after the first time
Don't know if that made sense.
Mark M.
um, use AlarmManager to get control at midnight, I suppose
and use WakefulIntentService or WakefulBroadcastReceiver to arrange for a service to do the "hey! do we have an important message!" work
EGHDK
I rather do it at like... 8am... so AlarmManger would have to do?
Mark M.
I don't know how else you plan to get control at 8am daily
EGHDK
Hahaha.
Mark M.
if you have a server, I suppose the server could send a GCM message at 8am daily
EGHDK
Well, I don't want it to go off every day at 8am I mean.
Mark M.
but that's like swatting a fly with a Buick
8:10 PM
Mark M.
OK, now I'm lost
EGHDK
Okay, let me start over.
So, I have an app where I have a db with a table _id, message, date.
When I open the app, I do a query to see if date in table == todays date.
If it does, then grab the message and display it in the textView
Simple.
So this app has a DB of 20 "events/messages" that I know a year in advance.
What would be the best way to show them in the notification. I don't want to create a check EVERY day. I already KNOW the days. Can I set alarms for a month in advance? 4 months in advance?
Mark M.
you can try
EGHDK
But is that practical?
Mark M.
I have heard complaints that long-interval alarms are unreliable
and you would also need to remember to rebuild your alarms on a reboot
EGHDK
alarms aren't persistent?
Mark M.
nope, they are wiped out on a reboot
(or a Force Stop from Settings)
EGHDK
Did not know. Okay.
Mark M.
if you use a non-_WAKEUP alarm, the incremental power usage for your app checking today's messages is not that bad
EGHDK
I feel like checking every day for something I know will only be used 20/365 days is overkill.
8:15 PM
Mark M.
understood
8:15 PM
Mark M.
and you're welcome to try setting the alarms that far out, and see how it works
unfortunately, it's the sort of thing that takes a really long time to test
EGHDK
So you think non-_WAKEUP alarm is the way to go?
(Don't know what that is, but I'll look it up)
Mark M.
personally, I'd probably go that route
that's all covered in the rather long chapter on AlarmManager in the book
EGHDK
Haha. Okay, I will take a look at that.
I guess I have one more question/statement. Feel free to talk to Tom first.
Mark M.
Tom: do you have another question?
8:20 PM
Mark M.
EGHDK: go ahead
EGHDK
I'm kind of freaking out about the "Application" class. I feel like no one ever talks about it or uses it. I didn't even know about it, or its methods. onCreate() onTrimMemory(). I'm wondering why is that? Is application not used in most apps? If not... then when would you actually use it?
Tom
has left the room
Mark M.
that's the single best writeup of when to use what Context that I know of
just tweeted about it again a few days ago
EGHDK
Good article. I've "read" it many times.
But is that "Context"?
Is application just context?
Mark M.
Application extends Context, just like Activity and Service do
there are a few places where using Application as your Context is useful (e.g., something that will reside in a static data member, to prevent leaks)
some people create custom subclasses of Application for the purposes of singleton-type stuff, but I haven't found much value in that
EGHDK
Like a DB
Mark M.
yes, a singleton SQLiteOpenHelper should use Application for its Context
onTrimMemory() needs more love, though
and I gotta cover it more in the book someday
partly, that's because I totally misunderstood something about Dalvik
EGHDK
Gotcha. Yeah, idk. I never knew Application existed really.
Mark M.
once Andy Fadden clued me in on how Dalvik does release system RAM, onTrimMemory() made more sense
EGHDK
Gothca.
Mark M.
Application is "the red-headed step-child" of the Context realm
8:25 PM
EGHDK
Alright, well I have one more question. But times just about out, so I guess I shall save it for later.
Activities don't extend from APplication in any way right?
Mark M.
no, they do not
EGHDK
Gotcha.
Next time, get ready to answer what the hell a Bundle is for me.
Mark M.
a Bundle is effectively a multiple-type-aware HashMap, that is Parcelable, so it can cross process boundaries
EGHDK
...
I just don't get the whole savedInstanceState thing.
Mark M.
ah, that's a separate issue
EGHDK
And I actually never saw it. I just thought it had to be there.
Mark M.
did you read the resources and configuration change chapter?
EGHDK
but I was usuing a library of yours, and you switched bundle for icicle or something, and I just noticed it.
Mark M.
"Resource Sets and Configurations"
pages 357-383 (PDF)
EGHDK
Okay, I will read that next.
Mark M.
onSaveInstanceState() is a method
it takes a Bundle as a parameter
you can call that parameter whatever you want
the original 2007 conventional name was "icicle"
because onSaveInstanceState(), at that time, was named onFreeze()
EGHDK
I know. I just never "noticed" that it was even there hahah. I saw icicle and was confused... like "what is this?"
Mark M.
by the time Android 1.0 rolled around, they renamed onFreeze() to onSaveInstanceState()
EGHDK
oh!
Mark M.
old-timers like me sometimes still call it the icicle
EGHDK
That little analogy actually is helpful.
Mark M.
you can call it "state", or "george", or whatever, since it is your method implementation
EGHDK
yeah
8:30 PM
EGHDK
Gotcha. Okay, I will read about it. Thanks.
Mark M.
and that's a wrap for today's chat
next one is Thursday, 10am US Eastern Time
I'll post this transcript to http://commonsware.com/office-hours/ shortly
have a pleasant day!
EGHDK
you too thanks
EGHDK
has left the room
Mark M.
turned off guest access

Thursday, January 23

 

Office Hours

People in this transcript

  • Adam F.
  • Caldwell Shine
  • EGHDK
  • Mark Murphy
  • Tom