Search code examples
androiddelphiinterfacenullpointerexceptiondelphi-xe6

Delphi XE6 - How to implement an Android interface and create a listener?


I tried to implement a thing similar to the one done in FMX.Advertising.Android.

type
  // Forward declaration
  JAttentiveListener = interface;   //com.pack.AttentiveListener
  //...
  JAttentiveListenerClass = interface(IJavaClass)
  ['{28A2CA13-A965-4EAB-A4F0-481E20C9AF2A}']
  end;

  [JavaSignature('com/pack/AttentiveListener')]
  JAttentiveListener = interface(IJavaInstance)
  ['{45D40262-E5C2-4650-B64A-4C5D56EA6107}']
    {Methods}
    procedure onClicked; cdecl;
    procedure onNotReceived(message1: JString); cdecl;
    procedure onReceived; cdecl;
  end;
  TJAttentiveListener = class(TJavaGenericImport<JAttentiveListenerClass, JAttentiveListener>) end;

  TMyListener = class(TJavaLocal, JAttentiveListener)     // JAttentiveListener is Android interface imported above using JNI
  private
    FObj: TCallbackObj;
  public
    constructor Create(Obj: TCallbackObj);
    destructor Destroy; override;
    procedure onClicked; cdecl;
    procedure onNotReceived(message1: JString); cdecl;
    procedure onReceived; cdecl;
  end;

{TMyListener}

constructor TMyListener.Create(Obj: TCallbackObj);
begin
  inherited Create;   // exception here.
  FObj := Obj;
end;

Constructor is called in UI thread and throws NullPointerException during the call to a parent's constructor. There are following messages in a log: [dvmFindClassByName rejecting, java.lang.NullPointerException

I've tried to debug step-by-step, and stepped into TJavaLocal's c-tor. Exception occurs in the following statement of this c-tor:

FLocalRefObjectID := AJNIEnv^.CallObjectMethodA(AJNIEnv, AJNIObject, CreateProxyClass, PJNIValue(ArgsToJNIValues([ClsID, Self])));
HandleJNIException(AJNIEnv);    // NullPointerException is here

Why does the same thing work in FMX.Advertising.Android and doesn't work in my code? (I'm trying to create a listener implementing an interface and doing everything like in AdsListener from FMX.Advertising.Android.)


Solution

  • Pay more attention to the log output. NullPointerException is preceded by 'dvmFindClassByName rejecting X', and it means that dalvik can't find the class of listener. Maybe it is absent in a classes.dex file, maybe you've specified the wrong signature in [JavaSignature('com/pack/AttentiveListener')].