Office Hours — Today, January 11

Thursday, January 6

Jan 11
7:55 PM
Mark M.
has entered the room
Mark M.
turned on guest access
Suzanne A.
has entered the room
Mark M.
howdy, Suzanne!
Suzanne A.
hey Mark!
So, the baby names app ...
I created a db and table using MOTODEV Studio
But Studio converts all column names to uppercase, so _id became _ID
And I couldn't pull data into my SimpleCursorAdapter
Mark M.
CursorAdapter should be case-insensitive
8:00 PM
Mark M.
if not, try using SELECT _ID as _id, ... or something
and smack the engineer who forced uppercase on the column names in Studio... :-)
Suzanne A.
But I get an error that column _id doesn't exist, even though it does
will do, on the smack :-)
CursorAdapter says this ..
The Cursor must include a column named "_id" or this class will not work.
I entered _id, but got _ID
Mark M.
If you look at Database/Constants in the source to _The Busy Coder's Guide to Android Development_, you will see that I have a table with an _id column but I query and retrieve _ID
I had assumed that meant it was case-insensitive, since that code works
Julius
has entered the room
Suzanne A.
hm. so why do I get that error?
Mark M.
perhaps even though I query as _ID, it is coming in as _id in my Cursor
I've never checked
anyway, try SELECT _ID AS _id, ... and see if that helps
(BTW, howdy, Julius!)
you don't really need it as _id in the table, so long as it is _id in the Cursor
Suzanne A.
except that I created a db helper and content provider, also using Studio
right. so I'm using managedQuery() to get the data
Mark M.
oh
Suzanne A.
yeah. I thought I was being smart by generating a content provider ...
Mark M.
you'd need to hand-modify the helper
fix up the code-generated stuff
have it use _id
leastways, I'm assuming Studio is generating code for you
Suzanne A.
ok. _id in the cursor, even if the table has _ID?
yes, it is (but buggy code)
Mark M.
well, if you're going to fix the code, you may as well fix it across the board
I'd standardize on _id everywhere
Jon J.
has entered the room
Suzanne A.
of course! I'm telling the Studio guys, but I have to get my project done before they can release the bug fix
Julius
hi
Jon J.
Hi, everyone.
Mark M.
well, software development perhaps goes slower in Oklahoma... :-)
(BTW, howdy, Jon!)
8:05 PM
Suzanne A.
I know :-)
Mark M.
next up, Julius: do you have a question?
Julius
Hi yes. I am using a WakefulIntentService to do some work and was wondering whether you might know what would happen if I created a Handler to queue Runnables whether at the end of doUsefulWork() the IntentService would stop itself or it would wait for the Runnables to finish.
Mark M.
um, I'm skeptical that Handler and IntentService will get along
Julius
to be more clear - the original work being done is parsing xml and I'd like to download some images in a separate thread
Mark M.
I certainly have no idea what the behavior of that combo would be
Julius
as I go
Mark M.
that sounds like you need to back off from IntentService and go back to a regular Service
the problem is that the IntentService will shut down once onHandleIntent() wraps
Julius
ah ok thanks - I have another small question so I can wait.
Mark M.
which means WakefulIntentService will shut down when doWakefulWork() is done
you might want to peek at the new LocationPoller project I released
Julius
oh ok I'll google it :)
oh thanks!
Mark M.
it involves a service that is "wakeful" but not an IntentService
might give you some ideas
moving along...Jon: do you have a question?
Julius
thank you very much
Mark M.
Jon?
OK...Suzanne, do you have another question?
8:10 PM
Jon J.
I've got a WakefulIntentService question too.
Mark M.
OK, Jon, go ahead
Jon J.
I followed the recipe in the book, and my OnAlarmReceiver logs when its onReceive method gets called.
WakefulIntentService.sendWakefulWork(context, ReportLocationService.class);
but that never results in happy things for me :)
Suzanne A.
no, but thanks. gotta run, but tyvm
Jon J.
So I'm mostly wondering what else I can do to troubleshoot since I log a message before and after that sendWakefulWork() call but don't know what else to try.
Suzanne A.
has left the room
Mark M.
Jon: I guess I'm confused
what specifically isn't happening?
Jon J.
You're probably nowhere near as confused as I am. :)
Nothing happens.
When the alarm fires, in my onReceive method my logging runs, but the sendWakefulWork doesn't do anything I can see.
Mark M.
OK
are you seeing any warnings in LogCat (e.g., can't resolve the service Intent)?
Jon J.
As I understand it, my ReportLocationService class's doWakefulWork method should get called. Is that right?
Mark M.
yes
Jon J.
I was when I used an Intent that was based on a String name, rather than class.
But when I stuck with the above, no.
Mark M.
first, I'd run the standard demo project from cwac-wakeful
make sure that works properly for you
if it doesn't, then there is some environmental issue at play
Jon J.
That's an obvious idea that escaped me. :)
I saw in your latest version that API 5 is now required.
I think I'm using the jar that needs API 4.
8:15 PM
Mark M.
I'd move to the latest edition
Jon J.
I've been trying to write everything to use only API 3, so maybe I'm causing trouble somehow that way.
This app hasn't deployed to our userbase yet, and I don't yet have a good feel for whether we'll be cutting off too many people if we don't support < Android 2.1.
Mark M.
yeah, unfortunately, the "wakeful" semantics don't work well until API 5
Jon J.
I wonder if I could ship the app for API 3 but disallow these features for API < 5.
How dangerous is it to use an alarm receiver without doing the wakeful tricks?
Mark M.
the other thing to do is copy the WakefulIntentService source into your project and sprinkle it liberally with log statements
Jon J.
Does it just fail often because the phone goes back to sleep?
ah, right
Mark M.
yes
Jon J.
So it's really not a useful system service without taking the wakeful workarounds into account.
Mark M.
the phone may go to sleep before the work starts, or while the work is, um, working
well, not all alarms are _WAKEUP
it's only needed for _WAKEUP alarms
did that give you enough to chew on for a bit?
Jon J.
Yes, thanks.
Mark M.
Julius: got another question?
Julius
Hi yes, I have an application which has some Oauth consumer keys in it. I'm concerned about security but currently have the keys in strings.xml because there are multiple brands for the application and each has its own consumer key so I keep each inits own strings.xml. Is there a better place other than a source file to store consumer keys?
8:20 PM
Julius
inits => in its
Mark M.
I haven't done OAuth yet
are "consumer keys" something you have to keep secret?
Julius
(can be nightmarish!)
yes that's the idea, but you need to distribute them with the application
Mark M.
well, technically, you're screwed
Julius
yeah that's what I figured
Mark M.
you can encrypt them, but then you need the decryption key in your source
and it's turtles all the way down
Julius
with Oauth you get given a username and password which the calls use to authenticate your app to the service
maybe soemthing which downloaded the keys might be a work around
Mark M.
still not a defense against anyone who wants them
root the device, get the keys
Julius
yeah...
it's not that serious, just wondered if there was a better way
Mark M.
frankly, I have no idea how Hulu and Netflix plan to do Android apps, short of firmware deals
none that I'm aware of
it would be nice if Android had some sort of keystore for this sort of thing
alas, it doesn't
Julius
I wonder how Amazon does it
Mark M.
no clue
Jon: do you have another question?
Julius
btw thanks for the update to the wakefulintentservice
Mark M.
Julius: you're very welcome
8:25 PM
Mark M.
ok...anyone have any questions?
Julius
I do have one more if you don't mind...
Mark M.
go ahead
Julius
if you have a minute that is
View paste (4 more lines)
			// Release / cover icon
			if(null!=getReleaseCoverImageView()) {
				getReleaseCoverImageView().setImageDrawable(mContext.getResources().getDrawable(R.drawable.cover_proxy_list));
				
				if(c.getInt(7)==SDITrack.TRACK_TYPE_7DI) {
					releaseBitmap = BitmapFactory.decodeFile(
								SDICoverHelper.getListCoverFilenameForReleaseSdiId(
										mContext,c.getLong(4), mDisplayDensity));
				} else if(c.getInt(7)==SDITrack.TRACK_TYPE_LOCAL) {
					releaseBitmap = BitmapFactory.decodeFile(
							SDICoverHelper.getListCoverFilenameForLocalReleaseId(
									mContext,c.getLong(3),mDisplayDensity));
				}
 
				if(null!=releaseBitmap) {
...
I have this set of code in mypopulateFrom in a list and I'm wondering if there's anything inherintly inefficient about it
Mark M.
uh
it's a little tough to answer that in the abstract
not knowing much of what this is about
is this being called in a loop, or once per row, or something?
Julius
oh right - I should check that's its being called once each time!
ok I'll go work on it some more
thanks for stimulating my brain :)
I've been working on it for ages I guess I got stale on it.
Mark M.
also, your R.drawable.cover_proxy_list resource is not changing, so you might consider caching the Drawable reference rather than looking it up each time
8:30 PM
Mark M.
also also, decodeFile() does file I/O, which is not ideal if being run on the main application thread
Julius
oh ok that sounds really sensible.
Mark M.
that's why StrictMode will whine about it by default (if you use StrictMode on Android 2.3)
Julius
so should I decode the images separately and then refer to a Vector of images or something?
hmmm I'll have to get 2.3 going
Mark M.
I would display a static placeholder image, and use some background logic for the decodeFile()
either AsyncTasks or perhaps my own thread pool
swap in the real images for the placeholders once ready
Julius
oh ok
ok lots of things to work on there
Mark M.
yup, this is why _Tuning Android Applications_ is my primary book for 2011
Jon J.
Mark, I've got a more general Android development question for you.
Mark M.
Jon: go ahead
Julius
sweet bfn thanks again!
Jon J.
I look forward to that book!
Julius
has left the room
Jon J.
I wrote my application's base class to extends Application, and put various static state variables in there.
Then I have a Service, and several Activity classes.
What's your opinion on all these pieces ... if I have a Service, and several Activity classes, does that seem to make sense to keep app-wide state in the Application class?
8:35 PM
Jon J.
I know there are plenty of apps that treat a startup Activity as the "main" class.
This is working for me, but I'm just wondering if you have any guidance on general app design topics such as this.
Mark M.
for all intents and purposes, the scope of a plain Java static data member and the Application singleton is the same
I'd go the Application route if I really needed a Context to be managing some of that stuff
Jon J.
That's what I thought, and the static members seemed to be the easiest to access from outside that class.
Mark M.
right
Jon J.
Would it be better to use the singleton's instance members instead?
I'm not sure how to get at them. :)
Mark M.
getApplicationContext() returns your Application
you'd have to cast that to be your own class
I ran down that path once with an app, and it was kinda a pain
Jon J.
IIRC the thing that got me on the route to using an Application class was that I'm using Urban Airship's AirMail, and they did that in their demo app that sets up the connection with their code. And it seemed to make sense.
So you feel it's fine to use static members and not access the Application singleton from elsewhere?
Mark M.
well, on the whole, I try to minimize all of that, just to avoid memory leaks
that being said, I'd go with static data members unless I had a compelling reason to use a custom Application, such as needing what amounts to a static Context
Jon J.
I'm not sure how I'd leak memory if there are just a few static members (no collections etc.) so any object references would be overwritten sooner or later by newer ones, and then the garbage collector would take care of it, right?
Mark M.
well, the key words there are "sooner or later"
Jon J.
:)
8:40 PM
Mark M.
if the scope of the static data is less than the lifetime of the process, you gotta make sure you're nulling those things out, or something
Jon J.
Right.
I think I'm ok then.
Mark M.
particularly if they might reference something that in turn references a component (e.g., a widget that holds its activity)
Jon J.
This app has a background service with an entry in the notification bar, so it's intended to always be running.
Mark M.
you mean startForeground()?
Jon J.
I'll double-check to see if any of those static members could reference something else.
yes
Mark M.
ok
Jon J.
I'm not calling that directly, but using some Google sample code that uses newer API code when it's there, and falls back to an old way. You've seen it I'm sure.
Mark M.
right
Jon J.
Do you have any advice for debugging startup crashes that happen only occasionally on some real devices, but never in development?
I think I probably need to attach to USB and get some debugging logging from the device.
Mark M.
startup meaning on reboot?
Jon J.
No, app startup.
Mark M.
are you using anything to report your stack traces from the field?
Jon J.
No, not yet. There's no "field" yet, but will be soon.
I was checking out Microlog.
Do you recommend that or anything similar?
Mark M.
might want to get that going, as that can help you with this problem
I'm keeping an eye on ACRA
I'm trying to convince them to make a pluggable back-end
right now, it posts to Google Spreadsheets, which is OK, but I'd rather collect the data on my own Web service
Jon J.
Yeah, me too.
But that looks nice -- thanks for the tip.
And I appreciate the Android 1.5 compatibility. :)
Does it queue up the report if network is down?
8:45 PM
Jon J.
I'm a little worried that the Verizon lack of voice + data at same time is going to be troublesome in the field.
Mark M.
not sure
yes, I know what you mean
in fact, I'm curious to see how iPhone 4 fares with that
Jon J.
Indeed. They've not had to deal with that before.
Well, I'll try out ACRA. That looks like a better fit for this specifically. Microlog may still be useful for logging from the field, but I'm already sending a few things to our web service and that's been fine.
Have you done any mobile development on non-Android platforms? I'm curious how it compares in ease, time of development etc.
But many people out on the webs seem pretty partisan, and not able to say.
Mark M.
nothing modern
poked at WinMo a bit
Jon J.
ok
Mark M.
and older stuff yet
I can tell you, based on discussions with students, that Android is a fair bit easier than Blackberry
that's close to apples-to-apples, since they're both Java
Jon J.
Android's the first for me, and I haven't done much Java before either, so it's been a fun time.
Ah, that's interesting. J2ME for Blackberry?
Mark M.
yes
plus I think some proprietary APIs
compared to iOS development, I think it's a bit of a wash, perhaps leaning slightly towards iOS being easier
Jon J.
Interesting.
Mark M.
Symbian has always been a development train wreck, and I'm not aware that's improved any
8:50 PM
Jon J.
I get the impression from your books that you're not a fan of Eclipse. Do you just use a normal text editor and command-line tools?
Mark M.
more or less
I gave IntelliJ IDEA 10 a spin
might try that on a future project
but, for me, unless the IDE is tightly integrated with the environment (Smalltalk, VB), I'm happy with editors and the command line
Jon J.
I'd never used Eclipse before, and since so much Android tutorial stuff assumes that, I gave it a try.
I suffered for a while and finally when I got the vi keybindings plugin was able to tolerate it fairly well. :)
Mark M.
yeah, Eclipse tends to be a love-it or hate-it sort of tool
Jon J.
I normally use shell + Vim etc. so Eclipse feels huge. But I see that there are some nice things about it. Trying to keep an open mind.
Well, thanks for your pointers on wakeful topics. I don't want to tie up your time any more since I don't have any other Android questions at the moment.
Mark M.
hey no problem
it's not like the chat room overfloweth
Jon J.
It's my first time here, so didn't want to wear out my welcome.
Oh, I do have another question!
Mark M.
I rotate between participants, to give everyone a shot
go ahead
Jon J.
I'm using a time picker and for some reason had trouble figuring out how to get the OS-wide locale setting for 12/24 hour.
This was weeks ago, so maybe I just need to go look again...
8:55 PM
Jon J.
I ended up just setting a constant app-wide for 12/24 hour and figured I'd look again later.
Is there a way to fetch the user's 12/24 hour locale selection in my app?
Mark M.
android.provider.Settings.System
TIME_12_24
based on some quick scanning
or, just use android.text.format.DateFormat
Jon J.
create an instance and then check is24HourFormat?
That Settings.System looks promising, though I can't tell what the String constant will hold in either case ... it kinda looks like "12" vs. "24"
oh, duh -- is24HourFormat is static
Mark M.
yes, I'm just poking through the SDK to find likely sources of the data
Jon J.
gotcha -- that's probably the best way
Mark M.
haven't tried any of these
and, yes, that's static
probably it just calls Settings.System behind the scenes
since it asks for a Context
Jon J.
Right. The boolean is handy. Thanks for being my grep. :)
Mark M.
no problem
and now, your moment of Zen: http://aviationhumor.net/combat-kangaroos/
9:00 PM
Jon J.
That's delightful. :)
Mark M.
OK, well, that's a wrap for this evening
Jon J.
Thanks again for your help!
And have a good night.
Mark M.
next chat is Thursday, same time
have a pleasant evening!
Jon J.
bye
Jon J.
has left the room
Mark M.
turned off guest access

Thursday, January 6

 

Office Hours

People in this transcript

  • Jon Jensen
  • Julius
  • Mark Murphy
  • Suzanne Alexandra