Tuesday, 13 August 2013

Barcode Scanning in Android Apps

Barcode scanning is one of the most potentially useful resources you will come across on the Android platform. The ZXing (Zebra Crossing) project is bar far the easiest and most effective way to implement barcode scanning for most development purposes. Since the project is open source, you can either use the code within it to implement your own custom scanning functions or can access the library classes via Intent, leaving the details up to the ZXing classes.

ZXing can scan numerous barcode formats in use on a variety of products, including EAN/ ISBN, UPC, QR codes, Data Matrix, Aztec and more. The resource is implemented in Java, with Android-specific classes available for quick use in your own projects.

Usage

For a detailed introduction to using barcode scanning in Android apps, see this tutorial I wrote for Mobiletuts+: Create a Barcode Reader and this series on creating a book scanner app for more of a real-world example: Create a Book Scanning App. For a comprehensive reference, see the ZXing docs: Scanning Via Intent.

The simplest way to include scanning functions in your apps is by Intent. You simply copy the Intent Integrator and Intent Result classes into your app and call on them in your own classes.

To use the ZXing integration classes in your app, import them to the Activity class you want to access them in, for example the following if you use the default package names:
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
You can then launch the scanner in your Activity class as follows:
IntentIntegrator zxingIntegrator = new IntentIntegrator(this);
zxingIntegrator.initiateScan();
If the user does not have the ZXing barcode scanner installed on their device, they will be prompted to download it from Google Play at this point, so you don't have to carry out any checking of your own. When you initiate a scan, you can optionally pass a parameter indicating the types of barcode you want to scan - the parameter should be a Collection of Strings.

You can then retrieve the results of the user's scanning operation inside the onActivityResult method for your class:
IntentResult scannedResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
The Intent Result object will now provide access to the content and format of the returned scan data if there is any:
scannedResult.getContents();
scannedResult.getFormatName();
Options

While using the integration classes is by far the simplest way to utilise the ZXing functionality, there may be times when you need to implement your own bespoke scanning functions. If so, you can download the source code. It's probably only advisable to do this if you have no other option, since using the integration classes gives your app access to the continual updates within the ZXing app without you having to update your own code.

Applications

There are lots of potential applications of barcode scanning in Android, from inventory and warehouse functions to shopping apps. Your apps need to respond to the data within a barcode in a relevant way, so your code must examine the scan results before attempting to use them in further processing, for example opening a URL in the browser.

As usual, Stack Overflow has the answers to lots of common questions and problems with ZXing.

Thursday, 8 August 2013

Using the SeekBar Control in Android Apps

In this tutorial we will work through the process of using the SeekBar control in an Android app. The SeekBar control allows users to select a numerical amount using a slider control. Using the SeekBar is straightforward, you can add one to an XML layout file and retrieve the user input in your Java Activity classes.

To demonstrate the process of using the SeekBar, we will add one to a Dialog control launched on clicking a user interface item. Here is the end result:

Add the SeekBar to an XML layout in your app as follows:
<SeekBar
android:id="@+id/level_seek"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
To include this in a basic layout you could use the following, saved as "level_layout.xml" for use with the below Java code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView android:id="@+id/level_txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="5dp"
android:textStyle="bold"
android:text="100%"/>
<SeekBar android:id="@+id/level_seek"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
<Button android:id="@+id/level_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"/>
</LinearLayout>
The user selection can be retrieved when they click the button and the TextView can update as they move the slider control, to reflect the current amount selected, which in this tutorial will be a percentage value.

Now in an Android Activity class, you can set the initial value and retrieve the chosen user value. To use it in a Dialog, which is a typical usage of the slider control in many application UIs, add the following to a click listener onClick block in an Activity class for a button or other control you want the SeekBar to appear for:
final Dialog levelDialog = new Dialog(this);
levelDialog.setTitle("Select level:");
levelDialog.setContentView(R.layout.level_layout);
Retrieve references to the TextView and SeekBar items in the layout defined above:
final TextView levelTxt = (TextView)levelDialog.findViewById(R.id.level_txt);
final SeekBar levelSeek = (SeekBar)levelDialog.findViewById(R.id.level_seek);
Set the maximum value for the SeekBar:
levelSeek.setMax(100);
levelSeek.setProgress(100);
We are using 100 as the maximum since the SeekBar is going to set a percentage. Next set up a listener for changes on the SeekBar control:
levelSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//change to progress
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
levelTxt.setText(Integer.toString(progress)+"%");
}
//methods to implement but not necessary to amend
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
You can of course implement the start and stop tracking methods to tailor user interaction with the SeekBar in your app. All we do here is update the TextView with the current level as the user slides the control up or down. Next retrieve a reference to the "OK" button we added to the layout:
Button okBtn = (Button)levelDialog.findViewById(R.id.level_ok);
Set up a click listener for the button:
okBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//respond to level
int chosenLevel = levelSeek.getProgress();
levelDialog.dismiss();
}
});
In this onClick method you can add whatever code you need to respond to the user's chosen level using the retrieved integer value. The method also dismisses the Dialog. Finally, still inside the onClick method, show the Dialog:
levelDialog.show();
Your app should now have the ability to let users set levels using this intuitive control, which almost all smartphone users are well accustomed to.

Further Resources:
Android Developers: SeekBar Class
TechRepublic: Android's SeekBar your way