Android JNI网桥Toast C ++无法正常工作 - 如何解决?

时间:2015-03-12 17:16:18

标签: c++ delphi java-native-interface c++builder c++builder-xe7

我试图用我的hpp单元解决一个小问题。 我在互联网上发现了一些例子,展示了如何使用Android JNI桥在屏幕上烘烤信息,但它只是在pascal(delphi)中,所以我决定使用相同的pas文件但是使用hpp文件进行转换。 直到现在我明白了:

#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单元,请点击这里:

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.

然而,在使用此来源进行填写时出现错误... 我该怎么办?

PS:我刚刚将该AppMetthod资源与我正在制作的内容进行比较而来到该州......

日志:

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

从现在开始,非常感谢。

1 个答案:

答案 0 :(得分:7)

.hpp文件格式不正确。

interface文件的.pas部分中定义的所有公共类型均未在.hpp文件中定义。特别是,缺少TToastLength枚举。 {。1}在.pas文件中声明为Toast(),因此没有返回值,但在.hpp文件中有一个(错误的)返回值。

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

  1. 初始procedure / Android_JNI_ToastHPP中的#ifndef定义与相应#define中的Fmx_Helpers_AndroidHPP不符。

    < / LI>
  2. Delphi编译器总是通过大写第一个字母和小写其余字母来为Pascal单元名命名C ++名称空间,但是这个.hpp文件有一个全大写的#endif命名空间。

    < / LI>

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

    话虽如此,JNI应该重命名为Android.JNI.Toast.pas(重命名.hpp文件并相应更新其名称空间),以便与Embarcadero的其他JNI单元保持一致(并匹配{{1}中的示例3}})。这也应该有助于缓解Androidapi.JNI.Toast.pas错误。

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

    Androidapi.JNI.Toast.pas:

    reference to 'Android' is ambiguous

    Androidapi.JNI.Toast.hpp:

    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.