B4A Library I Love My Back Key (And My Back Key Loves Me Back)

this is Backster. it addresses the missing back key touch that some users may be experiencing.

for devices running < sdk 33, the back key functions as normal. you don't need Backster.

starting with android 13 and running through android 16 (and sdk 33 through 36), google phased out what happens when you touch the back key. it essentially nullifies B4A's activity_keypress. that is to say, your app is terminated. no warning, no error, no bug. it was a design decision. fortunately, your participation in this scheme was (mostly) optional.
we are given the chance to opt out of this new behavior by a statement in the manifest: AddManifestText(<application android:enableOnBackInvokedCallback="false">)
this allowed your activity_keypress sub to work as before. unless your device runs android 17!

update regarding the struck-through statement above:
beginning with sdk 37, there is no opting out. for sdk's 33 through 36, if you add: AddManifestText(<application android:enableOnBackInvokedCallback="false">), our legacy activity.keypress behavior is maintained. if you don't add this statement to the manifest, android's predictive gesture scheme will default, and your app will appear to crash when you tap the back key.

if you want to see what it's like to maintain the legacy effect under the predictive gesture scheme, add this to the manifest: AddManifestText(<application android:enableOnBackInvokedCallback="false">) and use Backster.

copy the attached .jar and .xml files to your additional libraries folder and build and run the example. pay attention to the manifest.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
update in post #12. new example with multiple activities to show how to deal with that.
 

Attachments

  • backster.png
    backster.png
    9.8 KB · Views: 160
  • backster.zip
    13.2 KB · Views: 90
Last edited:

drgottjr

Expert
Licensed User
Longtime User
my bad. try this.
archive with missing files has been added to post #1. sorry
 
Last edited:

Scantech

Well-Known Member
Licensed User
Longtime User
** Activity (main) Create (first time) **
sdk target: 36
Backster says: [CRITICAL] You must add 'AddManifestText(<application android:enableOnBackInvokedCallback="true">)' to your B4A Manifest for this library to intercept gestures on Android 16+!
setting up Back key intercept
** Activity (main) Resume **
original activity_keypress
36
build version: 36
target sdk 36 and opted in. trying to stay alive
back key intercepted!
** Activity (main) Pause, UserClosed = true **
closed
** Activity (main) Create **
sdk target: 36
Backster says: [CRITICAL] You must add 'AddManifestText(<application android:enableOnBackInvokedCallback="true">)' to your B4A Manifest for this library to intercept gestures on Android 16+!
setting up Back key intercept
** Activity (main) Resume **
original activity_keypress
36
build version: 36
target sdk 36 and opted in. trying to stay alive
original activity_keypress
36
build version: 36
target sdk 36 and opted in. trying to stay alive
First back key pressed popup shows and exits successfully, i reenter app and press back key, the pop msgbox is hidden behind activity and therefore cant exit. same with 3rd attempt.
I removed 'MsgboxAsync("phone is " & v & " sdk version. target is " & targetSdkVersion,"Back Key Touched") which fixes that issue. It did not like 2 msgbox stack together for some reason.


[CRITICAL] You must add 'AddManifestText( ? i did enable it in manifest? It probably just a reminder.

It did work fine. Thanks

This is tested on Emulator API 36.
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
First back key pressed popup shows and exits successfully, i reenter app and press back key, the pop msgbox is hidden behind activity and therefore cant exit. same with 3rd attempt.
I removed 'MsgboxAsync("phone is " & v & " sdk version. target is " & targetSdkVersion,"Back Key Touched") which fixes that issue. It did not like 2 msgbox stack together for some reason.


[CRITICAL] You must add 'AddManifestText( ? i did enable it in manifest? It probably just a reminder.

It did work fine. Thanks

This is tested on Emulator API 36.
i can't vouch for results with the emulator.
the "critical" log error is a reminder.
i don't follow the results you got exactly, but i certainly appreciate the feedback. i didn't experience what you did, but 1) i ran the app on real devices and 2) i definitely experienced no hidden/stacked msgboxes.

