webview, using loadData at onResume loses history - android

I have this app which reads articles in a webview. When ArticleActivity is first started, the html of the webpage is actually downloaded into a string and parsed to make it look like a mobile site, then I use wb.loadData(html, "text/html; charset=UTF-8", null);. The downloading occurs in an asynctask since I can't do internet activity on the ui thread, but for now, whenever a link on the page is clicked, it just defaults to loadUrl() as per the webviewclient. I can use goBack() in history with this, no problem.
The problem lies with the search bar widget. I call SearchResultsActivity, which opens a webview and loads a url. When the user clicks on an article, SearchResultsActivity sends it BACK to ArticleActivity through an intent. The problem with that is that I want to use loadData() for the new article link, and I try to do that in onResume(), but nothing happens if I'm still on the previously loaded page. The log statement shows that the Url from EXTRA_RETURN_RESULT did make it, so I think the intent is good. I think this is due to a javascript "same origin" thing, so that's why if I use loadDataWithBaseURL(), the page loads. But if I try the back button now, the previously loaded page is blank! What do I do to preserve history when I load the new page?
class SearchWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// if it is morning sign out AND is an article, send url to ArticleActivity
if(Uri.parse(url).getHost().endsWith("morningsignout.com")) {
Intent intent = new Intent(view.getContext(), ArticleActivity.class);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, url); // Put url in intent
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); // Open w/ old articleActivity if exists
view.getContext().startActivity(intent);
return true;
}
// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
// view.getContext().startActivity(intent);
return false;
}
}
from ArticleActivity
#Override
protected void onResume() {
super.onResume();
// URL from CategoryActivity
String intentURL = getIntent().getStringExtra(Intent.EXTRA_HTML_TEXT);
// Set webView to new article
if (intentURL != null) new URLToMobileArticle(webView).execute(intentURL);
else {
// If statement is reached, then intent originated from SearchResultsActivity
intentURL = getIntent().getStringExtra(Intent.EXTRA_RETURN_RESULT);
new URLToMobileArticle(webView).execute(intentURL);
Log.d("ArticleActivity", "Loading: " + intentURL);
}
}
what URLToMobileArticle is, getArticles() is the download/parsing function:
public URLToMobileArticle(WebView webview) {
this.wb = webview;
}
#Override
protected String doInBackground(String... params) {
return getArticle(params[0]);
}
#Override
protected void onPostExecute(final String html) {
wb.loadData(html, "text/html; charset=UTF-8", null);
// wb.loadDataWithBaseURL(link, html, "text/html; charset=UTF-8", null, null);
Log.d("URLToMobileArticle", "Loaded webpage");
}

The answer to this is that I can use shouldInterceptRequest() to always load the html in the way I see fit. I just need to ensure that I can distinguish between webpage urls and other requests like images or style sheets

Related

Loading an activity from WebView - works first time app is installed but not after that?

