The Inelegant Way to Scan Barcodes on Android with Delphi XE5

Embarcadero's shiny new Delphi XE5 Mobile Module seems to be lacking something rather important to those of us wishing to scan barcodes on Android. Although it is fairly simple to use intents to start up other Android activities, with their required parameters, there seems to be no way to register a callback function to receive results. This is my, rather inelegant, workaround whilst waiting for that deficiency to be fixed. I have currently only tried using the free, open source, ZXing library available on Google Play. See the ZXing Google Code page here  for more info the library and licensing. I'm assuming a similar state of ignorance to the one I was in starting out with XE5, also a form containing a button, an editcontrol and a timer. The following needs to be present in the main form
Uses FMX.platform,, androidapi.JNI.GraphicsContentViewText, androidapi.jni.JavaTypes;
the first module is required for clipboard access, the others for the JNI (Java Native Interface) in the forms private declarations
ClipService: IFMXClipboardService; Elapsed: integer;
in the FormCreate event
if not TPlatformServices.Current.SupportsPlatformService(IFMXClipboardService, IInterface(ClipService)) then     ClipService := nil; Elapsed := 0;
gives the app access to the clipboard The button's onclick event
procedure Tform1.Button1click(sender: Tobject); var   intent: jintent; begin   if assigned(ClipService) then   begin     clipservice.SetClipboard('nil');     intent := tjintent.Create;     intent.setAction(stringtojstring(''));     intent.putExtra(tjintent.JavaClass.EXTRA_TEXT,       stringtojstring('"SCAN_MODE", "CODE_39"'));     sharedactivity.startActivityForResult(intent,0); Elapsed := 0;     timer1.Enabled := true;   end; end;
the intent.putExtra is optional, if used it narrows the range of codes that ZXing looks for. The clipboard value can be set to anything you like, it’s only there to check for the clipboard changing. The variable Elapsed is there to provide a timeout in case the user cancels the scan. I have my timer set to 500ms intervals which seems okay in practice. The timer event looks like this
procedure TForm1.Timer1Timer(Sender: TObject); begin if (ClipService.GetClipboard.ToString <> 'nil') then begin timer1.Enabled := false; Elapsed := 0;     edit1.Text := ClipService.GetClipboard.ToString;   end else begin if Elapsed >9 then begin timer1.Enabled := false; Elapsed := 0; end else Elapsed := Elapsed +1; end; end;
That’s it!