Back button kicks me out of the app on WebView - java

I'm developing a Javascript based web app and thought that I could use Android's WebView ability to make it like an actual app, so I jumped right into Android Studio and made a simple WebView app without any Java knowledge, but the problem is, between page transitions whenever I want to return back and hit the back button, the app closes itself. I found some solutions but I have no idea how to implement them correctly, so can you help me please? Here are my WebView's FullscreenActivity.java codes.
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
WebView view = (WebView) this.findViewById(R.id.webView);
view.getSettings().setJavaScriptEnabled(true);
view.setWebViewClient(new ZeroBrowser());
view.loadUrl("http://www.google.com");
}
private class ZeroBrowserOverride extends WebViewClient implements ZeroBrowserOverride {
#Override
public boolean ShouldOverrideUrlLoading(WebView view, String Url){
view.loadUrl(Url);
return true;
}
}
Thank you so much!

You can try with this .
WebView view ; //Global
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
view = (WebView) this.findViewById(R.id.webView);
view.getSettings().setJavaScriptEnabled(true);
view.setWebViewClient(new ZeroBrowser());
view.loadUrl("http://www.google.com");
}
Then
#Override
public void onBackPressed() {
if (view.canGoBack()) {
view.goBack();
} else {
super.onBackPressed();
}
}
How to go back to previous page if back button is pressed in WebView?
http://developer.android.com/intl/es/guide/webapps/webview.html

You can check the clients history to go back within webview. Implement something like this:
#Override
public void onBackPressed() {
if (mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}

In your WebView class (or in parent view) override the listener:
#Override
public boolean onKeyDown(final int keyCode, final KeyEvent event) {
// Check if the key event was the Back button and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && this.canGoBack()) {
this.goBack();
return true;
}
// If it wasn't the Back key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}

Related

Searchview clear focus on hide keyboard

The user presses the hide keyboard button or the back button.
So I need to clear focus on the SearchView when the user is hiding the keyboard.
I tried this but it's not working. focus remains when the user hides the keyboard.
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
searchView.clearFocus();
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
app.requests.getApi().search(newText).enqueue(SearchFragment.this);
return false;
}
});
and this:
searchView.setOnQueryTextFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
app.functions.logWrite("has focus to searchview");
} else {
//code
}
}
});
Okay so try this it needs the use of a library unfortunately but it makes it easier.
In your build.gradle: add this:
dependencies {
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'
}
Register for the keyboard events using KeyboardVisibilityEvent library like this in the fragment/class where SearchView is declared:
KeyboardVisibilityEvent.setEventListener(
getActivity(),
new KeyboardVisibilityEventListener() {
#Override
public void onVisibilityChanged(boolean isOpen) {
if (!isOpen) {
View focusedView = getWindow().getCurrentFocus();
if (focusedView != null && focusedView instanceof SearchView) { // does SearchView have focus?
searchView.clearFocus();
}
}
}
});
searchView.clearFocus(); works on the assumption you have another focusable view in the hierarchy, if not add this to your fragments layout:
android:focusableInTouchMode="true"
Alternatively simply call focus(); on any other view element you want to receive focus.
This is what I use for handling back button clicks for SearchView, by Overriding onBackPressed()
#Override
public void onBackPressed() {
if (!searchView.isIconified()) {
searchView.setIconified(true);
ANY_VIEW_IN_YOUR_LAYOUT.requestFocus();
} else
super.onBackPressed();
}
Hope this helps. Feel free to ask for clarifications...

android.widget.Swtich - Keep state on pause?

