How to correctly use onVisibilityChanged(), onWindowVisibilityChanged(), onAttached/Detached()? - android

I've a custom class whose parent is SurfaceView. I have the class working correctly, drawing to the screen from its own thread etc. However I want to understand how the methods in the question title should be correctly handled.
For example, if my app is running (on a mobile phone) and a call is received, which method is called? Another example is if I implement a dialog box to be displayed if the user 'long-presses' on my custom SurfaceView, what method is called then? I assume the canvas is 'safe' to write to provided surfaceDestroyed() has not been called.
Basically I want to understand how I should handle eventualities as I've described (and possibly more?) and for what events each method is called.

on...-methods are called when something happened.
You probably don't have to implement them because the super class does the correct things in most cases.
If you put log in the methods in question you can see what happens / when they are called. You can also read the API doc and have a look at the source code to see what is done there.

Related

Android difference between callback and listener

So in my understanding listener is usually used to trigger some class when some thing happened on particular place. (for example when we click the button we want to do some action).
On the other hand I see some places where callbacks are used to execute/enqueue some code in different place. (retrofit uses this to enqueue API calls)
What is the main difference between these 2?
In short, they are the same.
Really?
Yes. But there are some "theoretical" (and in some cases practical differences).
Concepts
Listener is a word that in Android, it's commonly associated with a View ClickListener or similar. Where there are methods like addxxxListener(...) etc.
A Callback is often heard in the context of "for this particular event" I supply a "callback" and I will be called back when something happens.
In practice, they are often just instances of some interface passed along.
In my limited experience (only about 10 years of Java/Android -now Kotlin as well-), the term is used interchangeably.
I normally think of a callback when I am expecting something to "call me back" when something happens, and a listener as something where I listen to an event but as you can see by reading this... they could be the same. :)
It's often mentioned that one could have multiple listeners, but one callback (but there's nothing enforcing this and I have seen all use cases you can think of where either term is used) "You can add multiple callbacks" is not uncommon, even though if there are "multiple" then it "must be a listener". In fact, if you go as far as Android's View, the method is view.setOnClickListener { }
So it's a Listener, but you can only set ONE. So the above rule about 1 callback, N listeners is already broken since the early days of Android.
In some cases though, the convention is more tied to the method name, rather than the class' name:
setXXXyyy(...) allows you to set "one" and only one yyy listener/callback.
addXXXyyy(...) allows you to add one or more (though not always, so read the documentation) yyy listener/callback.
An add is often (...but not always) accompanied by a removeXXXyyy(...) implying that if you keep/have a reference to a callback/listener you could remove it (and no longer be listening or be called back).
In the case of set, it's often expected that if needed you call set...(null) and pass that null to "remove" the sole listener/callback. (Views do this for you, you don't need to call it, but you can).
Anyway, don't quote me on this, but I'd argue they are the same. This is also more complicated when you involve other languages/frameworks/tools, where there's an even blurrier line.
In many instances, you will see callback used, but the method contains the word "Listener", and vice-verse, so don't get too crazy about it.
If you can, where you can, however, don't use either, just use Coroutines :)
For a concrete example of how both are used as the same thing...
Look at the Android View.setOnClickListener method:
/**
* Register a callback to be invoked when this view is clicked. If this view is not
* clickable, it becomes clickable.
*
* #param l The callback that will run
*
* #see #setClickable(boolean)
*/
public void setOnClickListener(#Nullable OnClickListener l) {
Notice something strange?
The method is called setOnClickListener yet the Javadocs say: "a callback..."
They are the same! Two ways of naming an interface. In general, Listener is also a callback and VICE VERSA!
for a type of event you can have many listeners , but one callback !
A callback is a procedure where you pass as an argument to another procedure. The procedure receiving the parameter can call it, or share it so some other procedures in the system can call it.
A listener watches for an event to be fired. For example, KeyListener waits for KeyEvents, a MessageListener waits for messages to arrive on a queue, and so on.

Invalidate is failing to call onDraw when returning to an activity that has a custom view

I have inherited some code hence I don't have true freedom to change it. :(
I have a main activity, from which other activities (I will refer to these as sub activities from now on) are called. Whenever one of these completes, it calls finish and returns data to the main activity.
Each activity (including the main one) has a bar on the top that displays a custom view. The custom view contains a canvas which has a drawing that is dependant upon the state of the network.. i.e. wifi/mobile etc...
Since that 'state' data never changes, it's held within a singleton and the view gets data from the singleton to define what it draws. That is working with no issues, i.e. the data is always as I expect it.
When I first launch the MainActivity, as the network changes, the data changes and each call to 'invalidate' the view receives a system call to 'onDraw' as I would expect.
In each of the sub activities the same is again true.
Upon finishing a sub activity and returning to the mainActivity, calls to invalidate no longer cause a call to onDraw to occur.
I have looked at this for quite a while now and just cannot figure out what is going wrong.
In my constructor I have:
setWillNotDraw(false);
Whenever the data changes the following methods are called:
invalidate();
requestLayout();
Now, there's one more thing... upon returning to the activity at that immediate point, I refresh and this DOES draw correctly, i.e. invalidate does trigger an onDraw call... any subsequent network changes (which are propogated) fail to result in the onDraw call.
I'm wondering if this is to do with the view somehow being detached. I can see that 'onDetachedFromWindow' is called, however the trigger for this is the destruction of the subactivity, hence I don't see why that should affect the MainActivity but it's the only thing I can think of.
I'm hoping I've provided enough information for someone to help me...
Well, in the end my answer has very little to do with the question and I guess this is an example of how an issue can be solved by going back to absolute basics and checking for the obvious.
My activities all inherit from an abstract activity. Within that activity there is an instance of the view. The views in which I was having trouble were using that declaration as opposed to having their own instance, hence behaviour from one activity was then affecting another inadvertently.
So, if I'd been able to post up all the code, I'm sure someone else would have spotted this but, unfortunately I couldn't in this instance.
Still, whilst this posting doesn't provide a resolution that will help others, maybe it does say... step back and check the obvious first!

How can I know if the user took screenshot of my app?

My app represents funny sentences that my users upload, and in order to know which sentences are better I want to know if the user has taken a screenshot. The only related thing I found is from Google Maps. Anyone know how to make a "screenshot listener" or which method it invokes? Thanks.
One way to do this is by creating a class which is implementing FileObserver. Then add listener when you are loading activity ( by using onStart() activity's method) and remove listener when you are going out of your activity (by using onStop() activity's method).
Once you get FileObserver event, you have to be sure that is a picture creation.
Note that this method is not 100% safe but it's simple to make it works !

Android: Which Method performs the "onClick" Events of the Buttons, which are defined in the XML Layouts.

I'm trying to get a better understanding of the Android framework and therefore I've created a simple App, which actually consists of just one Button. Whenever this button gets clicked, a method called sendMessage in the MainActivity starts a new activity DisplayMessageActivity, which displays a random string.
My question now is, how does the onClick Event of a button (defined in the XML layout) work in particular?! I do understand, that whenever I click my button, the method, which i defined (android:onClick="sendMessage") gets called, but I'm really curious which method calls my method in the end, because there is obviously no call of my method in the syntax.
I've already decompiled my APK File to smalicode using androguard and searched for invokes of my sendMessage method. Unfortunatly i couldnt find anything.
Can anyone explain me how this mechanism functions, because according to this post:
How exactly does the android:onClick XML attribute differ from setOnClickListener?
there should actually be a method, which calls my onClick method in the end.
It's done by reflection.
If you want to know exactly who is calling your method, throw an Exception and have a look at the stack trace.

ResourceNotFound on layout inflation

My app may launch a sub-activity for a specific purpose. When that activity finishes, I get the results in onActivityResult. These results are then processed in the subsequent onResume. This consists of a setContentView and also starting an AsyncTask that puts up a ProgressDialog.
This all works well when initiated the normal way, which is via a user request (i.e., menu selection) after the app is up and running. However, under some conditions I need to do this right as the app is starting up, so I initiate this sequence right from my onCreate. What then happens is that I get fatal ResourceNotFound errors within any o/s call that implicitly calls the layout inflater. I got around this with setContentView by pre-inflating the view in my onCreate method, but the AsyncTask's onPreExecute still fails on ProgressDialog.show() as it "fails to find" Android's own progress_dialog.xml!
Anyone know what's happening here?
I suspect it's something to do with the timing, where this is occurring before the main activity has even had a chance to display its screen. These calls are all being made on the main UI thread, but maybe something hasn't completed within the o/s under these conditions.
As a closeout, the problem turned out to be totally unrelated to what I described in my post. Turns out it was due to blindly using some code that had been posted in some online forum showing how to get and use AssetManager. Trouble is, at the end of the block of code he had put "assMan.close()". Well, this closes the asset manager for the entire activity and resources can no longer be accessed!
It took a while to find it since it was not something that I did via my own understanding.

Categories

Resources