Office Hours — Today, December 14

Wednesday, December 7

Mark M.
has entered the room
Mark M.
turned on guest access
Dec 14
10:00 AM
trdillah
has entered the room
Mark M.
howdy, trdillah!
trdillah
Hi Mark!
Mark M.
how can I help you today?
trdillah
I have a three Android related questions
Mark M.
well, you are the only one here at the moment, so let's start in
trdillah
Great!
Mark M.
if others join in, we'll try to weave in time for them as well
10:05 AM
trdillah
The first has to do with the best way to handle large bitmaps in Android. I'm changing the wallpaper of an Android Tablet application using the following: Bitmap background = BitmapFactory.decodeResource(ctx.getResources(), mImageIds[imageId - 1]);
View paste
wpm.setBitmap(background);
based on the size of the image, I'll get an out of memory error message. I've handled this by making my images smaller but I feel like I should do some type of cleanup
This code exists in an Android widget
I am calling a service called "UpdateWallPaper"
and in the onUpdateWallPaper method, I'm changing the wallpaper
Mark M.
could you clarify what you mean by "this code exists in an Android widget"?
do you mean an app widget?
trdillah
Yes, an app widget
Sorry
Mark M.
why are you using a large bitmap for a small app widget?
trdillah
I'll give you an example. We have weather widgets on many of our android devices
Usually the widget has an icon that represents the weather.
Mark M.
icons are small, though, pretty much by definition
trdillah
Let's say you're on a different screen from the widget but you always want to know what the weather is like. Let's say the weather widget app changes the wallpaper based on the conditions outside
so the full wallpaper changes on the application even though you're not on the specific widget page.
Mark M.
changes the wallpaper, meaning changes the home screen's wallpaper?
trdillah
Yes, changes the home screen's wallpaper
Mark M.
ah, now we're getting somewhere
I have never written a live wallpaper
10:10 AM
Mark M.
and so I do not know of any specific recommendations for that
trdillah
technically, this isn't a live wallpaper
ie, i'm not using any live wallpaper features
i'm just changing the app wallpaper using the BitmapFactory
My general question is when using the BitmapFactory, is there a proper way to cleanup?
Mark M.
what is the "app"? the home screen implementation itself?
trdillah
No, technically the "app" is the widget application
But, you can access other activities by pressing an icon on the widget application
Mark M.
well, I'm totally lost, but that's OK
when you are done with a Bitmap object, call recycle()
that may or may not help with resources, though
Android seems to tend to cache those itself
it's worth a try
trdillah
ok, i'll give it a try. I read about the recycle call but it sounded like you only call recycle when you're completely done with an image
this application widget should reside on the device at all times
Mark M.
in theory, that's true
but the Bitmap does not
trdillah
hmm, "in theory?"
oh, ok
Mark M.
BTW, what version of Android is this running on?
trdillah
I'm running this on a tablet with version 2.3
it's an older tablet. it's a research project and i'm deploying the devices so i have some control over the versions.
Mark M.
someday, if you move to API Level 11 or higher, look at the inBitmap data member of BitmapFactory.Options
there's a flavor of decodeResource() that uses this
trdillah
I see
Mark M.
you might be able to keep reusing the same Bitmap object
also, even though you are deploying to 2.3, you might want to use MAT and Android 3.x/4.x to see where your memory is being used
trdillah
what's MAT?
10:15 AM
Mark M.
those newer versions of Android report bitmap data as part of the regular heap, whereas before bitmap data was effectively invisible
MAT is the Memory Analysis Tool
you use it to analyze the contents of your heap
to figure out where your memory is going
it's covered in _Tuning Android Applications_, available with your Warescription
trdillah
Okay, great!
Awesome!
Frank
has entered the room
trdillah
My next question is a question I posted last night on StackOverflow so it's described in detail there: http://stackoverflow.com/questions/8500037…. I just don't understand why the solutions don't work.
Mark M.
howdy, Frank!
Frank
Hi Mark & trdillah
trdillah
Hi Frank!
Mark M.
trdillah: margins may work
android:layout_marginRight="..." on the right-most widget
the scrollbar is designed to overlay the contents while a scroll is going on
trdillah
Ok, I'll give it a try. Thanks!
Mark M.
Frank: do you have a question?
trdillah
oh, so it's working as designed :/
Frank
View paste
Yes, I do!My App needs to display a horizontally scrolling list of images. Underneath each image I want to display a list of metadata (image title, etc.).

I am thinking of using a Gallery view for this purpose because I think flinging through the list of images will be more user friendly thanforcing the user to swipe image by image.

