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!
|
Mark M. |
how can I help you today?
|
Daniel B. |
Hello!
|
Daniel B. |
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
|
Daniel B. |
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
|
Mark M. |
(howdy, Guille -- I'll take a question from you shortly)
|
Mark M. |
even better, of course, would be to create a single Cursor with all your data, using joins
|
Apr 17 | 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
|
Mark M. |
let me take a question from Guille, and I'll swing back to you shortly
|
Mark M. |
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
|
Apr 17 | 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
|
Mark M. |
but I have not tried that
|
Mark M. |
(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
|
Mark M. |
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
|
Mark M. |
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:
|
Apr 17 | 4:15 PM |
Justin M. |
I'm working on an app where I essentially need to implement a custom push notification system...
|
Justin M. |
I am restricted with what 3rd party tools/libraries I can use due to client restrictions...
|
Justin M. |
So no C2DM or other pre-2.2 push notification options....
|
Justin M. |
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...
|
Justin M. |
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
|
Mark M. |
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...
|
Justin M. |
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)
|
Apr 17 | 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
|
Justin M. |
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
|
Mark M. |
the user can get rid of your service
|
Mark M. |
Android can get rid of your service
|
Mark M. |
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 :-(
|
Justin M. |
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)
|
Mark M. |
yeah, I would not have expected the minute delay issue
|
Mark M. |
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
|
Apr 17 | 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
|
Mark M. |
hands you data back
|
Mark M. |
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.
|
Justin M. |
OK, that sounds like a plan
|
Mark M. |
OK
|
Mark M. |
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...
|
Tom22 |
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.)
|
Tom22 |
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
|
Mark M. |
yes -- if the service is not running, LocalBroadcastManager will not start it
|
Mark M. |
I see LocalBroadcastManager more for service->activity communication
|
Tom22 |
Regarding LocalBroadcastManager - OK, got it.
|
Apr 17 | 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
|
Mark M. |
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
|
Guille C. |
i need to know if a user sent email cancelled
|
Mark M. |
ACTION_SEND does not support startActivityForResult()
|
Mark M. |
you have no way to know if the user sent an email or not
|
Guille C. |
that would make sense
|
Guille C. |
thanks again
|
Mark M. |
if anyone has any questions, chime in
|
Justin M. |
I do actually
|
Mark M. |
fire away
|
Apr 17 | 4:35 PM |
Justin M. |
With regards to the previous question and using regular threads instead of an AsyncTask...
|
Justin M. |
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)
|
Justin M. |
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...
|
Justin M. |
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
|
Mark M. | |
Mark M. |
here, I use an AtomicBoolean to bail out of a thread early, if the user exits the activity that forked the thread
|
Mark M. |
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!
|
Apr 17 | 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
|
Mark M. |
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…
|
Apr 17 | 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.
|
Daniel B. |
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
|
Mark M. |
probably not what you want
|
Mark M. |
have getViewTypeCount() return 2
|
Apr 17 | 4:50 PM |
Mark M. |
have getItemViewType() return 0 for normal rows, 1 for the CheckBox row
|
Mark M. |
Android will maintain separate object pools for recycling
|
Mark M. |
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
|
Mark M. |
wait, all rows have the CheckBox? I thought only one did
|
Daniel B. |
no, all rows have a checkbox
|
Daniel B. |
and some textviews
|
Mark M. |
ah, never mind then
|
Mark M. |
my mistake
|
Daniel B. |
does the same advise regarding giving it _id via setTag() work then?
|
Mark M. |
yes
|
Mark M. |
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()
|
Mark M. |
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 :)
|
Apr 17 | 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
|
Daniel B. |
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
|
Mark M. |
then call setVisibility(View.VISIBLE) if needed later
|
Mark M. |
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
|
Apr 17 | 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
|
Mark M. |
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 |