however, i have updated the example (just the example, not the library). update is in post #1. the original msgbox had things backwards. also, the new msgbox tries to clarify what i was trying to achieve using a msgbox. our activity_keypress returns a boolean to the system which then decides how to proceed. the new callback scheme api does not allow for a return value. the msgbox allows the user to mimic "return true/false". obviously you're not obliged to use a msgbox in your logic. you just need to know that the callback throws everything back to b4a. the callback expects nothing in return. there is no "return false". if you want to quit the app, you just call activity.finish when you're in the sub. if you want to continue, you just continue. and, side note: if the user is running an older device, activity_keypress stays the way it's always been. your app will have activity_keypress() and Backster.BackKeyPressed subs. so long as activity_keypress is supported, you have no choice but to have both subs (at least for devices running android 17+). for devices running anything up to and including android 16, you can opt out of the new api. android 17 shuts that door.

again, thanks for running it.
 
Last edited:

Scantech

Well-Known Member
Licensed User
Longtime User
Im kinda confused. I think im stepping away from emulator.

Api 33+ only backster_backkeypressed event gets fired and not with activity_keypress? In Emulator, both gets fired. However, samsung 21 ultra api 35 only backster_backkeypressed gets fired. I think backster is intended to work only for backster_backkeypressed for api 33+?

Tested on my app and your example.

Update: Emulator should be fine. Don't use the back key outside the screen. It will glitch. The back key in navigation works flawless.
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
I think backster is intended to work only for backster_backkeypressed for api 33+?
yes! if device is < 33, activity_keypress works as normal.
if device >= 33 and <= 36, activity_keypress OR backster_backeypressed. you can opt in or out.
if device >= 37 (android 17), backster_backkeypressed only. opt out not possible.

