title: Implementing Java/Android's callback/listeners in Delphi
body: <p>I'm trying to create an Android app in Delphi 10.2 Tokyo that makes use of <a href="https://developer.android.com/reference/android/hardware/camera2/package-summary.html" rel="nofollow noreferrer">Camera2</a> API. I used Java2OP to create the interfaces that I need. Some of these interfaces are for callback/listeners. For example <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.StateCallback.html" rel="nofollow noreferrer">CameraDevice.StateCallback</a> which Java2OP has translated to this:</p>
  
  <pre><code>JCameraDevice_StateCallbackClass = interface(JObjectClass)
      ['{3F5A7394-FD15-439C-9BFB-DF8D43F9F930}']
      {class} function _GetERROR_CAMERA_DEVICE: Integer; cdecl;
      {class} function _GetERROR_CAMERA_DISABLED: Integer; cdecl;
      {class} function _GetERROR_CAMERA_IN_USE: Integer; cdecl;
      {class} function _GetERROR_CAMERA_SERVICE: Integer; cdecl;
      {class} function _GetERROR_MAX_CAMERAS_IN_USE: Integer; cdecl;
      {class} function init: JCameraDevice_StateCallback; cdecl;
      {class} property ERROR_CAMERA_DEVICE: Integer read _GetERROR_CAMERA_DEVICE;
      {class} property ERROR_CAMERA_DISABLED: Integer read _GetERROR_CAMERA_DISABLED;
      {class} property ERROR_CAMERA_IN_USE: Integer read _GetERROR_CAMERA_IN_USE;
      {class} property ERROR_CAMERA_SERVICE: Integer read _GetERROR_CAMERA_SERVICE;
      {class} property ERROR_MAX_CAMERAS_IN_USE: Integer read _GetERROR_MAX_CAMERAS_IN_USE;
    end;
  
    [JavaSignature('android/hardware/camera2/CameraDevice$StateCallback')]
    JCameraDevice_StateCallback = interface(JObject)
      ['{3A3944F5-A71F-4CD6-98C6-04B8D65C3B52}']
      procedure onClosed(camera: JCameraDevice); cdecl;//Deprecated
      procedure onDisconnected(camera: JCameraDevice); cdecl;//Deprecated
      procedure onError(camera: JCameraDevice; error: Integer); cdecl;//Deprecated
      procedure onOpened(camera: JCameraDevice); cdecl;//Deprecated
    end;
    TJCameraDevice_StateCallback = class(TJavaGenericImport&lt;JCameraDevice_StateCallbackClass, JCameraDevice_StateCallback&gt;) end;
  </code></pre>
  
  <p>It is my understanding that I should combine <code>TJavaLocal</code> with the interface that I want to use as callback/listener (in this case <code>JCameraDevice_StateCallbackClass</code>). Here is what I have done:
  unit CamDevStateCallback;</p>
  
  <pre><code>interface
  
  uses
    Androidapi.JNIBridge, android.hardware.camera2;
  
  type
    TCamera2Event = procedure(camera: JCameraDevice) of object;
    TCamera2ErrorEvent = procedure(camera: JCameraDevice; error: Integer) of object;
  
    TCamDevStateCallback = class(TJavaLocal, JCameraDevice_StateCallback)
  
    protected
      FOnClosed: TCamera2Event;
      FOnDisconnected: TCamera2Event;
      FOnError: TCamera2ErrorEvent;
      FOnOpen: TCamera2Event;
  
    public
      procedure onClosed(camera: JCameraDevice); cdecl;
      procedure onDisconnected(camera: JCameraDevice); cdecl;
      procedure onError(camera: JCameraDevice; error: Integer); cdecl;
      procedure onOpened(camera: JCameraDevice); cdecl;
      class function CreateNew(aOnOpen, aOnClosed, aOnDisconnected: TCamera2Event; aOnError: TCamera2ErrorEvent): JCameraDevice_StateCallback;
      property OnCameraClosed: TCamera2Event read FOnClosed write FOnClosed;
      property OnCameraDisconnected: TCamera2Event read FOnDisconnected write FOnDisconnected;
      property OnCameraError: TCamera2ErrorEvent read FOnError write FOnError;
      property OnCameraOpen: TCamera2Event read FOnOpen write FOnOpen;
    end;
  
  implementation
  
  { TCamDevStateCallback }
  
  class function TCamDevStateCallback.CreateNew(aOnOpen, aOnClosed, aOnDisconnected: TCamera2Event;
    aOnError: TCamera2ErrorEvent): JCameraDevice_StateCallback;
  var
    tmpObj: TCamDevStateCallback;
  begin
    tmpObj := TCamDevStateCallback.Create;
    tmpObj.OnCameraClosed := aOnClosed;
    tmpObj.OnCameraDisconnected := aOnDisconnected;
    tmpObj.OnCameraError := aOnError;
    tmpObj.OnCameraOpen := aOnOpen;
    Result := TJCameraDevice_StateCallback.Wrap((tmpObj as ILocalObject).GetObjectID);
  end;
  
  procedure TCamDevStateCallback.onClosed(camera: JCameraDevice);
  begin
    if Assigned(FOnClosed) then
      FOnClosed(camera);
  end;
  
  procedure TCamDevStateCallback.onDisconnected(camera: JCameraDevice);
  begin
    if Assigned(FOnDisconnected) then
      FOnDisconnected(camera);
  end;
  
  procedure TCamDevStateCallback.onError(camera: JCameraDevice; error: Integer);
  begin
    if Assigned(FOnError) then
      FOnError(camera, error);
  end;
  
  procedure TCamDevStateCallback.onOpened(camera: JCameraDevice);
  begin
    if Assigned(FOnOpen) then
      FOnOpen(camera);
  end;
  
  end.
  </code></pre>
  
  <p>This code does not compile because it complains the <code>equals</code>, <code>toString</code> differ from previous declaration and <code>getClass</code>, <code>notify</code>, <code>notifyAll</code> and <code>wait</code> are missing.</p>
  
  <p><strong><em>android.hardware.camera2.pas</em></strong> is created by Java2OP and contains the interface definition of <code>JCameraDevice_StateCallback</code> and more.</p>