Firemonkey安卓NFC适配器

11

我刚接触Firemonkey和Android,不确定我的方式是否正确。我想要运行一个应用程序并读取NFC标签。

有没有办法在Firemonkey中使用安卓设备上的NFC读卡器?

通过FMXExpress的NFCAdapter的一部分(http://www.fmxexpress.com/full-android-sdk-interface-files-in-object-pascal-for-firemonkey/),我可以确定设备是否具有NFC读卡器,并且它是否已启用。但是,要使用所有功能,我必须手动定义所有接口并解决所有循环引用。我认为这不能导致适当的解决方案。

我面临的解决方案是构建自己的JavaClass,以像此博客文章中描述的那样与nfc适配器通信:http://blong.com/Articles/DelphiXE5AndroidActivityResult/ActivityResult.htm#Building


2
如果你还卡在这个问题上,@deterministicFail,我已经写了如何在Delphi Android应用程序中读写NFC标签的教程,适用于XE5、XE6和XE7。你可以在这里找到带有三篇文章链接的帖子:http://blog.blong.com/2014/09/delphi-and-nfc-on-android.html。祝愉快! - blong
1个回答

22
是的!您采取了正确的方法。
要让 Delphi 和 FireMonkey 正常工作,您可以使用以下 template,这是实现您想要的方式: 接口:
/ JNI NFC import demo
// Note - REQUIRES - PROJECT OPTIONS - USES PERMISSIONS - NFC

interface

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.GraphicsContentViewText,
  FMX.Helpers.Android,
  SysUtils,
  Classes;

type

NFC适配器:
  /////////////////////////// NfcAdapter /////////////////////////////////
  JNfcManager = interface;
  JNfcAdapter = interface;

  JNfcAdapterClass = interface(JObjectClass)
  ['{634258AC-7931-4E38-97E6-48DBF688A288}']
    {Property methods}
    function _ACTION_TAG_DISCOVERED: JString; cdecl;
    function _EXTRA_ID: JString; cdecl;
    function _EXTRA_NDEF_MESSAGES: JString; cdecl;
    function _EXTRA_TAG: JString; cdecl;
    {Properties}
    property ACTION_TAG_DISCOVERED: JString read _ACTION_TAG_DISCOVERED;
    property EXTRA_ID: JString read _EXTRA_ID;
    property EXTRA_NDEF_MESSAGES: JString read _EXTRA_NDEF_MESSAGES;
    property EXTRA_TAG: JString read _EXTRA_TAG;
  end;

  [JavaSignature('android/nfc/NfcAdapter')]
  JNfcAdapter = interface(JObject)
  ['{364D8F3F-23AE-4C28-A261-E30C0893B24C}']
    //Return true if this NFC Adapter has any features enabled
    function isEnabled: Boolean; cdecl;
  end;

  TJNfcAdapter = class(TJavaGenericImport<JNfcAdapterClass, JNfcAdapter>) end;

NfcManager:
  /////////////////////////// NfcManager /////////////////////////////////

  JNfcManagerClass = interface(JObjectClass)
  ['{812481E1-F491-47D2-AC1F-4C5AB509532B}']
  end;

  [JavaSignature('android/nfc/NfcManager')]
  JNfcManager = interface(JObject)
  ['{04B707EC-966A-4E4F-85DC-F003B7C9ACE3}']
    {Methods}
    function getDefaultAdapter: JNfcAdapter; cdecl;
  end;

  TJNfcManager = class(TJavaGenericImport<JNfcManagerClass, JNfcManager>) end;

function HasNfc: Boolean;
function IsNfcEnabled: Boolean;

implementation

function GetNfcManager: JNfcManager;
var
  ConnectivityServiceNative: JObject;
begin
  ConnectivityServiceNative := SharedActivityContext.getSystemService(TJContext.JavaClass.NFC_SERVICE);
  if not Assigned(ConnectivityServiceNative) then
    raise Exception.Create('Could not locate Nfc Service');
  Result := TJNfcManager.Wrap((ConnectivityServiceNative as ILocalObject).GetObjectID);
  if not Assigned(Result) then
    raise Exception.Create('Could not access Nfc Manager');
end;

function HasNfc: Boolean;
var
  NfcManager: JNfcManager;
  NfcAdapter: JNfcAdapter;
begin
  NfcManager := GetNfcManager;
  NfcAdapter := NfcManager.getDefaultAdapter;
  Result := Assigned(NfcAdapter);
end;

function IsNfcEnabled: Boolean;
var
  NfcManager: JNfcManager;
  NfcAdapter: JNfcAdapter;
begin
  NfcManager := GetNfcManager;
  NfcAdapter := NfcManager.getDefaultAdapter;
  Result := Assigned(NfcAdapter)and NfcAdapter.isEnabled;
end;

end.

{code}

usage
Memo1.Lines.Add('Nfc Enabled: '+BoolToStr(IsNfcEnabled, True));

如果您尝试运行这个示例代码,我相信它会正常工作!
我猜你被迫要尽可能地获得最好的一切,比如使用完全跨平台的API,它将让你在Android和iOS上运行完全相同的代码,而无需改变应用程序的前端和后端。是的,目前有一些工具正在开发中,旨在解决真正的多平台嵌入式开发问题,这可能在不久的将来实现完全集成。不幸的是,在移动平台开发的当前阶段,如果你正在实现更基本的应用程序,那么只能选择这样的多平台工具,而这些应用程序不会依赖于更特定的资源,比如NFC、Geofencing等。当然,如果你不处于生产环境中,那么最终你可能会有足够的时间去玩耍和研究。但假设这不是情况,那么请专注于快速地组合事物以使其工作,因为交付期限通常很紧。

话虽如此,实现NFC标签通信的最快最短的方法是使用Android NFC API资源,因为它自API级别9 - Android Gingerbread引入以来就已经存在。

enter image description here

NFC传输可以在两个支持NFC的设备之间,或设备与NFC“标签”之间进行。标签可以是无源标签,在扫描时传输URL,也可以是用于NFC支付解决方案中的复杂系统,例如Google Wallet

enter image description here

为了读取、写入或广播NFC消息,您的应用程序需要NFC清单权限:

<uses-permission android:name=”android.permission.NFC” />

当安卓设备用于扫描NFC标签时,系统将使用其自己的标签分发系统解码传入的有效负载,该系统分析标签、分类数据,并使用Intent启动一个应用程序来接收数据。

下面是一个示例代码,展示如何注册一个仅响应NFC标签的Activity:

<activity android:name=”.BlogViewer”>
    <intent-filter>
        <action android:name=”android.nfc.action.NDEF_DISCOVERED”/>
        <category android:name=”android.intent.category.DEFAULT”/>
        <data android:scheme=”http”android:host=”blog.example.com”/>
    </intent-filter>
</activity>

NfcAdapter.EXTRA_TAG额外包含一个代表扫描标签的原始Tag对象。NfcAdapter.EXTRA_TNDEF_MESSAGES额外包含一组NDEF消息的数组:
String action = getIntent().getAction();

if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
    Parcelable[] messages =
    intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    for (int i = 0; i < messages.length; i++) {
        NdefMessage message = (NdefMessage)messages[i];
        NdefRecord[] records = message.getRecords();
        for (int j = 0; j < records.length; j++) {
            NdefRecord record = records[j];
            // TODO Process the individual records.
        }
    }
}

enter image description here

NFC应用的潜力和可能性巨大,对该技术的需求趋势显著增长:

enter image description here

如果您可以使用智能手机作为支付方式,那么像公共交通和停车收费器等付款可能就像刷一下手机一样简单。您甚至可以在日常通勤中轻松点击报纸终端下载最新的问题到您的设备上。

感谢您详细的回答。不幸的是,我受限于Delphi和FireMonkey。 - deterministicFail
感谢您的努力。这些接口就是我在问题中所指的,也是网络上唯一的Delphi示例。根据我的研究,我得出结论,目前唯一正确的方法是实现自己的JavaClass并从Firemonkey中使用它。 - deterministicFail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接