I am a new developer writing an app that logs location when a switch is toggled. My switch works when I toggle it, but it loses it's state when I take the app out of the forefront. How do I keep the state of my android switch onPause and onResume?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
// set view, initiate switch
Switch mainSwitch = (Switch) findViewById(R.id.mainSwitch);
// deal with switch
mainSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#SuppressLint("MissingPermission")
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// if switch is on
if (isChecked) {
logLocation();
}
} else if (!isChecked) {
stopLocation();
}
// true if the switch is in the On position
Log.v("#############=", "" + isChecked);
}
});
}
Adding an answer instead of continuing in the comments.
By default Android will save the state of your UI if and only if you're using default components (meaning TextView, Button, Switch etc.) and your component has an id. This state will only survive if the OS kills the app and the user returns to it. This means that if the user presses the Home button and then returns to your Activity at a later stage, the UI state of all default components of that specific Activity will be restored. When pressing the Home button the Activity is stopped and onSaveInstanceState is called, so here you get a chance to save any state that isn't maintained by default components or if you have some data you downloaded for instance that is used to populate your UI components with data.
If the user presses the Back button the app will be killed and any UI state won't be restored per default.
To overcome this, you can use SharedPreferences or any other local storage mechanism to store your UI state to disk basically.
I've added a snippet of code, that shows how you can use the different approaches.
In your case you don't need the onSaveInstanceState method implementation, as you have a default UI component, that knows how to save its own state already and as mentioned Android does this automagically for you already.
Both states (savedInstanceState and what goes into the SharedPreferences) should be restored in the onCreate method as this is always called whenever an Activity is re-created or created the first time, while onRestoreInstanceState might not be called all the time.
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getName();
private static final String CHECKBOX__STATE = "CHECKBOX__SAVE_STATE";
private Switch checkbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkbox = findViewById(R.id.checkbox);
final boolean isChecked;
if (savedInstanceState != null) {
isChecked = savedInstanceState.getBoolean(CHECKBOX__STATE);
} else {
isChecked = PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(CHECKBOX__STATE, false);
}
// Setting the state (if any) of the Switch.
checkbox.setChecked(isChecked);
checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Log.d(TAG, "onCheckedChanged: isChecked = true - log location");
} else {
Log.d(TAG, "onCheckedChanged: isChecked = false - stop logging location");
}
}
});
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(CHECKBOX__STATE, checkbox.isChecked());
}
#Override
protected void onDestroy() {
super.onDestroy();
PreferenceManager.getDefaultSharedPreferences(this)
.edit()
.putBoolean(CHECKBOX__STATE, checkbox.isChecked())
.apply();
}
}
I hope this helps :-)

Want to open landscape links inside my android webview website by single click instead of two clicks

I am trying to make an android app from my website using webview such that I want a certain links in my website to open in landscape mode and others in portrait mode inside my webview. For this purpose, I have implemented below code inside the overridden function shouldOverrideUrlLoading which does the work, but not up to the mark. What this code does is, on clicking the landscape links the first time, it changes orientation of the present page to landscape mode but does not go to the website link and if I click it a second time when the current page is already in landscape mode, then it goes to the website link in landscape mode. This does the work, but it is very irritating because the link positions get changed in landscape mode and user will have to again search the link by scrolling and if the user clicks a portrait mode link during the second time, the present page turns to portrait mode but does not go to the website link. In short, the activity restarts due to orientation change, but the weird thing is this happens irrespective of the order of loadUrl and setRequestedOrientation functions and makes no difference on placing sleep ( for say 5 seconds ) before or after setRequestedOrientation, in either cases it sleeps ( for say 5 seconds ) first and then changes the orientation on first click and on second click, it sleeps first ( for say 5 seconds ) and then loads the url link and I am unable to understand the reason behind this strange behaviour ( Same feeling which quantum mechanics scientists experience ). I have tried everything like giving below code in AndroidManifest file :
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
And also tried overriding below functions in MainActivity file :
#Override
protected void onSaveInstanceState(Bundle outState )
{
super.onSaveInstanceState(outState);
mywebView.saveState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
mywebView.restoreState(savedInstanceState);
}
#Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
}
Experts please help in resolving this orientation change on first click only.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
/* try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
if(url.contains("<<some keywords>>")){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
else{
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
return true;
}
Please try this code ! i have implemented shouldOverrideUrlLoading,onPageStarted ,onPageFinished .Screen Orientation is changed in onPageStarted if any condition satisfy .
public class WebViewActivity extends AppCompatActivity
{
private WebView mywebView;
private ProgressBar myprogressBar;
private static final String TAG = "WebViewActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
myprogressBar = findViewById(R.id.myProgressBar);
myprogressBar.setVisibility(View.GONE);
mywebView = findViewById(R.id.myWebView);
mywebView.getSettings().setLoadsImagesAutomatically(true);
mywebView.getSettings().setJavaScriptEnabled(true);
mywebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mywebView.setWebViewClient(new MyBrowser());
mywebView.loadUrl("https://stackoverflow.com/");
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mywebView.saveState(outState);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mywebView.restoreState(savedInstanceState);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
private class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d(TAG, "shouldOverrideUrlLoading: loading ");
myprogressBar.setVisibility(View.VISIBLE);
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
Log.d(TAG, "onPageStarted: started");
myprogressBar.setVisibility(View.VISIBLE);
/*
here you have to include the your keywords instead of tags [hardcoded string]
*/
if (url.contains("tags")) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
myprogressBar.setVisibility(View.GONE);
Log.d(TAG, "onPageFinished: finished");
super.onPageFinished(view, url);
}
}
}

App button as keyboard press

