How to prevent GOBACK button for specific URL in Android Webview? - java

I have an web application that work on my Android WebView with out problem.
Here is my Android app launcher code:
public class MainActivity extends Activity {
WebView webView;
private String urlAddress = "http://www.YourDomainName.com/TheLoginPage";
private String loadingTxt = "Loading";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast loadingMsg = Toast.makeText(this,
loadingTxt, Toast.LENGTH_SHORT);
loadingMsg.show();
webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl(urlAddress);
webView.setWebViewClient(new myWebViewClient());
webView.setInitialScale(1);
webView.getSettings().setUseWideViewPort(true);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (webView.canGoBack()) {
webView.goBack();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
Every thing is working.
My Question: the default start page in the WebView is the web application login page. After a successful login process I want to prevent (build in) GO BACK button to back page to the default start page (login page) since I am successfully logged in?
Note: I will still use the GO BACK button to the rest of the web application or if I logout out again.

Here how I solved it, I have added if equals statement to compare the URL of the page that comes after the login process with the WebView URL, if they are identical then GO BACK is disallowed and a message "You are logged in", that way I prevent GO BACK. Here is the code and it works for me:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
String url = new String("http://www.YourDomainName.com/PageAfterSuccessfulLogin");
String webUrl = new String(webView.getUrl());
if (url.equals(webUrl)) {
Toast.makeText(this, "You are logged in",
Toast.LENGTH_SHORT).show();
} else {
if (webView.canGoBack()) {
Toast.makeText(this, "Back",
Toast.LENGTH_SHORT).show();
webView.goBack();
}
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}

Thanks maytham-maytham, it works charmly.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
String url = new String("https://www.domain name.com/index.php?logged=login%20successfully");
String webUrl = new String(webView.getUrl());
if (url.equals(webUrl)) {
Toast.makeText(this, "You are logged in",
Toast.LENGTH_SHORT).show();
}
else {
url = new String("https://www.domain name.com/main.php");
webUrl = new String(webView.getUrl());
if (url.equals(webUrl)) {
Toast.makeText(this, "Access Denied",
Toast.LENGTH_SHORT).show();
}
else
if (webView.canGoBack()) {
Toast.makeText(this, "Back",
Toast.LENGTH_SHORT);
webView.goBack();
}
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}

In which ever activity you want the back button to be disabled - DO THIS
#Override
public void onBackPressed(){
return;
}
You have to add this as a global function.
As in your case you want your back button to work in some cases and not work in some-
You can do this inside the onBackPressed()
if(BackButton_Dont_Work_Condition)
return
else
super.onBackPressed()

Related

Im not Getting the Button Release Toast in OnTouchListners

The issue is im not getting the Button release Toast.
i've a simple view in xml on which im performing onTouch.
hidenBtn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
firstTime=System.currentTimeMillis();
Toast.makeText(MainActivity.this, "Pressed", Toast.LENGTH_SHORT).show();
} else if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL) {
Toast.makeText(MainActivity.this, "Released", Toast.LENGTH_SHORT).show();
secondTime=System.currentTimeMillis();
if(secondTime-firstTime>=5000){
//do your actions here,prev,curr are fields in a class
ShowDialog();
}
else{
firstTime=0;
secondTime=0;
}
}
// TODO Auto-generated method stub
return false;
}
});
Change your OnTouchListener like this:
hidenBtn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
firstTime=System.currentTimeMillis();
Toast.makeText(MainActivity.this, "Pressed", Toast.LENGTH_SHORT).show();
return true;
} else if (action == MotionEvent.ACTION_UP
|| action == MotionEvent.ACTION_CANCEL) {
Toast.makeText(MainActivity.this, "Released", Toast.LENGTH_SHORT).show();
secondTime=System.currentTimeMillis();
if(secondTime-firstTime>=5000){
//do your actions here,prev,curr are fields in a class
ShowDialog();
}
else{
firstTime=0;
secondTime=0;
}
}
// TODO Auto-generated method stub
return false;
}
});
You are returning false at ACTION_DOWN which means you are not consuming your touch event, so no other steps of the same event are triggered. Therefore you need to return true in the ACTION_DOWN so you can intercept ACTION_UP.

Android Things onTouch doesnt release GPIO

