【问题标题】:How to analyze incoming message (JavaFX on Android)如何分析传入消息(Android 上的 JavaFX)
【发布时间】:2015-08-31 23:49:18
【问题描述】:

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

【问题讨论】:

  • 您的问题应该更加具体。你打算实现什么,你已经尝试过什么。你想让你的 JavaFX 应用程序知道传入的消息吗?并且每条新短信都能阅读或阅读完整的收件箱吗?

标签: java javafx javafx-2 javafx-8 javafxports


【解决方案1】:

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

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

第 1 步

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

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

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

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<SMSMessage> 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<SMSMessage> {

        @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);
            }
        }
    }

}

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

第 2 步

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

public interface PlatformProvider {

    void sendSMS(String number, String message);

    List<SMSMessage> readSMSs();

    void listenToIncomingSMS();

    ObjectProperty<SMSMessage> messageProperty();

}

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

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

第 3 步

现在让我们在 Android 上实现这些服务。为此,我在 SO 上遵循了几个很好的答案:发送 SMS,阅读 inbox 并收听传入的 SMS

从最后一个开始,我们可以创建一个类,每次接收到一个对象时都会设置一个ObjectProperty 和一个SMSMessage 对象:

public class SmsListener extends BroadcastReceiver {

    private final ObjectProperty<SMSMessage> 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<SMSMessage> 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<SMSMessage> 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'
    }
}

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

<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.jpereda.sms" android:versionCode="1" android:versionName="1.0">
        <supports-screens android:xlargeScreens="true"/>
        <uses-permission android:name="android.permission.READ_SMS"/>
        <uses-permission android:name="android.permission.SEND_SMS"/>
        <uses-permission android:name="android.permission.RECEIVE_SMS" />
        <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="21"/>
        <application android:label="SMSTracker" android:name="android.support.multidex.MultiDexApplication">
                <activity android:name="javafxports.android.FXActivity" android:label="SMSTracker" android:configChanges="orientation|screenSize">
                        <meta-data android:name="main.class" android:value="org.jpereda.sms.SMSTrackerFX"/>
                        <meta-data android:name="debug.port" android:value="0"/>
                        <intent-filter>
                                <action android:name="android.intent.action.MAIN"/>
                                <category android:name="android.intent.category.LAUNCHER"/>
                        </intent-filter>
                </activity>
                <receiver android:name=".SmsListener">
                    <intent-filter android:priority="2147483647">
                        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                    </intent-filter>
                </receiver>
        </application>
</manifest>

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

完整项目

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

【讨论】:

    猜你喜欢
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-28
    • 2023-03-17
    相关资源
    最近更新 更多