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!
|
Suzanne A. |
So, the baby names app ...
|
Suzanne A. |
I created a db and table using MOTODEV Studio
|
Suzanne A. |
But Studio converts all column names to uppercase, so _id became _ID
|
Suzanne A. |
And I couldn't pull data into my SimpleCursorAdapter
|
Mark M. |
CursorAdapter should be case-insensitive
|
Jan 11 | 8:00 PM |
Mark M. |
if not, try using SELECT _ID as _id, ... or something
|
Mark M. |
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
|
Suzanne A. |
will do, on the smack :-)
|
Suzanne A. |
CursorAdapter says this ..
|
Suzanne A. |
The Cursor must include a column named "_id" or this class will not work.
|
Suzanne A. |
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
|
Mark M. |
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
|
Mark M. |
I've never checked
|
Mark M. |
anyway, try SELECT _ID AS _id, ... and see if that helps
|
Mark M. |
(BTW, howdy, Julius!)
|
Mark M. |
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
|
Suzanne A. |
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
|
Mark M. |
fix up the code-generated stuff
|
Mark M. |
have it use _id
|
Mark M. |
leastways, I'm assuming Studio is generating code for you
|
Suzanne A. |
ok. _id in the cursor, even if the table has _ID?
|
Suzanne A. |
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
|
Mark M. |
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... :-)
|
Mark M. |
(BTW, howdy, Jon!)
|
Jan 11 | 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
|
Mark M. |
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
|
Mark M. |
you might want to peek at the new LocationPoller project I released
|
Mark M. | |
Julius |
oh ok I'll google it :)
|
Julius |
oh thanks!
|
Mark M. |
it involves a service that is "wakeful" but not an IntentService
|
Mark M. |
might give you some ideas
|
Mark M. |
moving along...Jon: do you have a question?
|
Julius |
thank you very much
|
Mark M. |
Jon?
|
Mark M. |
OK...Suzanne, do you have another question?
|
Jan 11 | 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.
|
Jon J. |
WakefulIntentService.sendWakefulWork(context, ReportLocationService.class);
|
Jon J. |
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
|
Mark M. |
what specifically isn't happening?
|
Jon J. |
You're probably nowhere near as confused as I am. :)
|
Jon J. |
Nothing happens.
|
Jon J. |
When the alarm fires, in my onReceive method my logging runs, but the sendWakefulWork doesn't do anything I can see.
|
Mark M. |
OK
|
Mark M. |
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.
|
Jon J. |
But when I stuck with the above, no.
|
Mark M. |
first, I'd run the standard demo project from cwac-wakeful
|
Mark M. |
make sure that works properly for you
|
Mark M. |
if it doesn't, then there is some environmental issue at play
|
Jon J. |
That's an obvious idea that escaped me. :)
|
Jon J. |
I saw in your latest version that API 5 is now required.
|
Jon J. |
I think I'm using the jar that needs API 4.
|
Jan 11 | 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.
|
Jon J. |
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.
|
Jon J. |
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?
|
Jon J. |
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
|
Mark M. |
well, not all alarms are _WAKEUP
|
Mark M. |
it's only needed for _WAKEUP alarms
|
Mark M. |
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?
|
Jan 11 | 8:20 PM |
Julius |
inits => in its
|
Mark M. |
I haven't done OAuth yet
|
Mark M. |
are "consumer keys" something you have to keep secret?
|
Julius |
(can be nightmarish!)
|
Julius |
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
|
Mark M. |
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
|
Julius |
maybe soemthing which downloaded the keys might be a work around
|
Mark M. |
still not a defense against anyone who wants them
|
Mark M. |
root the device, get the keys
|
Julius |
yeah...
|
Julius |
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
|
Mark M. |
none that I'm aware of
|
Mark M. |
it would be nice if Android had some sort of keystore for this sort of thing
|
Mark M. |
alas, it doesn't
|
Julius |
I wonder how Amazon does it
|
Mark M. |
no clue
|
Mark M. |
Jon: do you have another question?
|
Julius |
btw thanks for the update to the wakefulintentservice
|
Mark M. |
Julius: you're very welcome
|
Jan 11 | 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
|
Julius |
View paste
(4 more lines)
|
Julius |
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
|
Mark M. |
it's a little tough to answer that in the abstract
|
Mark M. |
not knowing much of what this is about
|
Mark M. |
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!
|
Julius |
ok I'll go work on it some more
|
Julius |
thanks for stimulating my brain :)
|
Julius |
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
|
Jan 11 | 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?
|
Julius |
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()
|
Mark M. |
either AsyncTasks or perhaps my own thread pool
|
Mark M. |
swap in the real images for the placeholders once ready
|
Julius |
oh ok
|
Julius |
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.
|
Jon J. |
Then I have a Service, and several Activity classes.
|
Jon J. |
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?
|
Jan 11 | 8:35 PM |
Jon J. |
I know there are plenty of apps that treat a startup Activity as the "main" class.
|
Jon J. |
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
|
Mark M. |
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?
|
Jon J. |
I'm not sure how to get at them. :)
|
Mark M. |
getApplicationContext() returns your Application
|
Mark M. |
you'd have to cast that to be your own class
|
Mark M. |
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.
|
Jon J. |
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
|
Mark M. |
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. |
:)
|
Jan 11 | 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.
|
Jon J. |
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.
|
Jon J. |
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?
|
Jon J. |
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.
|
Jon J. |
I was checking out Microlog.
|
Jon J. |
Do you recommend that or anything similar?
|
Mark M. |
might want to get that going, as that can help you with this problem
|
Mark M. |
I'm keeping an eye on ACRA
|
Mark M. | |
Mark M. |
I'm trying to convince them to make a pluggable back-end
|
Mark M. |
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.
|
Jon J. |
But that looks nice -- thanks for the tip.
|
Jon J. |
And I appreciate the Android 1.5 compatibility. :)
|
Jon J. |
Does it queue up the report if network is down?
|
Jan 11 | 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
|
Mark M. |
yes, I know what you mean
|
Mark M. |
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.
|
Jon J. |
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.
|
Jon J. |
Have you done any mobile development on non-Android platforms? I'm curious how it compares in ease, time of development etc.
|
Jon J. |
But many people out on the webs seem pretty partisan, and not able to say.
|
Mark M. |
nothing modern
|
Mark M. |
poked at WinMo a bit
|
Jon J. |
ok
|
Mark M. |
and older stuff yet
|
Mark M. |
I can tell you, based on discussions with students, that Android is a fair bit easier than Blackberry
|
Mark M. |
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.
|
Jon J. |
Ah, that's interesting. J2ME for Blackberry?
|
Mark M. |
yes
|
Mark M. |
plus I think some proprietary APIs
|
Mark M. |
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
|
Jan 11 | 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
|
Mark M. |
I gave IntelliJ IDEA 10 a spin
|
Mark M. |
might try that on a future project
|
Mark M. |
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.
|
Jon J. |
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.
|
Jon J. |
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
|
Mark M. |
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.
|
Jon J. |
Oh, I do have another question!
|
Mark M. |
I rotate between participants, to give everyone a shot
|
Mark M. |
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.
|
Jon J. |
This was weeks ago, so maybe I just need to go look again...
|
Jan 11 | 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.
|
Jon J. |
Is there a way to fetch the user's 12/24 hour locale selection in my app?
|
Mark M. |
android.provider.Settings.System
|
Mark M. |
TIME_12_24
|
Mark M. |
based on some quick scanning
|
Mark M. |
or, just use android.text.format.DateFormat
|
Jon J. |
create an instance and then check is24HourFormat?
|
Jon J. |
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"
|
Jon J. |
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
|
Mark M. |
and, yes, that's static
|
Mark M. |
probably it just calls Settings.System behind the scenes
|
Mark M. |
since it asks for a Context
|
Jon J. |
Right. The boolean is handy. Thanks for being my grep. :)
|
Mark M. |
no problem
|
Mark M. |
and now, your moment of Zen: http://aviationhumor.net/combat-kangaroos/
|
Jan 11 | 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!
|
Jon J. |
And have a good night.
|
Mark M. |
next chat is Thursday, same time
|
Mark M. |
have a pleasant evening!
|
Jon J. |
bye
|
Jon J. | has left the room |
Mark M. | turned off guest access |