Sep 24 | 3:55 PM |
Mark M. | has entered the room |
Mark M. | turned on guest access |
Ron B. | has entered the room |
Mark M. |
hello, Ron!
|
Mark M. |
how can I help you today?
|
Ron B. |
Hi Mark!
|
Sep 24 | 4:00 PM |
Ron B. |
I am trying to display a web view from an Activity started from another activity. I want the user to be able to return to the original activity via the back button. The problem is that it takes two back button taps to achieve this. I can't seem to catch the first one on any callback.
|
Gabriele | has entered the room |
Gabriele |
Hi :)
|
Mark M. |
I am not aware that a WebView automatically grabs the BACK button
|
Mark M. |
(BTW, hello, Gabriele -- be with you shortly!)
|
Gabriele |
no problem, just reading :P
|
Gabriele |
I don't have any question :)
|
Mark M. |
Ron: what OS level are you using, and what callbacks did you try?
|
Ron B. |
I have onBackPressed and onPause, but these seem to catch the second one. It occurs on 2.3.6 and 4.2.
|
Ron B. |
Is it something the webpage is setting?
|
Mark M. |
does it make a difference what, if anything, the user has done in the WebView itself?
|
Ron B. |
There isn't much to do in the webview but look at it.
|
Ron B. |
Very reproduceable
|
Mark M. |
so you get this even though the user has not clicked any links, etc.?
|
Ron B. |
Correct. Just on entry.
|
Sep 24 | 4:05 PM |
Mark M. |
I have not run into this personall
|
Mark M. |
er, personally
|
Mark M. |
for example, in the APK edition of my book, bringing up help does not require multiple BACK presses to return
|
Ron B. |
The first back button generates a blank screen.
|
EGHDK | has entered the room |
Ron B. |
On mine.
|
Mark M. |
I would use Hierarchy View and/or uiautomatorviewer to determine where you are at that point in time (blank screen)
|
Mark M. |
(BTW, hello, EGHDK, be with you shortly!)
|
Mark M. |
IOW, what activity are you on, what widgets are visible, etc.
|
Mark M. |
for example, are you *sure* that what you are reading the Web content in is actually your app?
|
Mark M. |
I can definitely see your scenario occurring if a server redirect caused the content that you thought was coming up in a WebView to go into the user's default browser
|
Mark M. |
let me take questions from the others, and I can swing back to you in a bit
|
Mark M. |
Gabriele: just double-checking -- do you have a question?
|
Sep 24 | 4:10 PM |
Mark M. |
OK, EGHDK: do you have a question?
|
EGHDK |
Okay, so I have a problem in my application. It's released for API level 15+ so it works fine on thsoe devices. I have a problem with 2.3 devices (API 10). For some reason every time I press the back button once I drilled deeper down into the application, I go back to the previous activity and the entire screen is white. And it stays there. If I click any button on that screen, the onCLick of that buttons fire appropriately. I don't know how to begin to debug. I have tried heirchy viewer
|
EGHDK |
The button fires appropriately, and the screen comes back into view.
|
Mark M. |
so, until the first touch event, the screen is white, and once you touch something, it draws?
|
EGHDK |
Yeah it won't draw until I otuch something.
|
EGHDK |
But I have to touch a button, hitting "white space" doesn't do anything.
|
Mark M. |
not sure how you are getting into that state
|
Mark M. |
try calling invalidate() on your top-level container, or the FrameLayout known as android.R.id.content, and see if that helps
|
EGHDK |
It happens on every 2.x device.
|
Mark M. |
call that in onResume(), or perhaps onStart()
|
EGHDK |
onStart? I will try that. It doesn't only happen on the main drawer activity though
|
Mark M. |
what I suggested was a hack, just to temporarily get you past the problem
|
EGHDK |
Main drawer activity is activity A. I click a button to go to activity B, and I click another button to go to activity C. If I press back (to get to B) I will still get a white screen on B.
|
EGHDK |
And B has nothing to do with the drawer at all.
|
Sep 24 | 4:15 PM |
Mark M. |
well, I never implied anything about a drawer
|
Mark M. |
I have never seen the behavior that you are describing, though, and so I don't have any particular recommendations on a more permanent fix
|
EGHDK |
Anything else that I could try?
|
Mark M. |
play around with some other project for a bit
|
Mark M. |
such as any of my book samples
|
EGHDK |
To debug? The only other information is that I have a bunch of libraries.
|
Mark M. |
if you do see this behavior in the other samples, then there's something up with your device(s)
|
EGHDK |
That I'm using. I have thought about slowly removing libraries to see if that will fix anything.
|
Mark M. |
if you do not see this behavior in the other code, start adding in stuff of note until the behavior pops up
|
EGHDK |
No, I've tried my own sample applications. And it works fine.
|
EGHDK |
It's only in my one app, but I was always testing on a gnex, so I never noticed the problem.
|
Mark M. |
right
|
Mark M. |
ah
|
Mark M. |
yeah, unfortunately, this tends to be a bit of "debugging by weedwhacker" at this point
|
EGHDK |
I thought that maybe it was a listView issue so I tried cacheColorHint, but nothing came from that.
|
Mark M. |
it feels like something is interfering with the normal redraw when you come back into the foreground
|
Mark M. |
and I have no idea what would do that or how
|
Mark M. |
other than it is probably something that you are using in all affected activities
|
Mark M. |
let me swing back to the others, and I'll return to you in a bit
|
Mark M. |
Ron: do you have another question?
|
Sean D. | has entered the room |
Ron B. |
Back on webviews. I may be off on terminology. Not a lot of experience with webview. I specify a webview layout and do a loadUrl into it.
|
Mark M. |
and that's fine, so long as the URL does not result in a redirect request from the server
|
Mark M. |
if the server sends back a 301 or 304 or something, the default behavior of a WebView is to load the redirected-to URL in the default browser
|
Sep 24 | 4:20 PM |
Mark M. |
you can use WebViewClient and shouldOverrideUrlLoading() to control this behavior
|
Ron B. |
OK, thanks. I'll look into it.
|
Mark M. |
Sean: hi! do you have a question?
|
Sean D. |
hi! yeah, i had a quick question on using SQLLite
|
Sean D. |
in my application, i've been storing data in a flat file and also holding it all in memory to reduce how often i need to read from the disk
|
Sean D. |
and recently i've been considering switching to SQLLite and maybe a content provider
|
Mark M. |
OK... but what is your question?
|
Sean D. |
i was reading your section about using SQLLite with listviews... so does it query the DB (and read from disk) every time it refreshes the listview?
|
Mark M. |
that is one approach, and usually the default one
|
Mark M. |
same thing happens with a ContentProvider and a CursorLoader
|
Sep 24 | 4:25 PM |
Sean D. |
okay, if that's standard then i might go with that... i just wasn't sure, i thought reading from disk so often might be bad
|
Mark M. |
well, the first rule of disk I/O is to do it on a background thread
|
Mark M. |
which reduces the impact
|
Sean D. |
yeah, i need to make that change... i just found out about StrictMode and i've been reading on the main thread
|
Mark M. |
keeping a live copy of an in-memory cache up to date and synchronized properly with the database and all other users of the data gets complicated
|
Sean D. |
i also have a map view... would it be easy to integrate with the DB as well?
|
Mark M. |
well, that depends on what you mean by integrating a MapView with a database
|
Sean D. |
each instance has its own coordinates so the mapview displays the same number that the listview does
|
Mark M. |
you mean that you are using markers on the map, one per database entry?
|
Sean D. |
yeah, sorry
|
Jeff | has entered the room |
Mark M. |
that should not be especially hard, though the devil is in the details
|
Mark M. |
in particular, things get messy if you need to display information in an info window that you do not already have in memory (e.g., as columns in the Cursor)
|
Mark M. |
I'll have some stuff on that particular problem in the next book update
|
Mark M. |
let me take questions from the others, and I'll be back with you in a bit
|
Mark M. |
Jeff: hi! do you have a question?
|
Sep 24 | 4:30 PM |
Sean D. |
okay
|
Jeff |
hi Mark
|
Jeff |
I'm drawing what should be a simple screen: header/title, list fragment, and edit text
|
Jeff |
when I use linear layout, then a large number of list entries pushes the edit text off the screen
|
Mark M. |
use weights to control
|
Mark M. |
give the ListView a height of 0 and a weight of 1
|
Mark M. |
give the EditText a height of wrap_content (and the default weight of 0)
|
Jeff |
relative layout solves that problem using align bottom and below
|
Mark M. |
that too can work
|
Ron B. | has left the room |
Jeff |
but the relative layout fills the screen with the edit text when the list is empty
|
Mark M. |
oh, sorry, misunderstood how you were using the RelativeLayout
|
Mark M. |
change the EditText to be alignParentBottom=true and no other RelativeLayout rules
|
Mark M. |
change the ListView to be alignParentTop=true and above=@id/yourEditText
|
Jeff |
ahh - above
|
Mark M. |
you want to have the EditText be its natural height, and stretch the ListView to fill available space
|
Jeff |
exactly
|
Jeff |
I see
|
Jeff |
thanks
|
Jeff |
I felt like I was taking the long way around the barn
|
Mark M. |
Gabriele: if you come up with a question, chime in!
|
Mark M. |
well, sometimes, it's a rather large barn :-)
|
Mark M. |
EGHDK: do you have another question?
|
Sep 24 | 4:35 PM |
EGHDK |
Not really. Unless my original question marinated in your head long enough for you to pose another plan of attack.
|
EGHDK |
I will add in the invalidate onstart. I just wish I knew when this problem started happening.
|
Mark M. |
not really, no, sorry
|
Mark M. |
this is one advantage of a service like Apkudo
|
Mark M. |
free monkey testing across a lot of devices
|
Jeff |
can you repeat the problem?
|
Mark M. |
running that every so often would help catch these things before a manual test might
|
EGHDK |
Yes I can repeat the problem.
|
Jeff |
btw, I use apkudo and like it - not perfect but helpful
|
Mark M. |
Jeff: his problem was that on a BACK press, his activities were coming up visually blank until tapping on something
|
EGHDK |
It happens every time in my app. I thought maybe it was Action bar sherlock. but nothing on SO points to that.
|
Mark M. |
yeah, lots of my samples use ABS, and I have not had that problem on Android 2.x
|
EGHDK |
Anyway. Okay, so other question is a programming one. Since I don't really understand some of the more general concepts in OOP/java.
|
Jeff |
do you override onStop() and onPause()?
|
EGHDK |
@ Jeff. Yes I do.
|
Jeff |
bummer
|
EGHDK |
Just weird that it works perfectly on 2.3
|
EGHDK |
So Mark, "What is a callback?" I hear that a lot, and I feel like I know what it means. But your definitions have been helpful to clear things up as well.
|
Mark M. |
in the context of Android, a "callback" is some method of yours being invoked by the framework
|
Mark M. |
this will either be something you are overriding from a parent class, or a method on an interface that you are implementing
|
Sep 24 | 4:40 PM |
Mark M. |
so, onCreate(), onClick(), onListItemClick(), would all be considered callbacks
|
EGHDK |
Gotcha.
|
EGHDK |
What about onPause onStop?
|
Mark M. |
same thing
|
Mark M. |
again, if *Android* is calling *you*, a common convenience term for that is a callback
|
Mark M. |
it's not the most scientific term out there
|
Mark M. |
but, it's a convenient shorthand
|
EGHDK |
Gotcha. Cool. That's what my idea of a callback was, so that's good. lol
|
Mark M. |
Sean: do you have another question?
|
Sean D. |
just one followup: you said earlier that things get tricky if you want to display info that's not in memory... did you mean things not held in the Cursor?
|
Sean D. |
or including columns in the Cursor
|
Mark M. |
yes, and I mean *specifically* for an info window to be displayed when the user taps on a marker
|
Sean D. |
okay... the info displayed in the info window would be within the Cursor, so i'll get to researching and implementing
|
Sean D. |
thanks for your help
|
Mark M. |
Jeff: do you have another question?
|
Sep 24 | 4:45 PM |
Mark M. |
EGHDK: do you have another question?
|
Mark M. |
OK, if anyone has a question, feel free to chime in
|
EGHDK |
I guess I'm having a tough time learning what an interface is. I've read a ton about them, but I've never found a use for them in java or android (yet) but I hear them talked about a lot. Any examples you can throw at me? Or any github resources on it from you?
|
Mark M. |
refresh my memory: what other programming languages do you know?
|
EGHDK |
Erm... none really.
|
Mark M. |
ah
|
Mark M. |
OK
|
Mark M. |
an interface is pretty much just what the name implies
|
Mark M. |
it is a basket of method signatures, that implementers of that interface must implement
|
Mark M. |
you use this for things like polymorphism
|
Mark M. |
so, for example, to respond to a click on a widget, you need to call setOnClickListener() on the View
|
Sep 24 | 4:50 PM |
EGHDK |
Yeah, so I kinda know what it means. I have seen youtube videos explaining it, but I guess in the context of Android, do you have any more examples with it?
|
Mark M. |
you pass in an implementation of an OnClickListener interface
|
Mark M. |
the View does not care *what* the actual underlying object is, from a class standpoint
|
Mark M. |
all it knows and cares about is that the object implements the OnClickListener interface
|
Mark M. |
and therefore we can call onClick() on it
|
Mark M. |
you can think of the standard US 3-prong AC outlet as being an interface to the power in your home
|
EGHDK |
But I've never done MainActivity extends Activity implements OnClickListener. And I have setOnClickListeners on thousands of views.
|
Mark M. |
the outlet does not care whether you are plugging in a television, a toaster, or a teakettle, so long as it has those three prongs
|
Mark M. |
*every* time you called setOnClickListener(), you passed in an implementation of the OnClickListener interface
|
Mark M. |
whether you implement OnClickListener on the Activity, on the Fragment, or on something else is largely up to you
|
Mark M. |
(garbage collection and OO design considerations aside for the moment)
|
EGHDK |
Interesting. Okay, where would I find "proof" that I'm passing an implementation of the OnCLickListener interface when I set it on a view?
|
EGHDK |
Is that interface implemented in the View object?
|
Mark M. |
if you don't, your code will not compile
|
Mark M. |
no, View does not implement OnClickListener
|
Sep 24 | 4:55 PM |
EGHDK |
Hmm... okay. I still don't understand where I'm implementing it then.
|
EGHDK |
I thought setOnCLickListener was just a mthod of a view.
|
Mark M. |
it is
|
Mark M. |
myButton.setOnClickListener(foo);
|
EGHDK |
Foo is the interface?
|
Mark M. |
foo must implement the OnClickListener interface for this code to compile, assuming that myButton is an implementation of the android.view.View class
|
Mark M. |
here, foo is a parameter being passed to setOnClickListener()
|
Mark M. |
you *really* need to step away from Android development for a while and read a book on Java
|
EGHDK |
Gotcha. Okay, if you have any more examples where I would use "... extends Activity implements XYZ" in Android. Let me know. I see a couple of people online that voice strong opinions about interfaces, and I'm just sitting here like... I've never implemented an interface.
|
EGHDK |
Yeah, I guess I might purchase that head first java book.
|
Mark M. |
what you are probably seeing in terms of "strong opinions" is *where* you implement the interface
|
EGHDK |
You think head first java will cover java timers and threads etc?
|
Mark M. |
I would hope it would cover threads
|
Mark M. |
Timer is largely deprecated, and usually not the right choice in Android anyway
|
EGHDK |
Hrm... I was thinking about doing a project with Timers. What would be the right choice in Android?
|
EGHDK |
SInce timers were in java, I thought I'd go with them.
|
Mark M. |
well, it depends on what you are trying to do
|
Sep 24 | 5:00 PM |
EGHDK |
Yeah, I guess it can go a few ways. But if I was just trying to keep count of something, I thought java timers sounded good enough
|
Mark M. |
usually, to count, an integer is enough
|
Sean D. | has left the room |
Jeff | has left the room |
Mark M. |
and that's a wrap for today's chat
|
EGHDK |
Yeah. Alright, looks like we're closing up.
|
EGHDK |
Thanks Mark
|
Mark M. |
the chat transcript will be posted to http://commonsware.com/office-hours/ shortly
|
Mark M. |
the next chat is Thursday at 7:30pm Eastern
|
Mark M. |
have a pleasant day, all!
|
Gabriele |
thank you, bye :)
|
Gabriele |
you too!
|
Gabriele | has left the room |
EGHDK | has left the room |
Mark M. | turned off guest access |