It doesn't seem like the Gallery View is used very often.
Do you know why? Do you know of any drawbacks to using the Gallery View?
Mark M.
Gallery is not used as much as other selection widgets, like ListView
it's really mostly designed for thumbnail previews, as in wallpaper pickers
10:20 AM
Mark M.
is the metadata a fixed set of widgets that change based upon the image selection?
or are there widgets for each image that scroll with the image?
rephrase: or are there metadata widgets for each image that scroll with the image
?
Frank
Yes the metadata changes with each image.
I was thinking of having it scroll synchronously with the images.
Mark M.
that definitely feels like a Gallery, then
wait
let's say the Gallery is capable of showing 5 images
are there 5 sets of visible metadta? or 1?
Frank
Well...
Mark M.
(er, metadata)
Frank
no
I was thinking of 1 image. And just a peek of the other images on each side.
Mark M.
that's going to be difficult with multiple screen sizes
Frank
Yeah I haven't really thought about tablets...
Mark M.
you're welcome to give Gallery a try, using a LinearLayout or RelativeLayout for the elements in the Gallery
where each of those holds onto your image and your metadata
but, even beyond tablets, a 3" and a 5" phone will be trouble for having "1 image and just a peek of the other images on each side"
Frank
ok, thanks!
why?
Mark M.
because 5" is 2" more than 3" :-)
10:25 AM
Frank
Of course I'm resizing the images to fit on the screen...
Mark M.
...which adds overhead
Frank
The images come from the camera on the device.
Resizing once, then caching.
Mark M.
OK
Frank
Do you see any problems with this approach?
Mark M.
I'm still nervous about screen sizes, and memory management for lots of bitmaps is problematic, but otherwise, it's certainly worth trying
Gallery isn't the most flexible widget out there, which is one of the reasons it is not more popular (e.g., selected element must be centered horizontally)
Frank
What could I do to optimize the bitmaps, aside from making them smaller?
Mark M.
use SoftReferences in your cache, recycle() the Bitmap objects ASAP, etc.
this is a major topic area for _Tuning Android Applications_ that I'll be getting into in early-ish 2012
Frank
View paste
Yes I was worried about the lack of flexibility... 
The Horizontal center is actually good, at least with one image...
Mark M.
trdillah: do you have another question?
trdillah
Yes, I'm still having the scroll bar issue
Frank
Nice! I'm looking forward to reading you on the subject.
trdillah
perhaps I misunderstood how to use android:layout_marginRight="..."
10:30 AM
trdillah
I think it would work as I expected if I moved the scrollview below the first linear layout
but, android doesn't allow me to do that
Mark M.
well, you can only have one root
is the first LinearLayout supposed to scroll?
trdillah
no, the first linear layout doesn't need to scroll
its just the layout with the textview
Mark M.
well, it sounds like you need to ponder what needs to scroll and what doesn't, and organize a layout that accomplishes that
trdillah
The textview is the only part that needs to scroll
Mark M.
which TextView? You have two, not counting the EditText
trdillah
but if the scrollview can only have one root, how can it support multiple linear layouts?
Mark M.
no, sorry, you have 3
ScrollView can only have one child
all widgets only have one parent
all layouts only have one root, because that's imposed by XML
ScrollView scrolls multiple children by having those children organized in some sort of container (LinearLayout, RelativeLayout, etc.)
if you do not want some things to scroll, they do not belong inside the ScrollView's portion of your view hierarchy
10:35 AM
trdillah
ok, i think i understand.
Mark M.
Frank: do you have another question?
Rich F.
has entered the room
Frank
View paste
Yes. Coming back to my App with Images and metadata; I'm thinking of storing the metadata in a Sqlite DB. Concering storing the image data, what are the pros and cons of storing it in the DB or in external files?
Mark M.
is the metadata something that is derived from the image itself (e.g., pixel size) or is it coming from other sources?
(BTW, howdy, Rich!)
Frank
Hi Rich!
Rich F.
Hey :)
trdillah
Hi RIch!
Frank
the metadata is things like the title, and other sundry text.
Mark M.
the challenge you have with either data store is keeping it in sync with the images themselves
if these images are from the camera, they are hopefully on external storage, and so the user can delete them as desired
beyond that, though, I'd probably use a database
you can't query across a bunch of files
Frank
yes if external storage is available I will use it
I was worrying about putting large blobs in Sqlite.
I don't know how well the DB would handle a largish collection of images.
Mark M.
what large blobs? the images themselves?
Frank
Yes
Mark M.
oh, yeah, I definitely would not do that
10:40 AM
Mark M.
for starters, the user does not have access to the images then, except through your app
Frank
The metadata goes in the DB no question. But the images...
Mark M.
I'd keep the images in external storage, in the designated folder for photos
Frank
That isn't necesarily a problem. It wouldn't be a good if the user deletes the image from under the App
Mark M.
it's their camera
it's their device
Frank
Hmmm
Mark M.
if they take pictures with your app, and uninstall the app, they should get to keep the pictures
now, that assumes this is a consumer app
business apps may have different rules
Frank
Can I put the images in a special folder so that they don't pollute the other pics of the user?
Mark M.
if by "pollute" you mean "they don't show up in the Gallery app and such", drop a .nomedia file in the directory
Frank
Consumer, but the images are of a specific nature.
But then we're pretty much back to the images being inaccessible to 95% of the users...
Mark M.
the images are available to 100% of the users who plug their device into their PC
Frank
What about performance? Do you know of any problems with large DBs containing a collection of BLOBS?
Mark M.
.nomedia affects MediaStore, not USB Mass Storage or USB Media Transfer Protocol
Frank
Correct
10:45 AM
Mark M.
transactions may be slower to apply with larger contents
but, I haven't put large images in a SQLite database, let alone on Android
I prefer 'em in the filesystem, regardless of Android consumer expectations
Frank
you put them in external files?
Mark M.
easier to debug that way :-)
yes
Frank
OK, thanks that's good enough for me!
Mark M.
Rich: do you have a question?
Rich F.
Yeah... haven't found any info on this for about a week on SO or Google Groups.
Frank
But external files are a bit harder to keep in sync with the DB...
Rich F.
View paste
Is there any other reason that the Intent that is passed to onStartCommand(Intent, int, int) would be NULL besides the system restarting the service via a flag such as START_STICKY?