I am using Android Things v1 and trying to use an on-screen Button to activate a motor as long as the button is pressed (tap & long press).
The problem I have is once the button is pressed the motor will not stop. I would like it to stop once the button is released.
Here is the button code:
mtrbtnGD.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
}
catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
return true;
}
});
EDIT:
Here is the new code from Sam's reply:
public class MainActivity extends Activity {
private Gpio mtrGpio;
private GestureDetector mtrbtnGD;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mtrbtnGD = (Button) findViewById(R.id.mtrbtn);
Button closebtn = (Button) findViewById(R.id.closebtn);
Button stopmtrbtn = (Button) findViewById(R.id.stopmtrbtn);
final PeripheralManager manager = PeripheralManager.getInstance();
List<String> portList = manager.getGpioList();
if (portList.isEmpty()) {
Log.i(TAG, "No GPIO port available on this device.");
} else {
Log.i(TAG, "List of available ports: " + portList);
}
mtrbtnGD.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
return true; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
// RELEASED
mtrGpio.close();
return true; // if you want to handle the touch event
}
}
catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
return true;
}
});
The motor still doesn't stop when I release the on-screen button.
close() closes your connection to the GPIO peripheral, it does not change the value of that connection before closing it. You need to use setValue(false); as so:
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
return true; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
// RELEASED
mtrGpio.setValue(false); // ADD THIS
mtrGpio.close();
return true; // if you want to handle the touch event
}
Ideally, if you expect the motor to be turned on and off a lot, you should keep the connection open.
public class MainActivity extends Activity {
private Gpio mtrGpio;
private GestureDetector mtrbtnGD;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mtrbtnGD = (Button) findViewById(R.id.mtrbtn);
try {
PeripheralManager manager = PeripheralManager.getInstance();
mtrGpio = manager.openGpio("BCM24");
mtrGpio.setEdgeTriggerType(Gpio.EDGE_NONE);
mtrGpio.setActiveType(Gpio.ACTIVE_HIGH);
mtrGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
} catch (IOException e) {
throw new IllegalStateException("cannot open gpio", e);
}
mtrbtnGD.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
mtrGpio.setValue(true);
Log.i(TAG, "Motor started");
return true;
case MotionEvent.ACTION_UP:
// RELEASED
mtrGpio.setValue(false);
return true;
}
} catch (IOException e) {
Log.w(TAG, "Unable to access GPIO", e);
}
return true;
}
});
}
#Override
protected void onDestroy() {
try {
mtrGpio.close();
} catch (IOException ignore) {
Log.w(TAG, "Unable to close GPIO", ignore);
}
super.onDestroy();
}
You can use this code inside onTouch method and Check event.getAction() :
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// PRESSED
return true; // if you want to handle the touch event
case MotionEvent.ACTION_UP:
// RELEASED
return true; // if you want to handle the touch event
}

Press Twice to exit the activity not working

