Office Hours — Today, August 30

Tuesday, August 28

Aug 30
7:20 PM
Mark M.
has entered the room
7:25 PM
Mark M.
turned on guest access
7:35 PM
Ettie S.
has entered the room
7:40 PM
Ettie S.
Hello. I was wondering if you could clarify about lowering a targetsdk to bypass an error. Is this a good idea?
Mark M.
hello, Ettie!
not usually, particularly if you are planning on distributing your app on the Play Store
the Play Store is starting to enforce minimum required values for targetSdkVersion
and the minimum accepted value will increase each year
so, eventually, you will need to find another solution to whatever the problem is
Ettie S.
That's a problem then. I upgraded the targetsdk to 27 and then got the same error as in this SO question: https://stackoverflow.com/q/49633271/5095571. I'm not sure how else to solve it. I would go back to 26 but I'm guessing that Google will keep wanting updates to user higher sdk's as they go along. Do you have any recommendations?
This is a Webkit issue.
Mark M.
is this happening consistently, or only on select devices?
it feels like the device does not have a reasonably current System WebView
7:45 PM
Ettie S.
So then it depends if the device updated Webview in the Play Store?
Mark M.
that is my interpretation of that stack trace, and from what I know about how the System WebView stuff works
however, I haven't run into this stack trace personally
Ettie S.
Makes sense but I'm not sure how to solve this, particularly because the app doesn't crash, it just reveals the class and line number for this issue even when it's released and proguard is on and logs are removed.
Mark M.
well, if the app doesn't crash... are you experiencing other symptoms? otherwise, I would write this off as over-aggressive logging by the WebView developers
Ettie S.
Thankfully it's working.
Aaron
has entered the room
Mark M.
View paste
you might also try adding <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
android:value="false" /> to your <application> and see if that helps, given the specific thing it is failing on
(BTW, hello, Aaron -- I will be with you shortly!)
Ettie S.
Thanks. I'm just concerned about security, it's showing class and line number.
Aaron
thanks!
Ettie S.
Is that really not safe? Everything else is hidden.
Mark M.
well, frankly, ProGuard obfuscation is not much of a defense -- some attackers have indicated it actually helps them
Ettie S.
Anything else I can do?
Mark M.
I doubt it
7:50 PM
Mark M.
particularly if the exception is raised from inflation of a layout, as it is in that SO question
Ettie S.
Ok. I'll try the code you wrote.
Thank you!
Mark M.
you're welcome!
let me take a question from Aaron, and I will return to you in a bit
Aaron: your turn! do you have a question?
Aaron
7 questions, lol. The first four are the priorities if there's not time for all. Here they are:
View paste (10 more lines)
1. Our last chat about replacing fragments was very helpful, but I'm still confused about one thing. You said that fragment replacement is a "1:1 operation", but the documentation says calling replace is the same as calling remove on all currently added fragments followed by adding the new one, which to me sounds like a many-to-1 relationship. Can you clarify what you meant by 1:1?

