Have a little program with a WebView loading e.g. "www.google.com". I have tried to start searching automatic without ENTER by user, after scanning a barcode, like this:
final String scanedCode = "123456";
runOnUiThread(new Runnable() {
#Override
public void run() {
dispatchKeyEvent(new KeyEvent(100, scanedCode, 1, 0));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
}
);
The number "123456" will displayed in google search field, but the ENTER, or rather the automatic search is not started.
Have tried many ways and searched here, but I still cannot get these simple thing. Could someone give me some tips?
A more robust approach will be to inject your own javascript code directly into the WebView. This injection does not care which URL is loaded inside, so you can do it to any site.
It sounds like a big security hole but this really isn't. The browser is inside your app which means you are the browser therefore you can do anything you want while parsing the HTML code of the websites you're showing.
Here is a code example which loads some JS into a google hosted page:
final WebView webview = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
webview.getSettings().setJavaScriptEnabled(true);
/* WebViewClient must be set BEFORE calling loadUrl! */
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url)
{
webview.loadUrl("javascript:(function() { " +
"document.getElementsByTagName('body')[0].style.color = 'red'; " +
"})()");
}
});
webview.loadUrl("http://code.google.com/android");
If you can run your own JS you can pretty much do anything you want - including traversing the DOM directly, accessing the search-box itself and making sure it has focus.
In order to figure out which JS code you want to inject, use Google Chrome on your PC and open google.com inside Chrome Developer Tools. Then try to type JS commands in the console until you get the required result. Typing JS lines in the console = injecting JS code into the page.
Related
What I'm trying to achieve is basically something like android web view's shouldOverrideUrlLoading. I'm loading a specific URL into the web view which in turn have a series of redirects. The goal is to intercept the last URL and handle it by the application instead of the WebView component. It seems that something similar is available for the ios platform (onShouldStartLoadWithRequest) but didn't get to the android yet (https://github.com/facebook/react-native/pull/6478).
The workaround I've tried is to use onNavigationStateChange, parsing the URL and stopping the web view loading if needed:
onNavigationStateChange = (navState) => {
const url = new URL(navState.url);
const lastSegment = url.pathname.substr(url.pathname.lastIndexOf('/') + 1);
// Handle the get token ourselvs
if (lastSegment === GETTOKEN) {
this.refs[WEBVIEW_REF].stopLoading();
this.getToken()
}
this.setState({
url: navState.url,
backButtonEnabled: navState.canGoBack
});
}
The problem is that the stopLoading function is not really working in my case. I see that while executing the async function getToken() the browser continues the loading of the last URL.
Any suggestion would be appreciated.
Although issues with shouldOverrideUrlLoading() are well discussed in SO (I probably read most of them), I still didn't find a solution to what seems to me such a generic problem, that I believe has been solved.
The QUESTION: How to stop in shouldOverrideUrlLoading() for external links, e.g. "http://www.example.com", for pages I loaded with webView.loadDataWithBaseURL(), where baseUrl is "file:///..."?
My override method for shouldOverrideUrlLoading() is not called when external links are touched (clicked).
Here it says " URLs that can't be resolved against the base URL are dropped on the floor (you won't get any callbacks for them, neither shouldOverrideUrlLoading nor onPageStarted)."
Android developer site says here that "If you loaded the page by calling ... loadDataWithBaseURL(), then you will receive the shouldOverrideUrlLoading() callback for this type of link on the page."
This is my code:
public void loadEpub(final EpubInfo epubInfo)
{
post(new Runnable()
{
#Override
public void run()
{
epubBaseUrl = "file://" + epubInfo.path;
if (!epubBaseUrl.endsWith("/"))
epubBaseUrl += "/";
String path = epubBaseUrl + epubInfo.baseUrl;
String page = generatePage(epubInfo);
EpubWebView.super.loadDataWithBaseURL(path, page, "text/html", "UTF-8", null);
}
});
}
where my baseUrl (path) is "file:///storage/sdcard0/Android/data/...".
Many thanks in advance.
Pinpointed the problem, and found a solution.
If your page runs in an iframe, clicking on external (http://www...) links does NOT trigger shouldOverrideUrlLoading()! Unless you add target="_top"
So there are at least 2 possible solutions:
1) if you can, run without an iframe
2) if you add to each href, target="_top", shouldOverrideUrlLoading() WILL BE triggered.
I went for solution 2). The following JavaScript code adds the target attribute to each link.
function change_links_target()
{
var all_document_links = mFrameDocument.getElementsByTagName("a");
for (i = 0; i < all_document_links.length; i++){
all_document_links[i].setAttribute("target", "_top");
}
}
I need help regarding SSL trust. I am loading a payment gateway page in WebView. It is a POST request and I am passing a payload.
This is happening successfully till now.(Shown below)
mWebView = (Android.Webkit.WebView)Control;
string payload = "myPayload";
byte[] valTest = Encoding.UTF8.GetBytes(payload.ToCharArray(0, payload.Length));
mWebView.Settings.JavaScriptEnabled = true;
mWebView.Settings.DomStorageEnabled=true;
mWebView.SetWebViewClient(new MyWebViewClient(this));
mWebView.SetWebChromeClient(new ChromeClient());
mWebView.PostUrl("https://mypage", valTest);
After filling up the form and submit I am getting a callback in the OnReceivedSslError method of the WebViewClient class. Here I ask it to proceed (as per various forums). Once this is done I am not getting any success callback. I need to be able to read javascript values once I get a response from the webview. I do not know how this is to be achieved.
Shown below is the OnSSLErrorReceived Callback method.
public override void OnReceivedSslError(Android.Webkit.WebView view, SslErrorHandler handler, Android.Net.Http.SslError error)
{
base.OnReceivedSslError(view, handler, error);
handler.Proceed();
}
}
Expectations-
1. On submitting the form it should be trusted(it is a self-signed certificate).
2. Once this above step is done we are expecting a response from the webpage. We need to read javascript values from the page. How can I achieve this?
I do not see any SuccessCallback or ResponseCallback.
I use the below to read the JS values.But this is not working.
view.EvaluateJavascript("document.getElementById('test').value", new MyCallbackClass());
The above issue has been resolved. Calling handler.Proceed in OnSSLError method was fine but the issue was with calling the base inside this callback. Once I removed base.OnSSLError my code worked fine.
After the page finishes I am able to read JS values in the OnPageFinished callback method.
Also the evaluate JS function is also working and I get callbacks.
Is there a way to create a serious HTML/CSS/JS project with multiple HTML, CSS, JS files on JSfiddle.net ?
If yes, how to do it ?
I want to create a basic mobile apps based on HTML/CSS/JS, about a dozen of HTML/CSS/JS files. I would like to develop it all on JSfiddle, my favorite Online JavaScript IDE. But JSfiddle.net while a clean way to test projects stays limited to:
1 html file (personal)
1 CSS file (personal)
1 JS file (personal)
several external resources (CSS, JS libs, data) which request you another webhosting.
The official doc suggesting Github hosting for 1HTML/1JS/1CSS/someDataFiles is not satisfying. I wish all on JSFiddle, and more files in my project.
You can do it inside a jsFiddle but there are few limitations, and you are probably not going to be satisfied with it.
You can test only 1 HTML multiple pages template. But in case of jQuery Mobile framework this will be enough, as you can place numerous jQM pages inside a 1 html file.
For example, this is my jsFiddle template when helping to this group: http://jsfiddle.net/Gajotres/yWTG2/
You cant use normal form submitting. Instead you should use ajax to sumbit form data.
In my other answer you can find solutions for ajax form submitting and how to send parameters during the page transition: jQuery Mobile: Sending data from one page to the another
In case you want to communicate with an remote host:
var ajax = {
sendRequest:function(save_data){
$.ajax({url: 'http://localhost/JSONP_Tutorial/json.php',
data: save_data,
async: true,
beforeSend: function() {
// This callback function will trigger before data is sent
$.mobile.showPageLoadingMsg(true); // This will show ajax spinner
},
complete: function() {
// This callback function will trigger on data sent/received complete
$.mobile.hidePageLoadingMsg(); // This will hide ajax spinner
},
success: function (result) {
if(result == "true") {
$.mobile.changePage( "#index", { transition: "slide"} ); // In case result is true change page to Index
} else {
alert('Login unsuccessful, please try again!'); // In case result is false throw an error
}
// This callback function will trigger on successful action
},
error: function (request,error) {
// This callback function will trigger on unsuccessful action
alert('Network error has occurred please try again!');
}
});
}
}
jsFiddle has a stupid policy where they want to prevent usage of full HTML files. They are trying to enforce this with stupid error warnings in HTML content part. You will need to have something like firebug plugin for Firefox or Chrome to remove this stupidity. Or you can even do it with Grease Monkey plugin.
In case you want to use full HTML template like in this example: http://jsfiddle.net/Gajotres/yWTG2/ you will need to use your javascript code in onDomready state.
Some functionalities are not going to work. Like window.orientationchange event.
I have been researching all morning about integrating an android barcode scanner app into a web page, but haven't found exactly what I need to know. I want to have a web page that the user can fill in text fields by using an android barcode scanner. So the user would be on a web page and would either click inside the text field or click a button next to the text field that would start the android barcode scanner. They would then scan the barcode and the text field would be filled in.
I have found solutions on how to do this and then go to a different page, but it is important that the user stays on the same page. I have seen the zxing project and thought that might be able to be used, but I'm not sure if it allows for the page to stay the same.
I'm pretty sure this is possible and is wondering if any one could give me a high level overview on how they would do it. I was thinking it might be able to be done with an ajax request that gets submitted on a button click. The ajax request would get sent to my server, the server would send something to the android device that would start the scanner and return the data which in turn gets sent back in the ajax response. Is there any way to cut out the server though and just have the android browser starting the barcode scanner? Thank you for your time and I appreciate any discussion on it.
ZXing (zebra crossing) provides the capability to initiate the bar code scanner via a webpage through a button click event, anchor tag, or other action that could call a URL on a mobile device.
When the barcode scanner application is installed on an android device, a URL call to:
zxing://scan/?ret=http://foo.com/products/{CODE}/description&SCAN_FORMATS=UPC_A,EAN_13
Will bring up the device bar code reader, the user scans the code, and the code is returned via the callback URL parameter supplied in the zxing URL.
You can view an example (works on android) here: http://zxing.appspot.com/scan
You can try this for Android:
You can use Zxing library for barcode scan for webpages
<!DOCTYPE html>
<script type="text/javascript">
//This entire block of script should be in a separate file, and included in each doc in which you want scanner capabilities
function zxinglistener(e){
localStorage["zxingbarcode"] = "";
if(e.url.split("\#")[0] == window.location.href){
window.focus();
processBarcode(decodeURIComponent(e.newValue));
}
window.removeEventListener("storage", zxinglistener, false);
}
if(window.location.hash != ""){
localStorage["zxingbarcode"] = window.location.hash.substr(1);
self.close();
window.location.href="about:blank";//In case self.close is disabled
}else{
window.addEventListener("hashchange", function(e){
window.removeEventListener("storage", zxinglistener, false);
var hash = window.location.hash.substr(1);
if (hash != "") {
window.location.hash = "";
processBarcode(decodeURIComponent(hash));
}
}, false);
}
function getScan(){
var href = window.location.href.split("\#")[0];
window.addEventListener("storage", zxinglistener, false);
zxingWindow = window.open("zxing://scan/?ret=" + encodeURIComponent(href + "#{CODE}"),'_self');
}
</script>
<html>
<head>
<script type="text/javascript">
function processBarcode(b){
var d = document.createElement("div");
d.innerHTML = b;
document.body.appendChild(d);
}
</script>
</head>
<body>
<button onclick="getScan()">get Scan</button>
</body>
</html>
For reference: Read link
Using a javascript interface and loadurl(javascript...) you can communicate with your webpage from Android
public void loadScript(String script){
webview.loadUrl("javascript:(function() { " + script + "})()");
}
private class JavaScriptInterface {
public void startQRScan() {
...
}
}
There are plenty of examples on google.