I have encountered a very strange effect as I get near to finishing my project. I introduced the line
<uses-sdk android:minSdkVersion="8" />
into the manifest and re-ran the project in both the emulator and a phone (HTC Desire). I noticed that the "back" button wasn't operating in a number of areas of the program. When I put the code into debug, the onKeyDown listener was firing OK [and handed off ok to super.onKeyDown(..)] whereas the onBackPressed listener wasn't firing at all.
When I removed the uses-sdk entry from the manifest all returned to normal. Can anyone explain please because I really need to use the min-sdk statement.
Update:
I have experimented right down to min-sdk="1" (the default value) and the effect is the same. I then removed the min-sdk value and used the target-sdk value instead with EXACTLY THE SAME consequences i.e. the back button won't work in all places. Simply removing the tag <uses-sdk .... /> completely fixes the effect but leaves me with the problem of needing to declare a minimum sdk value before I deploy. Please help, someone, anybody...
Maybe we met the same problem.
I use this way to simulate a soft back button, but when "min-sdk" is added, the button doesn't work. It seems like "dispatchKeyEvent" and "min-sdk" are in conflict. I used "onBackPressed" instead, it works fine for me.
public class BackButtonClickListener implements View.OnClickListener {
public void onClick(View v) {
Activity host = (Activity) v.getRootView().getContext();
host.onBackPressed();
}
}
Button back = (Button) findViewById(R.id.your_button_id);
back.setOnClickListener(new BackButtonClickListener());
Why not use onKeyDown?
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// do some stuff
return true;
}
return super.onKeyDown(keyCode, event);
}
Related
I have a certain activity that begins when I tap my smart watch's screen. There is a timer and bunch of stuff that happens, but the process is crucial, so I am handling certain cases or things that might happen that would disturb the flow of things.
So basically, I want to prevent the home button of my watch to exit the app and go to the homescreen while my timer is running. I keep looking this up and most people say to override the onBackPressed method. But this was for the back button, and I I realized the button is a home button not a back button.
frameLayout.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
clicked = clicked + 1;
if (clicked == 2)
{
Toast.makeText(toolandmode.this, "Clicks:" + clicked, Toast.LENGTH_SHORT).show();
startTimer();
}
else if (clicked >= 4)
{
Toast.makeText(toolandmode.this, "Clicks:" + clicked, Toast.LENGTH_SHORT).show();
AlertMessage();
}
}
return true;
}
});
this is the main method I use
Just override the onBackPressed function.
#Override
public void onBackPressed ()
{
//Control the flow
}
Use third part library in case if it solves your problem.
Here is the link:
https://github.com/shaobin0604/Android-HomeKey-Locker
The general consensus is that you can't override the home button behavior on a Wear OS device, just like you can't override the home button on an Android phone. This is by design to prevent developers from preventing the user to leave an application. Even if there is a hacky way to do it, this is not officially supported and may stop working at any time in future OS versions. I highly suggest not doing it since it goes against the basic navigation model of the device.
More details, and some workarounds for common use cases where people think they need to override the home button can be found in this blog post.
I have Actors that I need to move when the keyboard becomes visible (When I press a TextField), or they are stuck behind it. I do this by moving the camera up:
stage.getViewport().getCamera().position.set(stage.getWidth()/2, stage.getHeight()/3, 0);
stage.getViewport().getCamera().update();
This works fine. It also works fine to move it back when I touch something outside the TextField and call stage.unfocusAll();
My problem is, when I'm in a TextField and press Androids Back button, it hides the keyboard, but does not call the code I have inside the Inputprocessor (THIS CODE CAPTURES BACK-BUTTON ALWAYS EXCEPT WHEN INSIDE A TEXTFIELD AND KEYBOARD IS VISIBLE):
InputProcessor backProcessor = new InputAdapter() {
#Override
public boolean keyDown(int keycode) {
if ((keycode == Input.Keys.ESCAPE) || (keycode == Input.Keys.BACK) )
{
moveBack();
}
return false;
}
};
I looked around and read that it is not possible to catch the back-button when inside a TextField. Which leads me to my questions:
This must be a common scenario (moving UI to work with keyboard), how do other people do it?
If other people do like me (move camera), how do you handle the Android back-button?
EDIT: This answer captures the back-key while inside a TextField, however it has to be done in the Android Launcher, so I can't reach the elements I need to reach. I also overwrites all other calls to the BACK-button from inside the LibGdx project.
Ok so with the help of This I got a solution working, but it's not very pretty.
Basically I rewrite my GDX Launcher class, and use the following code as the layout:
RelativeLayout layout = new RelativeLayout(this) {
#Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if(event.getAction() == KeyEvent.ACTION_DOWN){
game.setMoveBack(true); }
}
return super.dispatchKeyEventPreIme(event);
}
};
Then, in the render-method of my MainScreen (Screen that all other Screens inherit from), inside the render-method I call:
if(game.isMoveBack()){
stage.getViewport().getCamera().position.set(stage.getWidth()/2, stage.getHeight()/2, 0);
stage.getViewport().getCamera().update();
game.setMoveBack(false);
}
If anyone has an easier way to do this please post and Ill accept that as an answer, but for now, this works if anyone finds themselves where I am :)
I've followed the example pattern for handling the android back button in the react-native docs and it works well. I can use the hardware back button to pop my navigation stack.
At the point that there's only 1 view in the stack though I don't pop it (just like the example), and I return false from my hardwareBackPress event listener. At this point it I see the componentWillUnmount method being called in my final view, at which point my app shuts down.
If I return true then nothing happens at all obviously.
What I want to happen is that the app merely gets "backgrounded" instead of exiting completely.
Answered my own question. The trick is to override the default back button behaviour in the MainActiviy:
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "foo";
}
#Override
public void invokeDefaultOnBackPressed() {
// do not call super. invokeDefaultOnBackPressed() as it will close the app. Instead lets just put it in the background.
moveTaskToBack(true);
}
}
Though I may be very late in giving the answer it may help other facing the issue.
Recently I came across the same requirement where I have to move the app to the background. I tried the solution provided by #pomo. Though it worked I faced problems. Sometimes on multiple clicking of the back button, the app misbehaves in android though it worked perfectly fine in iOS.
And then I came across the following issues in GitHub where it mentions the reason for the misbehaviour.
The following solution works perfectly fine now.
// android/app/.../MainActivity.java
#Override
public void invokeDefaultOnBackPressed() {
moveTaskToBack(true);
}
<!-- AndroidManifest.xml -->
<activity
...
android:launchMode="singleTop">
Link from where I get the solution
I hope I'm able to help guys with the same requirement.
I use the following method to delete values from EditText when user presses the delete button of an android device.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL) {
onDeleteKey();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void onDeleteKey() {
if (edt_passcode1.isFocused()) {
} else if (edt_passcode2.isFocused()) {
edt_passcode1.requestFocus();
edt_passcode1.setText("");
} else if (edt_passcode3.isFocused()) {
edt_passcode2.requestFocus();
edt_passcode2.setText("");
} else if (edt_passcode4.isFocused()) {
edt_passcode3.requestFocus();
edt_passcode3.setText("");
}
}
I want to delete the previous EditText value when user presses the delete button on their device, but it's not called when the delete button is pressed. But onKeyDown() method doesn't called.
Please help me about it.
Thanks.
From the docs of activity:
Called when a key was pressed down and not handled by any of the views
inside of the activity. So, for example, key presses while the cursor
is inside a TextView will not trigger the event (unless it is a
navigation to another object) because TextView handles its own key
presses.
Im guessing thats your problem?
Link:
http://developer.android.com/reference/android/app/Activity.html#onKeyDown%28int,%20android.view.KeyEvent%29
EDIT:
One possible solution would be to attach a custom onKeyListener to your TextView. It is not necessary to subclass TexView like a commenter suggested, although thats an option as well.
You can get a template for the keyListener from this SO-Question:
Get the key pressed in an EditText
NEXT EDIT:
I just realized the first solution will only work for hardware keyboards.
If you want Virtual Keyboard Support, my best guess wild be an TextWatcher.
See a Sample implementation here:
Validating edittext in Android
NEXT AND HOPEFULLY FINAL EDIT:
Some googling turned up Activity's dispatchKeyEvent() - method. just implement it like you did with onKeyDown, you will be passed a KeyEvent that will tell you all about the pressed key.
Here's a link to the docs:
http://developer.android.com/reference/android/app/Activity.html#dispatchKeyEvent%28android.view.KeyEvent%29
I am learning app development from a book, and have run into a problem with the avd. I have my code set up to change some text when the right arrow key is pressed:
public boolean onKeyDown(int keyCode, KeyEvent event){
if(keyCode==KeyEvent.KEYCODE_DPAD_RIGHT){
textUpdate();
return true;
}
return false;
}
When I run the virtual device and press the arrow keys nothing happens. When I press the arrow keys on my physical keyboard, still nothing. I have done a lot of research and can't find the solution. I have tried editing the avd settings and editing the device(Nexus One) itself to accept keyboard and dpad input. What should I try now?
Have you overriden the method?
There should be an #Override above that function.
Override calls that function whenever its triggered so you can modify it to your specific implementation.
Hope this helps
the "arrow key" means the back key on android device?
if it is then you should override the onBackPressed
#Override
public void onBackPressed() {
// do something
}
Alright, what happened was my onKeyDown() function was inside a Fragment. I don't know why, but when I moved this code into the mainActivity it worked fine. If anyone has an answer as to why this worked and how I could get it to work in the fragment please comment.
Thanks