I want to make webview which load javascript, but not working in API 15. I already test on API 21 and working. Anyone know to make it working? Thanks
public class MainActivity extends AppCompatActivity {
private WebView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (WebView) this.findViewById(R.id.webView);
view.getSettings().setJavaScriptEnabled(true);
view.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
view.setWebViewClient(new MyBrowser());
view.loadUrl("http://mywebsite.com");
}
private class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && view.canGoBack()) {
view.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Method shouldOverrideUrlLoading(WebView view, String url) must return true, only if you want to load url different from original, or not to load at all. In this case can return false and load url in usual way. If your page executes JS by loading 'javascript:' link, you can return false for all urls, started with javascript:. Note, that on SDK 24+, shouldOverrideUrlLoading(WebView view, WebResourceRequest request) called instead.
Related
I am trying to load a URL in to android native webview, but it does not render CSS and Angular
CODE:
WebView wvFAQs = (WebView) mFragmentView.findViewById(R.id.wvUrls);
Map<String, String> headersMap = new HashMap<>();
headersMap.put(ApiConstants.AUTHORIZATION, BuildConfig.SS_API_AUTH);
wvFAQs.setWebViewClient(new WebViewClient() {
#SuppressWarnings("deprecation")
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
#TargetApi(Build.VERSION_CODES.N)
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
return false;
}
});
wvFAQs.getSettings().setJavaScriptEnabled(true);
wvFAQs.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
wvFAQs.loadUrl(mUrl,headersMap);
ERRORS:
"Uncaught ReferenceError: _ is not defined",
"Uncaught ReferenceError: angular is not defined",
"Uncaught ReferenceError: $ is not defined",
but this URL works fine in mobile browsers (chrome & default android browser).
when i googled this issue, i came to know that i need to enable html5 support feature in webiew, here is the link, but still not working.
Can anyone tell me what might be the issue? is there any issue with the URL or webview?
I use this Java code to load the webview:
public class MainActivity extends AppCompatActivity {
private WebView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
view = (WebView) this.findViewById(R.id.webView);
view.getSettings().setJavaScriptEnabled(true);
view.setWebViewClient(new MyBrowser());
view.loadUrl("file:///android_asset/www/index.html"); //try js alert
view.setWebChromeClient(new WebChromeClient()); // adding js alert support
}
private class MyBrowser extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && view.canGoBack()) {
view.goBack(); //method goback()
return true;
}
return super.onKeyDown(keyCode, event);
}
What I can say is if that you use Jquery you need to add it to your assets because external links like from cdn like:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
would not load.
I need to read text on the button which is located on the website. I tried to parse the page using JSOUP, but JSOUP doesn't see Javascript object. That is why I decide to use WebView to read text. But it doesn't work. I need to return the button text from Javascript to Java. Is it possible?
public class MainActivity extends AppCompatActivity {
WebView mWebView;
Button mButton, mClick;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.web_view);
mButton = (Button) findViewById(R.id.start_URL);
mClick = (Button) findViewById(R.id.click);
}
#Override
protected void onResume() {
super.onResume();
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.setWebViewClient(new PersonalWebView());
mWebView.setWebChromeClient(new PersonalWebChrome());
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
mWebView.loadUrl(URL);
mClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.loadUrl("javascript: window.JSInterface.callFromJS('buttonText')");}
}
private class JavaScriptInterface {
#JavascriptInterface
public void callFromJS(String buttonText) {
Log.d("JScript","callFromJS "+ buttonText);
}
}
private class PersonalWebView extends WebViewClient{
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
#Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
}
}
private class PersonalWebChrome extends WebChromeClient {
private PersonalWebChrome() {
super();
}
#Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
}
#Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.d("TAG", consoleMessage.message()+" "+consoleMessage.sourceId());
return super.onConsoleMessage(consoleMessage);
}
}
I tried to change code, but it doesn't work:
mClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
ValueCallback<String> result = new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
Log.d("TAG", value);
}
};
mWebView.evaluateJavascript("javascript: window.JSInterface.callFromJS('buttonText')",result);}}
In the Log I see:
D/TAG: Uncaught TypeError: Cannot read property 'callFromJS' of undefined
This is not the correct way of dealing with injected Java objects:
mWebView.addJavascriptInterface(new JavaScriptInterface(), "javaCallback");
mWebView.loadUrl("javascript:window.javaCallback.callFromJS('buttonText')";
Injected objects only become "visible" on the next page load after calling addJavascriptInterface. Loading javascript: URIs doesn't count as a page load.
Check out the sample from the docs:
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
The loadData in between is what actually makes the object to be inserted. You can as well use loadUrl but it needs to be a real page (from the network, assets, about:blank, whatever), but not a javascript: URI.
The problem should be in trying to call callFromJS method before registering interface. You register the JS interface only on the button click:
mClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mWebView.addJavascriptInterface(new JSInterface(), "JSInterface");
}
}
But you try to call the callFromJS immediately.
Instead of doing this, move your mWebView.evaluateJavascript("javascript: window.JSInterface.callFromJS('buttonText')",result); inside onClick()
I have a WebView and I wanted to when someone click on a link it should open in a browser not in my app. How can I do that?
I want to show a webpage but when someone click on it it should open in a new browser that's all I want. How can i do that?
Here is the code that I am using
public class tab2 extends Fragment {
WebView webView ;
ProgressBar progressBar;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.tab2, container, false);
webView = (WebView) view.findViewById(R.id.webview1);
progressBar = (ProgressBar)view.findViewById(R.id.progressBar1);
webView.setWebViewClient(new myWebClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://facebook.com");
return view;
}
public class myWebClient extends WebViewClient
{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
progressBar.setVisibility(View.VISIBLE);
view.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
}
}
}
Instead of
view.loadUrl(url);
You could try to use:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);
I've looked at several similar posts on S/O but I can't find an answer to my problem. I'm trying to grab the html from a web view but I can't get my "onPageFinished() callback to fire. I've even tried using the progress callback on the WebChromeClient but nothing is working. neigh the web client or web chrome client receive any callbacks. I am running this code as an Android unit test and using a test HTML from the assets directory which I've confirmed via assert and debug is being located. What am I missing?
** Update **
I've stepped through the test method in debug. It does load the html (it's a unit test so I cannot actually see the rendered content). It then blocks on the wait() call, times out then performs the assert at the bottom without ever receiving a callback from either client. (Both the web client and chrome client should/would call notify())
The difference here would be that I am running within an Android unit test. The WebView is NOT attached to any Activity or container. I'm wondering if that has anything to do with the missing callbacks. I'll try sticking it on an Activity to see if it makes any difference.
** /Update **
public class MyWebViewTest extends InstrumentationTestCase {
private WebView webView;
private String html;
public void setUp() throws Exception {
super.setUp();
Context context = getInstrumentation().getContext();
this.webView = new WebView(context);
assertTrue("requires test.html",
Arrays.asList(context.getResources().getAssets().list("www")).contains("test.html"));
}
public void tearDown() throws Exception {
}
#JavascriptInterface
public void viewContent(String content) {
this.html = content;
}
public void testCanLoadAndReadWebContentFromWebView() throws Exception {
webView.addJavascriptInterface(this, "_webContainer");
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView webView, String url) {
super.onPageFinished(webView, url);
onPageLoaded(webView);
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
webView.setWebChromeClient(new WebChromeClient() {
#Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if(newProgress==100)
onPageLoaded(webView);
}
});
webView.loadUrl("file:///android_asset/www/test.html");
synchronized (this) {
wait(5000);
}
assertNotNull(html);
}
private void onPageLoaded(WebView webView) {
webView.loadUrl("javascript:window._webContainer.viewContent(document.documentElement.innerHTML);");
synchronized (this) {
notify();
}
}
}
I was correct in my assumption! When the WebView is not attached to an Activity it will not load, render, or do much of anything. I ended up extending ActivityInstrumentationTestCase2 and attaching the web view to an Activity. At that point my breakpoints in the callbacks started lighting up. Here's my working test case:
public class MyWebViewTest extends ActivityInstrumentationTestCase2<TestMeActivity> {
private WebView webView;
private String html;
public MyWebViewTest() {
super(TestMeActivity.class);
}
public void setUp() throws Exception {
super.setUp();
Context context = getInstrumentation().getContext();
this.webView = getActivity().getView();
assertTrue("requires test.html",
Arrays.asList(context.getResources().getAssets().list("www")).contains("test.html"));
}
public void tearDown() throws Exception {
}
#JavascriptInterface
public void viewContent(String content) {
this.html = content;
}
public void testCanLoadAndReadWebContentFromWebView() throws Exception {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
configureWebView();
}
});
synchronized (MyWebViewTest.this) {
MyWebViewTest.this.wait(25000);
}
assertEquals("<head></head><body>\n" +
"Hello\n" +
"\n" +
"</body>",html);
}
private void configureWebView() {
webView.addJavascriptInterface(this, "_webContainer");
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView webView, String url) {
super.onPageFinished(webView, url);
onPageLoaded(webView);
}
});
webView.loadUrl("file:///android_asset/www/test.html");
}
#TargetApi(Build.VERSION_CODES.KITKAT)
private void onPageLoaded(WebView webView) {
webView.evaluateJavascript("javascript:window._webContainer.viewContent(document.documentElement.innerHTML);",
new ValueCallback<String>() {
#Override
public void onReceiveValue(String value) {
synchronized (MyWebViewTest.this) {
MyWebViewTest.this.notify();
}
}
}
);
}
}
and here's the Activity I threw together to back it:
public class TestMeActivity extends Activity{
private WebView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
view = new WebView(this);
setContentView(view);
}
public WebView getView() {
return view;
}
}
In short there is quite a bit of work involved in testing the contents of a WebView from an Android TestCase. You have to add a Javascript interface to the web view, insert some Javascript to invoke the internal Javascript interface object, passing the contents of the web view, through the interface and finally collect it in your test case. I sure wish it were easier but this is the best I can come up with.
I have followed this very basic example tutorial for loading a URL in a WebView async:
android-asynctask-example.
However the app force closes when i click 'Load Webpage', with the error:
"Can't create handler inside thread that has not called
Looper.prepare()".
When I remove the line "webView.getSettings().setJavaScriptEnabled(true);", the app works fine, and displays a WebView (obviously with no JavaScript enabled in the WebView).
If i leave that line in, but set enabled to false, the app also works without crashing.
I wish to modify this project, however i need JavaScript enabled, so was wondering if anyone had a clue as to why it was failing?
Any help will be greatly appreciated!
Try it this way,
public class MainActivity extends Activity {
final Context context = this;
WebView webView =null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
private class LoadWebPageASYNC extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute(String result) {
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
}
#Override
protected String doInBackground(String... urls) {
webView.loadUrl(urls[0]);
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
public void dummyFunc(View view){
Toast.makeText(MainActivity.this, "Button Clicked", Toast.LENGTH_SHORT).show();
}
public void readWebpage(View view) {
LoadWebPageASYNC task = new LoadWebPageASYNC();
task.execute(new String[] { "http://www.javacodegeeks.com" });
}
}