My Android app objective is to scan a bar/QR code and pass it to the HTML file loaded at webView element.
The app has ONE layout only, that contain a button and the webview element. Once the button is clicked, the app open the bar/QR scanner and return the result to the activity, and I need to pass this result to my HTML file for further processing.
The MainActivity is working correctly, as in this tutorial, and return the result here:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
String scanContent = scanningResult.getContents();
String scanFormat = scanningResult.getFormatName();
formatTxt.setText("FORMAT: " + scanFormat);
contentTxt.setText("CONTENT: " + scanContent);
/*** I NEED to SEND the 'scanContent' to the my HTML file loaded at the WebView element ***/
}
else{
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
I read this and this and this and this and thisand got the below below files:
JavaScriptInterface.java
public class JavaScriptInterface {
Context mContext;
/** Instantiate the interface and set the context */
JavaScriptInterface(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();
}
}
and the WebViewActivity.java:
public class WebViewActivity extends Activity {
// private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView webView = (WebView)findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
/*** I think something wrong in this area **/
webView.loadUrl("file:///android_asset/myFile.html");
webView.setWebViewClient(new WebViewClient(){
public void onPageFinished(WebView view, String url){
view.loadUrl("javascript:init('" + url + "')");
}
});
//webView.loadUrl("http://www.google.com");
// String customHtml = "<html><body>" +
// ""+
// "</body></html>";
// webView.loadData(customHtml, "text/html", "UTF-8");
}
}
No errors appeared in the Android Studio IDE, and when running the app the button for scanning work, but nothing appear in the webview, only white page!! white page always, from the start up of the up, and after scanning the code!
Any idea where I got lost, and how to fix it!
Note I need to send the data to the JavaScript used in the HTML file loaded at webView in the same activity, not just sending URL to be loaded.
After reading this and this and this, I found my case can be summarized in the below point:
So, the solution can be summarized in the below:
JavaScriptInterface
class that can interact with JavaScript commands@JavascriptInterface
annotation before each function required to interact with the JavaScriptmodule
in the JavaScript file as: myWebView.addJavascriptInterface(new JavaScriptInterface(this), "module");
in this statement, the module
is the name module to be called in the javaScript file as module.function()
getter
and setter
to communicate between Android classes.My MainActivity.java
file became like this:
package com.fonix.qr;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements OnClickListener {
private Button scanBtn;
private TextView formatTxt, contentTxt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
scanBtn = (Button) findViewById(R.id.scan_button);
formatTxt = (TextView) findViewById(R.id.scan_format);
contentTxt = (TextView) findViewById(R.id.scan_content);
scanBtn.setOnClickListener(this);
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());
myWebView.addJavascriptInterface(new JavaScriptInterface(this), "fonix");
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("file:///android_asset/index.html");
}
public void onClick(View v) {
if (v.getId() == R.id.scan_button) {
scanCode();
// IntentIntegrator scanIntegrator = new IntentIntegrator(this);
// scanIntegrator.initiateScan();
}
}
public void scanCode(){
IntentIntegrator scanIntegrator = new IntentIntegrator(this);
scanIntegrator.initiateScan();
}
public String scanContent;
public String scanFormat;
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
scanContent = scanningResult.getContents();
scanFormat = scanningResult.getFormatName();
formatTxt.setText("FORMAT: " + scanFormat);
contentTxt.setText("CONTENT: " + scanContent);
} else {
Toast toast = Toast.makeText(getApplicationContext(),
"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
public String getContent(){ return scanContent; }
public class JavaScriptInterface {
Context mContext;
/* Instantiate the interface and set the context */
JavaScriptInterface(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 scanJS() {
scanCode();
}
@JavascriptInterface
public String scanResult() {
return getContent();
}
}
}
and the assets -> index.html
file is:
<!DOCTYPE html>
<html>
<head>
<title>QR and BarCode Scanner using both Android Native and JavaScript Functionality</title>
</head>
<body>
Hello Android! <br/>
<br/>
The above button in Native Android, while the below one is JavaScript button. <br/>
<br/>
<input type="button" value="Scan from JavaScript button" onClick="scan()" />
<br/>
<br/>
<br/>
Below button will show the latest scan result, regardless read through Native Android button, or JavaScript button, and will display the result as Native Android Toast.
<br/>
<br/>
<input type="button" value="Show Scan result" onClick="showScanResult()" />
</body>
<script type="text/javascript">
function scan() {
fonix.scanJS();
}
function showScanResult() {
var scanResult = fonix.scanResult();
// (!scanResult) equal === null or === undefined
if(!scanResult)fonix.showToast("Nothing had been scanned");
else fonix.showToast(fonix.scanResult());
}
</script>
</html>
The layout -> activity_main.xml
file is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.fonix.qr.MainActivity">
<Button android:id="@+id/scan_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/scan"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/scan_format"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:layout_below="@id/scan_button"
android:layout_alignEnd="@+id/scan_button" />
<TextView
android:id="@+id/scan_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="true"
android:layout_below="@+id/scan_format"
android:layout_alignEnd="@+id/webview" />
<WebView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/webview"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_below="@+id/scan_content" />
</RelativeLayout>
The values -> strings.xml
file is:
<resources>
<string name="app_name">QR and BarCode reader</string>
<string name="scan">Scan from Native Android button</string>
</resources>
The AndroidManifest.xml
file is:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fonix.qr">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
The Final App app structure is:
and when reading .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With