Here is my code, this is literally step by step from developer.android.com
and it just doesn't work, no matter how many times I run it.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
myWebView.loadUrl("http://www.google.com");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
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();
}
}
}
When I run my app, the webpage will load, toast never shows.
I just can't seem to find the problem. Can someone tell me if this works for them?
EDIT: Here is some more that I'm confused about. Right after this, the instructions are
This creates an interface called Android for JavaScript running in the
WebView. At this point, your web application has access to the
WebAppInterface class. For example, here's some HTML and JavaScript
that creates a toast message using the new interface when the user
clicks a button:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast);
}
</script>
I have no idea where that part of js code goes either..
I have no idea where that part of js code goes either..
Create an html page in your assets folder, let's say named myWonderfulWebPage.html.
Copy the following HTML code to it :
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast);
}
</script>
As you can see, when you'll click the button, the function showAndroidToast will be called and this function will call the one you defined in your Java code.
Now go back in your activity and load this page into your webview :
myWebView.loadUrl("file:///android_asset/myWonderfulWebPage.html");
Now you will see that it shows a blank page, with a button. Click it and it will show you the Toast on your webpage.
If the code you show is what is actually used then of course it will not work.
myWebView.loadUrl("http://www.google.com");
Google.com does not invoke the JS function you have added a bridge to. You need to use your own webpage that does indeed invoke the function, either local or on the web.-.-
Related
I have this weird problem when showing an activity which consists (only) out of a webview.
The first time I start this Activity B by clicking on something in activity A, B is properly loaded and functional. I press the return button, go back to A, then click on the same button to go to B and my webview doesn't show anything. Debugged it tons of times and nothing seems out of the ordinary. There are also no crashes in the stack trace log... This problem by the wway occurs always in debug mode and only sometimes in run mode.
Here is the code for the activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_spin);
myItem = (Item) getIntent().getSerializableExtra("Item");
initView();
initHandlers();
}
private void initView()
{
webView = findViewById(R.id.webview_spin);
//TODO : webViewClient vs webChromeClient ?
webView.setWebViewClient(new WebViewClient());
webView.setWebChromeClient(new WebChromeClient());
webView.getSettings().setJavaScriptEnabled(true);
String json = new Gson().toJson(myItem);
webView.loadUrl("file:///android_asset/item.html?item="+json);
}
private void initHandlers()
{
OrientationEventListener orientationEventListener = new OrientationEventListener(this) {
#Override
public void onOrientationChanged(int orientation) {
webView.reload();
}
};
orientationEventListener.enable();
}
FYI this problem occured before setting the orientationlistener.
That looks like somehow the render process of the WebView is failing. You could store the WebViewClient you created on a variable and check the result of its method onRenderProcessGone() to check if it is rendering the second time you load the activity. Here you have all the WebViewClient methods: https://developer.android.com/reference/android/webkit/WebViewClient
I have a WebView that shows the content from a HTML file with a SVG object and inside it some clickable objects with a onclick() function calling the Android interface with java.performClick().
Here's a code sample:
WebView wvMapa = (WebView) findViewById(R.id.wvMapa);
wvMapa.getSettings().setBuiltInZoomControls(true);
wvMapa.getSettings().setSupportZoom(true);
wvMapa.loadUrl("file:///" + file.getAbsolutePath());
WebSettings wsMapa = wvMapa.getSettings();
wsMapa.setJavaScriptEnabled(true);
wvMapa.addJavascriptInterface(new Object(){
public void performClick(String id){
/*MY ACTION*/
}
}, "java");
It works great on the first run, but when I click Home button and after Resume or open another Intent and go back, it doesn't work anymore. Looks like the JavascriptInterface is unattached everytime I leave the screen.
What's missing?
I use this code to check if a user touched inside a webview
webview.setOnTouchListener(new View.OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_UP)
{
//action
}
return false;
}
});
but I will need to do action only if user clicked (touched ) a link only ,not if the the user touch some pictures or do a scrool in webview.
I need to reinit some variables when new webpage is loaded ,or when a user clicks on a link , but not when he click random on screen or he do scrool.
i can not use
public void onPageStarted(WebView view, String url, Bitmap favicon)
or
public boolean shouldOverrideUrlLoading(WebView view, String url)
cause this are called multiple times while a page is loaded and I only need to do action first time only 1 time , when user click on a link (or button or something that make webview to load a new page)
Does anybody knwo how to do this?
Thank you in advance
first step - enable JavaScript:
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
second step - create interface between Java and Javascript:
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();
}
}
register your interface:
webView.addJavascriptInterface(new WebAppInterface(this), "Android");
and put this JS in your html page:
<script type="text/javascript">
function showAndroidToast(toast) {
Android.showToast(toast);
}
</script>
example for html:
<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
if pages which you are showing are not your you might download them as plain text, then insert JS and load html with myWebView.loadDataWithBaseURL. this way you have full control of which user is clicking and what to do with it
to be honest I don't understand why you cannot do this with shouldOverrideUrlLoading(WebView view, String url) by checking what is arriving in url String and setting 'consumed' flag or smth like this
also: whole code is stolen from HERE
I am currently creating an android application.
The aim of the application is to fire off some injected JavaScript code into the WebView that I have created within my android application. The problem that I am having is that the action that has been injected doesn't work.
You should also be aware that the html page that I am loading has been created locally. aim of the application is to have a toast message display.The code listing is below:
//uses javascript that is in the local HTML file
public class MainActivity extends Activity {
final String URL = "file:///android_asset/index.html";
private WebView myWebView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");
String test= "test";
String javascript ="javascript:document.addEventListener('click', function(){Android.showToast(toast)})";
myWebView.loadUrl(javascript);
myWebView.loadUrl(URL);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
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();
}
}
}
There are several issues with your implementation.
The toast variable might not be defined in the scope of your callback. Also, you are missing two semicolons, one right after calling the showToast method, and the other one at the end of the addEventListener method which results in a syntax error.
Finally, you are loading the Javascript code before loading the page, which gets it invalidated. You should be injecting your javascript code after the webpage has finished loading such as in the below example.
I've taken your example and rewrote it in a custom app to make sure it was working. Here's what I've written :
Android :
// Registering the JS interface
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
// Waiting for the page to be fully loaded, and injecting the JS code
mWebView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
#Override
public void onPageFinished(WebView view, String url) {
view.loadUrl(INJECTED_CODE);
}
});
// Load your custom url
mWebView.loadUrl(YOUR_ACTUAL_URL);
/**
* Interface between Java and Javascript.
*/
public class JSInterface {
#JavascriptInterface
public void showToast(String toast) {
Log.d("debug", "I got : " + toast);
}
}
Injected javascript :
public static final String INJECTED_CODE = "javascript:"
+ "(function() { "
+ "document.addEventListener('click', function(){JSInterface.showToast('Hello Android !');});"
+ "})()";
You are attempting to call that JS code before loading your html page.
I would guess that the document object is not ready.
Change your event listener and bind to the window
From:
String javascript ="javascript:document.addEventListener('click', function(){Android.showToast(toast)})";
To:
String javascript ="javascript:window.addEventListener('click', function(){Android.showToast(toast)})";
And you should get a result. If not what is logcat spitting out when you click?
EDIT: Just saw Halim Qarroums onPageFinished solution, that is probably a better one in your case.
I'm trying to call JS functions from Android native code, but they don't seem to be working. I've tried many solutions but to no solution. Here is my code:
public class MainActivity extends Activity {
private WebView webView;
#SuppressLint("SetJavaScriptEnabled")
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView1);
webView.setWebViewClient(new MyCustomWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.loadUrl("http://google.com");
}
private class MyCustomWebViewClient extends WebViewClient {
#Override
public void onPageFinished(WebView view, String url) {
webView.loadUrl("javascript:alert('shadow');");
Toast.makeText(getApplicationContext(), "DONE", Toast.LENGTH_LONG).show();
}
}
}
Please help.
Thanks
You can't do alert() with Android's WebView. If you want to show alert dialogs, you need to handle it in your Activity code or use a WebChromeClient. Per the docs:
Creating and setting a WebChromeClient subclass. This class is called
when something that might impact a browser UI happens, for instance,
progress updates and JavaScript alerts are sent here (see Debugging
Tasks).
See: https://developer.android.com/reference/android/webkit/WebView.html
With a WebView you can still write a JavaScript function that sets the value of a textbox to some string. If you need specific code to help you with this, let me know. If you've gotten this far though, you probably can handle it on your own is my guess.
Edit 1
First create a method in JavaScript called sendValueToAndroid()
myWebView.loadUrl("javascript:sendValueToAndroid()");
In the JavaScript method, call an exposed method in your Android code.
function sendValueToAndroid()
{
val divValue = ...
Android.sendValueToAndroid(divValue);
}
Expose a method in the Android app in any object of your choosing.
#JavascriptInterface
public String sendValueToAndroid(String val)
{
//do something in your app
}
Basically, what you're doing is telling the WebView to invoke a JavaScript method which invokes a callback method in your own app.