Office Hours — Today, April 17

Thursday, April 12

Mark M.
has entered the room
Mark M.
turned on guest access
Apr 17
4:00 PM
Daniel B.
has entered the room
Mark M.
howdy, Daniel!
how can I help you today?
Daniel B.
Hello!
I have what might be a stupid question but hope that's ok :p
Mark M.
there are no stupid questions
Daniel B.
I have a custom adapter that I'm using its from CursorAdapter
Mark M.
embarrassing ones, now... :-)
Daniel B.
inside it one of the views is displaying the number of items it has from another table, so I'm using a cursor, but I'm doing that inside the Adapter. Is this ok to do that? The downside now is that when that data is updated, it doesn't update the listview until I refresh that activity
I tried to create a loader for it, but I can't do that inside an Adapter, which lead me to this conclusion: probably not best to do it that way, so what other way is there?
Guille C.
has entered the room
Mark M.
well, assuming performance isn't an issue, "ok" is up to you to decide
Guille C.
Hello hello, first time using the office hours so if I do something wrong please let me know.
Daniel B.
Performance seems "ok" for 3 items in the list, I can take a guess that with 1000 items it probably is far from "ok"
Mark M.
you would need to call notifyDataSetChanged() on the CursorAdapter to get it to update
(howdy, Guille -- I'll take a question from you shortly)
even better, of course, would be to create a single Cursor with all your data, using joins
4:05 PM
Daniel B.
I did try that first, but seems to have some issues, shame I didn't write them down. I could try that and hopefully ask you next office hours about my issues.
Mark M.
OK
let me take a question from Guille, and I'll swing back to you shortly
Guille: do you have a question?
Guille C.
yup typing it out now
Justin M.
has entered the room
Guille C.
I have a quick question about managing database versions, I used the github tool you described for packaging the database. Loved it! But my question is this, say I deploy version 1.0 with the database. Database will be at version 1. Then I do some modifications so now database will be at version 2. when i deployed only some people updated the app... now i do more updates so now database is at version 3. how will this affect people going from version 1 of the db straight to version 3?
Mark M.
howdy, Justin -- be with you in a moment!
Justin M.
Great, thanks :-)
Mark M.
by "github tool", you mean SQLiteAssetHelper?
Guille C.
yes sir
4:10 PM
Mark M.
you are probably better off asking those sorts of questions on that project -- I am not expert in all corners of third-party projects
Tom22
has entered the room
Mark M.
that being said, my understanding is that you have your choice of creating a direct 1->3 upgrade script, or it will use your 1->2, then 2->3 upgrade scripts
but I have not tried that
(howdy, Tom22 -- you're after Justin, be with you shortly!)
Tom22
Thanks - no hurry.
Mark M.
Guille: this is no different than how you would handle it with your own SQLiteOpenHelper
if you peek through _Android Programming Tutorials_, you will see where we augment the schema over time, applying upgrade rules progressively to handle all upgrade combinations
in the case of SQLiteAssetHelper, the upgrades are handled via scripts instead of Java code, but the same concept applies
Guille C.
great I will take a look at the tutorials. Thanks
Mark M.
Justin: do you have a question?
Justin M.
Yes, I certainly do :-)
Mark M.
go right ahead
Justin M.
First off, long time no talk. Been in iOS land for a while, finally back doing 2 Android gigs again, so going to have lots of questions.. Here's one that I'm hoping you can help with:
4:15 PM
Justin M.
I'm working on an app where I essentially need to implement a custom push notification system...
I am restricted with what 3rd party tools/libraries I can use due to client restrictions...
So no C2DM or other pre-2.2 push notification options....
So, that being said, I'm trying to just create a TCP socket on the device that listens for incoming connections, receives the message, and then will pass it off to another portion of the app...
This runs in a Service-derived subclass using an AsyncTask currently...
Mark M.
that's unlikely to work, unless the device is only ever on WiFi, and the push-er is on the same LAN segment
and I *definitely* would not use AsyncTask here, as you will need the thread indefinitely
Justin M.
OK, the part about the threading is good to know...
Mark M.
fork your own thread and use a Handler, or runOnUiThread(), to pass work to the main application thread
Justin M.
What are the issues with it being unlikely to work? I can tell you that the problem I'm having is that I can establish a connection to the device and send it data, and it receives it fine.. for a while...
I have a partial wake lock and wifi lock set up to try to keep the device running (the client is aware of the battery drain issues and is OK with this)
4:20 PM
Justin M.
But I see that after some time when I turn the display off, the connection seems to get sluggish. It will almost always receive the data, but there can be sometimes a minute delay in receiving it
I know it's a totally kludgy solution...
name
has entered the room
Mark M.
my "unlikely to work" was in terms of trying to push to a device on mobile data, or across the Internet -- you need the push-er and the device to have IP routing between them, and you would not in those scenarios
Justin M.
Unfortunately, I don't think using C2DM is going to be an option with this client. Is there any possibility of being able to get a custom push notification solution to work?
Mark M.
I would say that it will be very difficult to make a reliable push system yourself
the user can get rid of your service
Android can get rid of your service
plus the problems you are experiencing (which I can't explain)
Justin M.
Yeah, I know, I've explained that to them emphatically, so I have to come up with some way to try to keep the service alive by having other services monitoring "heartbeats"... It's kind of a mess :-(
OK, that's what I wanted to know, whether or not there was an explanation for what I'm seeing given the fact that I have a wifilock and partial wakelock which, in theory, should keep everything running when the device sleeps
Mark M.
(btw, howdy "name" -- be with you after Tom22)
yeah, I would not have expected the minute delay issue
it's as if Android is buffering the packets and not handing them to you, which is odd
Justin M.
Once the messages get through after the delay, they flow through continuously again
4:25 PM
Justin M.
I'm using a BufferedReader for right now, could that be the problem?
Mark M.
that's definitely something to experiment with
Justin M.
(flow through continuously again until after a few minutes when it gets delayed once again)
Mark M.
I don't know what the rules are for when BufferedReader
hands you data back
you might try dropping that and seeing what the behavior is
Justin M.
We're still in the exploratory phase with the client so I don't know what the data format is so I've just been using a BufferedReader. I will take your advice about the threading though, need to read up more on threads in general.
OK, that sounds like a plan
Mark M.
OK
let me take questions from others
Justin M.
So I think I'm good for now, I'll just hang out and wathc
Mark M.
Tom22: do you have a question?
Justin M.
thanks a million :-)
Tom22
I have a question about broadcast receivers and serializing intents. I'll tell you how I think things work so you can correct me if I'm wrong...
My app has a broadcast receiver that is registered in the manifest to handle multiple intents. It can get invoked even when app/service are not running, and then decides whether to launch the service. If the receiver decides to launch the service it sends another intent that causes the service to start and its onStartCommand to be called with the intent. (I see now that I should be using the LocalBroadcastManager for this.)
I believe that, if I get multiple calls to service's onStartCommand they all happen in the same context/thread: they are serialized by Android.
Mark M.
actually, LocalBroadcastManager doesn't buffer, so if the service is not running, I doubt that would be the right answer
name
has left the room
Mark M.
onStartCommand() is definitely called on the main application thread
Tom22
My aside about using LocalBroadcastmanager was just for the intent that the receiver uses to invoke the service - does your response still hold?
Mark M.
"serialized" is simply a matter of that onReceive() and onStartCommand() are *both* on the main application thread
yes -- if the service is not running, LocalBroadcastManager will not start it
I see LocalBroadcastManager more for service->activity communication
Tom22
Regarding LocalBroadcastManager - OK, got it.
4:30 PM
Tom22
Regarding my onRecieve - you are saying that it too only runs on the main application thread? So I can assume that all invocations of my broadcast receiver occur in serial?
Mark M.
yes
Tom22
Good. That simplifies the implementation of my onReceive. Thanks.
Mark M.
Daniel: do you have another question?
Daniel B.
You can skip me for time being
Mark M.
OK
Guille: do you have another question?
Guille C.
Yes sir :)
Tom22
has left the room
Guille C.
So I am trying to show a alert after a user send a email.. I am using the ACTION_SEND intent. The problem I am having is onActivityResult the resultCode is always 0
i need to know if a user sent email cancelled
Mark M.
ACTION_SEND does not support startActivityForResult()
you have no way to know if the user sent an email or not
Guille C.
that would make sense
thanks again
Mark M.
if anyone has any questions, chime in
Justin M.
I do actually
Mark M.
fire away
4:35 PM
Justin M.
With regards to the previous question and using regular threads instead of an AsyncTask...
I was originally going to go down that route, but I wanted to have the ability to stop the thread at some point (or rather, terminate it)
And I didn't see a good way to do that... With the AsyncTask, I saw there was a cancel() method which would set a boolean that you could check for while doInBackground was running...
So if I use regular threads instead, how would I stop it from running without messing things up bad?
Mark M.
you can set your own AtomicBoolean for that
here, I use an AtomicBoolean to bail out of a thread early, if the user exits the activity that forked the thread
while this example is the epitome of "trivial", the same technique would hold in your case
Justin M.
I was thinking of this in the context of starting and stopping a service, where in starting the service I would kick off the thread, and in stopping it, I would then bail out of the thread. Would this still make sense for that?
Mark M.
sure
Justin M.
Great. I'll look at the code and see what I can come up with. Thanks a bunch!
4:40 PM
Daniel B.
I have a question if that is ok
Mark M.
go right ahead!
Daniel B.
I have a custom adapter for a list view that has a few views in it, mostly text views but in one fo them a checkbox. I have created a listener for it and verify that it fires when the box is clicked, but how can I get the _id of the item the checkbox is in, so I can do some processing related to that?
Mark M.
stuff the _id value in the tag of the CheckBox via setTag(), and retrieve it later via getTag(), I suppose
Daniel B.
perhaps foolishly, the listener is within the Adapter? I don't know if that is right, but it acknowledges that its been pressed
Mark M.
make sure you are using getViewTypeCount() and getItemViewType(), so recycling does not get messed up with your multiple row types
with respect to the location of the listener, I am using that same approach in one sample app: https://github.com/commonsguy/cw-android/b…
4:45 PM
Daniel B.
great, will definitely look into that
Mark M.
so long as you are handling the row recycling properly, it should be fine AFAIK
Daniel B.
well, not entirely sure im handling recyling properly.
I looked at some sample code, I'm extending CursorAdapter, which means that getView is handled for me and I create own methods for bindView and newView?
Mark M.
yes
Daniel B.
as far as I saw, or thought, getView is where the recycling happens?
Mark M.
yes, with CursorAdapter
Daniel B.
OK, then I think the recycling happens properly
Mark M.
so long as you are implementing getViewTypeCount() and getItemViewType()
Daniel B.
hmm, don't think I am.
Mark M.
without those, you might get handed your CheckBox row when you are trying to populate a non-CheckBox row
probably not what you want
have getViewTypeCount() return 2
4:50 PM
Mark M.
have getItemViewType() return 0 for normal rows, 1 for the CheckBox row
Android will maintain separate object pools for recycling
so you are ensured that in bindView(), you get the right row type
Daniel B.
All rows I think are the same, just comprise of many views, which I assign values within bindView from the cursor passed in, and using setText, or in the checkbox .setChecked
Mark M.
this assumes that these rows are being inflated from separate layouts, of course
wait, all rows have the CheckBox? I thought only one did
Daniel B.
no, all rows have a checkbox
and some textviews
Mark M.
ah, never mind then
my mistake
Daniel B.
does the same advise regarding giving it _id via setTag() work then?
Mark M.
yes
you only need to set up your listener in newView()
Daniel B.
Ok thanks, sorry for the confusion
Mark M.
and update the tag in bindView()
so when your listener fires, it can get the _id of the actual entry
Daniel B.
Ok great sounds good. I think I understand that :)
4:55 PM
Mark M.
we're running low on time -- chime in if you have a question
Daniel B.
I only have silly questions left, so would only ask if no one else has something
Mark M.
go ahead
Daniel B.
In my application for the listview I have an empty view thing that the listview diplsays when its empty
but obviously it displays that while the data is loading, which can be annoying. Is there any nice way to hide this till the data is loaded then decide if its empty or not after that?
Mark M.
give it android:visibility="invisible" in the layout
then call setVisibility(View.VISIBLE) if needed later
that might not work, as ListActivity/ListFragment wants to manage the visibility
Daniel B.
sounds simple enough, thanks
Mark M.
if it doesn't work, you can always fall back on managing it all yourself, just by changing the widget ID to something other than @android:id/empty
5:00 PM
Mark M.
well, that's a wrap for today's chat
Justin M.
Thanks Mark!
Mark M.
next one is Thursday, 10am Eastern
have a pleasant day, all!
Daniel B.
Thank you
Daniel B.
has left the room
Guille C.
has left the room
Justin M.
has left the room
Mark M.
turned off guest access

Thursday, April 12

 

Office Hours

People in this transcript

  • Daniel Bell
  • Guille Carlos
  • Justin Munger
  • Mark Murphy
  • name
  • Tom22