2. In another previous chat you explained that onSaveInstanceState is not invoked when the user intentionally destroys an activity with BACK. Instead, you said: "onSaveInstanceState() is for configuration changes (e.g., screen rotation) and short-term process termination (e.g., user presses HOME, then returns to the app 20 minutes later)". I'm still confused about this. What is a "short term process termination"? My understanding is that Android's automatic process termination is when the low-memory killer algo kicks in to shut down stopped apps and reclaim RAM, and this is the only other scenario besides config changes where the bundle is saved. If a user comes back 20 minutes later, isn't it more likely that the app _won't_ have been killed off yet, and it'll simply be restarted from a stopped state -
...
Mark M.
1. IMHO, having more than one fragment in a container is a code smell, which is why I only think of replace() as being 1:1
2. "What is a "short term process termination"?" -- when your app is no longer in the foreground, your process could be terminated within milliseconds
Aaron
ok, so you were just referring to a case where it happens sooner rather than later
Mark M.
how long it lives is dependent upon a laundry list of environmental conditions: amount of system RAM, number and size of active apps, what the user is doing, etc.
right, specifically within ~30 minutes of moving to the background
7:55 PM
Mark M.
in that case, Android wants to pretend like your process was around all along, even though in reality it nuked your process from orbit
Aaron
ok got it. I thought you were making a distinction between multiple types of process termination
Mark M.
3. Because getAdapter() returns Adapter, not T (where T is the specific subtype of Adapter that you are using)
Aaron
so to summarize #2: there is only one type of process termination, it may happen nearly immediately after your app is backgrounded, or it may not happen for hours or days, but when it does happen, that is when the Bundle is saved - correct?
Mark M.
no
Aaron
ahh
Mark M.
onSaveInstanceState() will be called around the time that you move into the background
the Bundle is *used* when you return to the foreground, even if your process was terminated (but, in that case, only if the user returns to you within ~30 minutes)
after ~30 minutes, Android just starts over from your launcher activity (or whatever activity is at the root of the task, in more complex scenarios) and does not bother with the Bundle
let me take another question from Ettie, and I'll return to your list shortly
Aaron
huh, OK, is this covered in your book? I don't recall reading anything about 30 minutes
Mark M.
Ettie: back to you! do you have another question?
Aaron
thanks
8:00 PM
Mark M.
(Aaron: I mention the 30-minute task lifetime in the Tasks chapter, though not in the chapter on the saved instance state Bundle)
Ettie S.
Yes, thank you. Android Studio question: what do I do if the sdk manager won't let me download sdk 28? It shows that it's available but the checkbox won't click? By the way, I still couldn't get the Webkit error to work so I think I'll have to use a html parser like JSoup.
Mark M.
if you check the "Show Package Details" checkbox, does the Android API 28 entry expand to show the individual pieces?
Ettie S.
I'm sorry but I don't see that.
Mark M.
see the checkbox I'm pointing to with the red arrow
8:05 PM
Mark M.
note: this is from Android Studio 3.1
Ettie S.
Thanks. That probably is it. I need to upgrade Android Studio. Sorry, my mistake.
Thank you.
Mark M.
what version of Studio do you have?
Ettie S.
3.0.1
Mark M.
yeah, it is possible that's the problem
Google doesn't support older versions of Android Studio particularly well
Ettie S.
Ok. Thank you so much!
Mark M.
note that Android Studio 3.2 should ship in final form within the next few weeks
let me switch back to Aaron's list, and I'll be back with you in a bit
Ettie S.
I'll be sure to update ASAP. Thanks.
Mark M.
Aaron: continuing the march through your list...
4. "If this line were removed, the compiler would include a default call to super() instead" -- no, that is only for constructors
Ettie S.
has left the room
Mark M.
"What would happen in that case?" -- without the super.onCreate() call, you crash at runtime with a SuperNotCalledException
"Also, Fragment's superclass is java.lang.Object, whose constructor knows nothing about Bundles" -- onCreate() is a method, not a constructor
5. "Does File -> Sync Project With Gradle Files mean the same thing as "perform a Gradle sync"?" -- probably, though I'd have to see the context
"Is it the same thing as the "Sync Now" hyperlink that appears after modifying your build.gradle?" -- yes, as every now and then, that banner doesn't show up when it should
6. AFAICT, Invalidate Caches/Restart is an IDE-level thing, and it clears out IDE-level caches
Build > Clean Project clears out build/ directories in the project
8:10 PM
Mark M.
Invalidate Caches/Restart is the sort of thing that I rarely ever need (and it would be truly never except for the project of a current consulting client of mine...)
Aaron
I see
Mark M.
whereas Clean Project is something that I do routinely, particularly if I'm switching between git branches or otherwise making wholesale changes to the project contents
7. I haven't used ExoPlayer, though I've heard good things
you don't necessarily need VideoView -- you can use MediaPlayer with your own SurfaceView or TextureView
VideoView is for lightweight scenarios, and you'll want something more flexible for anything significant
Aaron
OK interesting
Mark M.
whether that's MediaPlayer or ExoPlayer is up to you, though I would lean in the ExoPlayer direction
Aaron
good info, thanks. about #2 and #4...
let me fact check something
Vipin
has entered the room
Vipin
Hi
8:15 PM
Mark M.
Aaron: let me take a question from Vipin, and I'll return to you shortly
Aaron
no problem
Mark M.
Vipin: hi! welcome to the chat! how can I help you today?
Vipin
HI Mark.
I am actually working on an application
That kind of works like VPN
I am able to connect ot he VPN. THe small key shows up on the top
But I am not able to connect to the internet from the VPN
Can you point oout anyways to resolve this issue?
Mark M.
not really
I played with the ToyVPN sample a few years ago
otherwise, I have not worked with VpnService, and I do not know how it all works
Vipin
Okay No problem. thank you for trying
Mark M.
sorry!
Vipin
Thats fine HAve a great day :)
Mark M.
you too!
Aaron: do you have another question?
Aaron
yes
this is from a blog piece I read - is this a true or false statement?
"Right before the application is about to be terminated by low memory killer, each Activity is notified about this with a call to its onSaveInstanceState(Bundle) method. "
Mark M.
false
Aaron
I am trying to debug where my confusion is coming from :p
I see
Mark M.
it's called around the time that you move to the background
Aaron
so it's tied to the activity or fragment lifecycle - NOT to the task killer?
true?
Mark M.
at the time the system needs RAM, it might not have the time to be calling methods on your activities
the *calling* of onSaveInstanceState() is tied to the lifecycle
8:20 PM
Mark M.
the *relevance* of onSaveInstanceState() is tied, in part, to the out-of-memory process killer
you get the Bundle contents back in two primary scenarios:
1. the activity undergoes a configuration change, such as the user rotating the screen
2. your app was in the background, and your process was terminated, but the user tries returning to your app within ~30 minutes, and so Android creates a new instance of your last activity, and hands it the Bundle contents
Aaron
Ohhh. I think I get you now.
Mark M.
since #1 happens a lot more often and is easier to test, we tend to focus on #1
Aaron
I had no idea about this 30 minute thing, and none of the other resources I read (official docs, this blog, Big Nerd Ranch) mention it either
Mark M.
that's because we tend to focus on #1
Aaron
OK... I think it all clicks now
8:25 PM
Aaron
Before we run out of time, final follow up on Q4
yeah I was getting wires crossed w/r/t constructors, that makes sense -
but then what is super doing in this context? AFAIK super is only for calling a superclass constructor or accessing a hidden member of the superclass - but onCreate isn't a member of the superclass... so..?
Mark M.
Fragment implements an onCreate() method
we override it sometimes in our subclasses
sometimes, when we override a method, we need to chain to the superclass' implementation of the method, so it too gets a chance to do its work
Aaron
View paste
Fragment documentation says: public class Fragment
extends Object implements ComponentCallbacks, View.OnCreateContextMenuListener, LifecycleOwner, ViewModelStoreOwner
I don't see onCreate in any of those interfaces - what am I missing
Mark M.
onCreate() is the name of a method, not an interface
Aaron
right, but I don't see that it's part of the contract in any of the four interfaces that Fragment implements
Mark M.
it's a method implemented on Fragment
most methods on classes are not defined by interfaces
I would venture that fewer than 5% of the ones on Fragment are defined by interfaces
they are all implemented on Fragment
you can look at the source code to Fragment, if you like, and see the implementation
Vipin
has left the room
Mark M.
in your *subclass* of Fragment, you might override onCreate(), but Fragment still needs to execute its own onCreate(), so we chain to the superclass implementation
8:30 PM
Aaron
OK - there we go
that clicks
self teaching this stuff leads to all kinds of weird and nebulous misunderstandings, it's the worst, lol. very helpful though - think I have all this more or less straight now
thanks a lot!
Mark M.
you're welcome!
and that's a wrap for today's chat
the next chat is Saturday at 4pm US Eastern
this chat's transcript will be posted to https://commonsware.com/office-hours/ shortyl
er, shortly
Aaron
adios
Mark M.
see ya!
Aaron
has left the room
Mark M.
turned off guest access

Tuesday, August 28

 

Office Hours

People in this transcript

  • Aaron
  • Ettie Schreiber
  • Mark Murphy
  • Vipin

Files in this transcript