Mark M. | has entered the room |
Mark M. | turned on guest access |
Kai H. | has entered the room |
Kai H. |
Hello
|
Mark M. |
hello, Kai!
|
Mark M. |
how can I help you today?
|
Kai H. |
Those messages turned up in the wrong order for me 8)
|
Mark M. |
¯\_(ツ)_/¯
|
Kai H. |
I have an Activty that receives certain file types, which is denoted in the AndroidManifest.
|
Kai H. |
How would I start the App that this Activity is part of?
|
Kai H. |
Right now the Activity gets started with some support stuff, but not the main Application, as far as I see it.
|
Mark M. |
I guess I do not understand the question
|
Mark M. |
ummmmmm... that would be extraordinarily unusual
|
Dec 15 | 8:30 AM |
Mark M. |
how have you determined this?
|
Kai H. |
Guessing, I guess :D
|
Kai H. |
So I am not sure about it.
|
Mark M. |
the Application instance is created as part of forking the process
|
Mark M. |
so, if you already have an existing process, starting an activity does not create an Application instance
|
Mark M. |
however, that just means that the Application instance was created earlier
|
Kai H. |
So I only need to somehow switch to it. Or switch to another Activity within that Application.
|
Mark M. |
I don't know what either of those things mean, sorry
|
Kai H. |
We have an Activity that with an intent filter for files with a certain suffix. And so far that Activity was opened, something was done with the file and then the activity (and the App afaik) was closed again. Now I want it to open the main Activity of the App.
|
Mark M. |
"Now I want it to open" -- what is "it"?
|
Kai H. |
This Activity that handles the files.
|
Mark M. |
but, the user closed it ("and then the activity... was closed again")
|
Kai H. |
No, we close it programmatically.
|
Mark M. |
do you mean that you want back navigation to go to the main activity?
|
Dec 15 | 8:35 AM |
Mark M. |
um, under what circumstances do you close it programmatically? is that based on a button click or other user input?
|
Mark M. |
and, isn't this just a matter of calling startActivity() to start your main activity, before you call finish()?
|
trocchietto_Ivano | has entered the room |
Kai H. |
It's an activity that just displays a progress bar and then gives up control again.
|
Kai H. |
Probably.
|
trocchietto_Ivano |
hallo world
|
Mark M. |
(hello, Ivano -- I will be with you shortly!)
|
Kai H. |
Hello ivano
|
Kai H. |
I was under the assumption that the main application wasn't started, but I guess that was wrong.
|
Mark M. |
Kai: assuming that you are calling finish() to get rid of this file-processing activity, just call startActivity() to start your main activity before that finish() call
|
Mark M. |
the Application instance isn't really involved in anything of what you have described
|
Kai H. |
I'll try just doing an startActivity on the Activity that is registered for launcher and main.
|
Mark M. |
the fact that the user used a different entry point (some sort of ACTION_VIEW or ACTION_SEND Intent, I'm guessing) doesn't really change anything about your app, other than what activity gets displayed
|
Kai H. |
OK.
|
Mark M. |
to draw an analogy: the user linked to an article in the Web site rather than the home page -- this does not change how that article's page links back to the home page
|
Kai H. |
Should I start the MAIN/LAUNCHER Activity or the class in <application android:name="..."?
|
Mark M. |
startActivity() starts activities
|
Mark M. |
I am unclear why you are fixating on the Application instance -- again, it is not really related to anything about your scenario
|
Mark M. |
so, if your MAIN/LAUNCHER activity is MainActivity, use startActivity(this, MainActivity.class).
|
Mark M. |
(give or take a semicolon at the end)
|
Dec 15 | 8:40 AM |
Mark M. |
the Application instance will already have been created (when the process was started), and startActivity() does not change that
|
Kai H. |
Probably because it exists and I don't really know where our entry points for the App are and what I need to instantiate before.
|
Mark M. |
the launcher activity is not special, other than because of your <intent-filter>, it appears in the launcher
|
Mark M. |
Application is not an entry point -- it's more of an artifact of process creation
|
Mark M. |
any exported activity, particularly those with an <intent-filter>, are entry points
|
Mark M. |
and your app can have one, two, or a thousand of those
|
Mark M. |
from Android's standpoint, by and large, they are all equal
|
Mark M. |
a launcher activity is not particularly special -- it's just advertising itself as something a launcher might want to offer to users
|
Mark M. |
now, *in your app*, the launcher activity might be special, because you might be doing some one-time initialization logic there that perhaps should reside elsewhere... but that's a matter of your code, not Android
|
Mark M. |
IOW, you're overthinking this :-)
|
Kai H. |
Ok. I'll try it :)
|
Kai H. |
Thanks for the explanations.
|
Mark M. |
let me take a question from Ivano, and I'll be back with you in a bit
|
Mark M. |
Ivano: hi! how can I help you today?
|
trocchietto_Ivano |
View paste
|
Dec 15 | 8:45 AM |
Mark M. |
so, Order is the one with the override val badge line?
|
Mark M. |
(I am just confirming, so I can phrase my response more accurately)
|
trocchietto_Ivano |
I guess so ```
|
trocchietto_Ivano |
View paste
(3 more lines)
|
Mark M. |
yes, that line is part of your Order class
|
trocchietto_Ivano |
badge is the overridden method
|
Mark M. |
override val badge: String = totalOpinions.toString() // this will be executed when the Order instance is created
|
trocchietto_Ivano |
that is triggered by AssessableItemInterface that implements WIthBadge that has the proprety badge: String
|
Mark M. |
override val badge: String get() = totalOpinions.toString() // this will be executed each time something references the badge property to retrieve its value
|
trocchietto_Ivano |
yes
|
Mark M. |
either of those could be correct, neither is intrinsically right or wrong
|
Mark M. |
it is mostly a matter of whether you are trying to capture the value of totalOpinions.toString() at the point when the Order object is created or not
|
trocchietto_Ivano |
I see so the problem is in onActivityResult, because is only at refresh that I get the problem
|
trocchietto_Ivano |
but changing to get() it works
|
trocchietto_Ivano |
so I guess get() have to have some magic bl inside
|
trocchietto_Ivano |
kinda cache
|
Mark M. |
that implies that totalOpinions changes what its toString() returns while your Order object is around, and you need badge to reflect the latest totalOpinions state
|
Dec 15 | 8:50 AM |
trocchietto_Ivano |
yes
|
Mark M. |
for example -- and taking some guesses as to what these objects represent -- if something adds an opinion to totalOpinions, such that toString() now returns a higher count, the get() form will return that higher count, while the direct assignment will have captured the original count
|
trocchietto_Ivano |
but when user go back the string/number is not updated, returns null, basically onBindViewHolder is calling the interface but is null without get() accessory
|
trocchietto_Ivano |
yes you right
|
trocchietto_Ivano |
anyway ain't broken do not change is fine with me in this case
|
trocchietto_Ivano |
so no big deal just I cannot grasp why with get I get a no null value but the updated value
|
trocchietto_Ivano |
the binding is made with rxjava
|
trocchietto_Ivano |
and the adapter calls the interface
|
trocchietto_Ivano |
order.setBadge(view)
|
trocchietto_Ivano |
so the badge method is called also when I refresh, but gives a null value
|
trocchietto_Ivano |
(notice order is an extension function)
|
Mark M. |
well, I cannot really get into that, as I do not know much about your app -- all I can do is help you with the differences in those two bits of Kotlin syntax that you asked about
|
Mark M. |
in Kotlin, a property maps to a Java field, plus a getter method and a setter method
|
Mark M. |
with that in mind...
|
trocchietto_Ivano |
anyway never mind mark, no big deal if you say to me that there is not major difference between get and assignment I guess is a kind of temporary delay that is caused by an assigment
|
trocchietto_Ivano |
instead of get that should be faster
|
Mark M. |
override val badge: String = totalOpinions.toString() // this assigns a value to the field
|
trocchietto_Ivano |
OK
|
Mark M. |
override val badge: String get() = totalOpinions.toString() // this overrides the getter method
|
Dec 15 | 8:55 AM |
trocchietto_Ivano |
I see
|
trocchietto_Ivano |
maybe a getter has a return inside
|
trocchietto_Ivano |
as in Java
|
trocchietto_Ivano |
and that is why does not work
|
trocchietto_Ivano |
make sense
|
Mark M. |
override val badge: String get() { return totalOpinions.toString() }
|
trocchietto_Ivano |
all the Kotlin thing is confusing if used improperly
|
trocchietto_Ivano |
I miss the verbosity of java
|
trocchietto_Ivano |
thanks
|
Mark M. |
sure!
|
Mark M. |
let me take another question from Kai, and I'll return to you shortly
|
trocchietto_Ivano |
I say good bye mark
|
trocchietto_Ivano |
thanks but cannot chat I am @work
|
Kai H. |
Good luck with Kotlin :D
|
trocchietto_Ivano |
thank you kai
|
trocchietto_Ivano |
have a nice day both of you
|
Kai H. |
same
|
Mark M. |
Kai: one quick follow-up to your original question: "We have an Activity that with an intent filter for files with a certain suffix" -- you do realize that file extension matching in <intent-filter> doesn't really work well in modern versions of Android, right?
|
Mark M. |
most of our Uri values do not have extensions, and so the <intent-filter> is not going to match on them, if it is working off of file extensions
|
Kai H. |
I actually don't.
|
Mark M. |
most of our Uri values nowadays come from content providers, and have a content:// scheme
|
Mark M. |
there is no tradition of content:// Uri values having file extensions
|
Kai H. |
View paste
|
Mark M. |
think of them as being more like https:// URLs
|
Mark M. |
yeah, that has a low probability of success for any given user invocation
|
Kai H. |
That is what we're using atm, besides similar entries with android:scheme="file"
|
Mark M. |
right, with file:// as the scheme, the extension part is more likely to work... but file:// Uri values have been largely banned since Android 7.0
|
Dec 15 | 9:00 AM |
Mark M. |
with content:// as the scheme, you should not assume that the Uri has any particular file extension
|
Kai H. |
I had the problem that it wouldn't work on Android 11 with the file:// scheme, so I added the same entries with the content:// scheme and it worked once again.
|
Kai H. |
Wouldn't work == The app was not found as a receiver for .foobarprofile files.
|
Mark M. |
it will depend a *lot* on the implementation of the provider
|
Mark M. |
so, for example, it might not work at all on phones from certain manufacturers
|
Kai H. |
How would the system find an app for a file with the .foobarprofile extension?
|
Mark M. |
purely by MIME type
|
Mark M. |
and, if Android (or the app with the content) does not know what .foobarprofile is, it might wind up using some default MIME type like application/octet-stream
|
Kai H. |
The use case is that you have that file in an email app or file explorer, click it and our app get suggested, which will then deal with the file.
|
Kai H. |
And only our app should be suggested.
|
Mark M. |
and if that works more than 2% of the time on Android 7.0+, I will be surprised
|
Kai H. |
I didn't have consistent problems with it
|
Kai H. |
And have been testing on 7.1, 9, 10 and 11
|
Mark M. |
there are hundreds of file managers, and dozens (if not hundreds) of email clients
|
Dec 15 | 9:05 AM |
Kai H. |
That is true. I have tested maybe 5 file managers.
|
Mark M. |
for the Uri that you are getting, there are three main possibilities:
|
Mark M. |
1. it has a file:// scheme, in which case the file extension is probably "for realz", and your app will match
|
Mark M. |
2. it has a content:// scheme, and the content provider happens to use the file extension of an underlying file in its Uri, in which case your app will match
|
Mark M. |
3. it has a content:// scheme, and the Uri does not have a file extension, in which case your app will not match
|
Kai H. |
I think we might be talking from different ends of the app.
|
Mark M. |
scenario #1 used to be the dominant form
|
Kai H. |
Or I am confused.
|
Mark M. |
my assumption is that your <intent-filter> is for an ACTION_VIEW Intent
|
Mark M. |
given the description of the behavior that you are seeking
|
Kai H. |
View paste
|
Mark M. |
that's what I expected
|
Mark M. |
your activity, when started, will get the Uri of the content via getIntent().getData()
|
Mark M. |
in the abstract, that Uri could be of the three forms that I described... except that your activity would never get started for scenario #3
|
Kai H. |
Ok
|
Mark M. |
because, unless there are other <data> elements in play here, your activity will not match the Uri, because the Uri lacks a file extension
|
Kai H. |
intent.getExtras().getString(Intent.EXTRA_STREAM) actually
|
Mark M. |
not for ACTION_VIEW
|
Mark M. |
EXTRA_STREAM should work 0% of the time for ACTION_VIEW
|
Mark M. |
EXTRA_STREAM is an ACITON_SEND thing
|
Mark M. |
(er, ACTION_SEND)
|
Kai H. |
Sorry, you're right.
|
sudokai | has entered the room |
Dec 15 | 9:10 AM |
Mark M. |
so, the assumption of your pathPattern <intent-filter> is that the Uri will have a file extension
|
trocchietto_Ivano | has left the room |
Mark M. |
and I'm just warning you that this is not assured, and I would expect may not even be all that probable on many devices
|
Mark M. |
(BTW, hello, sudokai -- I will be with you shortly!)
|
Kai H. |
Isn't the pathPattern used to find our application for the file extension?
|
Mark M. |
yes, but there is no requirement for a Uri to have a file extension
|
Mark M. |
suppose that the file manager decides that the Uri for this file is content://com.whatever/something/hey/this/has/n...
|
Mark M. |
that is a perfectly legitimate Uri, and it might truly point to the user's desired content
|
Kai H. |
So your point is that some file managers won't look at the extension when trying to find a the right app to open a file with?
|
Mark M. |
correct, because file managers aren't doing that in the first place
|
Mark M. |
they create an Intent and ask Android "hey, what are the options here?"
|
Mark M. |
and Android is what applies the <intent-filter> algorithm
|
Mark M. |
for an Intent with a Uri of content://com.whatever/something/hey/this/has/n..., Android will conclude that your app does not match
|
Kai H. |
Huh.
|
Mark M. |
because your <intent-filter> is looking for a particular extension, and that Uri does not have that extension
|
Kai H. |
So I was kinda lucky it worked on my Pixel 4a and my Oneplus Nord and Huawei Tablet and Emulator=?
|
Mark M. |
the particular file managers and email clients that you tested either are specifically using Uri values that have the right file extension, or something else is leading them to your activity other than that <intent-filter>
|
Mark M. |
now, if I were writing a file manager or email client, I probably would try to use the file extension on the Uri, just to improve compatibility with apps like yours
|
Mark M. |
but you shouldn't assume that, and some system-generated Uri values are not going to reliably have file extensions
|
Dec 15 | 9:15 AM |
Mark M. |
so, in addition to your <intent-filter>, make sure that your users have some other way to indicate what content they want your app to process (e.g., ACTION_OPEN_DOCUMENT)
|
Kai H. |
So if in the future I might wonder why our app will not be in the list of apps to open .foobarprofile files with, I now know why.
|
Mark M. |
correct -- and, from a customer service standpoint, you need to be prepared to deal with those sorts of inquiries
|
Kai H. |
But ACION_OPEN_DOCUMENT is from the our app to the external, not the other way around.
|
Kai H. |
ACTION
|
Mark M. |
correct
|
Kai H. |
Ok, I think I understood now.
|
Kai H. |
Thank you
|
Mark M. |
it's like Windows: supporting drag-and-drop from Explorer is nice, but usually you also have a File > Open menu
|
Mark M. |
and with that, let me take a question from the very patient sudokai :-)
|
Mark M. |
sudokai: hi! sorry for the delay! how can I help you?
|
Kai H. |
Yes. Hello kai and thanks.
|
Dec 15 | 9:20 AM |
Mark M. |
sudokai: do you have a question?
|
sudokai |
Hi
|
sudokai |
I'm working with location services
|
sudokai |
LocationManager
|
sudokai |
I request periodic updates using requestlocationupdates
|
sudokai |
But on some phones, sometimes it just doesn't receive new locations
|
sudokai |
It works for a while, then it stops
|
sudokai |
The app doesn't crash or anything
|
sudokai |
The stream of locations just stops
|
sudokai |
Have had any similar experiences Mark?
|
sudokai |
have you*
|
Mark M. |
there are a few forms of requestLocationUpdates(), including ones that take a LocationListener or a PendingIntent parameter -- which one are you calling?
|
sudokai |
The one with LocationListener
|
Mark M. |
OK, then locations will stop when your process terminates
|
sudokai |
Yeah, but that's the point
|
Mark M. |
do you have evidence that your process is still running, yet you are not receiving updates?
|
sudokai |
It doesn't terminate
|
Mark M. |
OK, how are you determining that?
|
sudokai |
Yeah, logs
|
Dec 15 | 9:25 AM |
Mark M. |
are you sure that it is one continuous process, and not that your process stopped and got restarted?
|
sudokai |
Mmm, I subscribe to location updates again if the process restarts
|
Mark M. |
IOW, what is keeping your process around? are you using a foreground service or something?
|
sudokai |
Yeah, foreground service when the app goes to the background, with type set to location
|
sudokai |
I know there are a lot of manufacturer shenanigans surrounding this stuff
|
Mark M. |
yeah, I was about to point that out
|
sudokai |
By this stuff, I mean location access
|
sudokai |
Have you had any similar experiences
|
Mark M. |
no, but I have not had to deal with this in a couple of years, thankfully
|
Mark M. |
are you requesting ACCESS_BACKGROUND_LOCATION? I assume that you must be, if this is working at all on Android 10+
|
sudokai |
I also suspect that on some Xiaomi devices, when the app is "minimized" then the "while-in-use" location access doesn't work, even if you use a foreground service
|
sudokai |
No I don't
|
sudokai |
I don't need to because I use a foreground service
|
sudokai |
That's the theory at least
|
sudokai |
I have the foreground notification
|
Mark M. |
I forget the rules around ACCESS_BACKGROUND_LOCATION -- you may be right
|
sudokai |
I have ACCESS_COURSE_LOCATION and ACCESS_FINE_LOCATION
|
Mark M. |
the "process died, was restarted, and you requested locations" scenario is what made me think of the ACCESS_BACKGROUND_LOCATION concern
|
sudokai |
ah, yes
|
sudokai |
Good catch
|
sudokai |
Because the screen would be off
|
sudokai |
And Android 11 at least has restrictions around that
|
Dec 15 | 9:30 AM |
Mark M. |
yeah, this whole area got doubly-murky, both from the "doing background work" changes we've been dealing with, plus now the "getting background locations" changes
|
sudokai |
Thanks Mark, that at least is a plausible scenario
|
Mark M. |
which is why I am grateful that I have not had to deal with this in a while :-)
|
sudokai |
Lucky you, it's really a nightmare
|
Mark M. |
and with that... that's a wrap for today's chat
|
sudokai |
FusedLocationProvider is buggy as hell too
|
sudokai |
Thanks!
|
Kai H. |
Thanks
|
Mark M. |
next one is Thursday at 7:30pm US Eastern
|
Mark M. |
have a pleasant day!
|
sudokai |
You too
|
Kai H. | has left the room |
sudokai | has left the room |
Mark M. | turned off guest access |