{"id":1580,"date":"2010-12-30T22:51:36","date_gmt":"2010-12-30T22:51:36","guid":{"rendered":"http:\/\/dalelane.co.uk\/blog\/?p=1580"},"modified":"2010-12-30T23:02:06","modified_gmt":"2010-12-30T23:02:06","slug":"programmatically-identifying-dvds-by-their-barcodes-from-android","status":"publish","type":"post","link":"https:\/\/dalelane.co.uk\/blog\/?p=1580","title":{"rendered":"Programmatically identifying DVDs by their barcodes from Android"},"content":{"rendered":"<p><strong>Overview<\/strong><\/p>\n<p>A few Android code snipperts for how to identify a DVD by it&#8217;s barcode <\/p>\n<p><a href=\"http:\/\/www.flickr.com\/photos\/dalelane\/5307965172\/\" title=\"Untitled by dalelane, on Flickr\"><img loading=\"lazy\" decoding=\"async\" style=\"border: thin black solid\" align=\"right\" hspace=10 vspace=10 src=\"http:\/\/farm6.static.flickr.com\/5249\/5307965172_baf614675d_m.jpg\" width=\"144\" height=\"240\" alt=\"\" \/><\/a><strong>Background<\/strong><\/p>\n<p>In November, I wrote a simple Android app that lets me <a href=\"http:\/\/dalelane.co.uk\/blog\/?p=1530\">add films to my LOVEFiLM list by taking a photo of a movie poster<\/a>. <\/p>\n<p>It also works by taking a photo of the front of a DVD case, as the DVD covers are essentially mini-posters. But a few people pointed out that using image recognition for the front of a DVD case is overkill, when DVD cases have a machine-readable barcode printed on them.<\/p>\n<p>So I spent an evening adding the ability to scan barcodes to the app &#8211; and now you can add to your LOVEFiLM list either by photos of posters or barcodes.<\/p>\n<p>I thought I&#8217;d quickly share how I did it, in case it&#8217;s useful to anyone else.<\/p>\n<p><!--more--><strong>Scanning a barcode<\/strong><\/p>\n<p>No need to re-invent the wheel here. Although the ability to scan a barcode doesn&#8217;t come built-in to Android, there is a widely-used common library available: <a href=\"http:\/\/code.google.com\/p\/zxing\/\" target=\"_blank\">ZXing<\/a><\/p>\n<p>If a user has installed their stand-alone barcode scanning app from the Android Market, they will have this library on their phone. (The app can be launched by an &#8220;Intent&#8221; &#8211; programmatically from another app.)<\/p>\n<p>The first thing to do is to check whether the user has installed Barcode Scanner.<\/p>\n<p>I do this by trying to call it, and catching the ActivityNotFoundException that will be thrown if they don&#8217;t.<\/p>\n<p>If it&#8217;s not installed, I can launch the Android Market to the right place so that the user can install it. (It is free.)<\/p>\n<p>If it is installed, then that code launches the barcode scanner. The mode tells the scanner what type of code to look for &#8211; e.g. QR codes vs barcodes. I want the sorts of 1D codes you get on products like DVDs.<\/p>\n<pre style=\"border: thin solid silver; background-color: #eeeeee; padding: 0.7em; font-size: 1.1em; overflow: auto;\">Intent intent = new Intent(\"com.google.zxing.client.android.SCAN\");\r\nintent.putExtra(\"SCAN_MODE\", \"PRODUCT_MODE\");\r\n\r\ntry\r\n{\r\n  startActivityForResult(intent, 0);\r\n}\r\ncatch (ActivityNotFoundException exc)\r\n{\r\n  AlertDialog.Builder instDlg = new AlertDialog.Builder(this);\r\n  instDlg.setTitle(\"Install barcode scanner?\");\r\n  instDlg.setMessage(\"Sorry - to do this, I need you install a barcode scanner. Is that okay?\");\r\n  instDlg.setPositiveButton(\"Yes\", new DialogInterface.OnClickListener() {\r\n                              public void onClick(DialogInterface dlgInt, int i) {\r\n                                Uri uri = Uri.parse(\"market:\/\/search?q=pname:com.google.zxing.client.android\");\r\n                                Intent intent = new Intent(Intent.ACTION_VIEW, uri);\r\n                                startActivity(intent);\r\n                              }\r\n                            });\r\n  instDlg.setNegativeButton(\"No\", new DialogInterface.OnClickListener() {\r\n                              public void onClick(DialogInterface dlgInt, int i) {}\r\n                            });\r\n  instDlg.show();\r\n}<\/pre>\n<p>Once the user has sucessfully scanned a barcode, onActivityResult is called with the barcode number.<\/p>\n<pre style=\"border: thin solid silver; background-color: #eeeeee; padding: 0.7em; font-size: 1.1em; overflow: auto;\">@Override\r\nprotected void onActivityResult(int requestCode, int resultCode, Intent intent)  \r\n{\r\n  if (requestCode == 0)\r\n  {\r\n    if (resultCode == RESULT_OK)\r\n    {\r\n      String barcodeContents = intent.getStringExtra(\"SCAN_RESULT\");\r\n    }\r\n  }\r\n}<\/pre>\n<p><strong>Identifying the barcode<\/strong><\/p>\n<p>I&#8217;m using <a href=\"http:\/\/base.google.com\/\" target=\"_blank\">Google Base<\/a> as a source of info about barcodes.  <\/p>\n<p>(Annoyingly, the <a href=\"http:\/\/developer.lovefilm.com\/\" target=\"_blank\">LOVEFiLM API<\/a> doesn&#8217;t have support for barcode numbers, so I need to go from barcode to DVD title, which I can use with the LOVEFiLM API to add stuff to my rental queue.)<\/p>\n<p>Google Base have a decent set of DVDs info in their database, and a straightforward API with no need for user authentication or API keys.<\/p>\n<p>You can find a demo page to play with the Google Base Data API at <a href=\"http:\/\/www.google.com\/base\/api\/demo\/html\/demo.html\" target=\"_blank\">google.com\/base\/api\/demo\/html\/demo.html<\/a> and a more detailed reference at <a href=\"http:\/\/code.google.com\/apis\/base\/docs\/2.0\/reference.html\" target=\"_blank\">code.google.com\/apis\/base\/docs\/2.0\/reference.html<\/a>.<\/p>\n<p>For a barcode number of 8717418242275, I&#8217;m using something like this:<br \/>\n<a href=\"http:\/\/www.google.com\/base\/feeds\/snippets?bq=[ean%28text%29:%228717418242275%22]&#038;crowdby=title:1&#038;max-results=1&#038;content=none\">http:\/\/www.google.com\/base\/feeds\/snippets?bq=[ean(text):&#8221;8717418242275&#8243;]&#038;crowdby=title:1&#038;max-results=1&#038;content=none<\/a><\/p>\n<p>Click on the link to see what it returns, but basically it returns me an XML document (you can add <code>&alt=json<\/code> if you prefer JSON) with the details of the DVD. <\/p>\n<p>I&#8217;ve added arguments that reduce the amount of data returned to an absolute minimum &#8211; because I&#8217;m using it in a mobile app. Android comes with a decent XML parser, but even so &#8211; the less I have to download, and the less I have to parse, the quicker the app will be (as well as reducing the impact on the battery).<\/p>\n<p><a href=\"http:\/\/www.flickr.com\/photos\/dalelane\/5307965046\/\" title=\"Eye for LOVEFiLM - screenshot by dalelane, on Flickr\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/farm6.static.flickr.com\/5281\/5307965046_3b45e694f8_m.jpg\" align=left hspace=10 vspace=10 style=\"border: thin black solid\" width=\"144\" height=\"240\" alt=\"Eye for LOVEFiLM - screenshot\" \/><\/a><strong>That&#8217;s it<\/strong><\/p>\n<p>That&#8217;s all there is to it. <\/p>\n<p>I&#8217;m using this for DVDs, but the same approach will work for other products with barcodes. <\/p>\n<p>An updated version of my LOVEFiLM app with this barcode support is in the Market now.<br clear=\"all\"\/><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Overview A few Android code snipperts for how to identify a DVD by it&#8217;s barcode Background In November, I wrote a simple Android app that lets me add films to my LOVEFiLM list by taking a photo of a movie poster. It also works by taking a photo of the front of a DVD case, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[291,476],"class_list":["post-1580","post","type-post","status-publish","format-standard","hentry","category-code","tag-android","tag-barcode"],"_links":{"self":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1580"}],"version-history":[{"count":0,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1580\/revisions"}],"wp:attachment":[{"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dalelane.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}