Android JNI桥Toast C ++无法正常工作-如何解决? [英] Android JNI bridge Toast C++ not working - How to fix it?

查看:141
本文介绍了Android JNI桥Toast C ++无法正常工作-如何解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试解决我的hpp装置的一个小问题. 我在互联网上找到了一些示例,这些示例显示了如何使用Android JNI桥在屏幕上举起一个信息,但是它只是以帕斯卡(delphi)为单位,因此我决定使用相同的pas文件,但使用一个hpp文件进行转换. 直到现在我明白了:

I'm trying to solve a little problem with my hpp unit. I found some examples on the internet showing how to Toast an information on screen with an Android JNI bridge, but it was just in pascal (delphi), so I decided to use the same pas file but with it an hpp file for conversion. Till now I got it:

#ifndef Android_Jni_ToastHPP
#define Android_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 <FMX.Helpers.Android.hpp>                        // Pascal unit
#include <Androidapi.JNIBridge.hpp>                       // Pascal unit
#include <Androidapi.JNI.JavaTypes.hpp>                   // Pascal unit
#include <Androidapi.JNI.GraphicsContentViewText.hpp>     // Pascal unit
#include <Androidapi.JNI.Util.hpp>                        // Pascal unit
#include <Androidapi.JNI.App.hpp>                         // Pascal unit
#include <FMX.Surfaces.hpp>                               // Pascal unit

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

namespace Android
{
namespace Jni
{
namespace Toast
{
//-- type declarations -------------------------------------------------------

extern DELPHI_PACKAGE Androidapi::Jni::Toast __fastcall Toast(const System::UnicodeString Msg, TToastLength duration);

#pragma pack(pop)

//-- type declarations -------------------------------------------------------
//-- var, const, procedure ---------------------------------------------------

}   /* namespace Android */
}   /* namespace JNI     */
}   /* namespace Toast   */
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROID_JNI_TOAST)
using namespace Android::Jni::Toast;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROID_JNI)
using namespace Android::Jni;
#endif
#if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_ANDROID)
using namespace Android;
#endif
#pragma pack(pop)
#pragma option pop

#pragma delphiheader end.
//-- end unit ----------------------------------------------------------------
#endif  // Androidapi_Jni_ToastHPP

如果您想拥有Pascal单位,就在这里:

If you would like to have the pascal unit, here is it:

unit Android.JNI.Toast;

interface

{$IFDEF ANDROID}

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText;
{$ENDIF}
{$IFDEF ANDROID}

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.

但是使用此源进行编译时出现错误... 我该怎么办?

However I get error when compilling using this source... What con I do?

PS:我到达该状态时只是将AppMetthod的来源与我所做的进行了比较...

PS.: I arrived on that state just comparing AppMetthod sources with what I was making...

日志:

Checking project dependencies...
Compiling WebBrowser.cbproj (Debug, Android)
bccaarm command line for "uMain.cpp"
  c:\program files (x86)\embarcadero\studio\15.0\bin\bccaarm.exe -cc1 -D _DEBUG -isysroot 
  C:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\android-ndk-r9c\platforms\android-14\arch-arm -idirafter =\usr\include -idirafter 
  C:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\android-ndk-r9c\sources\cxx-stl\gnu-libstdc++\4.8\include -idirafter 
  C:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\android-ndk-r9c\sources\cxx-stl\gnu-libstdc++\4.8\libs\armeabi-v7a\include -idirafter 
  C:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\android-ndk-r9c\sources\android\native_app_glue -I 
  "C:\Users\Public\Documents\Embarcadero\Studio\15.0\Samples\CPP\Mobile Snippets\WebBrowser" -isystem "c:\program files 
  (x86)\embarcadero\studio\15.0\include" -isystem "c:\program files (x86)\embarcadero\studio\15.0\include\android\rtl" -isystem "c:\program files 
  (x86)\embarcadero\studio\15.0\include\android\fmx" -isystem "c:\program files (x86)\embarcadero\studio\15.0\include\android\crtl" -g 
  -fno-limit-debug-info -fborland-extensions -fborland-auto-refcount -nobuiltininc -nostdsysteminc -triple thumbv7-none-linux-androideabi -emit-obj 
  -mconstructor-aliases -pic-level 2 -target-abi aapcs-linux  -nostdinc++ -fdeprecated-macro -fexceptions -fcxx-exceptions -munwind-tables 
  -mstackrealign -fno-spell-checking -fno-use-cxa-atexit -main-file-name uMain.cpp -x c++ -std=c++11 -O0 -tU -o .\Android\Debug\uMain.o 
  -dependency-file .\Android\Debug\uMain.d -MT .\Android\Debug\uMain.o uMain.cpp 