i need to close and activity and start another only when the user presses back twice. I am using this code
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
Log.e("Entering","Yes");
DatabaseHandler db=new DatabaseHandler(AddBreakfastActivity.this);
db.deleteTodaysUnsavedMenu(Integer.parseInt(newDay),Integer.parseInt(newIntMonth));
Intent intent=new Intent(AddBreakfastActivity.this,ProvidersUpdateActivity.class);
startActivity(intent);
finish();
}
else {
this.doubleBackToExitPressedOnce = true;
Log.e("BOOLEANVALUE", String.valueOf(doubleBackToExitPressedOnce));
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
}
On pressing back once the app exits and shows the Toast message.
It doesnt wait for the second press. How can i resolve this?
Thank you.
EDIT
Found it to be working as expected when the back button is pressed. However shows aforesaid issue when called from
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id==android.R.id.home){
onBackPressed();
}
}
you can also do this with on keydown event as code below remove backpressed
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==KeyEvent.ACTION_DOWN && keyCode==KeyEvent.KEYCODE_BACK)
{
if (doubleBackToExitPressedOnce) {
Log.e("Entering","Yes");
DatabaseHandler db=new DatabaseHandler(AddBreakfastActivity.this);
db.deleteTodaysUnsavedMenu(Integer.parseInt(newDay),Integer.parseInt(newIntMonth));
Intent intent=new Intent(AddBreakfastActivity.this,ProvidersUpdateActivity.class);
startActivity(intent);
finish();
}
else {
this.doubleBackToExitPressedOnce = true;
Log.e("BOOLEANVALUE", String.valueOf(doubleBackToExitPressedOnce));
Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
return false;
}
}
return super.onKeyDown(keyCode, event);
}
Here's an example of "Press Twice to Exit" with fragments:
boolean doublePressToQuit = false;
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
if (doublePressToQuit) {
DashBoardActivity.this.finish();
} else {
this.doublePressToQuit = true;
Toast.makeText(this, getString(R.string.quit_notification), Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doublePressToQuit = false;
}
}, 2000);
}
}
}
Include super.onBackPressed(); inside your IF statement to override the onBackPressed() event.
Try the below code, it works for me
boolean firstBackPressed = false;
.
.
.
#Override
public void onBackPressed() {
if (!firstBackPressed) {
firstBackPressed = true;
Toast.makeText(MainMenu.this, "Press back again to exit", Toast.LENGTH_SHORT).show();
} else {
super.onBackPressed();
}
}
Please find this
private boolean isShownExit;
#Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(Gravity.LEFT)) {
drawerLayout.closeDrawer(Gravity.LEFT);
isShownExit = false;
return;
} else {
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
if (!isShownExit) {
isShownExit = true;
showToast(this, "Press again to exit");
} else {
hideSoftKeyboardDialogDismiss(this);
startAnotherActivityHereWhichDoYouwant();
}
} else {
getSupportFragmentManager().popBackStack();
}
}
}

Back button press twice before quitting app

How can I configure the back button to be pressed twice before the app exits? I want to trigger
#Override
public void onBackPressed() {
//custom actions
//display toast "press again to quit app"
super.onBackPressed();
}
Try this:
private boolean doubleBackToExitPressedOnce = false;
#Override
protected void onResume() {
super.onResume();
// .... other stuff in my onResume ....
this.doubleBackToExitPressedOnce = false;
}
#Override
public void onBackPressed() {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Press twice to exit", Toast.LENGTH_SHORT).show();
}
This snippet handle also the reset state when the activityis resumed
I see this question is a bit old but I though this might help some people looking for an alternative to the answers already given.
This is how I handle backing out of my applications. If someone has a better -- or a Google suggested -- method of accomplishing this I'd like to know.
Edit -- Forgot to mention this is for Android 2.0 and up. For previous versions override onKeyDown(int keyCode, KeyEvent event) and check for keyCode == KeyEvent.KEYCODE_BACK. Here is a good link to check out.
private boolean mIsBackEligible = false;
#Override
public void onBackPressed() {
if (mIsBackEligible) {
super.onBackPressed();
} else {
mIsBackEligible = true;
new Runnable() {
// Spin up new runnable to reset the mIsBackEnabled var after 3 seconds
#Override
public void run() {
CountDownTimer cdt = new CountDownTimer(3000, 3000) {
#Override
public void onTick(long millisUntilFinished) {
// I don't want to do anything onTick
}
#Override
public void onFinish() {
mIsBackEligible = false;
}
}.start();
}
}.run(); // End Runnable()
Toast.makeText(this.getApplicationContext(),
"Press back once more to exit", Toast.LENGTH_SHORT).show();
}
}
You could do what you're asking with a global integer and just count it, if > 2, quit.
But you could take a better (IMO) approach, where you question the user if they would like to quit or not:
private void questionQuit(){
final CharSequence[] items = {"Yes, quit now", "No, cancel and go back"};
builder = new AlertDialog.Builder(mContext);
builder.setCancelable(false);
builder.setTitle("Are you sure you want to quit?");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
switch(item){
case 0:
quit();
break;
case 1:
default:
break;
}
}
}).show();
AlertDialog alert = builder.create();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK :
int i = 0 ;
if(i == 1 )
{
finish();
}
i++;
return true;
}
}
return super.onKeyDown(keyCode, event);
}

Scope Variable issue for onKeyDown event

