使用 Gluon-mobile 中的 ALARM_SERVICE 服务安排 Android 中的任务
Schedule a Task in Android using ALARM_SERVICE service in Gluon-mobile
我参考了这个 link 并尝试了这个代码 所以 far.But 我不知道在 gluon-mobile 中实现这个代码。什么我打算做的是我想开始一个缩进,在特定的后台做一些工作 time.My 问题是我不知道 gluon-mobile behaves.So 如何帮助我完成它。
package com.application;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import javafxports.android.FXActivity;
public class Schedular {
AlarmManager manager=null;
FXActivity activity=null;
public Schedular()
{
manager=(AlarmManager) FXActivity.getInstance().getSystemService(Context.ALARM_SERVICE);
activity=FXActivity.getInstance();
}
public void schedule()
{
Intent indent = new Intent(activity,Alarm.class);
PendingIntent pIntent = PendingIntent.getBroadcast(activity, 0, indent, 0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime()+2*1000,indent); //This is Where I went Wrong
}
}
我想在 运行-time 用户指定的特定时间安排任务,这就是函数 public void schedule(Calendar calendar,boolean flag ) 确实如此。
Alarm.class
public class Alarm extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// Your code to execute when the alarm triggers
// and the broadcast is received.
new bluetooth.turnOn();
}
并且我已将 Alarm.class 添加到 AndroidManifest.xml 为
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.application" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="26"/>
<application android:label="Wifischeduler" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
<activity android:name="javafxports.android.FXActivity" android:label="Wifischeduler" android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.application.Main"/>
<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>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.NotificationActivity"
android:parentActivityName="javafxports.android.FXActivity">
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="javafxports.android.FXActivity"/>
</activity>
<activity android:name="com.application.AndroidPlatform$PermissionRequestActivity" />
<receiver android:name="com.application.Alarm" /> // this is where I have included the Alarm.class
<receiver android:name="com.gluonhq.impl.charm.down.plugins.android.AlarmReceiver" />
</application>
当调用 schedule 方法时,应用程序退出...
我有 运行 adb logcat -v threadtime 并在 cmd
上得到了这个输出
--------- beginning of crash
07-22 09:21:44.878 13516 13516 E AndroidRuntime: FATAL EXCEPTION: main
07-22 09:21:44.878 13516 13516 E AndroidRuntime: Process: com.application, PID: 13516
07-22 09:21:44.878 13516 13516 E AndroidRuntime: java.lang.RuntimeException: Unable to instantiate receiver com.application.Alarm: java.lang.IllegalAccessException: java.lang.Class<com.application.Alarm> is not accessible from java.lang.Class<android.app.ActivityThread>
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:2739)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.access00(ActivityThread.java:153)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1452)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5529)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: Caused by: java.lang.IllegalAccessException: java.lang.Class<com.application.Alarm> is not accessible from java.lang.Class<android.app.ActivityThread>
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at java.lang.Class.newInstance(Native Method)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:2734)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: ... 8 more
07-22 09:21:44.885 1804 3742 D StatusBar: onNotificationPosted: Key: 0|com.application|123456|charm://down/Id/abcd12340|10276 GroupKey: 0|com.application|123456|charm://down/Id/abcd12340|10276 Connected: true
07-22 09:21:44.885 1804 1804 D StatusBar: GroupChild: false GroupsContainsKey: false IsUpdate: false IsGroupSummary: false hasIcon: true
07-22 09:21:44.886 1804 1804 D PhoneStatusBar: addNotification pkg=com.application;basepkg=com.application;id=123456
07-22 09:21:44.888 3047 10359 I GCoreUlr: Successfully inserted 1 locations
07-22 09:21:44.922 1804 1804 W ProgressBarDelegate: Unknown Drawable subclass, src=android.graphics.drawable.ScaleDrawable@eb9196
07-22 09:21:44.922 1804 1804 W ProgressBarDelegate: Unknown Drawable subclass, src=android.graphics.drawable.ScaleDrawable@aace117
07-22 09:21:44.932 3451 3518 I octvm_klo: klo lock
我不知道为什么我不能实例化接收器 (Alarm.class),
@FXML void start()
{
try{
Schedule schedule =(Schedule) Class.forName("com.application.Schedular").newInstance();
schedule.schedule();
}
替换缩进
来自
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10L, pIntent);
也给indent的构造函数,传递所需的"activity"或"service"
Intent intent = new Intent(context, AlarmReceiver.class); //AlarmReceiver is an activity that will be launched after an hour
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() +
60 * 1000, pIntent); //60mins from now
您的代码并不完全适合我:我不得不将 intent
更改为 schedule()
中的 pIntent
,并将 Schedule
更改为 Class
在 Java 实现上(你如何导入它?)。除此之外,对我来说运行宁没问题(使用Android目标25),我没有任何例外。
我将 post 初始解决方案(基于您的方法),然后是更好的方法。
初步解决方案
虽然添加平台特定代码的首选方法是遵循 Charm Down 设计模式(参见 https://bitbucket.org/gluon-oss/charm-down),但让 Android 代码正常工作的一种非常快速且肮脏的方法是:
Android
Scheduler.java
package com.gluonhq.scheduler.android;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import javafxports.android.FXActivity;
public class Scheduler {
private final AlarmManager manager;
public Scheduler() {
manager = (AlarmManager) FXActivity.getInstance().getSystemService(Context.ALARM_SERVICE);
Intent indent = new Intent(FXActivity.getInstance(), AlarmReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(FXActivity.getInstance(), 0, indent, 0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 2000, pIntent);
}
}
AlarmReceiver.java
package com.gluonhq.scheduler.android;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm ON", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gluonhq.scheduler" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="25"/>
<application android:label="GluonScheduler" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
<activity android:name="javafxports.android.FXActivity" android:label="GluonScheduler" android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.gluonhq.scheduler.GluonScheduler"/>
<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="com.gluonhq.scheduler.android.AlarmReceiver" />
</application>
</manifest
Main/Java
这是使用 Gluon IDE 插件的单一视图模板项目的基本视图:
胶子Scheduler.java
package com.gluonhq.scheduler;
import com.gluonhq.charm.glisten.application.MobileApplication;
import com.gluonhq.charm.glisten.visual.Swatch;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class GluonScheduler extends MobileApplication {
public static final String BASIC_VIEW = HOME_VIEW;
@Override
public void init() {
addViewFactory(BASIC_VIEW, () -> new BasicView(BASIC_VIEW));
}
@Override
public void postInit(Scene scene) {
Swatch.BLUE.assignTo(scene);
((Stage) scene.getWindow()).getIcons().add(new Image(GluonScheduler.class.getResourceAsStream("/icon.png")));
}
}
BasicView.java
package com.gluonhq.scheduler;
import com.gluonhq.charm.glisten.control.AppBar;
import com.gluonhq.charm.glisten.control.Icon;
import com.gluonhq.charm.glisten.mvc.View;
import com.gluonhq.charm.glisten.visual.MaterialDesignIcon;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
public class BasicView extends View {
public BasicView(String name) {
super(name);
Button button = new Button("Schedule task");
button.setGraphic(new Icon(MaterialDesignIcon.ALARM_ON));
button.setOnAction(e -> {
try {
Class c = Class.forName("com.gluonhq.scheduler.android.Scheduler");
c.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
Logger.getLogger(BasicView.class.getName()).log(Level.SEVERE, null, ex);
}
});
VBox controls = new VBox(button);
controls.setAlignment(Pos.CENTER);
setCenter(controls);
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> System.out.println("Menu")));
appBar.setTitleText("Basic View");
}
}
build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.6'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.gluonhq.scheduler.GluonScheduler'
dependencies {
compile 'com.gluonhq:charm:4.3.5'
}
jfxmobile {
downConfig {
version = '3.3.0'
// Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
android {
manifest = 'src/android/AndroidManifest.xml'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
部署到您的 Android 设备 (./gradlew androidInstall
) 和 运行。按下按钮,两秒后你会看到吐司:
首选解决方案
报警服务
虽然上面的代码有效,但是使用起来不是很方便Class.forName
。
按照 Charm Down 服务(例如 LocalNotification),我将改为这样做(您必须保持相同的包名称):
Java
AlarmService.java
package com.gluonhq.charm.down.plugins;
public interface AlarmService {
public void schedule();
}
AlarmServiceFactory.java
package com.gluonhq.charm.down.plugins;
import com.gluonhq.charm.down.DefaultServiceFactory;
public class AlarmServiceFactory extends DefaultServiceFactory<AlarmService> {
public AlarmServiceFactory() {
super(AlarmService.class);
}
}
Android
AndroidAlarmService.java
package com.gluonhq.charm.down.plugins.android;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import com.gluonhq.charm.down.plugins.AlarmService;
import com.gluonhq.scheduler.android.AlarmReceiver;
import javafxports.android.FXActivity;
public class AndroidAlarmService implements AlarmService {
private final AlarmManager manager;
private final FXActivity activity;
public AndroidAlarmService() {
activity = FXActivity.getInstance();
manager = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
}
@Override
public void schedule() {
Intent indent = new Intent(activity, AlarmReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(activity, 0, indent, 0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 2000, pIntent);
}
}
(保持与上面相同的AlarmReceiver
class)。
最后,在您看来:
BasicView.java
button.setOnAction(e ->
Services.get(AlarmService.class).ifPresent(AlarmService::schedule));
现在可以再次部署和运行,结果是一样的。但显然,这种首选方式具有更多优势。
- 使用该服务,您还可以 运行 在桌面上或部署到 iOS:该应用程序将运行(单击按钮时它不会执行任何操作)。
- 如果需要,您可以实施桌面和 iOS 解决方案。
- 您可以通过界面轻松添加更多功能。
我参考了这个 link 并尝试了这个代码 所以 far.But 我不知道在 gluon-mobile 中实现这个代码。什么我打算做的是我想开始一个缩进,在特定的后台做一些工作 time.My 问题是我不知道 gluon-mobile behaves.So 如何帮助我完成它。
package com.application;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import javafxports.android.FXActivity;
public class Schedular {
AlarmManager manager=null;
FXActivity activity=null;
public Schedular()
{
manager=(AlarmManager) FXActivity.getInstance().getSystemService(Context.ALARM_SERVICE);
activity=FXActivity.getInstance();
}
public void schedule()
{
Intent indent = new Intent(activity,Alarm.class);
PendingIntent pIntent = PendingIntent.getBroadcast(activity, 0, indent, 0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime()+2*1000,indent); //This is Where I went Wrong
}
}
我想在 运行-time 用户指定的特定时间安排任务,这就是函数 public void schedule(Calendar calendar,boolean flag ) 确实如此。
Alarm.class
public class Alarm extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// Your code to execute when the alarm triggers
// and the broadcast is received.
new bluetooth.turnOn();
}
并且我已将 Alarm.class 添加到 AndroidManifest.xml 为
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.application" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="26"/>
<application android:label="Wifischeduler" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
<activity android:name="javafxports.android.FXActivity" android:label="Wifischeduler" android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.application.Main"/>
<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>
<activity android:name="com.gluonhq.impl.charm.down.plugins.android.NotificationActivity"
android:parentActivityName="javafxports.android.FXActivity">
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="javafxports.android.FXActivity"/>
</activity>
<activity android:name="com.application.AndroidPlatform$PermissionRequestActivity" />
<receiver android:name="com.application.Alarm" /> // this is where I have included the Alarm.class
<receiver android:name="com.gluonhq.impl.charm.down.plugins.android.AlarmReceiver" />
</application>
当调用 schedule 方法时,应用程序退出...
我有 运行 adb logcat -v threadtime 并在 cmd
--------- beginning of crash
07-22 09:21:44.878 13516 13516 E AndroidRuntime: FATAL EXCEPTION: main
07-22 09:21:44.878 13516 13516 E AndroidRuntime: Process: com.application, PID: 13516
07-22 09:21:44.878 13516 13516 E AndroidRuntime: java.lang.RuntimeException: Unable to instantiate receiver com.application.Alarm: java.lang.IllegalAccessException: java.lang.Class<com.application.Alarm> is not accessible from java.lang.Class<android.app.ActivityThread>
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:2739)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.access00(ActivityThread.java:153)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1452)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:102)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.os.Looper.loop(Looper.java:154)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5529)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: Caused by: java.lang.IllegalAccessException: java.lang.Class<com.application.Alarm> is not accessible from java.lang.Class<android.app.ActivityThread>
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at java.lang.Class.newInstance(Native Method)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: at android.app.ActivityThread.handleReceiver(ActivityThread.java:2734)
07-22 09:21:44.878 13516 13516 E AndroidRuntime: ... 8 more
07-22 09:21:44.885 1804 3742 D StatusBar: onNotificationPosted: Key: 0|com.application|123456|charm://down/Id/abcd12340|10276 GroupKey: 0|com.application|123456|charm://down/Id/abcd12340|10276 Connected: true
07-22 09:21:44.885 1804 1804 D StatusBar: GroupChild: false GroupsContainsKey: false IsUpdate: false IsGroupSummary: false hasIcon: true
07-22 09:21:44.886 1804 1804 D PhoneStatusBar: addNotification pkg=com.application;basepkg=com.application;id=123456
07-22 09:21:44.888 3047 10359 I GCoreUlr: Successfully inserted 1 locations
07-22 09:21:44.922 1804 1804 W ProgressBarDelegate: Unknown Drawable subclass, src=android.graphics.drawable.ScaleDrawable@eb9196
07-22 09:21:44.922 1804 1804 W ProgressBarDelegate: Unknown Drawable subclass, src=android.graphics.drawable.ScaleDrawable@aace117
07-22 09:21:44.932 3451 3518 I octvm_klo: klo lock
我不知道为什么我不能实例化接收器 (Alarm.class),
@FXML void start()
{
try{
Schedule schedule =(Schedule) Class.forName("com.application.Schedular").newInstance();
schedule.schedule();
}
替换缩进
来自
manager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10L, pIntent);
也给indent的构造函数,传递所需的"activity"或"service"
Intent intent = new Intent(context, AlarmReceiver.class); //AlarmReceiver is an activity that will be launched after an hour
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() +
60 * 1000, pIntent); //60mins from now
您的代码并不完全适合我:我不得不将 intent
更改为 schedule()
中的 pIntent
,并将 Schedule
更改为 Class
在 Java 实现上(你如何导入它?)。除此之外,对我来说运行宁没问题(使用Android目标25),我没有任何例外。
我将 post 初始解决方案(基于您的方法),然后是更好的方法。
初步解决方案
虽然添加平台特定代码的首选方法是遵循 Charm Down 设计模式(参见 https://bitbucket.org/gluon-oss/charm-down),但让 Android 代码正常工作的一种非常快速且肮脏的方法是:
Android
Scheduler.java
package com.gluonhq.scheduler.android;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import javafxports.android.FXActivity;
public class Scheduler {
private final AlarmManager manager;
public Scheduler() {
manager = (AlarmManager) FXActivity.getInstance().getSystemService(Context.ALARM_SERVICE);
Intent indent = new Intent(FXActivity.getInstance(), AlarmReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(FXActivity.getInstance(), 0, indent, 0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 2000, pIntent);
}
}
AlarmReceiver.java
package com.gluonhq.scheduler.android;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm ON", Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gluonhq.scheduler" android:versionCode="1" android:versionName="1.0">
<supports-screens android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="25"/>
<application android:label="GluonScheduler" android:name="android.support.multidex.MultiDexApplication" android:icon="@mipmap/ic_launcher">
<activity android:name="javafxports.android.FXActivity" android:label="GluonScheduler" android:configChanges="orientation|screenSize">
<meta-data android:name="main.class" android:value="com.gluonhq.scheduler.GluonScheduler"/>
<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="com.gluonhq.scheduler.android.AlarmReceiver" />
</application>
</manifest
Main/Java
这是使用 Gluon IDE 插件的单一视图模板项目的基本视图:
胶子Scheduler.java
package com.gluonhq.scheduler;
import com.gluonhq.charm.glisten.application.MobileApplication;
import com.gluonhq.charm.glisten.visual.Swatch;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class GluonScheduler extends MobileApplication {
public static final String BASIC_VIEW = HOME_VIEW;
@Override
public void init() {
addViewFactory(BASIC_VIEW, () -> new BasicView(BASIC_VIEW));
}
@Override
public void postInit(Scene scene) {
Swatch.BLUE.assignTo(scene);
((Stage) scene.getWindow()).getIcons().add(new Image(GluonScheduler.class.getResourceAsStream("/icon.png")));
}
}
BasicView.java
package com.gluonhq.scheduler;
import com.gluonhq.charm.glisten.control.AppBar;
import com.gluonhq.charm.glisten.control.Icon;
import com.gluonhq.charm.glisten.mvc.View;
import com.gluonhq.charm.glisten.visual.MaterialDesignIcon;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
public class BasicView extends View {
public BasicView(String name) {
super(name);
Button button = new Button("Schedule task");
button.setGraphic(new Icon(MaterialDesignIcon.ALARM_ON));
button.setOnAction(e -> {
try {
Class c = Class.forName("com.gluonhq.scheduler.android.Scheduler");
c.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
Logger.getLogger(BasicView.class.getName()).log(Level.SEVERE, null, ex);
}
});
VBox controls = new VBox(button);
controls.setAlignment(Pos.CENTER);
setCenter(controls);
}
@Override
protected void updateAppBar(AppBar appBar) {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> System.out.println("Menu")));
appBar.setTitleText("Basic View");
}
}
build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.6'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.gluonhq.scheduler.GluonScheduler'
dependencies {
compile 'com.gluonhq:charm:4.3.5'
}
jfxmobile {
downConfig {
version = '3.3.0'
// Do not edit the line below. Use Gluon Mobile Settings in your project context menu instead
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
android {
manifest = 'src/android/AndroidManifest.xml'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
部署到您的 Android 设备 (./gradlew androidInstall
) 和 运行。按下按钮,两秒后你会看到吐司:
首选解决方案
报警服务
虽然上面的代码有效,但是使用起来不是很方便Class.forName
。
按照 Charm Down 服务(例如 LocalNotification),我将改为这样做(您必须保持相同的包名称):
Java
AlarmService.java
package com.gluonhq.charm.down.plugins;
public interface AlarmService {
public void schedule();
}
AlarmServiceFactory.java
package com.gluonhq.charm.down.plugins;
import com.gluonhq.charm.down.DefaultServiceFactory;
public class AlarmServiceFactory extends DefaultServiceFactory<AlarmService> {
public AlarmServiceFactory() {
super(AlarmService.class);
}
}
Android
AndroidAlarmService.java
package com.gluonhq.charm.down.plugins.android;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import com.gluonhq.charm.down.plugins.AlarmService;
import com.gluonhq.scheduler.android.AlarmReceiver;
import javafxports.android.FXActivity;
public class AndroidAlarmService implements AlarmService {
private final AlarmManager manager;
private final FXActivity activity;
public AndroidAlarmService() {
activity = FXActivity.getInstance();
manager = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
}
@Override
public void schedule() {
Intent indent = new Intent(activity, AlarmReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(activity, 0, indent, 0);
manager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 2000, pIntent);
}
}
(保持与上面相同的AlarmReceiver
class)。
最后,在您看来:
BasicView.java
button.setOnAction(e ->
Services.get(AlarmService.class).ifPresent(AlarmService::schedule));
现在可以再次部署和运行,结果是一样的。但显然,这种首选方式具有更多优势。
- 使用该服务,您还可以 运行 在桌面上或部署到 iOS:该应用程序将运行(单击按钮时它不会执行任何操作)。
- 如果需要,您可以实施桌面和 iOS 解决方案。
- 您可以通过界面轻松添加更多功能。