There are very few large players when it comes to e-commerce and they all have invested heavily in native mobile applications. Having a native applications provides your users a more streamlined experience.
However most of the e-commerce websites have all the features they need and there is no real need of developing a native application. But mobile phones are getting more and more powerful and we should utilize this power. I am not recommending that everyone should start building a native application but if your website is responsive already then there is a quick way to wrap it into a native application.
Wrapping your existing site into an app (inside web views) is almost equivalent to opening it in a mobile browser but it gives you some control by which you can build application specific features for your site.
Let me give you an example, what if you can still use your website as-it-is but you can add feature like barcode scanning to it. In this post I am going to achieve following things :
- Wrap an existing responsive site into an android application.
- Launch barcode scanner within the app by clicking a link on the site
- Pass the scanned barcode back to the site
Click here to test barcode scanner if you are opening this post using app described below in the post and scanned barcode is =
no-barcode-scanned
.
If you have not read my previous posts on Android Barcode Scanner then please go and have a look. I am going to reuse the code in this post.
Step 1: Open the site in webview
Create a new application in Android studio with blank activity. Lets name the activity as MainActivity. Android studio will create a layout file in your layout folder with name activity_main.xml. Lets add a webview in our layout with id mainWebView and make sure it expands to full height and width. Following is the code.
<?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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="in.whomeninja.app.barcodescannerforwebsite.MainActivity">
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mainWebView"></WebView>
</RelativeLayout>
Now in our activity file (MainActivity.java) we will access this webview and open our site in it. We also want that our site should open in full view so we have to hide the action bar as well which comes along with our layout. So add the following line to onCreate function in MainActivity.
//hide actionbar on top of activity
ActionBar action_bar = getSupportActionBar();
action_bar.hide();
Now we will access out webview and load our URL in it. Before that we need to have permissions to access internet otherwise our URL will not load. So add the following line to your AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET"/>
WebView has default client which handle the basic operation of loading the URL. We want to override methods of this client to display errors on screen in “Toast” and check which URL is getting loaded. Lets update our code, access the webview in layout and enable javascript
main_web_view = (WebView) findViewById(R.id.mainWebView);
//enable javascript
main_web_view.getSettings().setJavaScriptEnabled(true);
Now set a new client for webview with two overridden methods, onReceivedError to interrupt the error and show it in a Toast and shouldOverrideUrlLoading which we will use to check which URL is loaded (will be used later in the post)
// get the activity context final
Activity activity = this;
//set client to handle errors and intercept link clicks
main_web_view.setWebViewClient(new WebViewClient(){
@Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
String msg = "error : "+description+" Request URL : "+failingUrl;
Toast.makeText(activity, msg, Toast.LENGTH_LONG).show();
}
@Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
// we will interrupt the link here
return super.shouldOverrideUrlLoading(view,request);
}
});
Now finally, we will load our URL. I have declared my URL as a public static final String MAIN_SITE_URL and used as an argument to loadUrl function.
//load the Site URL
main_web_view.loadUrl(MAIN_SITE_URL);
This will load the URL in your webview.
Step 2 : Open barcode scanner when a link is clicked
Now we need to add barcode scanner to our application, full details of how to do that is explained in my post Android Barcode Scanner please go through the post and add the code to your app.
I believe you have read my post Android Barcode Scanner and you have updated your build.gradle file to include the barcode library as a dependency and rebuild your project. Unlike my last post we will not call the scanNow function from layout, we will call this function from within the client of webview. Just to make sure that you have added the right code the scanNow function will look like
public void scanNow(){
IntentIntegrator integrator = new IntentIntegrator(this);
integrator.setDesiredBarcodeFormats(IntentIntegrator.ONE_D_CODE_TYPES);
integrator.setPrompt(String.valueOf("Scan Barcode"));
integrator.setResultDisplayDuration(0);
integrator.setWide(); // Wide scanning rectangle, may work better for 1D barcodes
integrator.setCameraId(0); // Use a specific camera of the device
integrator.initiateScan();
}
This function will start the barcode-scan and we need to receive the scanned barcode, by default the xing library looks for function with name “onActivityResult”. Lets add this function and receive the scanned barcode.
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
//retrieve scan result
IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanningResult != null) {
//we have a result
String codeContent = scanningResult.getContents();
String codeFormat = scanningResult.getFormatName();
//load the URL and Pass the scanned barcode
openUrl(POST_URL+"?barcode="+codeContent);
}else{
Toast toast = Toast.makeText(getApplicationContext(),"No scan data received!", Toast.LENGTH_SHORT);
toast.show();
}
}
Now we need to make few changes in our previous code, lets add a new function named “openUrl” and move our code related to open the URL in webview into it from “onCreate” function. This will help us in reusing the same function for opening different URLS when we need.
public void openUrl(String url){
main_web_view = (WebView) findViewById(R.id.mainWebView);
//enable javascript
main_web_view.getSettings().setJavaScriptEnabled(true);
// get the activity context
final Activity activity = this;
//set client to handle errors and intercept link clicks
main_web_view.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
String msg = "error : "+description+" Request URL : "+failingUrl;
Toast.makeText(activity, msg, Toast.LENGTH_LONG).show();
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// we will interrupt the link here
if(isURLMatching(url)) {
scanNow();
return true;
}
return super.shouldOverrideUrlLoading(view,url);
}
});
//load the URL
main_web_view.loadUrl(url);
}
onCreate function will now look like
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//hide actionbar on top of activity
ActionBar action_bar = getSupportActionBar();
action_bar.hide();
// load site URL
openUrl(MAIN_SITE_URL);
}
To start the barcode scan on click of a link we need to decide the link, I have added a link in the beginning of this post. The link is of this post but with added string “firebarcodescannerforwebsites=1”. You can decide whatever URL pattern you want to use and use it in the code. I have created a static final string “STRING_TO_MATCH_FOR_BARCODE_SCAN” to hold this value.
I have also created a function named “isURLMatching” to encapsulate the logic. You can update this function as per your needs.
protected boolean isURLMatching(String url){
return url.toLowerCase().contains(STRING_TO_MATCH_FOR_BARCODE_SCAN.toLowerCase());
}
Now we have to update shouldOverrideUrlLoading function of the webview defined within the openUrl function and add the condition to check for a match.
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// we will interrupt the link here
if(isURLMatching(url)) {
scanNow();
return true;
}
return super.shouldOverrideUrlLoading(view,url);
}
if the URL matches then we will call the scanNow() function which will initiate the scan. Once scan is done and result will be received in onActivityResult function. This function will add the scanned barcode at the end of URL of this post and reload the page.
I am reading parameter “barcode” in the URL of this post and display the value at the beginning right next to test link.
I hope this post gives you creative ideas on how you can turn your existing e-commerce website into an app and use the native barcode scanner.
Complete source code of this application can be found on my Github under add-android-barcode-scanner-to-website
12 Responses to “Add Android Barcode Scanner to your website”
April 29, 2017
cristianHi Rajinder, this post is wonderful as always!
I have ne question:
how can I use the string read by the scan function to fill a form inside the website opened in the webview?
Thanks a lot!
Cristian
May 1, 2017
Rajinder DeolHi Christian,
There are different ways by which you can use the scanned data in a webview. Easiest way is to pass the scanned code in the URL to webview and in your code load the page and read the vale from url.
Second way is to use javascript and fill the value in the form. There is a great example at stackoverflow : http://stackoverflow.com/questions/21402605/how-to-fill-fields-in-web-view-in-android-with-java-and-javascript
Let me know if you need more help.
March 15, 2018
danielHi Rajinder, this post is great!
I have a question:
Can you make tutorial about Second way is to use javascript and fill the value in the form with barcode scanner
Thanks a lot!
daniel
July 24, 2018
Emrehello qr code and webview work the same way over this one application ?
July 24, 2018
Rajinder DeolHi Emre,
this will work for QR-code as well
July 24, 2018
Eren Yıldırımthis post is wonderful as always! thank you 🙂
July 24, 2018
Rajinder DeolThanks for the appreciation
December 8, 2018
StevenHi, Rajinder,
Do I need to put a button in this webview in order for me to activate the scanner? Step 1 is ok, but Step 2
“Open barcode scanner when a link is clicked”, the link mean button as below?
Thanks and regards.
December 9, 2018
Rajinder DeolHi Steven,
you can use a button or redirect the user to a URL, the idea is to understand when to bring the scanner up. Inside webview it is easy to track the URL changes without adding complex logic. So we decide a URL and look it that URL is navigated in the website and open up the scanner.
I am working on writing another blog post to use pure javascript to launch scanner and put the code back on the same page inside an input box.
December 23, 2018
StevenHi, Rajinder,
Thank you for your prompt reply. The tracking URL works perfectly to trigger the scanning.
I have now modified the code to scan into portrait mode.
Zxing version, android studio version, sdk version all has changed since 2016. Anyway it is like mix and match thing going on our head.
Thank you for your help for setting the base. Looking forward for your pure javascript blog post.
February 10, 2021
Manu PriyamHi Rajinder,
I have a typical problem.
Your solution seems to be when we load a HTML page embedded inside project in webview.
But my android webview invokes a url which is remote url. and JS is on that URL.
Now, how do i make that website and webview interact with each other to scan the barcodes?
thanks
February 25, 2021
Rajinder DeolHi Manu,
if you are loading any URL you can pass the scanned code as a URL argument, which any JS on that URL can access. Example http://any-remote-url.com?code=1231245667378
On the remote URL side they can access it using URLSearchParams function of Javascript.
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const scannedCode = urlParams.get(‘code’);