Android JNI bridge Toast C++ not working - How to fix it?

偶尔善良 提交于 2019-12-06 15:33:16

The .hpp file is malformed.

None of the public types defined in the interface section of the .pas file are defined in the .hpp file. In particular, the TToastLength enum is missing. And Toast() is declared as a procedure in the .pas file and thus has no return value, but it has an (erroneous) return value in the .hpp file.

Did you (or someone else) create the .hpp file manually? I suspect this is the case, for two noticable reasons:

  1. the Android_JNI_ToastHPP define in the initial #ifndef/#define does not match the Fmx_Helpers_AndroidHPP in the corresponding #endif.

  2. the Delphi compiler always names C++ namespaces for Pascal unit names by uppercasing the first letter and lowercasing the remaining letters, but this .hpp file has an all-uppercase JNI namespace.

The Delphi compiler would not makes those mistakes.

With that said, Android.JNI.Toast.pas should be renamed to Androidapi.JNI.Toast.pas (and the .hpp file renamed and its namespaces updated accordingly) for consistency with Embarcadero's other JNI units (and to match the example in this article). That should also help alleviate the reference to 'Android' is ambiguous errors as well.

I strongly suggest you correct the .pas file, run it through the Delphi compiler once to produce the correct .hpp file, and then use it as-is in your C++ code.

Androidapi.JNI.Toast.pas:

unit Androidapi.JNI.Toast;

interface

{$IFDEF ANDROID}

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText;

type
  TToastLength = (LongToast, ShortToast);

  JToast = interface;

  JToastClass = interface(JObjectClass)
    ['{69E2D233-B9D3-4F3E-B882-474C8E1D50E9}']
    { Property methods }
    function _GetLENGTH_LONG: Integer; cdecl;
    function _GetLENGTH_SHORT: Integer; cdecl;
    { Methods }
    function init(context: JContext): JToast; cdecl; overload;
    function makeText(context: JContext; text: JCharSequence; duration: Integer)
      : JToast; cdecl;
    { Properties }
    property LENGTH_LONG: Integer read _GetLENGTH_LONG;
    property LENGTH_SHORT: Integer read _GetLENGTH_SHORT;
  end;

  [JavaSignature('android/widget/Toast')]
  JToast = interface(JObject)
    ['{FD81CC32-BFBC-4838-8893-9DD01DE47B00}']
    { Methods }
    procedure cancel; cdecl;
    function getDuration: Integer; cdecl;
    function getGravity: Integer; cdecl;
    function getHorizontalMargin: Single; cdecl;
    function getVerticalMargin: Single; cdecl;
    function getView: JView; cdecl;
    function getXOffset: Integer; cdecl;
    function getYOffset: Integer; cdecl;
    procedure setDuration(value: Integer); cdecl;
    procedure setGravity(gravity, xOffset, yOffset: Integer); cdecl;
    procedure setMargin(horizontalMargin, verticalMargin: Single); cdecl;
    procedure setText(s: JCharSequence); cdecl;
    procedure setView(view: JView); cdecl;
    procedure show; cdecl;
  end;

  TJToast = class(TJavaGenericImport<JToastClass, JToast>)
  end;

procedure Toast(const Msg: string; duration: TToastLength = ShortToast);

{$ENDIF}

implementation

{$IFDEF ANDROID}

uses
  FMX.Helpers.Android, Androidapi.Helpers;

procedure Toast(const Msg: string; duration: TToastLength);
var
  ToastLength: Integer;
begin
  if duration = ShortToast then
    ToastLength := TJToast.JavaClass.LENGTH_SHORT
  else
    ToastLength := TJToast.JavaClass.LENGTH_LONG;
  CallInUiThread(
    procedure
    begin
      TJToast.JavaClass.makeText(SharedActivityContext, StrToJCharSequence(Msg),
        ToastLength).show
    end);
end;
{$ENDIF}

end.

Androidapi.JNI.Toast.hpp:

// CodeGear C++Builder
// Copyright (c) 1995, 2014 by Embarcadero Technologies, Inc.
// All rights reserved

// (DO NOT EDIT: machine generated header) 'Androidapi.JNI.Toast.pas' rev: 28.00 (Android)

#ifndef Androidapi_Jni_ToastHPP
#define Androidapi_Jni_ToastHPP

