Android JNI桥Toast C ++无法正常工作-如何解决? [英] Android JNI bridge Toast C++ not working - How to fix it?
问题描述
我正在尝试解决我的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:
-
初始
#ifndef
/#define
中的Android_JNI_ToastHPP
定义与相应的#endif
中的Fmx_Helpers_AndroidHPP
不匹配.
the
Android_JNI_ToastHPP
define in the initial#ifndef
/#define
does not match theFmx_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屋!