In the login screen (LoginActivity) of my Android app, there is a 'Sign up' button that takes the user to a registration webpage that is displayed in a WebView (in SignupActivity). After the user has registered (i.e. clicked the 'CreateAccount' button), I would like to take them back to LoginActivity.
My current code is below. It works the first time the app is installed, but after repeating the process the 2nd time, the if/else clause doesn't trigger at all (neither of the Logs shows up and the redirection doesn't happen). Why?
public class SignupActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("SignupActivity", "Signup Activity started");
WebView webView = new WebView(this);
setContentView(webView);
webView.setWebViewClient(new MyWebViewClient());
webView.loadUrl("https://commons.m.wikimedia.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes");
}
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.equals("https://commons.m.wikimedia.org/w/index.php?title=Main_Page&welcome=yes")) {
// Signup success, so load LoginActivity again
Log.d("SignupActivity", "Overriding URL");
CookieSyncManager.createInstance(getApplicationContext());
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.removeAllCookie();
cookieManager.setAcceptCookie(false);
cookieManager.removeSessionCookie();
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
return true;
} else {
Log.d("SignupActivity", "Not overriding URL, URL is: " + Uri.parse(url).getHost());
return false;
}
}
}
And in LoginActivity I have attached this method to a button click:
//Called when Sign Up button is clicked
public void signUp(View view) {
Intent intent = new Intent(this, SignupActivity.class);
startActivity(intent);
}
However I am new to WebViews so I am happy to change this setup if necessary.
You should simplt override the shouldOverrideUrlLoading method in your WebViewClient. Then when the user signups, it should be redirected to let's say a success page. So you know the url of success is https://www.example.com/success. In your shouldOverrideUrlLoading check that if the url about to be loaded is the success URL. If it is, then just finish this activity and do whatever you want.
EDIT:
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("SignupActivity", "Loading URL: " + url);
if (url.equals("https://commons.m.wikimedia.org/w/index.php?title=Main_Page&welcome=yes")) {
// Signup success, so load LoginActivity again
Log.d("SignupActivity", "Overriding URL");
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
return true;
} else {
Log.d("SignupActivity", "Not overriding URL, URL is: " + Uri.parse(url).getHost());
return false;
}
}
}
There is simple approach you can follow for this situation.And that is when you click on "Signup" Button open new activity(WebActivity) from your LoginActivity.
You can add LoginActivity as ParentActivity for WebActivity in your manifest.
So, when you click on signup button and go to WebActivity, do not call finish() method because it will destroy your LoginActivity.
Now, When you press Signup button, WebActivity will open and LoginActivity on backstack And whenever you press back button in WebActivity that time super.backpressed() method redirect you to LoginActivity.
Update(After Read comment) :
If you want to redirect user to LoginActivity then you can call Backpressed() method when user click on "Create account button".Which should be in your Activity.
I think you need JavascriptInterface to do this.
After reading your question, I think the main point of your question is that "How to close the WebView and bring the user data to native".
Take the user to a web page is all depends on your logic, so you need to consider how to deal with it.
But if you want to take the user back, you need to interact with the web page. After user's registration, the web page tells you whether the registration is successful or not, and the data about the user.
Call this function to add a JavascriptInterface to the WebView:
WebView.addJavascriptInterface(Object object, String name)
After registration, web page use JS to call your native method, and in the method, you can get the result of the registration and do what you want.
You may need to read this for more information about JavascriptInterface.

How to close a webview app if no activity within 5 minutes?

I am asking this after long searches without help.
I created a simple webview app with eclipse.
(Sometimes – app opens a web browser depending on the url)
I need to kill the app if there are no clicks (not active) within 5 minutes.
Whenever a user clicks on any link in the app – the timer would reset.
I know it should be simple but I’ve got mixed up with too many lines of code… :/
Can anyone be nice and show a code example for how it’s done ?
Thank you dearly
public class MainActivity extends Activity {
private WebView webView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final WebView webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
// if url contains url1,2,3 - launch in browser
#Override public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
if(url.contains("url1.com")||(url.contains("url2.com")) ||(url.contains("url3.com")) ) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
}
else {
view.loadUrl(url);
return false;
}
}
});
webView.loadUrl("http://starter-site.com");
}
}
Use a Handler. Create a Runnable that finishes your activity.
Each time a user clicks a link, do something like this:
myHandler.removeCallbacks(myFinishingRunnable);
myHandler.postDelayed(myFinishingRunnable, 5000);
Be careful not to leak your activity (if your Runnable is an inner class, make it static and give it a WeakReference to your activity). And it's probably a good idea to set/unset the callback when your activity is resumed/paused.
It seems like I have found a better solution. I decided to kill the app if a specific url string is in use.
So, if the click went on Google, it would simply launch the browser and shut down.
Hope this is ok in the Android way of mind...I guess not.
#Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {
if (url.contains("url1.com") || (url.contains("url2.com")) || (url.contains("url3.com"))) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
if (url.contains("google")) {
finish();
}
return true;
} else {
view.loadUrl(url);
return false;
}
}

Android: unable to pass a url in webview

i am trying to pass a url which start with www.example.com/xxxxxxx in my webview it can be anything in the place of xxxxxxx. see the code you will understand
private class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (Uri.parse(url).getHost().equals("http://www.example.com"+"*")) {
// This is my web site, so do not override; let my WebView load the page
return false;
}
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
}
}
i want to pass any url from my website only else open it in default browser.
Uri.getHost() return the host from the authority, you should try to use if (Uri.parse(url).getHost().equals("www.example.com")) or if (Uri.parse(url).getHost().equals("example.com")).
Also, as a good practice, you should reverse your equals() statement like this: "example.com".equals(Uri.parse(url).getHost()) as you know that "example.com" will never be null and, as such, never throw a NullPointerException.

