Leggere un Barcode

Il mondo è pieno di codici a barra e secondo alcuni telefilm anche gli uomini ne avranno uno sul collo!!! Dobbiamo quindi predisporre al più presto le nostre applicazioni per recuperarli!
Per fortuna, c'è chi ha già pensato di fare un software per il riconoscimento e la codifica di questi, il nostro lavoro si riduce quindi a chiamare queste applicazioni ed attendere il risultato!
Una di queste applicazioni è Barcode Scanner, ed è anche quella che utilizzerò in questo tutorial.
Per richiamare una applicazione Android sappiamo benissimo che abbiamo bisogno di un Intent, in questo caso l'intent è il seguente:
Intent SCAN_INTENT = new Intent("com.google.zxing.client.android.SCAN"); Ci basterà far partire l'Activity legata all'Intent, ed attendere il risultato: startActivityForResult(SCAN_INTENT, 0); Come per tutti gli altri casi, il risultato di una chiamata effettuata tramite metodo startActivityForResult lo otteniamo nel metodo onActivityResult. Questo metodo ha in ingresso come parametri:

  • int requestCode
  • int resultCode
  • Intent data

Se tutto è andato a buon fine, avremo un resultCode uguale a Activity.RESULT_OK legato al requestCode passato come secondo parametro in startActivityForResult.
Il risultato dello scan lo otteniamo negli Extra dell'Intent data, in particolare esaminando la key SCAN_RESULT:
String scanResult = data.getStringExtra("SCAN_RESULT");

Il gioco è fatto!

Questo tutorial presenta una feature in più: come facciamo ad essere sicuri che il sistema su cui gira la nostra applicazione sia in grado di processare il nostro Intent? Semplicemente domandandoglielo!!!
Per fare questo utilizziamo la classe di sistema PackageManager, chiedendo al sistema "Dammi informazioni su come risolvi questo Intent":
ResolveInfo resolveInfo = packageManager.resolveActivity(SCAN_INTENT, PackageManager.GET_RESOLVED_FILTER); A questo punto, se resolveInfo è diverso da null, capiamo che nel sistema c'è qualcosa che sa risolvere il nostro Intent e possiamo procedere, altrimenti blocchiamo l'utente in qualche modo (il codice che ho postato, ad esempio, disabilita il pulsante dello scan e visualizza il link per scaricare l'applicazione).

Ultima feature aggiuntiva del tutorial: gestire il click di un pulsante da file xml.
Premetto che è una cosa che a me non piace molto (IMHO sporca un poco il codice), ma è giusto conoscerne l'esistenza!
Se nel file xml di un layout all'interno del tag Button inseriamo
android:onClick="onScan" al click del pulsante verrà richiamata la funzione
public void onScan(View view) in questo modo viene risparmiata la parte di codice in cui bisogna aggiungere un OnClickListener al Button (solitamente nel metodo onCreate).

Buon Barcoding a tutti!

Sorgenti

MyBarcodeScannerActivity

package com.marcoduff.mybarcodescanner; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MyBarcodeScannerActivity extends Activity { private static final Intent SCAN_INTENT = new Intent("com.google.zxing.client.android.SCAN"); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); PackageManager packageManager = this.getPackageManager(); ResolveInfo resolveInfo = packageManager.resolveActivity(SCAN_INTENT, PackageManager.GET_RESOLVED_FILTER); if(resolveInfo==null) { ((Button)this.findViewById(R.id.scanButton)).setEnabled(false); ((TextView)this.findViewById(R.id.scanResult)).setText("Non hai installato nessuna applicazione per effettuare lo scan!!!\nScaricala qui: http://www.appbrain.com/app/com.google.zxing.client.android"); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK && requestCode == 0) { String scanResult = data.getStringExtra("SCAN_RESULT"); ((TextView)this.findViewById(R.id.scanResult)).setText(String.format("Risultato dello scan: %1$s", scanResult)); } else { ((TextView)this.findViewById(R.id.scanResult)).setText("Operazione annullata!"); } } public void onScan(View view) { startActivityForResult(SCAN_INTENT, 0); } }

main.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/scanButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=">>> SCAN <<<" android:onClick="onScan"/> <TextView android:id="@+id/scanResult" android:layout_width="fill_parent" android:layout_height="wrap_content" android:autoLink="web"/> </LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.marcoduff.mybarcodescanner" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="MyBarcodeScannerActivity"> <activity android:name=".MyBarcodeScannerActivity" android:label="MyBarcodeScannerActivity" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-sdk android:minSdkVersion="7" /> </manifest>