JavaFX アプリケーションを Android デバイスに移植しました。アプリケーションで着信 SMS メッセージを読み取り、それをデータベースに保存したいと考えています。ここ StackOverflow でいくつかの質問を見つけましたが、JavaFX アプローチで実装する方法がわかりません。助けてください!
1 に答える
以下は、JavaFX アプリケーションを作成して Android デバイスに移植するために必要な手順です。これにより、SMS メッセージを追跡できるようになり、次のことが可能になります。
- 入力した番号に SMS を送信します。警告: これにより、モバイル アカウントに費用がかかる場合があります。
- 受信トレイにある SMS のリストをすべて読んでいます。
- 着信 SMS をリッスンし、新しいメッセージが表示されたときにコンテンツを表示します。
ステップ1
NetBeans 用のGluonプラグインを使用して、新しい JavaFX プロジェクトを作成します。これを SMSTracker と呼びましょう。メイン クラスはorg.jpereda.sms.SMSTrackerFX
. で、 jfxmobile build.gradle
プラグインのバージョンを 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 を作成します。このサンプルでは、上記の 3 つのオプションに対して、3 つの主要な領域を持つ単純な 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サンプルPlatformService
に従って、必要なサービスを含むクラスとPlatformProvider
インターフェイスを追加します。
public interface PlatformProvider {
void sendSMS(String number, String message);
List<SMSMessage> readSMSs();
void listenToIncomingSMS();
ObjectProperty<SMSMessage> messageProperty();
}
このインターフェイスは、3 つのプラットフォーム (デスクトップ、iOS、および Android) のそれぞれに実装されます。明らかに、Android の実装のみに焦点を当てます。
これは、関連するすべてのパッケージとファイルを含む NetBeans のプロジェクト ビューです。
ステップ 3
それでは、Android でサービスを実装してみましょう。そのために、私は SO でいくつかの素晴らしい答えに従いました: SMSを送信し、受信トレイを読み、受信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 をデバイスにアップロードします。
プロジェクト全体