What is the purpose of the command APP_CMD_SAVE_STATE ? - android

Everytime the application loses focus (whether manually by hitting the menu button, or by going to idle ) an APP_CMD_SAVE_STATE command is sent.
In the example shown from the Android API documentation for native activity (https://developer.android.com/reference/android/app/NativeActivity.html) , when this particular command is sent they are saving some sort of "state" inside their android_app .
// (...)
switch (cmd) {
case APP_CMD_SAVE_STATE:
// The system has asked us to save our current state. Do so.
engine->app->savedState = malloc(sizeof(struct saved_state));
*((struct saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(struct saved_state);
break;
// (...)
If you look in their code, savedState is just a struct holding values. First I thought that we need to save every single value that matters for our app everytime we lose focus, because otherwise the values would all become corrupt or something like that (yeah scary!)
I run a simple test by removing the code snippet above, and fortunately nothing changed, the values of my struct stayed the same after regaining focus even without saving them.
So I was wondering what is the purpose of this command ? Is that something important to consider ?

The APP_CMD_SAVE_STATE command is sent when your app loses focus. The aim is to make it possible to not only suspend your app, but, if the system has to kill the app to get some resources (e.g. free RAM), the app can be restored seamlessly next time the user returns to it.
If you look in their code, savedState is just a struct holding values.
Yes, from the point of view of the Native Activity, it's just a struct. But this struct is passed to Android in ANativeActivity_onCreate() function that's called via JNI (and usually it's implemented in android_native_app_glue.c from the SDK, which you could alter or replace if you need). Thus, Android will take care of the data when managing apps.
I run a simple test by removing the code snippet above, and fortunately nothing changed, the values of my struct stayed the same after regaining focus even without saving them.
Your test was too soft :) Try opening the Recents screen and close your activity from there: tap the × button or Close All command. The effect will be to kill the app, and you should now find that your data have been wiped unless you use the save-restore mechanism.

Related

Kotlin: Why Array and ArrayList are not emptied before a rerun?

My scientific app is fully dynamic and there is only one activity, no fragment or intent.
In some situations, I need to finish the app completely.
So I run
(this as Activity).finishAndRemoveTask()
It works smoothly since Lollipop (Android 5.0), version 21.
Apparently, no app traces or services remains in the memory.
However, I've found a huge problem.
I have some global array or array list (I didn't see other variables).
that remains intact with a new rerun, even a I have a declaration
that empties that variables. It doesn't happen with a rerun via debugger,
should be a new rerun from cell phone.
Below I show a schematic example. I declare in one .kt file, outside any class or function.
class DispFu(
var id: Int = 0,
var isKeyl:Boolean=false,
}
var vDispFu = arrayListOf<DispFu>()
After, I populate vDispFu inside onCreate processing and reach 134 items.
To prove it, I've recorded a file on my phone inside my activity onCreate processing, before exit the program.
fun now():String{
var hora = LocalTime.now()
return "${hora.hour}:${hora.minute}:${hora.second}"
}
var fileDep:File = createOrGetFile(Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_DOWNLOADS),"DepCalc","") // File for debugging
fileDep.appendText("${now()} -> vDispFu size is ${vDispFu.size}\n")
Below there are 2 runs: the first run (inside debugger) and a independent rerun. Here is the file content:
11:3:2 -> vDispFu size is 0
11:3:18 -> vDispFu size is 134
I know that global variables are not recommended, but I just wanted to understand what is going on. It doesn't make sense to me.
If someone could give me some clue about what is happening and give me some alternative strategy, it would be great!
Obviously, for practical reasons, the solution could not involve completely reformulating the program, which has almost 40 thousand lines...
Finishing an Activity doesn't shut down your entire Application or VM, so all global variables continue to stay in memory. When you rerun your application with the debugger, it actually restarts the VM, which is why you're seeing it get cleared in that case.
System.exit() is not an ideal solution since it restarts your VM process. There will be extra churn to do that. It's really intended for abnormal unrecoverable errors. Not necessarily a problem in your particular case.
The more proper way to handle this would be to put your top-level data in a singleton and clear it manually when you are finishing the Activity.
I've solved my problem:
Sometimes, it is incredible how the effort to externalize a problem sometimes helps to solve it ....
The below procedure to quit completely an app:
(this as Activity).finishAndRemoveTask()
It's not enough, despite all the posts about it on Stack Overflow that advocate this strategy.
It's necessary includes other command:
(this as Activity).finishAndRemoveTask()
System.exit(0)
Now:
11:26:25 -> vDispFu size is 0
11:27:1 -> vDispFu size is 0

Running JUnit test multiple times gives different results

I have a test case for my app which fills in the TextViews in an Activity and then simulates clicking the Save button which commits the data to a database. I repeat this several times with different data, call Instrumentation.waitForIdleSync(), and then check that the data inserted is in fact in the database. I recently ran this test three times in a row without changing or recompiling my code. The result each time was different: one test run passed and the other two test runs reported different data items missing from the database. What could cause this kind of behavior? Is it possibly due to some race condition between competing threads? How do I debug this when the outcome differs each time I run it?
Looks like a race condition.
remember in the world of threading there is no way to ensure runtime order.
I'm not an android dev so I'm only speculating but UI is only on one event thread generally so when you call the method from another thread (your test) you're probably breaking that as you're outside of the event thread.
You could try using a semaphore or more likely a lock on the resource.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html
I (finally!) found a solution to this problem. I now call finish() on the tested Activity to make sure that all of its connections to the database are closed. This seems to ensure consistency in the data when I run the assertions.
I would suggest making a probe for the database data rather than a straight assert on it. By this I mean make a piece of code that will keep checking the database for up to a certain amount of time for a condition rather than waiting for x seconds (or idle time) then check, I am not on a proper computer so the following is only pseudo code
public static void assertDatabaseHasData(String message, String dataExpected, long maxTimeToWaitFor){
long timeToWaitUntil = System.getCurrentTimeMillis() + maxTimeToWaitFor;
boolean expectationMatched = false;
do {
if(databaseCheck() == dataExpected){
expecttionMatched == true;
}
}while(!expectationMatched && System.getCurrentTimeMillis() < timeToWaituntil);
assertTrue(message, expectationMatched);
}
When i get to a computer i will try to relook into the above and make it better (I would actually of used hamcrest rather than asserts but that is personal preference)

native-app is restarting after minimizing to background

I've got a simple native application for debugging,
only displaying a triangle slowly changing the color.
Now, when i press the home-button and put my app into background
and then start it again, it is completely restarted.
How can i resume the old state?
I already tried to do it like in the native-app-example with:
app->userdata = &my_state;
if (app->savedState != NULL)
my_state = *(State*)app->savedState;
and in handle_cmd with:
case APP_CMD_SAVE_STATE:
app->savedState = malloc(sizeof(State));
*((State*)app->savedState) = my_state;
app->savedStateSize = sizeof(State);
break;
where State is class with all things i want to save.
How could i do this?
Isn't necessary to be a class. It could be a struct (that in fact is the "same"). You have to have all your values that you'll need to restore the state of the app in that struct or class, and read from that place.
Reading some examples, you'll see that it's normal to put an engine in the app userData like:
app->userData = &engine;
and in that engine, to have the struct from State. From that way, you could save only what you need, and leave the other.
The important thing is to use always the values (like the colour of the triangle) from that save state, and restore with that code you write.
PD: For more complex things, when you use dynamic memory, you'll have to be more subtle saving data.

How to perform Redo Undo operation in EditText

I want to know is there any method or any link or tutorial to perform redo undo operation in Android edittext. If any one knows than please let me know.
Quick note on the Antti-Brax/Divers(Kidinov) solution. It works great, except if you try to use it with a TextView post-API 23, you'll run into problems, because guess-what, Google actually added a hidden UndoManager (android.content.UndoManager) and didn't document it or make it obvious it was there. But if you have a hard/bluetooth keyboard in Marshmallow or Nougat and hit ^Z or SHIFT-^Z, you'll get undo/redo.
The problem comes if you're already using Antti-Brax's class with an EditText, and you also hook it to ^Z and shift-^Z, you'll run into problems with anyone using a hard keyboard. Namely the ^Z will trigger BOTH the native and Antti-Brax's undo, leading to two undos simultaneously, which isn't good. And after a few of them, you'll probably get a Spannable out of bounds crash.
A possible solution I found is to subclass the TextView/TextEdit/whatever and intercept the undo/redo calls from the TextView so they don't run as follows:
#Override
public boolean onTextContextMenuItem(int id) {
int ID_UNDO, ID_REDO;
try {
ID_UNDO = android.R.id.undo;
ID_REDO = android.R.id.redo;
} catch (Resources.NotFoundException e) {
ID_UNDO = 16908338; // 0x1020032
ID_REDO = 16908339; // 0x1020033
}
return !((id == ID_UNDO) || (id == ID_REDO)) && super.onTextContextMenuItem(id);
}
Those magic id numbers were found here, and are used only as a backup if the android.R.id.undo values aren't found. (it also might be reasonable to assume that if the values aren't there the feature isn't there, but anyway...)
This is not the best solution because both undo trackers are still there and both are running in the background. But at least you won't trigger both of them simultaneously with ^Z. It's the best I could think to do until this gets officially documented and the getUndoManager() methods of TextView is no longer hidden...
Why they made a feature you can't turn off (or even know if it was there or not) "live" in released Android I can't say.
I just opened an issue on Android's issue tracker if anyone wants to follow this.
There is an implementation of undo/redo for Android EditText in
http://credentiality-android-scripting.googlecode.com/hg/android/ScriptingLayerForAndroid/src/com/googlecode/android_scripting/activity/ScriptEditor.java
The code works but does not handle configuration changes properly. I am working on a fix and will post here when it is complete.
My Google search was :-
android edittext onTextChanged undo
I know this is an old question, but as there is no accepted answer, and this is an issue I've tackled myself from many angles, I'd like to add my solution in case it helps anyone. My answer is probably most relevant to large (1,000words+) volumes of text editing apps that require this feature.
The simplest way to resolve this problem is to make periodic copies of all text on screen, save it to an array and call setText() every time the Undo method is called. This makes for a reliable system, but it isn't ideal for large (i.e. 1,000words+) text editing apps. This is because it:
Is wasteful. It could be that only one word changes in a two thousand word document, so that's one thousand, nine hundred and ninety nine words needlessly committed to memory.
Can lead to performance issues, as some low-tier hardware struggles with rendering large amounts of text. On some of my test devices, this method can lead to freezes of a few seconds whenever Undo is called.
The solution I currently use is comparatively complex, but I've published the results in a library here.
Essentially, this library saves a copy of text as soon as a user begins typing, and then another copy of text once they've stopped typing for a set amount of time (in my case, two seconds). The two text strings are then compared, and the altered section of text returned, the indexes where the alterations occured, and details on whether or not the change was an addition of new text, a deletion, or a replacement of old text with new text.
The net result is that only the necessary text is saved, and when Undo is called, there is only a local delete(), replace() or insert() call, which makes for much faster operations on large text fields.
Here is the undo/redo implementation that was linked to from Gary Phillips' answer extracted into a reusable and universal undo/redo plugin for any widget that descends from a TextView. I added some code for persisting the undo history.
http://code.google.com/p/android/issues/detail?id=6458#c123
Hope this helps.
To preserve EditText Styling with regards to undo:
You can create an ArrayList<EditText> or ArrayList<String> (String containing html text) to store your last 10 (for example) actions. So ArrayList [0] would contain html text from your first action and ArrayList [9] would contain html text from your very last action. Each time the user taps "undo" in your app, you would apply ArrayList [size()-1] to your EditText and then remove ArrayList [size()-1] from your Array.

How can I "poke" an android application that adheres to the Observer pattern?

I've got a small android application that implements the Observer pattern.
I want my "subject" (or the thing being observed) to change its state, such as changing its String from hello to hello world.
How can I do this via the emulator?
I need my (observing) android application to still run in the foreground so it can display whatever is being observed, but I need to find some way to alter the state of the observed object, is it possible to do this via the command line? How else can I "poke" the observed object to change its state.
One dirty-hack method I can think of is to set the observed object up in a loop, so every 10 seconds it changes its state, but that is not good as then I won't have control over it.
Correct answer: write a test case, and have the test case "poke" the observed object.
Not-quite-as-correct answer: add stuff to your activity to "poke" the observed object.

Categories

Resources