There are the 3 basic keys in an Android device.
1. Home button (middle button)
2. Menu button (left most button)
3. Back Button (right most button)
I'm trying to create a code the use will press the Back button and a AlertDialog will appear before return to the previous activity.
How can I handle the back button and do I have to insert it on the onCreate on the Java File of an Activity?
Thank You!
All (4) buttons are handled differently.
The home button and running apps buttons are completely outside your control.
To get the BackButton press, override this function.
#Override
public void onBackPressed(){
//Do Stuff
}
To get the Menu button key press, use the following
#Override
public boolean onKeyDown(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
doSomething();
return true;
}
return super.onKeyDown(keycode, e);
}
After you show the user your alert dialog, you can either send a real BackPress to the system using super.onBackPressed(), or you can manually finish() your activity.
#Override
public void onBackPressed(){
AlertDialog.Builder build=new AlertDialog.Builder(currentactivity.this);
build.setMessage("Are you sure you want to return?");
build.setCancelable(false);
build.setTitle("Note");
build.setPositiveButton("yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
Intent i =new Intent(currentactivity.this,anotheractivity.class);
startActivity(i);
//or just type finish();
}
});
build.setNegativeButton("no", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.cancel();
}
});
AlertDialog alert=build.create();
alert.show();
}
Related
This question already has answers here:
Android Fragment handle back button press [duplicate]
(25 answers)
Closed 7 years ago.
I am new on android. I cant handle onBackPressed method. I have an Activity class which has four fragment like A,B,C, D. When i lunched Activity by default Fragment A is active and there are link on fragment A to move another Fragment. I want when move another Fragment like B,C,D from Fragment A and pressed Back button it return to Fragment A and if i pressed Back button from Fragment A it show a dialog box.
I used onBackPressed() like below
public void onBackPressed() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
MainActivity.this);
// set title
alertDialogBuilder.setTitle("Exit");
// set dialog message
AlertDialog.Builder builder = alertDialogBuilder
.setMessage("Do you really want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, close
// current activity
MainActivity.this.finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
But it work on all fragment and i want to work only Fragment A
You have to handle such requirements in the Activity's onBackPressed only. I usually follow the following approach:
I keep an enum having all the fragments defined and a parameter to track the current fragment:
enum FRAGMENTS{
fragmentA, fragmentB, fragmentC, fragmentD
}
FRAGMENTS mCurrentFragment;
Now the logic where you change the fragment should have:
public void changeFragment(FRAGMENTS newFragment){
//Your logic
mCurrentFragment = newFragment;
}
And finally the logic onBackPressed:
onBackPressed{
if(mCurrentFragment == FRAGMENTS.fragmentA){
//Your code here of asking the user if he/she really wants to quit
super.onBackPressed();
}else{
changeFragment(getPreviousFragment(mCurrentFragment));
}
}
If you dont want to use enum, you can have final int or any other string values to represent different fragments and a mCurrentFragment parameter to keep a track of the currentFragment being shown and then you can easily play with the code in your Activity's onBackPressed method
Let me know if you need more clarification.
Add fragment to backStack while replacing
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
And then override onBackPressed method inside an Activity
So Here is your answer which you are looking for :)
Method 1
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// Your stuff here
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
// set title
alertDialogBuilder.setTitle("Exit");
// set dialog message
AlertDialog.Builder builder = alertDialogBuilder.setMessage("Do you really want to exit?")
.setCancelable(false).setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, close
// current activity
System.exit(0);
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
}
//Tell me if you face any issue
Method 2 or in your case just paste this method in your main activity so you can also achieve it what you want :)
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this);
// set title
alertDialogBuilder.setTitle("Exit");
// set dialog message
AlertDialog.Builder builder = alertDialogBuilder.setMessage("Do you really want to exit?").setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, close
// current activity
System.exit(0);
}
}).setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
If you want to override the onBack pressed method then add this code in your in onActivityCreated() method
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
getFragmentManager().popBackStack();
return true;
}
return false;
}
});
Use the below code hope it helps.
//Always replace/add your fragment with a tag so that you can use that tag in future
Fragment fr = getSupportFragmentManager().findFragmentByTag("Fragment_Name");//Fragment Name is a tag to identify fragment
if (fr == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_container, new Demo_Fragment(), "Fragment_Name").commit();
}
//Now override onBackPressed method in MainActivity Only no need to do it in Fragment Class
#Override
public void onBackPressed() {
Fragment fr = getSupportFragmentManager().findFragmentByTag("FragmentA");
if(fr==null)
//replace FragmentA
else
//Show Alert Box
}
For that you need to do following
Create method on the BaseFragment or Activity that save the current fragment object
public void setCurrentFragment(Fragment currentFragment) {
this.currentFragment = currentFragment;
}
and also create a method that return your current fragment object
public Fragment getCurrentFragment() {
return currentFragment;
}
now just you need to call the getCurrentFragment Method and checked that if the Fragment is an instance of the A fragment or not
if (getCurrentFragment() instanceof AFragment) {
showAlert
} else {
super.onBackPressed()
}
Let's say my first activity has the following code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == SET_PLAN_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
fixedPlan = data.getParcelableExtra("fixedPlan");
recreate();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crop_rotation_planner);
// Hide the action bar; I don't want to see that hideous thing, yet.
getSupportActionBar().hide();
// Initialize imageLoader
MainActivity.imageLoader = new ImageLoader(getApplicationContext());
restore(savedInstanceState);
}
private void restore(Bundle savedInstanceState) {
// Check if activity has been launched previously
if (savedInstanceState != null) {
// Get saved crop rotation plan
fixedPlan = savedInstanceState.getParcelable("fixedPlan");
// Enable or disable btnViewPlan
checkIfEnoughCropFamilies();
// Set number of crop families
setNumberOfCropFamilies();
// get mSoilTypesList
mSoilTypesList = (ArrayList<String>) savedInstanceState.getStringArrayList("mSoilTypesList");
selectedTypeOfSoil = savedInstanceState.getString("selectedTypeOfSoil");
mPlantList = savedInstanceState.getParcelableArrayList("mPlantList");
// if mSoilTypesList hasn't been acquired, then execute loadSoilTypesFromNet to fetch data
if (mSoilTypesList == null) {
loadSoilTypesFromNet.execute();
}
// else if mSoilTypesList already exists, just display the soil types
else {
// only display if user hasn't selected soil yet
if (selectedTypeOfSoil == null) {
displaySoilTypes();
}
// if user has already selected soil type, then display plants
else {
getPlants();
}
}
}
else {
loadSoilTypesFromNet.execute();
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putStringArrayList("mSoilTypesList", mSoilTypesList);
savedInstanceState.putParcelableArrayList("mPlantList", mPlantList);
savedInstanceState.putString("selectedTypeOfSoil", selectedTypeOfSoil);
savedInstanceState.putParcelable("fixedPlan", fixedPlan);
}
#Override
protected void onDestroy() {
dismissAlertDialog();
dismissProgressDialog();
loadPlantsFromNet.cancel(true);
loadSoilTypesFromNet.cancel(true);
super.onDestroy();
}
#Override
public void onBackPressed() {
if (!fixedPlan.isEmpty()) {
AlertDialog.Builder builder = new AlertDialog.Builder(CropRotationPlannerActivity.this);
builder.setTitle(R.string.str_dbox_exit_crp_title);
builder.setMessage(R.string.str_dbox_exit_crp_message);
builder.setPositiveButton(R.string.str_dbox_exit_crp_ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
CropRotationPlannerActivity.super.onBackPressed();
}
});
builder.setNegativeButton(R.string.str_dbox_exit_crp_cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert = builder.create();
alert.setCanceledOnTouchOutside(false);
alert.setCancelable(false);
alert.show();
}
else
super.onBackPressed();
}
And my proceeding activity has the following important code:
// We'll be sending our fixedPlan back to previous activity (CropRotationPlannerActivity)
#Override
public void onBackPressed() {
// TODO :: THINK OF THE SAVE FEATURE
final Intent intent = new Intent();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.str_dbox_exit_title);
builder.setMessage(R.string.str_dbox_exit_message);
builder.setPositiveButton(R.string.str_dbox_exit_yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
intent.putExtra("fixedPlan", fixedPlan);
setResult(RESULT_OK, intent);
// TODO : Somewhat buggy code here?
// TODO : Takes quite sometime to process :/
finish();
PlanActivity.super.onBackPressed();
}
});
builder.setNegativeButton(R.string.str_dbox_exit_no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
setResult(RESULT_CANCELED, intent);
dialog.dismiss();
finish();
PlanActivity.super.onBackPressed();
}
});
builder.setNeutralButton(R.string.str_dbox_exit_cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setCancelable(false); // so as to prevent the back button from closing the dialog box
alert = builder.create();
alert.setCanceledOnTouchOutside(false); // prevents user from canceling dialog box by clicking outside
alert.show();
}
When the user exits the first activity and the Object fixedPlan doesn't have any contents, I want the user to exit to the main menu. When it doesn't have any contents, I want to pop a DialogBox so that the user is aware that the current activity contains important info and ask the user one more time if he really wants to exit.
To get to the next activity, fixedPlan should not be empty. And getting out from that activity, fixedPlan is never empty, too. But why does the back button not respond once the user goes back to the previous activity? What should I do?
NOTE THAT THIS ONLY HAPPENS WHEN positive button is pressed ( in the second activity). Another thing is that once I have pressed the positive button on the second activity, and the moment I'm in the first activity, and then I go back there and press the negative button, the back button works. It's really an issue with the positive button. BTW, I can feel the back button's vibration when pressed. LOL. Just that. It doesn't respond.
Adding finish() does not work either (to the else statement in my onBackPressed method for the first activity).
Try changing adding dialog.dismiss() before finish() in Positive button click event inside the second activity?
Also, I believe you should remove the calls to PlanActivity.super.onBackPressed();, both under positive and negative buttons click.
I have developed an Android Service which will run in the background. The Service want to accept Yes or No confirmation from the user at an event(say when receive an SMS).
Its working fine; the Yes or No question will be shown to user. But i want the input from (press YES or NO) user without exit from the alert(exit by press on the Mobile Back button or Home button etc).
Please help me how it can be possible.
Below the code I am using;
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
//ctx is the Context
builder.setTitle("Emergency!");
String txt="Do you want to accept?";
builder.setMessage(txt);
builder.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//Do something
}
});
builder.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
///dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alert.show();
just add this in you AlertDialog
builder.setCancelable(false);
hope you are useing android.support.v7.app.AlertDialog;
You can disable back press while the dialog is shown (or possibly, send a "No" response when back button is pressed) with dialog.setOnKeyListener
dialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface arg0, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
dialog.dismiss();
}
return true;
}
});
Unfortunately you can't override Home button press on Android. You can, however, react to an activity being sent to the background via Home button by implementing onUserLeaveHint in the activity hosting your dialog.
Edit: You may also want to disable dismissing the dialog by touching outside (which is the default behavior) by doing
dialog.setCanceledOnTouchOutside(false);
I am using cocos2dx to make a small game and in the activity of my game i give the following functions to handle back button.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return super.onKeyDown(keyCode, event);
}
#Override
public void onDestroy()
{
android.os.Process.killProcess(android.os.Process.myPid());
super.onDestroy();
}
On pressing back button i get the following warning in my logcat
Can't open keycharmap file
Error loading keycharmap file '/system/usr/keychars/qtouch-touchscreen.kcm.bin'. hw.keyboards.65538.devname='qtouch-touchscreen'
The call doesn't reach onKeyDown or onDestroy functions.
Please tell me why this warning is caused and why i cannot handle the android back button.
The functions work fine on my java android project but not in my cocos2d-x project
It is been handled here in the file Cocos2dxGLSurfaceView.java
change it to below, where myActivity is the cocos2dActicity
case KeyEvent.KEYCODE_BACK:
AlertDialog ad = new AlertDialog.Builder(myActivity)
.setTitle("EXIT?")
.setMessage("Do you really want to exit?")
.setPositiveButton("YES", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
((Cocos2dxActivity)myActivity).finish();
}
})
.setNegativeButton("NO", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}).create();
ad.show();
return true;
case KeyEvent.KEYCODE_MENU:
To handle back button pressing you need to redefine onBackPressed() method of your activity, not this two methods.
Have you enabled the touch? If not then please enable it and Hope, it'll sort-out your problem.
I assume that's button in your game screen.
Just your apps implements for override method for onKeyDown,
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
// Here to implements for your code.
Log.d(TAG, "KEYCODE_BACK");
}
return super.onKeyDown(keyCode, event);
}
Here's an update for Cocos2d-x version 3+
This has been answered simply (and works) here
as well as a slightly less complete youtube here
I am running a service that starts a new activity when specific
applications are launched.
For example, when I launch sms application, my service detects it by
checking a top activity package name and starts a new activity.
But the problem is that after starting a new activity, when I finish
that activity and press BACK button from sms application to go back to
Home screen, it does not finish my sms application.
Even though the screen is at home(launcher), when I check top activity
name, sms app is running as the top activity, which means sms app is
not finished after pressing BACK button.
I use Intent.FLAG_ACTIVITY_NEW_TASK intent flag for starting a new
activity and finish() to finish it. Does anyone have an idea why my
BACK button does not finish sms application in this case?
thanks,
777
From what I've seen, the back button will halt the current activity, whatever it's doing. If you absolutely need to finish it off, take a look at the lifecycle of an activity, and perhaps put some code into the onPause() and onStop() functions.
OK if it doesnt workout.. try overriding the OnBackPressed method
and put finish() in that.. hope this helps
If you want to finish the activity when user navigate to back through device So you can use this code it is more helpful.
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
I did something like that in my activity:
#Override
public void onBackPressed(){
AlertDialog.Builder alert = new AlertDialog.Builder(ctx);
alert.setTitle("Wylogowanie i wylaczenie.");
alert
.setMessage("Exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//DO SOMETHING YOU NEED eg. destroy/close DB, stop services, and move the task to back
db.getWritableDatabase(); //getDB
db.destroyDB(context); //Destroy it
db.close(); //and close
stopService(new Intent(getBaseContext(), SVCKeepLogged.class)); //stop some service
moveTaskToBack(true); //hide activity (this do not kill it - you can use finish() here)
//finish();
}
})
.setNegativeButton("NOOO!", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
//Keep app alive.
dialog.cancel();
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
}
try this
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
// TODO
}
#Override
public boolean onOptionItemSelected(MenuItem item){
if(item.getItemId() == android.R.id.home){
finish();
}
}