In the previous blog post I discussed the underlying standards of the BCBP (Bar Coded Boarding Pass) following IATA Reso 792. Today I will built an Android mobile app that scans the PDF417 barcode and shows the raw content as well the decoded fields.
The are 3 main challenges for building the app, scanning/reading the barcode and decoding the text to individual attributes and as last, not to use any internet connection (to assure the user the users privacy and avoid any potential identity theft discussions)
As we build a native Android app we can rely on third party libraries to scan and decode barcodes. There is a number of commercial libraries in the market, but as I build a free app I will use the zxing-android-embedded library, which is a port of the ZXing (“Zebra Crossing”) barcode scanning library for Android with added embedding features, ZXing only provides the decoding logic. Both are licensed under Apache 2.0, ZXing can decode all the common types, such as EAN-8, EAN-13, UPC, ITF, PDF417, QRCode, Aztec, Data Matrix and a few more.
Integration Barcode Library ZXing
With the library the integration becomes as simple as adding a few lines of code only.
Add the dependency to the build gradle file
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12' compile 'com.journeyapps:zxing-android-embedded:3.5.0' }
Trigger the scan and read the result
public void scanCode(View view){ new IntentIntegrator(this).initiateScan(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); if(result != null) { if(result.getContents() == null) { System.out.println("Scan failed or cancelled."); } else { System.out.println(result.getContents()); } } else { super.onActivityResult(requestCode, resultCode, data); } }
For now, the app (“ReadMyBoP – Read My Boarding Pass”) does nothing but scan the barcode, identify if it is a valid boarding pass barcode, display the raw content and makes the content more human-readable. You can download from Google Playstore. It works with Android 4.1 and above.
There is one extra feature for now, it decodes the IATA fare codes (First, business, economy classes and the various discounted codes, it follows IATA Reso 728 if you want to look for the complete codeset.
Decoding the Raw Text
Given the fact, this is a fixed-length field text, it is no big deal to split the relevant info by substring’ing it using the decoding table that we started in the previous post. As basic validation we can use the mandatory “M” on position 1 and a length of not less than 59 characters (mandatory fields).
# | Element | Mandatory | Size | Sample | Remark |
---|---|---|---|---|---|
1 | Format Code | M | 1 | M | Always “M” |
2 | Number of legs encoded | M | 1 | ||
3 | Passenger Name | M | 20 | ||
4 | Electronic Ticket Indicator | M | 2 | E | |
5 | Operating carrier PNR Code | M | 7 | ||
6 | Origin IATA Code | M | 3 | FRA | Airport Code |
7 | Destination IATA Code | M | 3 | SIN | Airport Code |
8 | Operating carrier IATA Code | M | 3 | LH | Airline |
9 | Flight Number | M | 5 | 3456 | |
10 | Date of Flight | M | 3 | 280 | Julian Date |
11 | Compartment Code | M | 1 | B | First, Business, Economy |
12 | Seat Number | M | 4 | 25A | |
13 | Check-in Sequence Number | M | 5 | 0012 | |
14 | Passenger Status | M | 1 | 00 | |
15 | Size of optional Block | M | 2 | 5D | hexadecimal |
16 | Start Version Number | 1 | > | Always “>” | |
17 | Version Number | 1 | 5 | ||
18 | Field Size of follow ing structured message | 2 | |||
19 | Passenger Description | 1 | |||
20 | Source of check-in | 1 | |||
21 | Source of Boarding Pass Issuance | 1 | |||
22 | Date of Issue of Boarding Pass (Julian Date) | 4 | |||
23 | Document Type | 1 | |||
24 | Airline Designator of boarding pass issuer | 3 | |||
25 | Baggage Tag Licence Plate Number 1 | 13 | |||
26 | Baggage Tag Licence Plate Number 2 | 13 | |||
27 | Baggage Tag Licence Plate Number 3 | 13 | |||
28 | Field Size of follow ing structured message | 2 | |||
29 | Airline Numeric Code | 3 | |||
30 | Document Form/Serial Number | 10 |
Is there a roadmap ? For sure, if I find the time I will add the optional fields, an airline and airport code dictionary (must check the size of a local sqllite db if we want to stay offline). Maybe add baggage tag reader feature and local barcode image storage for boarding. Stay tuned !
Application Disclaimer: The application is for educational and research purpose. It is provided as-is, no warranty included. It does not transmit data over the internet and does not store any data upon exiting the app.