I am having trouble using the var "str" in an if statement. I know that it is a scope problem but I am not sure how to fix it. I have failed several times.
My goal is to use the value of "str" in an if statement to show an alert or not.
Restriction is I have to assign the value of "str" this way only.
public class MyJavaScriptInterface
{
public String showHTML(String html)
{
String str = html;
return str;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
//Handle the back button
if(keyCode == KeyEvent.KEYCODE_BACK && str =="0")
{
//Ask the user if they want to quit
Update:
OK I was try not to bother you with reading the whole code but it's short and it might help.
In a webview I show the html page and I also read a hidden variable which will decide if an alert box should show or not. I am just trying to get that value to the if statement in the keydown push. Here is the whole code.
package com.ishop.pizzaoven;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class buttonOne extends Activity
{
WebView wb = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.buttons);
wb = new WebView(this);
wb.getSettings().setJavaScriptEnabled(true);
wb.setWebViewClient(new HelloWebViewClient());
wb.getSettings().setJavaScriptEnabled(true);
wb.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");
/* WebViewClient must be set BEFORE calling loadUrl! */
wb.setWebViewClient(new WebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
/* This call inject JavaScript into the page which just finished loading. */
wb.loadUrl("javascript:window.HTMLOUT.showHTML(document.getElementById('sendtextcoupon').value);");
}
});
wb.loadUrl("http://ishopstark.com/mobileapp.php?category=1");
setContentView(wb);
}
private class HelloWebViewClient extends WebViewClient
{
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
view.loadUrl(url);
return true;
}
}
final Context myApp = this;
public class MyJavaScriptInterface
{
public void showHTML(String html)
{
String str = html;
}
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
//Handle the back button
if(keyCode == KeyEvent.KEYCODE_BACK)
{
//Ask the user if they want to quit
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Coupon")
.setMessage("Do you want a coupon texted to you?")
.setPositiveButton("YES!", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//Stop the activity
Toast.makeText(buttonOne.this, "Great! You'll get one in just a couple of minutes.", Toast.LENGTH_LONG).show();
finish();
}
})
.setNegativeButton("Not now", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//Stop the activity
finish();
}
})
.show();
return true;
}
else
{
return super.onKeyDown(keyCode, event);
}
}
}// End of main class
Update 2:
ok so i changed my code a bit. But now I get alert errors any ideas? "The method setIcon(int) is undefined for the type buttonOne.MyJavaScriptInterface" I get this error on .setIcon(android.R.drawable.ic_dialog_alert) and return super.onKeyDown(keyCode, event);
public class MyJavaScriptInterface
{
public String showHTML(String html)
{
String str = html;
return str;
}
public boolean onKeyDown(int keyCode, KeyEvent event, String str)
{
//Handle the back button
if(keyCode == KeyEvent.KEYCODE_BACK && str == "0")
{
//Ask the user if they want to quit
AlertDialog.Builder alertbox = new AlertDialog.Builder(buttonOne.this);
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Coupon")
.setMessage("Do you want a coupon texted to you?")
.setPositiveButton("YES!", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//Stop the activity
Toast.makeText(buttonOne.this, "Great! You'll get one in just a couple of minutes.", Toast.LENGTH_LONG).show();
finish();
}
})
.setNegativeButton("Not now", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
//Stop the activity
finish();
}
})
.show();
return true;
}
else
{
return super.onKeyDown(keyCode, event);
}
}
}
Not sure exactly what your aim is, but can you not make the string a member variable?
public class MyJavaScriptInterface
{
private String str;
public String showHTML(String html)
{
str = html;
return str;
}
}
It would be helpful to know which class the listener method is in; you have it outside the MyJavaScriptInterface class, but don't have any context around it. So when onKeyDown happens, do you have the html in order to run the showHTML(html) method? Has it already been run? Do you have an instance of MyJavaScriptInterface to run it on?
If you have an extra } in there and it is indeed a part of the same class, then I would agree with #Steve's answer.
If it's outside the class, then there are many solutions depending upon your actual situation. The simplest way would be to make str an instance variable as #Steve said, and then add an accessor method:
public String getStr(){
return str;
}
and then have your listener call that accessor instead of attempting to use str directly:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
// Get an instance of MyJavaScriptInterface;
MyJavaScriptInterface mjsi = new MyJavaScriptInterface();
//Handle the back button
if( keyCode == KeyEvent.KEYCODE_BACK && mjsi.getStr().equals("0") )
{
//Ask the user if they want to quit

Categories