android: node control and exit from the notification
|
@ -3,12 +3,14 @@
|
||||||
>
|
>
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||||
|
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
|
@ -19,6 +21,8 @@
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Main">
|
android:theme="@style/Theme.Main">
|
||||||
|
|
||||||
|
<receiver android:name=".NotificationActionsReceiver"/>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name=".FileProvider"
|
android:name=".FileProvider"
|
||||||
android:authorities="mw.gri.android.fileprovider"
|
android:authorities="mw.gri.android.fileprovider"
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
package mw.gri.android;
|
package mw.gri.android;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.*;
|
import android.app.*;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class BackgroundService extends Service {
|
import static android.app.Notification.EXTRA_NOTIFICATION_ID;
|
||||||
|
|
||||||
|
public class BackgroundService extends Service {
|
||||||
private static final String TAG = BackgroundService.class.getSimpleName();
|
private static final String TAG = BackgroundService.class.getSimpleName();
|
||||||
|
|
||||||
private PowerManager.WakeLock mWakeLock;
|
private PowerManager.WakeLock mWakeLock;
|
||||||
|
@ -18,12 +22,38 @@ public class BackgroundService extends Service {
|
||||||
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
||||||
private boolean mStopped = false;
|
private boolean mStopped = false;
|
||||||
|
|
||||||
private static final int SYNC_STATUS_NOTIFICATION_ID = 1;
|
private static final int NOTIFICATION_ID = 1;
|
||||||
private NotificationCompat.Builder mNotificationBuilder;
|
private NotificationCompat.Builder mNotificationBuilder;
|
||||||
|
|
||||||
private String mNotificationContentText = "";
|
private String mNotificationContentText = "";
|
||||||
|
private Boolean mCanStart = null;
|
||||||
|
private Boolean mCanStop = null;
|
||||||
|
|
||||||
|
public static final String ACTION_START_NODE = "start_node";
|
||||||
|
public static final String ACTION_STOP_NODE = "stop_node";
|
||||||
|
public static final String ACTION_EXIT = "exit";
|
||||||
|
public static final String ACTION_REFRESH = "refresh";
|
||||||
|
public static final String ACTION_STOP = "stop";
|
||||||
|
|
||||||
|
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (intent.getAction().equals(ACTION_STOP)) {
|
||||||
|
mStopped = true;
|
||||||
|
// Remove actions buttons.
|
||||||
|
mNotificationBuilder.mActions.clear();
|
||||||
|
NotificationManager manager = getSystemService(NotificationManager.class);
|
||||||
|
manager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
|
||||||
|
} else {
|
||||||
|
mHandler.removeCallbacks(mUpdateSyncStatus);
|
||||||
|
mHandler.post(mUpdateSyncStatus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final Runnable mUpdateSyncStatus = new Runnable() {
|
private final Runnable mUpdateSyncStatus = new Runnable() {
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mStopped) {
|
if (mStopped) {
|
||||||
|
@ -31,11 +61,11 @@ public class BackgroundService extends Service {
|
||||||
}
|
}
|
||||||
// Update sync status at notification.
|
// Update sync status at notification.
|
||||||
String syncStatusText = getSyncStatusText();
|
String syncStatusText = getSyncStatusText();
|
||||||
if (!mNotificationContentText.equals(syncStatusText)) {
|
boolean textChanged = !mNotificationContentText.equals(syncStatusText);
|
||||||
|
if (textChanged) {
|
||||||
mNotificationContentText = syncStatusText;
|
mNotificationContentText = syncStatusText;
|
||||||
mNotificationBuilder.setContentText(mNotificationContentText);
|
mNotificationBuilder.setContentText(mNotificationContentText);
|
||||||
NotificationManager manager = getSystemService(NotificationManager.class);
|
mNotificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(mNotificationContentText));
|
||||||
manager.notify(SYNC_STATUS_NOTIFICATION_ID, mNotificationBuilder.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send broadcast to MainActivity if exit from the app is needed after node stop.
|
// Send broadcast to MainActivity if exit from the app is needed after node stop.
|
||||||
|
@ -44,13 +74,60 @@ public class BackgroundService extends Service {
|
||||||
mStopped = true;
|
mStopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat notification update if service is not stopped.
|
|
||||||
if (!mStopped) {
|
if (!mStopped) {
|
||||||
mHandler.postDelayed(this, 500);
|
boolean canStart = canStartNode();
|
||||||
|
boolean canStop = canStopNode();
|
||||||
|
|
||||||
|
boolean buttonsChanged = mCanStart == null || mCanStop == null ||
|
||||||
|
mCanStart != canStart || mCanStop != canStop;
|
||||||
|
mCanStart = canStart;
|
||||||
|
mCanStop = canStop;
|
||||||
|
if (buttonsChanged) {
|
||||||
|
mNotificationBuilder.mActions.clear();
|
||||||
|
|
||||||
|
// Set up buttons to start/stop node.
|
||||||
|
Intent startStopIntent = new Intent(BackgroundService.this, NotificationActionsReceiver.class);
|
||||||
|
if (Build.VERSION.SDK_INT > 25) {
|
||||||
|
startStopIntent.putExtra(EXTRA_NOTIFICATION_ID, NOTIFICATION_ID);
|
||||||
|
}
|
||||||
|
if (canStart) {
|
||||||
|
startStopIntent.setAction(ACTION_START_NODE);
|
||||||
|
PendingIntent i = PendingIntent
|
||||||
|
.getBroadcast(BackgroundService.this, 1, startStopIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
mNotificationBuilder.addAction(R.drawable.ic_start, getStartText(), i);
|
||||||
|
} else if (canStop) {
|
||||||
|
startStopIntent.setAction(ACTION_STOP_NODE);
|
||||||
|
PendingIntent i = PendingIntent
|
||||||
|
.getBroadcast(BackgroundService.this, 1, startStopIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
mNotificationBuilder.addAction(R.drawable.ic_stop, getStopText(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a button to exit from the app.
|
||||||
|
if (canStart || canStop) {
|
||||||
|
Intent exitIntent = new Intent(BackgroundService.this, NotificationActionsReceiver.class);
|
||||||
|
if (Build.VERSION.SDK_INT > 25) {
|
||||||
|
exitIntent.putExtra(EXTRA_NOTIFICATION_ID, NOTIFICATION_ID);
|
||||||
|
}
|
||||||
|
exitIntent.setAction(ACTION_EXIT);
|
||||||
|
PendingIntent i = PendingIntent
|
||||||
|
.getBroadcast(BackgroundService.this, 1, exitIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
mNotificationBuilder.addAction(R.drawable.ic_close, getExitText(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update notification.
|
||||||
|
if (textChanged || buttonsChanged) {
|
||||||
|
NotificationManager manager = getSystemService(NotificationManager.class);
|
||||||
|
manager.notify(NOTIFICATION_ID, mNotificationBuilder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat notification update.
|
||||||
|
mHandler.postDelayed(this, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@SuppressLint({"WakelockTimeout", "UnspecifiedRegisterReceiverFlag"})
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
if (mStopped) {
|
if (mStopped) {
|
||||||
|
@ -78,15 +155,20 @@ public class BackgroundService extends Service {
|
||||||
mNotificationBuilder = new NotificationCompat.Builder(this, TAG)
|
mNotificationBuilder = new NotificationCompat.Builder(this, TAG)
|
||||||
.setContentTitle(this.getSyncTitle())
|
.setContentTitle(this.getSyncTitle())
|
||||||
.setContentText(this.getSyncStatusText())
|
.setContentText(this.getSyncStatusText())
|
||||||
|
.setStyle(new NotificationCompat.BigTextStyle().bigText(this.getSyncStatusText()))
|
||||||
.setSmallIcon(R.drawable.ic_stat_name)
|
.setSmallIcon(R.drawable.ic_stat_name)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||||
.setContentIntent(pendingIntent);
|
.setContentIntent(pendingIntent);
|
||||||
Notification notification = mNotificationBuilder.build();
|
Notification notification = mNotificationBuilder.build();
|
||||||
|
|
||||||
// Start service at foreground state to prevent killing by system.
|
// Start service at foreground state to prevent killing by system.
|
||||||
startForeground(SYNC_STATUS_NOTIFICATION_ID, notification);
|
startForeground(NOTIFICATION_ID, notification);
|
||||||
|
|
||||||
// Update sync status at notification.
|
// Update sync status at notification.
|
||||||
mHandler.post(mUpdateSyncStatus);
|
mHandler.post(mUpdateSyncStatus);
|
||||||
|
|
||||||
|
// Register receiver to refresh notifications by intent.
|
||||||
|
registerReceiver(mReceiver, new IntentFilter(ACTION_REFRESH));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -117,22 +199,26 @@ public class BackgroundService extends Service {
|
||||||
|
|
||||||
// Stop updating the notification.
|
// Stop updating the notification.
|
||||||
mHandler.removeCallbacks(mUpdateSyncStatus);
|
mHandler.removeCallbacks(mUpdateSyncStatus);
|
||||||
|
unregisterReceiver(mReceiver);
|
||||||
|
clearNotification();
|
||||||
|
|
||||||
// Remove service from foreground state.
|
// Remove service from foreground state.
|
||||||
stopForeground(Service.STOP_FOREGROUND_REMOVE);
|
stopForeground(Service.STOP_FOREGROUND_REMOVE);
|
||||||
|
|
||||||
// Remove notification.
|
// Release wake lock to allow CPU to sleep at background.
|
||||||
|
if (mWakeLock != null && mWakeLock.isHeld()) {
|
||||||
|
mWakeLock.release();
|
||||||
|
mWakeLock = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove notification.
|
||||||
|
private void clearNotification() {
|
||||||
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
NotificationManager notificationManager = getSystemService(NotificationManager.class);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
notificationManager.deleteNotificationChannel(TAG);
|
notificationManager.deleteNotificationChannel(TAG);
|
||||||
}
|
}
|
||||||
notificationManager.cancel(SYNC_STATUS_NOTIFICATION_ID);
|
notificationManager.cancel(NOTIFICATION_ID);
|
||||||
|
|
||||||
// Release wake lock to allow CPU to sleep at background.
|
|
||||||
if (mWakeLock.isHeld()) {
|
|
||||||
mWakeLock.release();
|
|
||||||
mWakeLock = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the service.
|
// Start the service.
|
||||||
|
@ -165,10 +251,24 @@ public class BackgroundService extends Service {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get sync status text for notification from native code.
|
// Get sync status text for notification.
|
||||||
private native String getSyncStatusText();
|
private native String getSyncStatusText();
|
||||||
// Get sync title text for notification from native code.
|
// Get sync title text for notification.
|
||||||
private native String getSyncTitle();
|
private native String getSyncTitle();
|
||||||
// Check if app from the app is needed after node stop from native code.
|
|
||||||
|
// Get start text for notification.
|
||||||
|
private native String getStartText();
|
||||||
|
// Get stop text for notification.
|
||||||
|
private native String getStopText();
|
||||||
|
|
||||||
|
// Check if start node is possible.
|
||||||
|
private native boolean canStartNode();
|
||||||
|
// Check if stop node is possible.
|
||||||
|
private native boolean canStopNode();
|
||||||
|
|
||||||
|
// Get exit text for notification.
|
||||||
|
private native String getExitText();
|
||||||
|
|
||||||
|
// Check if app from the app is needed after node stop.
|
||||||
private native boolean exitAppAfterNodeStop();
|
private native boolean exitAppAfterNodeStop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package mw.gri.android;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
public class NotificationActionsReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent i) {
|
||||||
|
String a = i.getAction();
|
||||||
|
if (a.equals(BackgroundService.ACTION_START_NODE)) {
|
||||||
|
startNode();
|
||||||
|
context.sendBroadcast(new Intent(BackgroundService.ACTION_REFRESH));
|
||||||
|
} else if (a.equals(BackgroundService.ACTION_STOP_NODE)) {
|
||||||
|
stopNode();
|
||||||
|
context.sendBroadcast(new Intent(BackgroundService.ACTION_REFRESH));
|
||||||
|
} else {
|
||||||
|
if (isNodeRunning()) {
|
||||||
|
stopNodeToExit();
|
||||||
|
context.sendBroadcast(new Intent(BackgroundService.ACTION_REFRESH));
|
||||||
|
} else {
|
||||||
|
context.sendBroadcast(new Intent(MainActivity.STOP_APP_ACTION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start integrated node.
|
||||||
|
native void startNode();
|
||||||
|
// Stop integrated node.
|
||||||
|
native void stopNode();
|
||||||
|
// Stop node and exit from the app.
|
||||||
|
native void stopNodeToExit();
|
||||||
|
// Check if node is running.
|
||||||
|
native boolean isNodeRunning();
|
||||||
|
}
|
15
android/app/src/main/res/drawable-anydpi/ic_close.xml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#FFFFFF">
|
||||||
|
<group android:scaleX="0.92"
|
||||||
|
android:scaleY="0.92"
|
||||||
|
android:translateX="0.96"
|
||||||
|
android:translateY="0.96">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
15
android/app/src/main/res/drawable-anydpi/ic_start.xml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#FFFFFF">
|
||||||
|
<group android:scaleX="0.92"
|
||||||
|
android:scaleY="0.92"
|
||||||
|
android:translateX="0.96"
|
||||||
|
android:translateY="0.96">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M8,5v14l11,-7z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
15
android/app/src/main/res/drawable-anydpi/ic_stop.xml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#FFFFFF">
|
||||||
|
<group android:scaleX="0.92"
|
||||||
|
android:scaleY="0.92"
|
||||||
|
android:translateX="0.96"
|
||||||
|
android:translateY="0.96">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M6,6h12v12H6z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
BIN
android/app/src/main/res/drawable-hdpi/ic_close.png
Normal file
After Width: | Height: | Size: 345 B |
BIN
android/app/src/main/res/drawable-hdpi/ic_start.png
Normal file
After Width: | Height: | Size: 272 B |
BIN
android/app/src/main/res/drawable-hdpi/ic_stop.png
Normal file
After Width: | Height: | Size: 140 B |
BIN
android/app/src/main/res/drawable-mdpi/ic_close.png
Normal file
After Width: | Height: | Size: 239 B |
BIN
android/app/src/main/res/drawable-mdpi/ic_start.png
Normal file
After Width: | Height: | Size: 171 B |
BIN
android/app/src/main/res/drawable-mdpi/ic_stop.png
Normal file
After Width: | Height: | Size: 119 B |
BIN
android/app/src/main/res/drawable-xhdpi/ic_close.png
Normal file
After Width: | Height: | Size: 383 B |
BIN
android/app/src/main/res/drawable-xhdpi/ic_start.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
android/app/src/main/res/drawable-xhdpi/ic_stop.png
Normal file
After Width: | Height: | Size: 168 B |
BIN
android/app/src/main/res/drawable-xxhdpi/ic_close.png
Normal file
After Width: | Height: | Size: 481 B |
BIN
android/app/src/main/res/drawable-xxhdpi/ic_start.png
Normal file
After Width: | Height: | Size: 374 B |
BIN
android/app/src/main/res/drawable-xxhdpi/ic_stop.png
Normal file
After Width: | Height: | Size: 197 B |
122
src/node/node.rs
|
@ -658,6 +658,128 @@ pub extern "C" fn Java_mw_gri_android_BackgroundService_getSyncTitle(
|
||||||
return j_text.unwrap().into_raw();
|
return j_text.unwrap().into_raw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Get start text for Android notification in Java string format.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_BackgroundService_getStartText(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) -> jni::sys::jstring {
|
||||||
|
let j_text = _env.new_string(t!("network_settings.enable"));
|
||||||
|
return j_text.unwrap().into_raw();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Get stop text for Android notification in Java string format.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_BackgroundService_getStopText(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) -> jni::sys::jstring {
|
||||||
|
let j_text = _env.new_string(t!("network_settings.disable"));
|
||||||
|
return j_text.unwrap().into_raw();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Get exit text for Android notification in Java string format.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_BackgroundService_getExitText(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) -> jni::sys::jstring {
|
||||||
|
let j_text = _env.new_string(t!("modal_exit.exit"));
|
||||||
|
return j_text.unwrap().into_raw();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Check if node launch is possible.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_BackgroundService_canStartNode(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) -> jni::sys::jboolean {
|
||||||
|
let loading = Node::is_stopping() || Node::is_restarting() || Node::is_starting();
|
||||||
|
return (!loading && !Node::is_running()) as jni::sys::jboolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Check if node stop is possible.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_BackgroundService_canStopNode(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) -> jni::sys::jboolean {
|
||||||
|
let loading = Node::is_stopping() || Node::is_restarting() || Node::is_starting();
|
||||||
|
return (!loading && Node::is_running()) as jni::sys::jboolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Check if node stop is possible.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_NotificationActionsReceiver_isNodeRunning(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) -> jni::sys::jboolean {
|
||||||
|
return Node::is_running() as jni::sys::jboolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Start node from Android Java code.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_NotificationActionsReceiver_startNode(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) {
|
||||||
|
Node::start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Stop node from Android Java code.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_NotificationActionsReceiver_stopNode(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) {
|
||||||
|
Node::stop(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[no_mangle]
|
||||||
|
/// Stop node from Android Java code.
|
||||||
|
pub extern "C" fn Java_mw_gri_android_NotificationActionsReceiver_stopNodeToExit(
|
||||||
|
_env: jni::JNIEnv,
|
||||||
|
_class: jni::objects::JObject,
|
||||||
|
_activity: jni::objects::JObject,
|
||||||
|
) {
|
||||||
|
Node::stop(true);
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|