Aug 30 | 7:20 PM |
Mark M. | has entered the room |
Aug 30 | 7:25 PM |
Mark M. | turned on guest access |
Aug 30 | 7:35 PM |
Ettie S. | has entered the room |
Aug 30 | 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!
|
Mark M. |
not usually, particularly if you are planning on distributing your app on the Play Store
|
Mark M. |
the Play Store is starting to enforce minimum required values for targetSdkVersion
|
Mark M. |
and the minimum accepted value will increase each year
|
Mark M. |
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?
|
Ettie S. |
This is a Webkit issue.
|
Mark M. |
is this happening consistently, or only on select devices?
|
Mark M. |
it feels like the device does not have a reasonably current System WebView
|
Aug 30 | 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
|
Mark M. |
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
|
Mark M. |
(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
|
Aug 30 | 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.
|
Ettie S. |
Thank you!
|
Mark M. |
you're welcome!
|
Mark M. |
let me take a question from Aaron, and I will return to you in a bit
|
Mark M. |
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:
|
Aaron |
View paste
(10 more lines)
|
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
|
Mark M. |
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.
|
Mark M. |
right, specifically within ~30 minutes of moving to the background
|
Aug 30 | 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
|
Mark M. |
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)
|
Mark M. |
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
|
Mark M. |
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
|
Aug 30 | 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. | |
Mark M. |
see the checkbox I'm pointing to with the red arrow
|
Aug 30 | 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.
|
Ettie S. |
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
|
Mark M. |
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
|
Mark M. |
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...
|
Mark M. |
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
|
Mark M. |
"Also, Fragment's superclass is java.lang.Object, whose constructor knows nothing about Bundles" -- onCreate() is a method, not a constructor
|
Mark M. |
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
|
Mark M. |
"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
|
Mark M. |
6. AFAICT, Invalidate Caches/Restart is an IDE-level thing, and it clears out IDE-level caches
|
Mark M. |
Build > Clean Project clears out build/ directories in the project
|
Aug 30 | 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
|
Mark M. |
7. I haven't used ExoPlayer, though I've heard good things
|
Mark M. |
you don't necessarily need VideoView -- you can use MediaPlayer with your own SurfaceView or TextureView
|
Mark M. |
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...
|
Aaron |
let me fact check something
|
Vipin | has entered the room |
Vipin |
Hi
|
Aug 30 | 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.
|
Vipin |
I am actually working on an application
|
Vipin |
That kind of works like VPN
|
Vipin |
I am able to connect ot he VPN. THe small key shows up on the top
|
Vipin |
But I am not able to connect to the internet from the VPN
|
Vipin |
Can you point oout anyways to resolve this issue?
|
Mark M. |
not really
|
Mark M. |
I played with the ToyVPN sample a few years ago
|
Mark M. |
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!
|
Mark M. |
Aaron: do you have another question?
|
Aaron |
yes
|
Aaron |
this is from a blog piece I read - is this a true or false statement?
|
Aaron |
"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
|
Aaron |
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?
|
Aaron |
true?
|
Mark M. |
at the time the system needs RAM, it might not have the time to be calling methods on your activities
|
Mark M. |
the *calling* of onSaveInstanceState() is tied to the lifecycle
|
Aug 30 | 8:20 PM |
Mark M. |
the *relevance* of onSaveInstanceState() is tied, in part, to the out-of-memory process killer
|
Mark M. |
you get the Bundle contents back in two primary scenarios:
|
Mark M. |
1. the activity undergoes a configuration change, such as the user rotating the screen
|
Mark M. |
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
|
Aug 30 | 8:25 PM |
Aaron |
Before we run out of time, final follow up on Q4
|
Aaron |
yeah I was getting wires crossed w/r/t constructors, that makes sense -
|
Aaron |
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
|
Mark M. |
we override it sometimes in our subclasses
|
Mark M. |
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
|
Aaron |
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. | |
Mark M. |
it's a method implemented on Fragment
|
Mark M. |
most methods on classes are not defined by interfaces
|
Mark M. |
I would venture that fewer than 5% of the ones on Fragment are defined by interfaces
|
Mark M. |
they are all implemented on Fragment
|
Mark M. |
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
|
Aug 30 | 8:30 PM |
Aaron |
OK - there we go
|
Aaron |
that clicks
|
Aaron |
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
|
Aaron |
thanks a lot!
|
Mark M. |
you're welcome!
|
Mark M. |
and that's a wrap for today's chat
|
Mark M. |
the next chat is Saturday at 4pm US Eastern
|
Mark M. |
this chat's transcript will be posted to https://commonsware.com/office-hours/ shortyl
|
Mark M. |
er, shortly
|
Aaron |
adios
|
Mark M. |
see ya!
|
Aaron | has left the room |
Mark M. | turned off guest access |