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
|
Dec 14 | 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]);
|
trdillah | |
trdillah |
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
|
trdillah |
This code exists in an Android widget
|
trdillah |
I am calling a service called "UpdateWallPaper"
|
trdillah |
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"?
|
Mark M. |
do you mean an app widget?
|
trdillah |
Yes, an app widget
|
trdillah |
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
|
trdillah |
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
|
trdillah |
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
|
Mark M. |
I have never written a live wallpaper
|
Dec 14 | 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
|
trdillah |
ie, i'm not using any live wallpaper features
|
trdillah |
i'm just changing the app wallpaper using the BitmapFactory
|
trdillah |
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
|
trdillah |
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
|
Mark M. |
when you are done with a Bitmap object, call recycle()
|
Mark M. |
that may or may not help with resources, though
|
Mark M. |
Android seems to tend to cache those itself
|
Mark M. |
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
|
trdillah |
this application widget should reside on the device at all times
|
Mark M. |
in theory, that's true
|
Mark M. |
but the Bitmap does not
|
trdillah |
hmm, "in theory?"
|
trdillah |
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
|
trdillah |
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
|
Mark M. |
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
|
Mark M. |
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?
|
Dec 14 | 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
|
Mark M. |
MAT is the Memory Analysis Tool
|
Mark M. |
you use it to analyze the contents of your heap
|
Mark M. |
to figure out where your memory is going
|
Mark M. |
it's covered in _Tuning Android Applications_, available with your Warescription
|
trdillah |
Okay, great!
|
trdillah |
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
|
Mark M. |
android:layout_marginRight="..." on the right-most widget
|
Mark M. |
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
|
Mark M. |
Gallery is not used as much as other selection widgets, like ListView
|
Mark M. |
it's really mostly designed for thumbnail previews, as in wallpaper pickers
|
Dec 14 | 10:20 AM |
Mark M. |
is the metadata a fixed set of widgets that change based upon the image selection?
|
Mark M. |
or are there widgets for each image that scroll with the image?
|
Mark M. |
rephrase: or are there metadata widgets for each image that scroll with the image
|
Mark M. |
?
|
Frank |
Yes the metadata changes with each image.
|
Frank |
I was thinking of having it scroll synchronously with the images.
|
Mark M. |
that definitely feels like a Gallery, then
|
Mark M. |
wait
|
Mark M. |
let's say the Gallery is capable of showing 5 images
|
Mark M. |
are there 5 sets of visible metadta? or 1?
|
Frank |
Well...
|
Mark M. |
(er, metadata)
|
Frank |
no
|
Frank |
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
|
Mark M. |
where each of those holds onto your image and your metadata
|
Mark M. |
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!
|
Frank |
why?
|
Mark M. |
because 5" is 2" more than 3" :-)
|
Dec 14 | 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.
|
Frank |
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
|
Mark M. |
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.
|
Mark M. |
this is a major topic area for _Tuning Android Applications_ that I'll be getting into in early-ish 2012
|
Frank |
View paste
|
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="..."
|
Dec 14 | 10:30 AM |
trdillah |
I think it would work as I expected if I moved the scrollview below the first linear layout
|
trdillah |
but, android doesn't allow me to do that
|
Mark M. |
well, you can only have one root
|
Mark M. |
is the first LinearLayout supposed to scroll?
|
trdillah |
no, the first linear layout doesn't need to scroll
|
trdillah |
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
|
Mark M. |
ScrollView can only have one child
|
Mark M. |
all widgets only have one parent
|
Mark M. |
all layouts only have one root, because that's imposed by XML
|
Mark M. |
ScrollView scrolls multiple children by having
those children organized in some sort of container (LinearLayout,
RelativeLayout, etc.)
|
Mark M. |
if you do not want some things to scroll, they do not belong inside the ScrollView's portion of your view hierarchy
|
Dec 14 | 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
|
Mark M. |
is the metadata something that is derived from the image itself (e.g., pixel size) or is it coming from other sources?
|
Mark M. |
(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
|
Mark M. |
if these images are from the camera, they are hopefully on external storage, and so the user can delete them as desired
|
Mark M. |
beyond that, though, I'd probably use a database
|
Mark M. |
you can't query across a bunch of files
|
Frank |
yes if external storage is available I will use it
|
Frank |
I was worrying about putting large blobs in Sqlite.
|
Frank |
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
|
Dec 14 | 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
|
Mark M. |
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
|
Mark M. |
now, that assumes this is a consumer app
|
Mark M. |
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.
|
Frank |
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
|
Dec 14 | 10:45 AM |
Mark M. |
transactions may be slower to apply with larger contents
|
Mark M. |
but, I haven't put large images in a SQLite database, let alone on Android
|
Mark M. |
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 :-)
|
Mark M. |
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
|
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
|
Mark M. |
however, Intents don't have to have actions
|
Mark M. |
e.g., startService(new Intent(this, MyService.class)); has no action)
|
Mark M. |
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
|
Dec 14 | 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
|
Mark M. |
er, score
|
Rich F. |
View paste
|
Rich F. |
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)
|
Rich F. |
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
|
Rich F. |
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
|
Rich F. |
One sec...
|
Dec 14 | 10:55 AM |
Rich F. |
LMAO DUH START_STICKY
|
Rich F. |
I feel stupid lol
|
Mark M. |
that would explain getting null Intents
|
Mark M. |
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
|
Rich F. |
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
|
Mark M. |
in the command pattern, there are usually things in the Intent that I care about
|
Mark M. |
and so I'd want that data back
|
Mark M. |
and so, I use START_REDELIVER_INTENT for those
|
Mark M. |
START_NOT_STICKY would be for cases where users start up the service
|
Mark M. |
and we don't want to restart the service automatically
|
Mark M. |
for example, Google and I disagree on a music player
|
Mark M. |
their docs say use START_STICKY
|
Mark M. |
IMHO, if music stops, the user should designate when the music starts up again, not the OS
|
Mark M. |
so I recommend START_NOT_STICKY for a music player
|
Mark M. |
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
|
Mark M. |
it will restart your service, like START_STICKY, with better Intent-delivery semantics
|
Dec 14 | 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
|
Rich F. |
You rock Mr Murphy :) :) :)
|
Mark M. |
somedays, I have rocks in my head
|
Mark M. |
does that count?
|
Mark M. |
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 |