[bccaarm Error] Android.JNI.Toast.hpp(36): expected a class or namespace
[bccaarm Error] Android.JNI.Toast.hpp(36): reference to 'Android' is ambiguous
  Android.JNI.Toast.hpp(28): candidate found by name lookup is 'Android'
  FMX.Helpers.Android.hpp(28): candidate found by name lookup is 'Fmx::Helpers::Android'
[bccaarm Error] Android.JNI.Toast.hpp(36): expected unqualified-id
[bccaarm Error] Android.JNI.Toast.hpp(47): expected a class or namespace
[bccaarm Error] Android.JNI.Toast.hpp(47): reference to 'Android' is ambiguous
  Android.JNI.Toast.hpp(28): candidate found by name lookup is 'Android'
  FMX.Helpers.Android.hpp(28): candidate found by name lookup is 'Fmx::Helpers::Android'
[bccaarm Error] Android.JNI.Toast.hpp(47): expected namespace name
[bccaarm Error] Android.JNI.Toast.hpp(50): expected a class or namespace
[bccaarm Error] Android.JNI.Toast.hpp(50): reference to 'Android' is ambiguous
  Android.JNI.Toast.hpp(28): candidate found by name lookup is 'Android'
  FMX.Helpers.Android.hpp(28): candidate found by name lookup is 'Fmx::Helpers::Android'
[bccaarm Error] Android.JNI.Toast.hpp(50): expected namespace name
[bccaarm Error] Android.JNI.Toast.hpp(53): reference to 'Android' is ambiguous
  Android.JNI.Toast.hpp(28): candidate found by name lookup is 'Android'
  FMX.Helpers.Android.hpp(28): candidate found by name lookup is 'Fmx::Helpers::Android'
[bccaarm Error] uMain.cpp(32): use of undeclared identifier 'Toast'
Failed
Elapsed time: 00:00:05.8

新日志文件:

[bccaarm Error] Androidapi.JNI.Toast.hpp(36): no type named 'Toast' in namespace 'Androidapi::Jni'
[bccaarm Error] Androidapi.JNI.Toast.hpp(36): expected unqualified-id
[bccaarm Error] uMain.cpp(32): unexpected namespace name 'Toast': expected expression
Failed

从现在开始,非常感谢.

Since now, thanks a lot.

推荐答案

.hpp文件格式错误.

The .hpp file is malformed.

.hpp文件中未定义在.pas文件的interface部分中定义的所有公共类型.特别是,缺少TToastLength枚举.并且Toast()在.pas文件中被声明为procedure,因此没有返回值,但是在.hpp文件中具有(错误)返回值.

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.

您(或其他人)是否手动创建了.hpp文件?我怀疑是这种情况,原因有两个:

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

  1. 初始#ifndef/#define中的Android_JNI_ToastHPP定义与相应的#endif中的Fmx_Helpers_AndroidHPP不匹配.

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

Delphi编译器始终通过将首字母大写而将其余字母小写来为Pascal单元名称命名C ++命名空间,但是此.hpp文件具有全大写的JNI命名空间.

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.

Delphi编译器不会犯这些错误.

The Delphi compiler would not makes those mistakes.

话虽如此,为了与Embarcadero的其他JNI单元保持一致(并与

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.

我强烈建议您更正.pas文件,通过Delphi编译器运行一次以产生正确的.hpp文件,然后按原样在C ++代码中使用它.

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:

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:

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

这篇关于Android JNI桥Toast C ++无法正常工作-如何解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