Issues with popup in WebView - javascript

Frustration has finally overcome me and I am reaching out for some assistance. Currently in my app I have a webview that loads a series of pages. On several of the pages there are JS Login popups that appear. If I use a WebChromeClient and just straight open the browser the pages work fine however in my webview I cannot for my life get the popups to appear. I have tried a custom ChromeClient to handle the JS popups. I have also tried dozens of questions and answers on SO to no avail. Essentially is there any way to get the straight functionality of the WebChromeClient but keep it in my fragments webview. Any help would be absurdly appreciated.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_m2_web, container, false);
web = (WebView) rootView.findViewById(R.id.m2webView);
web.getSettings().setJavaScriptEnabled(true);
web.getSettings().setLoadWithOverviewMode(true);
web.getSettings().setUseWideViewPort(true);
web.setWebViewClient(new WebViewController());
web.setWebChromeClient(new WebChromeClient());
web.getSettings().setAllowFileAccess(true);
web.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
web.getSettings().setLoadWithOverviewMode(true);
web.getSettings().setUseWideViewPort(true);
web.getSettings().setDomStorageEnabled(true);
web.loadUrl("myurl");
web.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) {
web.goBack();
return true;
}
return false;
}
});
return rootView;
}

Related

Start an Android activity from an HTML link in a webview

In an Android activity I am displaying a webview.
WebView myWebView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/html/cloud.html");
The webview loads a local HTML file that builds a cloud of keywords with a javascript file. (source: http://www.goat1000.com/tagcanvas.php)
<script src="tagcanvas.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function() {
try {
TagCanvas.Start('myCanvas','tags',{depth: 0.8, maxSpeed: 0.03});
} catch(e) {
// something went wrong, hide the canvas container
document.getElementById('myCanvasContainer').style.display = 'none';
}
The keywords are generated from a list of HTML links defined in the HTML file
<div id="tags">
<ul>
<li>keyword1</li>
<li>keyword2</li>
<li>keyword3</li>
</ul>
</div>
When a user taps on a link, instead of staying in the webview and going to the corresponding location, I would like him to start a new Android activity, so obviously with Android code
I have found resources showing an example of how to make Android and Javascript "communicate" with an interface but I didn't manage to make it work in my case.
Edit:
My implementation thanks to the answer of Vlad
myWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent intent = new Intent(Act1.this, Act2.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); //ugly solution to avoid starting 2 activities, not ideal but it works
startActivity(intent);
return true; //I always return true because I never want to open an HTML link
}
});
You can set a custom WebViewClient to the WebView, and intersect url loading in it:
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// check the URL, and do whatever you need to do according to the URL
// return true; // if you handled URL, and WebView should not load it
return false; // for the WebView to load the URL
}
});

webView loadURL not working on HTML button click

I have a webView in my application. The webView initially opens an HTML page I created with a few buttons on it. The buttons do various tasks (I'm trying to learn how to use webViews) like: 1)show android toast, 2)show javascript alert, 3)vibrate phone, 4)show current geolocation, 5)open google maps in webView.
It's this last one that's not working. I've searched this site and many others, but haven't found a solution that works.
I'm fairly certain I have all the manifest file 'stuff' correct (everything else is working, including the initial internet based web page). I'm happy to post that too though if you think it's needed.
My activity_main.xml file has never given me issues, but again, I'm happy to post that if you think it'll help.
Here are snippets from my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myWebView = (WebView) findViewById(R.id.webView);
myWebView.loadUrl(url); // this one works
myWebView.setWebViewClient(new MyWebViewClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setGeolocationEnabled(true);
...
}
That all works and again the other html buttons work.
Then there's this:
public class WebAppInterface {
Context mContext;
//** Instantiate the interface and set the context *//
WebAppInterface(Context c) {
mContext = c;
}
//** Show a toast from the web page */
#JavascriptInterface
public void showToast(String toast) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
}
#JavascriptInterface
public void vibrateDevice() {
Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);
}
#JavascriptInterface
public void showMapCurPos() {
new Handler().post(new Runnable() {
String url2 = "http://www.google.com/maps/#53.001153,-95.0752916,15z";
#Override
public void run() {
myWebView.clearCache(true);//Here you call the methond in UI thread
myWebView.loadUrl(url2);
}
});
}
}
Everything works there, except for showMapCurPos(). I've already tried just a simple myWebView.loadUrl(...) along with several attempts at intents. Depending on what I've tried, sometimes that method crashes the app, but most of the time the new URL just doesn't get displayed and it stays on the original URL.
Please forgive me if this is a repeat question, but I really have searched this site and many others for an answer (probably for a solid 8 hours or so). I've tried many of those answers to no avail. I'm guessing it's something simple and has to do with my lack of understanding of webViews or activities or intents or all three or maybe even my newness to android development.
I can't write a comment yet, so I'm writing this as an answer.
You could try this answer:
myWebView.post(new Runnable() {...});
instead of using new Handler

Calling JavascriptInterface method through the WebView and JS function after changing config often doesnt work