Android Issue with WebView and overriding the url

Below is the code which we are using to load the WebView. Capturing the url and redirecting to a new activity page is done using the “shouldOverrideUrlLoading”, once the user click on log in button in html page in the webview. But when loading the page, the page is redirecting after the security check(redirecting to https page) and control is coming to the “shouldOverrideUrlLoading” function and its making the activity blank. If we remove the “shouldOverrideUrlLoading” function we can see the log in screen on the WebView. But we are not able to go to the new activity. I tried to catch the redirection url and load it on the
“shouldOverrideUrlLoading” function, but its not allowing to load the content. And I try to return true and false for different conditions form “shouldOverrideUrlLoading” function that also not working.
Can anyone suggest what I need to do to load the log in page in the WebView after the redirecting from the security check and override the url after log in and redirect to a new activity?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_page);
WebView webview = (WebView) findViewById(R.id.wvLogin);
setContentView(webview);
webview.setWebViewClient(new WebViewClient()
{
// Override URL
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if(url.equals("http://Url which needs to override after login"))
{
Intent i = new Intent(getApplicationContext(), APImages.class);
startActivity(i);
}
return true;
}
});
webview.loadUrl("http://Login Page Url");
}

Android : click link in a page within web view

I have included a web application within android web view , and there is a link in the webpage which opens some other site , when the link is clicked it works fine for the first click, however when clicked for the second time the website is not found ,
the code is :
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("some site ")) {
Intent i = new
Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
} else {
view.loadUrl(url);
return false;
}
}
#THelper and #mikegr, thanks for the reply,
Actually in my case i have a modal panel (JSF) in my web application which contains some buttons, on clicking the button i am opening some other site using javascript window.open() method which works fine in desktop browser, however, when i wrap this web application within android webview, everything works fine except when i first click this button i'm able to open the other site using the external browser, however on second click the webview tries to open this othersite within the webview instead of the external browser and i get website not found with the entire URL of the other site, this happens even when i logout and login again as the application launched is still running.
also in my case after sometime when the application is idle i get the black screen.
i surfed through the net and found simillar issue but that didn't help either , here is the link:
http://groups.google.com/group/android-for-beginners/browse_thread/thread/42431dd1ca4a9d98
handling links in a webview ,
any help and ideas would be very helpful for me, this is taking too long for me,
since i'm trying to display my web application in the web view, i have only one activity, which contains code like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
// so that when launcher is clicked while the application is
// running , the application doesn't start from the begnining
} else {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
// Show the ProgressDialog on this thread
this.progressDialog = ProgressDialog.show(this, "Pleas Wait..", "Loading", true);
browser = (WebView) findViewById(R.id.webview);
browser.getSettings().setJavaScriptEnabled(true);
browser.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
Log.i(TAG, "Finished loading URL: " +url);
if (progressDialog.isShowing()) {
progressDialog .dismiss();
}
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("some site")) {
Intent i = new
Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
return true;
} else {
view.loadUrl(url);
return true;
}
}
});
browser.loadUrl("mysite");
}
}
I had the experience that shouldOverrideUrlLoading() is not called in certain circumstances.
There are a few bugs about this topic on
http://code.google.com/p/android/issues
like bug number 15827, 9122, 812, 2887
As a workaround try to add the method onPageStarted() and check if you get this call. For me this method is always called even if shouldOverrideUrlLoading() was not called before.
onPageStarted worked for me. Had to tweak it a bit, as that method is called when the webview is first rendered too, and I wanted to only execute it on the onClick of the banner's javascript.
I was simulating a banner with a custom page, so when the ad.html was being rendered, I avoided the startActivity. Otherwise, it launches the new browser window.
WebViewClient newWebClient = new WebViewClient() {
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
if(!url.equals("http://xxxx.ad.html"))
view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
};
Try to append the System parameter pattern in url before you load that, something like.
String url = "http://xxxx.ad.html?t="+System.nanoTime();
and in your shouldOverrideUrlLoading() method remove the query part (in a very first line).
int idx;
if ((idx = url.indexOf("?")) != -1) {
url = url.substring(0, idx);
}

Categories

Resources