Delphi 10.3 Android Intent BroadcastReceiver

I have a ZEBRA TC20, I have configured DataWedge according to this Guide:

https://techdocs.zebra.com/datawedge/6-6/guide/api/tutorials/

The only difference I made is Intent Action: com.xlr.ACTION

In Delphi, I have the following Unit to process this (found the example from Embarcadero):

unit uScanner;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Messaging, FMX.Platform,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, Androidapi.JNI.GraphicsContentViewText,
  FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts, FMX.WebBrowser, FMX.Objects, FMX.ScrollBox, FMX.Memo;



type
  TScanner = class(TForm)
    Memo1: TMemo;
    Label1: TLabel;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    function HandleAppEvent(AAppEvent: TApplicationEvent; Acontext: TObject) : Boolean;
    procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);
    function HandleIntentAction(const Data: JIntent): Boolean;
  public
    { Public declarations }
  end;

var
  Scanner: TScanner;

implementation

{$R *.fmx}

uses FMX.Platform.Android, Androidapi.JNI.JavaTypes, Androidapi.JNI.Net, Androidapi.JNI.Os, Androidapi.Helpers;

procedure TScanner.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree;
end;

procedure TScanner.FormCreate(Sender: TObject);
var
  AppEventService : IFMXApplicationEventService;
begin
  if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, AppEventService) then
    AppEventService.SetApplicationEventHandler(HandleAppEvent);

  MainActivity.registerIntentAction(StringToJString('com.xlr.ACTION'));

  TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage);
end;

procedure TScanner.HandleActivityMessage(const Sender: TObject; const M: TMessageBase);
begin
  if M is TMessageReceivedNotification then
    HandleIntentAction(TMessageReceivedNotification(M).Value);
end;

function TScanner.HandleAppEvent(AAppEvent: TApplicationEvent; Acontext: TObject): Boolean;
var
  StartupIntent: JIntent;
begin
  Result := False;
  if AAppEvent = TApplicationEvent.BecameActive then
  begin
    StartupIntent := MainActivity.getIntent;
    if StartupIntent <> nil then
      HandleIntentACtion(StartupIntent);
  end;
end;

function TScanner.HandleIntentAction(const Data: JIntent): Boolean;
var
  Extras: JBundle;
begin
  Result := False;
  if Data <> nil then
  begin
    Extras := Data.getExtras;
    if Extras <> nil then
      Label1.Text:=JStringToString(Extras.GetString(StringToJString('com.symbol.datawedge.data_string')));
  end;
end;

end.

I have also altered AndroidManifest.template.xml, it looks like this:

<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="%package%"
        android:versionCode="%versionCode%"
        android:versionName="%versionName%"
        android:installLocation="%installLocation%">

    <uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
    <%uses-permission%>
    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
    <application android:persistent="%persistent%" 
        android:restoreAnyVersion="%restoreAnyVersion%" 
        android:label="%label%" 
        android:debuggable="%debuggable%" 
        android:largeHeap="%largeHeap%"
        android:icon="%icon%"
        android:theme="%theme%"
        android:hardwareAccelerated="%hardwareAccelerated%"
        android:resizeableActivity="false">

        <%provider%>
        <%application-meta-data%>
        <%uses-libraries%>
        <%services%>
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="%activityLabel%"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="%libNameValue%" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
            <intent-filter>  
                <action android:name="com.xlr.ACTION" />
                <category android:name="" />
            </intent-filter> 
        </activity>
        <%activity%>
        <%receivers%>
    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->

I have launched the app in Debug mode, and set a breakpoint at HandleActivityMessage, but nothing happens.

Can someone please help me out a bit here?

1 answer

  • answered 2020-02-13 16:22 nolaspeaker

    The <action android:name="com.xlr.ACTION" /> needs an intent filter like this

    </intent-filter>
    <meta-data android:name="android.hardware.usb.action.com.xlr.ACTION" android:resource="@xml/strings.xml" />
    

    Strings.xml from the vendor, needs to be deployed with your project to res\xml. Be sure to edit the com.dwexample.ACTION to com.xlr.ACTION before deployment.

    type
      TUSBReceiver = class(TJavaLocal, JFMXBroadCastReceiverListener)
      public
        constructor Create;
        procedure onReceive(context: JContext; intent: JIntent); cdecl;
      end;
    
    private
         FUSBReceiver: TUSBReceiver;
         FReceiver1: JFMXBroadcastreceiver;
    
    procedure TfrmMain.InitListeners;
    begin
      FUSBReceiver := TUSBReceiver.Create;
      FReceiver1 := TJFMXBroadcastReceiver.JavaClass.init(FUSBListener);
      Filter := TJIntentFilter.JavaClass.init(TJUsbManager.JavaClass.com.xlr.ACTION);
        TAndroidHelper.context.getApplicationContext.registerReceiver(FReceiver1, Filter);
      end
    
    procedure TfrmMain.DeInitListeners;
    begin
      TAndroidHelper.Context.getApplicationContext.unregisterReceiver(FBroadcastReceiver1);
    end;
    
    constructor TUSBReceiver.Create;
    begin
      inherited;
    end;
    
    procedure TUSBReceiver.onReceive(context: JContext; intent: JIntent);
    var
      Action: String;
      i: Integer;
    begin
      Action := JStringToString(intent.getAction);
      if Action = 'android.hardware.usb.action.com.xlr.ACTION' then
      begin
        // do something with the intent
      end;
    end;