#pragma delphiheader begin
#pragma option push
#pragma option -w-      // All warnings off
#pragma option -Vx      // Zero-length empty class member 
#pragma pack(push,8)
#include <System.hpp>   // Pascal unit
#include <SysInit.hpp>  // Pascal unit
#include <Androidapi.JNIBridge.hpp> // Pascal unit
#include <Androidapi.JNI.JavaTypes.hpp> // Pascal unit
#include <Androidapi.JNI.GraphicsContentViewText.hpp>   // Pascal unit
#include <System.Rtti.hpp>  // Pascal unit

//-- user supplied -----------------------------------------------------------

namespace Androidapi
{
namespace Jni
{
namespace Toast
{
//-- type declarations -------------------------------------------------------
enum DECLSPEC_DENUM TToastLength : unsigned char { LongToast, ShortToast };

__interface JToastClass;
typedef System::DelphiInterface<JToastClass> _di_JToastClass;
__interface JToast;
typedef System::DelphiInterface<JToast> _di_JToast;
__interface  INTERFACE_UUID("{69E2D233-B9D3-4F3E-B882-474C8E1D50E9}") JToastClass  : public Androidapi::Jni::Javatypes::JObjectClass 
{

public:
    virtual int __cdecl _GetLENGTH_LONG(void) = 0 ;
    virtual int __cdecl _GetLENGTH_SHORT(void) = 0 ;
    HIDESBASE virtual _di_JToast __cdecl init(Androidapi::Jni::Graphicscontentviewtext::_di_JContext context) = 0 /* overload */;
    virtual _di_JToast __cdecl makeText(Androidapi::Jni::Graphicscontentviewtext::_di_JContext context, Androidapi::Jni::Javatypes::_di_JCharSequence text, int duration) = 0 ;
    __property int LENGTH_LONG = {read=_GetLENGTH_LONG};
    __property int LENGTH_SHORT = {read=_GetLENGTH_SHORT};
};

__interface  INTERFACE_UUID("{FD81CC32-BFBC-4838-8893-9DD01DE47B00}") JToast  : public Androidapi::Jni::Javatypes::JObject 
{

public:
    virtual void __cdecl cancel(void) = 0 ;
    virtual int __cdecl getDuration(void) = 0 ;
    virtual int __cdecl getGravity(void) = 0 ;
    virtual float __cdecl getHorizontalMargin(void) = 0 ;
    virtual float __cdecl getVerticalMargin(void) = 0 ;
    virtual Androidapi::Jni::Graphicscontentviewtext::_di_JView __cdecl getView(void) = 0 ;
    virtual int __cdecl getXOffset(void) = 0 ;
    virtual int __cdecl getYOffset(void) = 0 ;
    virtual void __cdecl setDuration(int value) = 0 ;
    virtual void __cdecl setGravity(int gravity, int xOffset, int yOffset) = 0 ;
    virtual void __cdecl setMargin(float horizontalMargin, float verticalMargin) = 0 ;
    virtual void __cdecl setText(Androidapi::Jni::Javatypes::_di_JCharSequence s) = 0 ;
    virtual void __cdecl setView(Androidapi::Jni::Graphicscontentviewtext::_di_JView view) = 0 ;
    virtual void __cdecl show(void) = 0 ;
};

class DELPHICLASS TJToast;
#pragma pack(push,4)
class PASCALIMPLEMENTATION TJToast : public Androidapi::Jnibridge::TJavaGenericImport__2<_di_JToastClass,_di_JToast> 
{
    typedef Androidapi::Jnibridge::TJavaGenericImport__2<_di_JToastClass,_di_JToast>  inherited;

public:
    /* TJavaImport.Create */ inline __fastcall TJToast(void * ID, void * ClsID, Androidapi::Jnibridge::TJavaVTable* VTable) : Androidapi::Jnibridge::TJavaGenericImport__2<_di_JToastClass,_di_JToast> (ID, ClsID, VTable) { }
    /* TJavaImport.Destroy */ inline __fastcall virtual ~TJToast(void) { }

};

#pragma pack(pop)

//-- var, const, procedure ---------------------------------------------------
extern DELPHI_PACKAGE void __fastcall Toast(const System::UnicodeString Msg, TToastLength duration = (TToastLength)(0x1));
}   /* namespace Toast */
}   /* namespace Jni */
}   /* namespace Androidapi */
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROIDAPI_JNI_TOAST)
using namespace Androidapi::Jni::Toast;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROIDAPI_JNI)
using namespace Androidapi::Jni;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROIDAPI)
using namespace Androidapi;
#endif
#pragma pack(pop)
#pragma option pop

#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif  // Androidapi_Jni_ToastHPP
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!