I have some problem with calling a JavaScript function in a WebView and getting response in the app (on my Galaxy Tab 2 '10). I call the js-function directly after content loading. According this one solution i use a PictureListener
webView.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
webView.loadUrl("javascript: JsImpl.init('{response}');");
}
});
it works fine: when content is loaded, onNewPicture always is started.
"javascript: JsImpl.init('{response}') loads js that calls:
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
In the log i see D/JsImpl(18400): {response}. It seems to be everything okay but...
When I switch my tab on a landscape or portrait mode the WebView is recreated, onNewPicture are started but the method public void init(String json) in the JsImpl is often not called at all!
So if i change orientation, sometimes js works, sometimes doesn't work. No exception, no errors...
Who faced with the same problem?
Below is full code
public class NextActivity extends Activity {
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
final WebView wv = (WebView) findViewById(R.id.WebView);
wv.getSettings().setJavaScriptEnabled(true);
wv.loadUrl("file:///android_asset/index.html");
wv.addJavascriptInterface(new JsImpl(), "JsImpl");
wv.setPictureListener(new PictureListener() {
#Override
public void onNewPicture(WebView view, Picture picture) {
wv.loadUrl("javascript: JsImpl.init('{responce}');");
}
});
}
class JsImpl {
private final static String LOG_TAG = "JsImpl";
#JavascriptInterface
public void init(String json) {
Log.d(LOG_TAG, json);
}
}
}
html code is not needed here, just put on the assets dir an empty html file index.html.
EDIT:
I've found one soution but i dont know exactly is it correct varion. But it works.
I added handler loop
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isJSSetup) return;
Log.i("handler-loop", "JS didn't handle. Reload page");
wv.loadUrl(CONTENT_PAGE);
handler.postDelayed(this, 1000);
}
}, 1000);
when #JavascriptInterface init(String json) is called, isJSSetup became true. In handler loop i check if JS is setup or no if (isJSSetup) return;. If no - i reload URL again wv.loadUrl(CONTENT_PAGE) and try to call init(String json). So long as it is not going to work. It's hardcode, so i'm still looking for a good solution.
I hope this will help, but I can't say for sure because you are not showing how your WebView is restored after orientation changes.
I was having very hard time making my nested fragments to work properly after orientation changes. I wanted to retain the form values and all functionality during screen rotations. It all worked fine except the JavascriptInterface was NEVER working after orientation changes.
My WebView is restored in the onCreateView. I had to remove the restoreState call for my WebView and it all works now.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.layoutT4, container, false);
webView = (WebView) rootView.findViewById(R.id.webViewT4);
prepareBrowser(); // the browser is initiated here including the JavascriptInterface
if (webView != null) {
String URL = (savedInstanceState == null) ? "" : savedInstanceState.getString("URL");
if (URL.equals("")) {
webView.loadUrl("yourhome.html");
} else {
//webView.restoreState(savedInstanceState.getBundle("webViewBundle")); // this line was preventing the JavascriptInterface to work properly
webView.loadUrl(URL); // this is saved in onSaveInstanceState - I just reopen the URL here, the PHP page will take care of reloading the data
}
}
return rootView;
}

interact with website using android webview

I run a forum which has a shoutbox plugin installed where users can talk to each other just like instant messaging. I decided to make what i thought would be a quick app which would just display the shoutbox so users could talk while on the go instead of using there browser. The problem i have found is that it all works great using android webview but when you try and send a shout it comes up with an error saying "fail!" as though it has no communication with the actual shoutbox.
My question is can webview be used like this or can it only be used to display a webpage with out actually interacting with it? Below is my code what i am using so you guys can see if i am missing anything and if so please point me in the right direction thanks.
public class splash extends Activity {
WebView mWebView;
#Override
public void onCreate(Bundle savedInstanceState)
{
final Activity mActivity = this;
super.onCreate(savedInstanceState);
// Adds Progrss bar Support
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
setContentView(R.layout.mainx);
// Makes Progress bar Visible
getWindow().setFeatureInt( Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
mWebView = (WebView) findViewById( R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("http://www.myforum.com/forums/shoutbox.php");
mWebView.setWebChromeClient(new WebChromeClient()
{
public void onProgressChanged(WebView view, int progress)
{
//Make the bar disappear after URL is loaded, and changes string to Loading...
mActivity .setTitle("Loading...");
mActivity .setProgress(progress * 100); //Make the bar disappear after URL is loaded
// Return the app name after finish loading
if(progress == 100)
{
setTitle(R.string.title);
}
}
});
}
}
Creating and setting a
WebViewClient
subclass. It will be called when things happen that impact the rendering of the content, eg, errors or form submissions. You can also intercept URL loading here (via shouldOverrideUrlLoading()).

Android webview "location.replace" doesn't work

I have an Android webview with a page that redirects to another page, using location.replace(url).
Lets say that I have page "A" that redirects to page "B" (using location.replace). When pressing "back" button from page "B", the page returns to page "A", which redirects it to page "B" again.
When I debug the history api (history.length), I can clearly see that on page "B" the length has incremented in "1" (only on Android 4.X webview. On iOS / web browser / Android 2.X it remains the same), which is a bug! (location.replace shouldn't change history.lenght!)
I work with Yaniv on this project and we found the cause of the problem, it was introduced when we tried to add mailto: links handling according to this answer.
The answer suggested using the following extending class of WebViewClient:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
view.loadUrl(url);
return true;
}
}
}
The problem was that explicitly telling the WebViewClient to load the URL and returning true (meaning "we handled this") added the page to the history. WebViews are quite capable of handling regular URLs by themselves, so returning false and not touching the view instance will let the WebView load the page and handle it as it should.
So:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(MailTo.isMailTo(url)){
MailTo mt = MailTo.parse(url);
// build intent and start new activity
return true;
}
else {
return false;
}
}
}
function locationReplace(url){
if(history.replaceState){
history.replaceState(null, document.title, url);
history.go(0);
}else{
location.replace(url);
}
}
Try this way..
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView mainWebView = (WebView) findViewById(R.id.webView1);
WebSettings webSettings = mainWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mainWebView.setWebViewClient(new MyCustomWebViewClient());
mainWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mainWebView.loadUrl("file:///android_asset/www/A.html");
}
Or get help from this and this link

Categories

Resources