I'm trying to make an Android version of a relativly simple iOS app that uses a webview, some buttons and then relies on javascript calls to a CMS.
But I'm stuck at a pretty early point of development: The webview doesn't function with javascript.I've read a lot of posts about how to enable JS in an Android webview, but no luck so far.
Below is some of my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebViewClient(new HelloWebViewClient()
{
#Override
public void onPageFinished(WebView view, String url)
{
//Calling an init method that tells the website, we're ready
mWebView.loadUrl("javascript:m2Init()");
page1(mWebView);
}
});
mWebView.loadUrl("http://my_url/mobile/iphone//app.php");
}
private class HelloWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
public void page11(View view)
{
mWebView.loadUrl("javascript:m2LoadPage(1)");
}
What am I doing wrong here?
The URL is working perfectly in my iOS app, and in a browser.
But not in my app!
Please tell me it's something obvious...
FIXED!
Spurred on by the error, I found out that I needed to set
setDomStorageEnabled(true)
for the webview settings.
Thanks for your help Stephan :)
In case something with WebView on Android does not work, I always try to make sure I set these crazy flags such as,
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDisplayZoomControls(false);
webSettings.setSupportZoom(true);
webSettings.setDefaultTextEncodingName("utf-8");
I wonder why these are not set by Default, who would expect webpages without javascript content nowadays, and whats the use having javascript enabled when DOM is unavailable unless specified. Hope someone filed this as a bug or improvement/feature-request already and the monkeys are working on it.
and then there is deprecated stuff rotting somewhere, like this:
webView.getSettings().setPluginState(PluginState.ON);
All this for loading webpages inside app.
On iOS, its all so simple - Swift 3.0
private func openURLWithInAppBrowser(urlString:String) {
guard let url = URL(string:urlString) else {
return
}
let sfSafari = SFSafariViewController(url:url)
present(sfSafari, animated: true, completion: nil)
}
Loading javascript in webview
webView.getSettings().setDomStorageEnabled(true);
Mainly, these three lines will be enough to make the Javascipt work in webView...
webSetting.setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
If it's not working after that also, then add below line also.
webSettings.setDomStorageEnabled(true);
Actually, you need both setJavaScriptEnabled() and setWebChromeClient(new WebChromeClient()) to make the JavaScript work. If you will use only webSetting.setJavaScriptEnabled(true); then it won't work.
Add the following lines of code in your MainActivity.java
It helped me to enable js
webSetting.setJavaScriptEnabled(true);
webView.setWebChromeClient(new WebChromeClient());
webView.setWebViewClient(new WebViewClient());
do not forget about this permission in AndroidManifest file.
<uses-permission Android:name="Android.permission.INTERNET" />
Did you enable the right internet permission in the manifest? Everything looks fine otherwise. By any chance, have you also tested this code on an actual Android phone? And not just on the emulator?
Here is a good tutorial on a slightly different approach. You may want to try that one to see if it works for you.
This video (http://youtu.be/uVqp1zcMfbE) gave me the hint to make it work.
The key is to save your html and js files in the Android assets/ folder.
Then you can easily access them via:
webView.loadUrl("file:///android_asset/your_page.html");
If you are in Kotlin you can use the following method to get the JavaScript working :
webView.apply {
loadUrl(
"file:///android_asset/frm/my_html_landing_page_here.html"
)
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
}
Also make sure that your entire folder is inside the Assets folder (this includes HTML, Javascript and other file needed)
Xamarin Android also has the same problem that WebView does not execute any Javascript. Follow #computingfreak answer:
this.SetContentView(Resource.Layout.activity_main);
var webView = this.FindViewById<WebView>(Resource.Id.webView);
var webSettings = webView.Settings;
webSettings.JavaScriptEnabled = true;
webSettings.DomStorageEnabled = true;
webSettings.LoadWithOverviewMode = true;
webSettings.UseWideViewPort = true;
webSettings.BuiltInZoomControls = true;
webSettings.DisplayZoomControls = false;
webSettings.SetSupportZoom(true);
webSettings.DefaultTextEncodingName = "utf-8";
Weirdly enough they changed all setter methods to properties except SetSupportZoom and SupportZoom stays as getter :/
Just permit your WebView to run JS, simple like that:
WebView web=(WebView)findViewById(R.id.web);
web.getSettings().setJavaScriptEnabled(true);
To enable javascript popups in WebView its necessary to set webChromeClient and override openFileChooser methods.
mWebview.setWebChromeClient(new WebChromeClient(){
// For Android 4.1+
#SuppressWarnings("unused")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(acceptType);
startActivityForResult(Intent.createChooser(i, "SELECT"), 100);
}
// For Android 5.0+
#SuppressLint("NewApi")
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (mUploadMessageArr != null) {
mUploadMessageArr.onReceiveValue(null);
mUploadMessageArr = null;
}
mUploadMessageArr = filePathCallback;
Intent intent = fileChooserParams.createIntent();
try {
startActivityForResult(intent, 101);
} catch (ActivityNotFoundException e) {
mUploadMessageArr = null;
Toast.makeText(activity,"Some error occurred.", Toast.LENGTH_LONG).show();
return false;
}
return true;
}
});
And handle the onActivityResult as below:
#SuppressLint("NewApi")
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) {
if (mUploadMessage == null) return;
Uri result = data == null || resultCode != Activity.RESULT_OK ? null : data.getData();
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
else if (requestCode == 101) {
if (mUploadMessageArr == null) return;
mUploadMessageArr.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
mUploadMessageArr = null;
}
}
If nothing above helped try to add delay in WebViewClient.onPageFinished listener
override fun onPageFinished(view: WebView?, url: String?) {
Handler().postDelayed({
//update your view with js here
super.onPageFinished(view, url)
}, 1000)
}
Related
I have an app with a web view in which I load HTML content with JavaScript enabled. The web view is inside a fragment.
This is how I initialize the web view inside the method onCreateView of the fragment :
WebView webview = (WebView) mainView.findViewById(R.id.webview);
WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDisplayZoomControls(false);
webSettings.setLoadsImagesAutomatically(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setDomStorageEnabled(true);
webSettings.setSupportMultipleWindows(true);
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
/*
* My code
*/
}
});
webview.setWebChromeClient(new WebChromeClient() {
#Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView.HitTestResult result = view.getHitTestResult();
String data = result.getExtra();
if (data != null) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(data));
startActivity(browserIntent);
}
return false;
}
});
webview.loadDataWithBaseURL(baseUrl, htmlData, "text/html", "utf-8", "");
In the web view, a map is loaded with JavaScript. On this map, we can click on elements and load photos. When clicked, the photo is displayed in a popup (still inside the web view). When I click on the back button to go back to the map, the app crashes.
Here is the error log :
A/libc: Fatal signal 5 (SIGTRAP), code 1 in tid 949 (Chrome_InProcRe)
[ 03-21 11:26:08.510 364: 364 W/ ]
debuggerd: handling request: pid=32610 uid=10289 gid=10289 tid=949
I tested and got the crash on Android 7.1.1, 6.0.1, 5.0.2. Then I tried with Android 4.4.2 and the app didn't crash.
When I click on the back button (as we can see on the GIF), it should go back to the previous state with the popup closed
Try to override the back navigation functionality and close the popup yourself.
You don't need to handle all the stack navigation logic, just have a state when you are showing this popup.
Apply your own navigation logic(like manually closing the popup).
void onBackPressed(){
if(isTheBuggyPopupIsOn){
closeTheBuggyPopup();
}
else{
super.onBackPressed();
}
}
Try this....
First add this
webView.setWebViewClient(new MyBrowser());
and then add this
public class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
if (url.equals(""YOUR URL)) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
return true;
} else {
return false;
}
}
}
I have an android activity that holds the webview and I have a page that contains a local variable marks. The local variable will be increased when user got the correct answer. In the webpage, there is a button called exit which is supposed to close the webpage and go back to the activity in android, and it should carry the local variable marks back to the activity too. I want to ask how the exit button can be done in the webpage to close the page and return local variable by using Javascript and how can the activity in android receive the local variable from the webpage.
My activity in android:
private WebView webview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
webview = new WebView(this);
webview.getSettings().setJavaScriptEnabled(true);
try {
webview.setWebViewClient(new WebViewClient());
webview.loadUrl("file:///android_asset/index.html");
}
catch(Exception ex)
{
ex.printStackTrace();
}
setContentView(webview);
}
My exit button is a div:
<div class="exit" onclick="finish()">Exit</div>
I am going to use the finish() function to return the variable and close the webpage back to the activity in android.
function finish() {}
To notify the host application that a page has finished loading. Then Call onPageFinished()
webview.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// do your stuff here
}
});
SOURCE
you can do one thing..On click on the exit call any url like http://../getmark?marks=2 and once url load in the webview finish/ exit from webview. In the activity
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
// parse the url here to get marks
}
});
Register a javascriptinterface to your webview in onCreate:
this.webview.addJavascriptInterface(new MyJSInterface(this), "Android");
Implement setCount method in your Activity:
public void setCount (int count) {
//do what ever you want with count
}
Make a new JavascriptInterface-Class:
public class MyJSInterface {
private YourActivity yourActivity = null;
public MyJSInterface (YourActivity yourActivity) {
this.yourActivity = yourActivity;
}
#JavascriptInterface
public void invoke (int count) {
this.yourActivity.setCount(count);
}
}
And in javascript:
function finish(marks) {
if (Android !== undefined) {
if (Android.invoke !== undefined) {
Android.invoke(marks);
}
}
}
I have a problem with Javascript in WebView. Currently I have a ViewPager, which adds View dynamically when needed. Before add a view to viewpager, I inflate it and load an embedded webview inside:
LayoutInflater inflater = this.getLayoutInflater();
FrameLayout v = (FrameLayout) inflater.inflate(R.layout.notebook_page, null);
setupWebView(v);
pagerAdapter.addView(v);
pagerAdapter.notifyDataSetChanged();
In the webview, first I load a local html, and then inject a JS fuction to set several input on HTML.
private void setupWebView(View v) {
myWebView = (WebView) v.findViewById(R.id.webview);
myWebView.getSettings().setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/web_resources/index.html");
myWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
super.onPageFinished(myWebView, url);
Log.d("WebView Content", "Injecting JS");
myWebView.loadUrl("javascript:function('" + input_var + "')");
}
});
}
Funtion setupWebView is called correctly for every view inflated, however, the JS function does not work properly
The same piece of code works perfectly in an Activity, if there is only 1 page. Just in ViewPager, where there are more than 1 pages to display the webviews, JS only loads in the last page.
Do you have any suggestion?
Firstly, on 5.0 Android you should use different method to use javascript. I use this snippet of code.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
webView.evaluateJavascript("javascript:window.HTMLOUT.processHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');", new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.e("LoginActivity onReceiveValue", s);
}
});
} else
webView.postUrl("javascript:window.HTMLOUT.processHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');", null);
Also, you should include #JavascriptInterface tag on your javascript method.
#SuppressWarnings("unused")
#JavascriptInterface
public void processHTML(final String html) {
//method called from javascript
}
I have to create we application in android.
So what i done is that,simply created raw folder under res and put html files there.
All works fine but when i click a button that is put inside that web page nothing happens and the click event not get work.
Here are my codes.
newfile.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form>
<input type="button" value="Click me" onclick="openDialog()">
<script>
function openDialog()
{
alert("ok");
}
</script>
</form>
</body>
</html>
and this is my java code,
webview.loadData(readTextFromResource(R.raw.newfile),"text/html", "utf-8");
readTextFromResource function
private String readTextFromResource(int resourceID)
{
InputStream raw = getResources().openRawResource(resourceID);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
int i;
try
{
i = raw.read();
while (i != -1)
{
stream.write(i);
i = raw.read();
}
raw.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return stream.toString();
}
Please some one point me why the click event not working !
I am doing this type of things using phonegap. If you want to call native functions, use java script enabled web view. I am extends DroidGap in my MainActivity and my Login.html file under assets folder
in your Main Activity.java,
WebView webView=new WebView(this);
webview.loadUrl("file:///android_asset/www/Phone/Login.html");
setContentView(webView);
Anyway, if problem not solved, try adding this (all codes in onCreate method)
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setSaveFormData(true);
webView.getSettings().setAllowContentAccess(true);
webView.getSettings().setAllowFileAccess(true);
webView.getSettings().setAllowFileAccessFromFileURLs(true);
webView.getSettings().setAllowUniversalAccessFromFileURLs(true);
webView.getSettings().setSupportZoom(true);
webView.setWebViewClient(new WebViewClient());
webView.setClickable(true);
webView.setWebChromeClient(new WebChromeClient());
If you want more about how to access Android native code through webpage here is the link
When a WebView doesn't respond to a button, you can test a web page inside a mobile browser or a desktop browser with minimum width (adaptive layout). You will see how the button works when you click it. Then you can press F12 and see what queries are sent in "Network" tab.
(If you press Ctrl+Shift+C, you will see a layout of the page, then can click an element (the button that you look for) and see a code.)
If the button shows a picture dialog (take a photo, upload a picture), you should use onShowFileChooser ([1]).
val startActivityForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult ->
//
}
#SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
with(webview) {
settings.javaScriptEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.domStorageEnabled = true
// webViewClient = MyWebViewClient()
webChromeClient = MyWebChromeClient()
}
}
private class MyWebChromeClient : WebChromeClient() {
override fun onShowFileChooser(
webView: WebView?,
filePathCallback: ValueCallback<Array<Uri>>?,
fileChooserParams: FileChooserParams?
): Boolean {
// Check permissions, create intent.
startActivityForResult.launch(chooserIntent)
return true
}
}
In case you have a JavaScript button, you can attach JavaScript interface ([1], [2], [3]):
#SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
with(webview) {
settings.javaScriptEnabled = true
settings.javaScriptCanOpenWindowsAutomatically = true
settings.domStorageEnabled = true
// WebView.setWebContentsDebuggingEnabled(BuildConfig.TEST)
addJavascriptInterface(
JsHandle(this#WebViewFragment),
"Android"
)
}
}
class JsHandle(private var fragment: WebViewFragment) {
#JavascriptInterface
fun notify(notify: String) {
//
}
}
Your web page should have javascript: inside.
In my Android web app I am trying to use javascript (from a remote HTML file) to control the visibility of an Android WebView.
I have attempted to use the addJavascriptInterface class with no success. (see http://developer.android.com/guide/webapps/webview.html)
Essentially I would like my javascript to be the following
<script>
function this() {
Android.hideView('myWebViewID');
}
window.onload = this;
</script>
Seems like it would be easy, yet all my attempts cause my app to crash during debugging.
My latest attempt was something along these lines:
public class JavaScriptInterface {
Context mContext;
JavaScriptInterface(Context c) {
mContext = c;
}
public void hideView(View v) {
WebView webview_x = (WebView) v;
webview_x.setVisibility(View.GONE);
}
}
The problem is that you are casting the string "myWebViewID" in a WebView object.
I guess this is impossible.
To do what you want, you have to implement something like a switch that convert the string you use in JS to an ID (int) that identifies your WebView:
public class JavaScriptInterface {
private Activity mContext;
JavaScriptInterface(Activity c) {
mContext = c;
}
public void hideView(String v) {
int id = stringToId(v);
WebView webview_x = (WebView) mContext.findViewById(id);
webview_x.setVisibility(View.GONE);
}
private Integer stringToId(String str) {
if(str.equals("stringForId1") {
return R.id.webView1;
} else if(str.equals("stringForId2") {
return R.id.webView2;
} else if(...) {
....
} else {
return null;
}
}
}
This is the solution:
WebView:
mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebChromeClient(new CustomWebChromeClient());
mWebView.addJavascriptInterface(new CustomJavaScriptInterface(),
"android");
mWebView.loadUrl("file:///android_asset/www/test.html");
CustomeJavascriptInterface:
final class CustomJavaScriptInterface {
public void hide() {
mHandler.post(new Runnable() {
public void run() {
mWebView.setVisibility(View.INVISIBLE);
}
});
}
}
HTML:
<div onclick="window.android.hide()">Click!</div>
You should be fine with this!
Note that you cannot access the webview and change its visibility without a handler!
Hope this helps!