i have 2 pixels running android 17. it doesn't matter what the targetsdk is. without backster, there is no activity_keypress sub. app closes immediately.
backster is needed if your device runs android 17 (you can't opt out). for devices running apis 33 to 36, you need backster if you choose to opt in (in manifest).

i don't know what you mean by "don't use back key outside the screen"...
 

drgottjr

Expert
Licensed User
Longtime User
by the way, at some point erel will have to deal with all this. but, in the meantime, if you have users whose devices run android 17+, any apps with activity_keypress will fail when the user taps the back key regardless of which sdk you target. you can, at least, test your apps with backster. you're going to have to have your code in place sooner or later. (note: i'm talking about non-b4xpages apps. it's too late in the game for me to start with b4xpages. for all i know, bxpages handles the backkey in a completely different way.)
 

drgottjr

Expert
Licensed User
Longtime User
Avoid this button in image. Use navigation back key in screen
that's an emulator thing. i don't believe i've ever seen such a thing on a real device.
 

drgottjr

Expert
Licensed User
Longtime User
for those following: new example and library in post #1.
the callback must be unregistered onpause. i've added this step to the example. that's the only change. have added some logging to the library so you can follow what it's doing. unregistering is important.
 

drgottjr

Expert
Licensed User
Longtime User
update:
example attached now has 2 activities. i'm attaching that example to this post since the library itself is not affected.
i have moved registering the callback to activity_resume. (note: registering/unregistering the callback is the way
the api is designed (by google). the api only has 2 methods: register and unregister. the system is activity-based.)
so, as you move from one activity to another and back, you register/unregister as applicable. it's not rocket science.
if you are accustomed to releasing resources (eg a mediaplayer), this will make sense to you.

i noticed that moving from one activity to another seems to behave differently from how it worked in the old days.
as i recall, the calling activity ended and was later recreated. with android 17, at least, the caller seems to remain
alive, and when the 2nd activity ends, the first activity goes right into resume. no (re)create. i could have sworn that
it used to go into create... in any case, that is why i moved registering the callback to activity_resume.

on the other hand, if activity 1 is still alive when you start activity 2, technically there is no need to unregister activity 1.
possibly a case of no harm, no foul. but since failure to unregister can cause memory leaks, i thought it prudent to
unregister the callback before starting activity 2 and then re-registering in activity_resume when activity 1 comes back.
since the entire application might be stopped from within activity 2, that would leave the callback in activity 1
unregistered. you're welcome to test both to see which causes a memory leak crash first. it strikes me as cleaner
just to keep an activity's callback within that activity. register/unregister.

regarding b4xpages, technically the library works (since b4xpages is still an activity). but the "pages" have
their own kind of keypress mechanism. since i don't use b4xpages, i'll have to research what this does. i seem to
recall some posts about this.
 

Attachments

  • 2activities.zip
    9 KB · Views: 105

Scantech

Well-Known Member
Licensed User
Longtime User
Thanks for the update. I just applied it to one of my big projects with many activities. It works like a charm. I know its a little bit early for the transition or Erels future revised back key, but i trust your library and will use it on all my projects. I just hope Erels future back key revision wont affect your library in usage. I'm not an expert but i think it will be ok.
 

drgottjr

Expert
Licensed User
Longtime User
Thanks for the update. I just applied it to one of my big projects with many activities. It works like a charm. I know its a little bit early for the transition or Erels future revised back key, but i trust your library and will use it on all my projects. I just hope Erels future back key revision wont affect your library in usage. I'm not an expert but i think it will be ok.
thanks for testing. the library's main purpose was to deal with android 17's no opting out of back key handling. in
effect, this has nothing to do with b4a. at some point, however, it will have to be incorporated into b4a (as has no
opting out of full screen). i assume it will no longer be necessary to use backster. i don't know if you've noticed but
there are a massive number of app updates from play store almost daily. developers (big and small) are forced to
scramble to keep up with google's changes. this is not b4a's fault. if backster is superfluous at some point, so be it.
it's no different from being forced to update an app because google moved the goal posts yet again. with all the
attention focused on full screen and sdk36, the back key issue has slipped by almost unnoticed.

note: you might want to pay attention to where you initialize and start intercepting the back key (ie, in create or resume).
i spend a lot of time testing this aspect.

also, i need to look at the async msgboxes. that last boolean parameter which allows the user to "back out" of the msgbox without tapping one of the supplied exits. that's next on my list...
update: with the async msgboxes, i always set cancelable to false because i want the user to chose from among the options that i provide (which do include a cancel option). anyway, for testing i set cancelable to true and backster didn't close the app. so, for me, that's a good thing.

after reading this, go back to post #1 and pick up new version (0.85) of library + explanation of changes.
 
Last edited:

Scantech

Well-Known Member
Licensed User
Longtime User
B4A Version: 13.70 BETA #1
Parsing code. (0.00s)
Java Version: 19
Building folders structure. (0.02s)
Compiling code. (0.01s)
Compiling layouts code. (0.00s)
Organizing libraries. (0.00s)
(AndroidX SDK)
Compiling resources (0.09s)
Linking resources (0.42s)
build tools: 36.0.0, android jar: android-36
Compiling generated Java code. Error
B4A line: 78
backkey.StartBlocking
src\com\georgieapps\achingback\main.java:426: error: cannot find symbol
}else if(anywheresoftware.b4a.keywords.Common.Not(mostCurrent._backkey.isBlocking)) {
^
symbol: variable isBlocking
location: variable _backkey of type Backster
v0.85 has issues.

B4X:
If Not(backkey.isInitialized) Then
        Log("initializing backster in main on resume")
        backkey.Initialize("backster")
        If backkey.isInitialized Then
            Log("backster initialized. starting blocking")
            backkey.StartBlocking
        End If
'    Else if Not(backkey.isBlocking) Then
'        Log("backster initialized. starting blocking")
'        backkey.StartBlocking
    End If
This compiles. Not(Backkey.isblocking) is the issue?

Check if isBlocking is declared as a public variable or if a Property Get method exists.
 
Last edited:

drgottjr

Expert
Licensed User
Longtime User
v0.85 has issues.

B4X:
If Not(backkey.isInitialized) Then
        Log("initializing backster in main on resume")
        backkey.Initialize("backster")
        If backkey.isInitialized Then
            Log("backster initialized. starting blocking")
            backkey.StartBlocking
        End If
'    Else if Not(backkey.isBlocking) Then
'        Log("backster initialized. starting blocking")
'        backkey.StartBlocking
    End If
This compiles. Not(Backkey.isblocking) is the issue?

Check if isBlocking is declared as a public variable or if a Property Get method exists.
it is public and it works for me (see attached). btw, backster should work with back swipes too. (i only use the 3 keys at the bottom of the screen). are you sure you were running v 0.85 and not 0.75 (where isBlocking doesn't exist)?
 

Attachments

  • backster2.png
    backster2.png
    30.1 KB · Views: 81

Scantech

Well-Known Member
Licensed User
Longtime User
Sorry my fault. I reinstalled xml and jar libraries. its ok now. I must of installed one of them only.
 
Last edited:
Top