如何分析传入消息(Android上的JavaFX)

我将我的JavaFX应用程序移植到我的Android设备上。 我希望我的应用程序读取传入的SMS消息并将其存储在数据库中。 我在StackOverflow中发现了几个问题,但我不知道如何在JavaFX方法中实现。 请帮忙!

这些是创建JavaFX应用程序并将其移植到Android设备所需的步骤,因此您可以跟踪SMS消息,从而允许:

  • 向您输入的号码发送短信。 警告:这可能会因您的移动帐户而产生费用。
  • 阅读收件箱中的所有短信列表。
  • 收听传入的短信,并在显示新内容时显示内容。

步骤1

使用NetBon的Gluon 插件创建一个新的JavaFX项目。 我们称之为SMSTracker,主类为org.jpereda.sms.SMSTrackerFX 。 在build.gradle ,将jfxmobile插件版本更新为b9:

 dependencies { classpath 'org.javafxports:jfxmobile-plugin:1.0.0-b9' } 

首先让我们用我们的模型创建一个JavaFX pojo的SMSMessage

 public class SMSMessage { private final StringProperty id; private final StringProperty address; private final StringProperty msg; private final StringProperty readState; //"0" not read, "1" read sms private final StringProperty time; private final StringProperty folderName; public SMSMessage(String id, String address, String msg, String readState, String time, String folderName){ this.id = new SimpleStringProperty(id); this.address = new SimpleStringProperty(address); this.msg = new SimpleStringProperty(msg); this.readState = new SimpleStringProperty(readState); this.time = new SimpleStringProperty(time); this.folderName = new SimpleStringProperty(folderName); } public String getId() { return id.get(); } public StringProperty idProperty() { return id; } public String getAddress() { return address.get(); } public StringProperty addressProperty() { return address; } public String getMsg() { return msg.get(); } public StringProperty msgProperty() { return msg; } public String getReadState() { return readState.get(); } public StringProperty readStateProperty() { return readState; } public String getTime() { return time.get(); } public StringProperty timeProperty() { return time; } public String getFolderName() { return folderName.get(); } public StringProperty folderNameProperty() { return folderName; } @Override public String toString(){ return id.get()+ ": " + address.get() + ": " + msg.get(); } } 

使用ScenicBuilder和FXML或通过代码,创建您的UI。 对于此示例,它将是一个简单的UI,具有三个主要区域,用于上述三个选项。

 public class SMSTrackerFX extends Application { @Override public void start(Stage stage) { BorderPane root = new BorderPane(); /* TOP :: Sending SMS Warning: This may by subjected to costs to your mobile account */ Button buttonSend = new Button("Send SMS"); TextField number = new TextField(); number.setPromptText("Insert number"); HBox.setHgrow(number, Priority.ALWAYS); HBox hbox = new HBox(10,buttonSend, number); TextField message = new TextField(); message.setPromptText("Insert text"); HBox.setHgrow(message, Priority.ALWAYS); VBox vboxTop = new VBox(10,hbox,message); buttonSend.disableProperty().bind(Bindings.createBooleanBinding(()->{ return number.textProperty().isEmpty() .or(message.textProperty().isEmpty()).get(); }, number.textProperty(),message.textProperty())); vboxTop.setPadding(new Insets(10)); root.setTop(vboxTop); /* CENTER :: Reading SMS Inbox */ Button button = new Button("Read SMS Inbox"); ListView view = new ListView<>(); view.setCellFactory(data -> new SMSListCell()); VBox.setVgrow(view, Priority.ALWAYS); VBox vboxCenter = new VBox(10,button,view); vboxCenter.setPadding(new Insets(10)); root.setCenter(vboxCenter); /* BOTTOM :: Listening to incoming SMS */ Label incoming = new Label("No messages"); VBox vboxBottom = new VBox(10,new Label("Incoming SMS"),incoming); vboxBottom.setPadding(new Insets(10)); root.setBottom(vboxBottom); Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds(); Scene scene = new Scene(root, visualBounds.getWidth(), visualBounds.getHeight()); stage.setScene(scene); stage.show(); } private static class SMSListCell extends ListCell { @Override protected void updateItem(SMSMessage item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { setGraphic(new Label(item.getId()+ ": " + item.getMsg())); } else { setGraphic(null); } } } } 

这就是我们现在所拥有的:

SMS1

第2步

在HelloPlatform 示例之后 ,我们将添加一个PlatformService类和一个PlatformProvider接口,以及所需的服务:

 public interface PlatformProvider { void sendSMS(String number, String message); List readSMSs(); void listenToIncomingSMS(); ObjectProperty messageProperty(); } 

该界面将在三个平台(桌面,iOS和Android)中的每一个上实现。 显然,我们只关注Android实现。

这是NetBeans上的项目视图,包含所有包和文件:

SMS2

第3步

让我们现在实现Android上的服务。 为此,我在SO上听了几个很棒的答案:发送短信 ,阅读收件箱和收听短信 。

从最后一个开始,我们可以创建一个类,每次收到一个带有SMSMessage对象的ObjectProperty

 public class SmsListener extends BroadcastReceiver { private final ObjectProperty messages = new SimpleObjectProperty<>(); @Override public void onReceive(Context cntxt, Intent intent) { if(intent.getAction().equals(Intents.SMS_RECEIVED_ACTION)){ for (SmsMessage smsMessage : Intents.getMessagesFromIntent(intent)) { SMSMessage sms = new SMSMessage("0", smsMessage.getOriginatingAddress(), smsMessage.getMessageBody(), smsMessage.getStatus()==1?"read":"not read", Long.toString(smsMessage.getTimestampMillis()), "inbox"); messages.set(sms); } } } public ObjectProperty messagesProperty() { return messages; } } 

为了启动这个监听器,我们使用FXActivity ,这个类扩展了Android Context类并提供了对Android服务的访问,以注册SmsListener的实例:

 public class AndroidPlatformProvider implements PlatformProvider { private final SmsListener receiver = new SmsListener(); @Override public void listenToIncomingSMS() { FXActivity.getInstance().registerReceiver(receiver, new IntentFilter(Intents.SMS_RECEIVED_ACTION)); } @Override public ObjectProperty messagesProperty() { return receiver.messagesProperty(); } } 

第4步

最后,我们需要做的就是将属性与UI上的标签绑定并启动广播:

  @Override public void start(Stage stage) { ... PlatformService.getInstance().messageProperty().addListener( (obs,s,s1)->{ Platform.runLater(()->incoming.setText(s1.toString())); }); // start broadcast PlatformService.getInstance().listenToIncomingSMS(); } 

请注意使用Platform.runLater()更新标签:广播线程与JavaFX线程不同。

第5步

构建apk之前的最后一步是修改AndroidManifest.xml文件以请求所需的权限。

由于jfxmobile-plugin默认创建一个,因此在此阶段运行gradlew android会生成它。 它位于SMSTracker\build\javafxports\tmp\android文件夹下。

将其复制到另一个位置( SMSTracker\lib )并在build.gradle文件中包含其引用:

 jfxmobile { android { manifest = 'lib/AndroidManifest.xml' } } 

现在编辑文件并添加所需的权限和接收者:

                        

保存,构建并运行gradlew androidInstall将apk上传到您的设备。

完整的项目

这个应用程序的所有代码都可以在这里找到,包括可以在Android设备上安装的apk 。