Also, when the service is restarted by the system the Intent.getAction() method returns NULL... sometimes. Intent is not NULL just getAction()
Mark M.
Rich: yes, I've seen your question
Rich F.
Wondering if you might take a stab at it
Mark M.
START_STICKY is the only reason for a null Intent that I'm aware of
however, Intents don't have to have actions
e.g., startService(new Intent(this, MyService.class)); has no action)
I didn't answer any of your SO/Google Groups posts in part because I didn't have much to add over what you already knew... :-(
Rich F.
Ok I have no problem there and check the Intent for null then ignore if it is... however, sometimes, getAction is null and it shouldn't be
Mark M.
have you dumped the contents of the null-action Intents to see what's in there overall?
Rich F.
lol that is what I figured... everyone left it alone because there isn't much to add
10:50 AM
Rich F.
I cannot reproduce it on any device I have but I keep getting ACRA reports that look like this...
Mark M.
yeah, your question was definitely the sort needing Googly love, and you didn't luck out on that scre
er, score
Rich F.
View paste
java.lang.Throwable: AutoResponseService.onStartCommand() :: intent.getAction() is NULL
	at com.jmarstudios.txtautoresponder.android.plugins.autoresponder.service.AutoResponseService.onStartCommand(AutoResponseService.java:132)
	at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2115)
	at android.app.ActivityThread.access$2800(ActivityThread.java:124)
	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1031)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:130)
	at android.app.ActivityThread.main(ActivityThread.java:3806)
	at java.lang.reflect.Method.invokeNative(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:507)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
	at dalvik.system.NativeStart.main(Native Method)
Now I am specifically throwing the null error but there is nothing in the intent... I am assuming that the system restarts my service and the action is then null... however it is only sometimes
Mark M.
any commonalities in the reports (certain OS releases? certain devices? certain moon phases when the reports come in?)
Frank
:-)
Rich F.
Not really... the devices are all over the place (although I THINK that Motorola doesn't have this issue I have a D2)
the versions are 2.2+ and 2.3+ (Froyo being the lowest I support)
Mark M.
hmmmm...
Rich F.
blah blah blah lol it is very confusing
I guess my question would be is it ok to assume that the service needs to be started regardless of action?
Mark M.
what are you returning from onStartCommand()?
Rich F.
The only other action would a stop action that the user has to explicitly perform
One sec...
10:55 AM
Rich F.
LMAO DUH START_STICKY
I feel stupid lol
Mark M.
that would explain getting null Intents
not sure why you might be getting null actions on a non-null Intent
Rich F.
Yeah that is cool it is the getaction thing that has me bothered
Mark M.
but personally, I prefer either START_REDELIVER_INTENT or START_NOT_STICKY
Rich F.
and like I said it is only sometimes
Ok I'm game... any particular reason? I can look it up
Mark M.
well, to me, START_STICKY doesn't cover many use cases
in the command pattern, there are usually things in the Intent that I care about
and so I'd want that data back
and so, I use START_REDELIVER_INTENT for those
START_NOT_STICKY would be for cases where users start up the service
and we don't want to restart the service automatically
for example, Google and I disagree on a music player
their docs say use START_STICKY
IMHO, if music stops, the user should designate when the music starts up again, not the OS
so I recommend START_NOT_STICKY for a music player
there may be scenarios where START_STICKY is precisely what you want, but I haven't run into any
Rich F.
Ok, however my app is an auto responder which people might set when going to bed and while sleeping they would want to know that it will consistantly run
Mark M.
so, try switching to START_REDELIVER_INTENT
it will restart your service, like START_STICKY, with better Intent-delivery semantics
11:00 AM
Rich F.
I am for sure... the only concern would be running the auto response twice... but thinking about it I don't think it could
You rock Mr Murphy :) :) :)
Mark M.
somedays, I have rocks in my head
does that count?
anyway, that's it for today's chat
Rich F.
lol me too good sir
Mark M.
next one is tomorrow, 4pm US Eastern Time
Rich F.
Take care and THANK YOU!!!!!!
Frank
thanks!
trdillah
Thanks!
Mark M.
have a pleasant day all!
trdillah
you too!
trdillah
has left the room
Frank
has left the room
Rich F.
has left the room
Mark M.
turned off guest access

Wednesday, December 7

 

Office Hours

People in this transcript

  • Frank
  • Mark Murphy
  • Rich Friedel
  • trdillah