Android 上的 NFC 使用 JavaFX 端口
NFC on Android using JavaFX Ports
我最近一直在尝试 JavaFXPorts and I have been trying to use it to build a native Android app. For the application I'm building I am trying to bake in NFC support but there doesn't seem to be much information out there about this. The only useful guide I found so far was some sample code written by johanvos on his BitBucket Repo here。
我现在面临的问题是使用此代码片段,Netbeans 不断报告我尝试引用的 android 库不存在。
这是我的一些代码:
package com.afropolymath.waitress;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import android.content.Context;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.ReaderCallback;
import android.nfc.Tag;
import android.os.Bundle;
import javafxports.android.FXActivity;
public class Waitress extends Application implements ReaderCallback {
private Stage stage;
private StackPane rootLayout;
@Override
public void start(Stage stage) {
this.stage = stage;
this.initLayout();
Context ctx = FXActivity.getInstance();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(ctx);
nfcAdapter.enableReaderMode(FXActivity.getInstance(), this, NfcAdapter.FLAG_READER_NFC_A, Bundle.EMPTY);
}
public void initLayout() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/RootLayout.fxml"));
rootLayout = (StackPane) loader.load();
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Scene scene = new Scene(rootLayout, visualBounds.getWidth(), visualBounds.getHeight());
stage.getIcons().add(new Image(Waitress.class.getResourceAsStream("/assets/icon.png")));
stage.setScene(scene);
stage.show();
} catch (IOException e) {
}
}
@Override
public void onTagDiscovered(Tag tag) {
}
}
这些是我遇到的错误:
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:12: error: package android.content does not exist
import android.content.Context;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:13: error: package android.nfc does not exist
import android.nfc.NfcAdapter;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:14: error: package android.nfc.NfcAdapter does not exist
import android.nfc.NfcAdapter.ReaderCallback;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:15: error: package android.nfc does not exist
import android.nfc.Tag;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:16: error: package android.os does not exist
import android.os.Bundle;
^
对可能出现的问题有什么想法吗?
虽然 Johan Vos 的 NFC 项目有效,但它基于 android 的使用和主包上的 dalvik 依赖项:
dependencies {
compile files("${ANDROID_HOME}/platforms/android-21/android.jar")
compile "org.javafxports:jfxdvk:8u60-b3"
}
但是 JavaFXPorts 旨在创建可以部署在不同平台上的项目,所以现在如果您使用 Gluon 的 NetBeans 插件创建项目,您会发现四个不同的文件夹来放置代码:
- 源码包[Java],所有通用代码,与所有平台共享
- Desktop/Java 包,用于 Java 代码,仅在 运行 桌面版
上可用
- Android/Java 包,用于 Java 或 Android 代码,仅在 Android
上可用 运行
- Ios/Java 包,用于 Java 代码,仅在 iOS.运行 可用。
此外,如果您检查项目依赖项,您会注意到 android.jar
仅适用于 Android。
这意味着您应该在主包上创建您的常规项目,并在 Android 包中添加 android 部分 仅 。为了调用 android class,您需要在主包上提供一些机制来创建它的实例。
如果您检查 HelloPlatform sample,您会注意到 PlatformService
用于根据平台加载 classes,而 PlatformProvider
是一个带有 method/s 的接口,可以从主包中调用,但会为每个平台提供实现。
有了这个想法,但使用 Class.forName()
而不是服务,Gluon Charm-Down 库实现了不同的本机服务。
你也可以看看详细解释它的GoNative sample and post。
如果您想实施新服务,例如 Android 的 NFC,
这些是可能需要的 classes。
主包
NFC平台
public abstract class NFCPlatform {
public abstract NFCService getNFCService();
}
NFC服务
public interface NFCService {
boolean isAvailable();
boolean isEnabled();
StringProperty tagIdProperty();
// other methods
}
Android 套餐
AndroidNFC平台
public class AndroidNFCPlatform extends NFCPlatform {
private AndroidNFCService nfcService;
@Override
public NFCService getNFCService() {
if (nfcService == null) {
nfcService = new AndroidNFCService();
}
return nfcService;
}
}
AndroidNFC服务
您实施的 NFC 服务。这里我们可以使用AndroidAPI。 NetBeans 不会抱怨。
这是一个最小的实现:
public class AndroidNFCService implements NFCService, ReaderCallback {
private final NfcAdapter nfcAdapter;
private StringProperty tagId;
public AndroidNFCService() {
NfcManager manager = (NfcManager) FXActivity.getInstance().getSystemService(FXActivity.NFC_SERVICE);
nfcAdapter = manager.getDefaultAdapter();
}
@Override
public boolean isAvailable() {
return nfcAdapter != null;
}
@Override
public boolean isEnabled() {
return isAvailable() && nfcAdapter.isEnabled();
}
@Override
public StringProperty tagIdProperty() {
if (tagId == null) {
tagId = new SimpleStringProperty();
}
return tagId;
}
@Override
public void onTagDiscovered(Tag tag) {
Platform.runLater(() ->
tagIdProperty().set(new String(tag.getId())));
}
}
最后,一旦您获得 NFCPlatform
.
的实例,您就可以在主 class 上使用此服务了
public static NFCPlatform getNFCPlatform() {
try {
if ("android".equals(System.getProperty("javafx.platform", "desktop"))) {
return (NFCPlatform) Class.forName("<your package>.AndroidNFCPlatform").newInstance();
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
System.out.println("Error " + ex);
}
return null;
}
@Override
public void start(Stage stage) {
NFCService nfcService = getNFCPlatform().getNFCService();
if (nfcService != null) {
System.out.println("Available: " + nfcService.isAvailable());
...
}
}
我最近一直在尝试 JavaFXPorts and I have been trying to use it to build a native Android app. For the application I'm building I am trying to bake in NFC support but there doesn't seem to be much information out there about this. The only useful guide I found so far was some sample code written by johanvos on his BitBucket Repo here。
我现在面临的问题是使用此代码片段,Netbeans 不断报告我尝试引用的 android 库不存在。
这是我的一些代码:
package com.afropolymath.waitress;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Screen;
import javafx.stage.Stage;
import android.content.Context;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.ReaderCallback;
import android.nfc.Tag;
import android.os.Bundle;
import javafxports.android.FXActivity;
public class Waitress extends Application implements ReaderCallback {
private Stage stage;
private StackPane rootLayout;
@Override
public void start(Stage stage) {
this.stage = stage;
this.initLayout();
Context ctx = FXActivity.getInstance();
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(ctx);
nfcAdapter.enableReaderMode(FXActivity.getInstance(), this, NfcAdapter.FLAG_READER_NFC_A, Bundle.EMPTY);
}
public void initLayout() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/RootLayout.fxml"));
rootLayout = (StackPane) loader.load();
Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
Scene scene = new Scene(rootLayout, visualBounds.getWidth(), visualBounds.getHeight());
stage.getIcons().add(new Image(Waitress.class.getResourceAsStream("/assets/icon.png")));
stage.setScene(scene);
stage.show();
} catch (IOException e) {
}
}
@Override
public void onTagDiscovered(Tag tag) {
}
}
这些是我遇到的错误:
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:12: error: package android.content does not exist
import android.content.Context;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:13: error: package android.nfc does not exist
import android.nfc.NfcAdapter;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:14: error: package android.nfc.NfcAdapter does not exist
import android.nfc.NfcAdapter.ReaderCallback;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:15: error: package android.nfc does not exist
import android.nfc.Tag;
^
/Users/chidieberennadi/NetBeansProjects/Waitress/src/main/java/com/afropolymath/waitress/Waitress.java:16: error: package android.os does not exist
import android.os.Bundle;
^
对可能出现的问题有什么想法吗?
虽然 Johan Vos 的 NFC 项目有效,但它基于 android 的使用和主包上的 dalvik 依赖项:
dependencies {
compile files("${ANDROID_HOME}/platforms/android-21/android.jar")
compile "org.javafxports:jfxdvk:8u60-b3"
}
但是 JavaFXPorts 旨在创建可以部署在不同平台上的项目,所以现在如果您使用 Gluon 的 NetBeans 插件创建项目,您会发现四个不同的文件夹来放置代码:
- 源码包[Java],所有通用代码,与所有平台共享
- Desktop/Java 包,用于 Java 代码,仅在 运行 桌面版 上可用
- Android/Java 包,用于 Java 或 Android 代码,仅在 Android 上可用 运行
- Ios/Java 包,用于 Java 代码,仅在 iOS.运行 可用。
此外,如果您检查项目依赖项,您会注意到 android.jar
仅适用于 Android。
这意味着您应该在主包上创建您的常规项目,并在 Android 包中添加 android 部分 仅 。为了调用 android class,您需要在主包上提供一些机制来创建它的实例。
如果您检查 HelloPlatform sample,您会注意到 PlatformService
用于根据平台加载 classes,而 PlatformProvider
是一个带有 method/s 的接口,可以从主包中调用,但会为每个平台提供实现。
有了这个想法,但使用 Class.forName()
而不是服务,Gluon Charm-Down 库实现了不同的本机服务。
你也可以看看详细解释它的GoNative sample and post。
如果您想实施新服务,例如 Android 的 NFC, 这些是可能需要的 classes。
主包
NFC平台
public abstract class NFCPlatform {
public abstract NFCService getNFCService();
}
NFC服务
public interface NFCService {
boolean isAvailable();
boolean isEnabled();
StringProperty tagIdProperty();
// other methods
}
Android 套餐
AndroidNFC平台
public class AndroidNFCPlatform extends NFCPlatform {
private AndroidNFCService nfcService;
@Override
public NFCService getNFCService() {
if (nfcService == null) {
nfcService = new AndroidNFCService();
}
return nfcService;
}
}
AndroidNFC服务
您实施的 NFC 服务。这里我们可以使用AndroidAPI。 NetBeans 不会抱怨。
这是一个最小的实现:
public class AndroidNFCService implements NFCService, ReaderCallback {
private final NfcAdapter nfcAdapter;
private StringProperty tagId;
public AndroidNFCService() {
NfcManager manager = (NfcManager) FXActivity.getInstance().getSystemService(FXActivity.NFC_SERVICE);
nfcAdapter = manager.getDefaultAdapter();
}
@Override
public boolean isAvailable() {
return nfcAdapter != null;
}
@Override
public boolean isEnabled() {
return isAvailable() && nfcAdapter.isEnabled();
}
@Override
public StringProperty tagIdProperty() {
if (tagId == null) {
tagId = new SimpleStringProperty();
}
return tagId;
}
@Override
public void onTagDiscovered(Tag tag) {
Platform.runLater(() ->
tagIdProperty().set(new String(tag.getId())));
}
}
最后,一旦您获得 NFCPlatform
.
public static NFCPlatform getNFCPlatform() {
try {
if ("android".equals(System.getProperty("javafx.platform", "desktop"))) {
return (NFCPlatform) Class.forName("<your package>.AndroidNFCPlatform").newInstance();
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
System.out.println("Error " + ex);
}
return null;
}
@Override
public void start(Stage stage) {
NFCService nfcService = getNFCPlatform().getNFCService();
if (nfcService != null) {
System.out.println("Available: " + nfcService.isAvailable());
...
}
}