I'm trying to map a button in my fragment layout as a keypress on a keyboard.
This is my button press:
Button down = (Button)(myView.findViewById(R.id.btnDOWN));
down.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(TAG, "Down pressed");
return false;
}
});
I wasn't able to find any library which would allow me to do so, all I've found was reverse case, when a keyboard or controller press would be sent to device.
What I'm trying to generally do here, is an app that acts like a controller for RetroPie by using the phone as a bluetooth keyboard, with only the keys necessary for a specific controller.
The method you're using is not correct. you should use the setOnClickListener:
Here an example from Android official guide:
public class MyActivity extends Activity {
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.content_layout_id);
final Button button = findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
}
}
If you're looking for continuos aka long click, you should change it to setOnLongClickListener:
down.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
return true;
}
});
It wasn't hard to find in this case the solution on this site

New Preferences not loading when back button is pressed

I have this preferences class (below) that saves two ListPreferences, but if the ListPreferences are changed and the back button is pressed, the changes don't take affect unless the application is restarted. Did I miss something? Have been looking everywhere, but just can't seem to find an answer the fits or works. Please help.
public class Preferences extends PreferenceActivity {
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onResume() {
super.onResume();
}
}
Application Code
public class Quotes extends Activity implements OnClickListener {
ProgressDialog dialog;
private WebView webview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String q = SP.getString("appViewType","http://www.google.com");
String c = SP.getString("appRefreshRate","20");
webview = (WebView) findViewById(R.id.scroll);
webview.getSettings().setJavaScriptEnabled(true);
webview.setWebViewClient(new QuotesWebView(this));
webview.loadUrl(q);
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
webview.reload();
}
}, 10, Long.parseLong(c),TimeUnit.SECONDS);
findViewById(R.id.refresh).setOnClickListener(this);
}
#Override
public void onPause(){
super.onPause();
}
#Override
public void onResume(){
super.onResume();
}
public void onClick(View v){
switch(v.getId()){
case R.id.refresh:
webview.reload();
break;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem about = menu.getItem(0);
about.setIntent(new Intent(this, About.class));
MenuItem preferences = menu.getItem(1);
preferences.setIntent(new Intent(this, Preferences.class));
return true;
}
}
You need to somehow reload your preferences when the preferences activity finishes. I thought Dirol's suggestion of loading them in onResume() instead of onCreate() was excellent; have you tried it? Or am I misunderstanding the problem as well.
In my own case, I launched the preferences activity with startActivityForResult() and then on the activity result callback, I reloaded the preferences.
Code snippets:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_PREFERENCES:
Intent intent = new Intent().setClass(this, CalcPreferences.class);
startActivityForResult(intent, MENU_PREFERENCES);
break;
default: return super.onOptionsItemSelected(item);
}
return true;
}
#Override
protected void onActivityResult(int req, int result, Intent data) {
switch( req ) {
case MENU_PREFERENCES:
SharedPreferences sp =
PreferenceManager.getDefaultSharedPreferences(this);
updatePreferences(sp);
break;
default:
super.onActivityResult(req, result, data);
break;
}
}
#Override
protected void updatePreferences(SharedPreferences sp) {
super.updatePreferences(sp);
keyclick = sp.getBoolean("keyclick", keyclick);
}
Anyway, this is what works for me. I may try moving my updatePreferences() call to onResume() myself to see if that works too.
Try overriding the onBackPressed() method.
If your "Up" button (top left <-) provides the correct result, then you can set the Back button to behave like the Up button.
#Override
public void onBackPressed() {
super.onBackPressed();
NavUtils.navigateUpFromSameTask(this);
}
You load preferences only on onCreate() method. That method called only when a fresh activity starts up. The addPreferencesFromResource inflates the xml file into the preferences, so you only get the info, which is already has been stored in the xml at the moment addPreferencesFromResource was called, not after.
Try to move that method to onResume. But watch for the memory leak. I don't know exactly what the addPreferencesFromResource do, but from the documentation - I would be very suspicious about that method activity.
I had the same problem and solved it as follows:
The main activity class implements OnSharedPreferenceChangeListener:
public class Activity_name extends Activity implements OnSharedPreferenceChangeListener {
...
}
Inside the main activity class the onSharedPreferenceChanged is run whenever a preference entry changes. I simply update all my variables from the preferences as i did in onCreate:
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
<read all preferences as you did in onCreate()>
}
This does the trick and I hope it saves you some time in searching for a solution.
I've had the same problem...
Try to create preference instance and load its data in every class and every activity where you need it.
It worked for me...Hope it helps.
You will need to reload your view or whatever object which uses those preferences, preferably when preference activity closes.
Preference activities do not change nothing but an internal file with your preferences(key=value list). When it is changed, preferenceActivity calls onPreferenceChaged() and nothing more. It doesn't refresh your stuff by itself. You need to reload prefs and to reuse them in onResume() method or equivalent.

Categories