android: fix exit on background
This commit is contained in:
parent
f95645ea81
commit
23712ca361
5 changed files with 83 additions and 36 deletions
|
@ -28,8 +28,13 @@ public class BackgroundService extends Service {
|
|||
NotificationManager manager = getSystemService(NotificationManager.class);
|
||||
manager.notify(SYNC_STATUS_NOTIFICATION_ID, mNotificationBuilder.build());
|
||||
|
||||
if (exitAppAfterNodeStop()) {
|
||||
sendBroadcast(new Intent(MainActivity.FINISH_ACTIVITY_ACTION));
|
||||
mStopped = true;
|
||||
}
|
||||
|
||||
if (!mStopped) {
|
||||
mHandler.postDelayed(this, 500);
|
||||
mHandler.postDelayed(this, 300);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -127,4 +132,5 @@ public class BackgroundService extends Service {
|
|||
|
||||
private native String getSyncStatusText();
|
||||
private native String getSyncTitle();
|
||||
private native boolean exitAppAfterNodeStop();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package mw.gri.android;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
|
@ -13,10 +17,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
|
||||
public class MainActivity extends GameActivity {
|
||||
|
||||
public static String FINISH_ACTIVITY_ACTION = "MainActivity.finish";
|
||||
|
||||
static {
|
||||
System.loadLibrary("grim");
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent i) {
|
||||
if (i.getAction().equals(FINISH_ACTIVITY_ACTION)) {
|
||||
onExit();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// Setup HOME environment variable for native code configurations.
|
||||
|
@ -40,6 +55,9 @@ public class MainActivity extends GameActivity {
|
|||
}
|
||||
onDisplayCutoutsChanged(Utils.getDisplayCutouts(this));
|
||||
|
||||
// Register receiver to finish activity from the BackgroundService.
|
||||
registerReceiver(mBroadcastReceiver, new IntentFilter(FINISH_ACTIVITY_ACTION));
|
||||
|
||||
// Start notification service.
|
||||
BackgroundService.start(this);
|
||||
}
|
||||
|
@ -62,10 +80,12 @@ public class MainActivity extends GameActivity {
|
|||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
unregisterReceiver(mBroadcastReceiver);
|
||||
|
||||
if (!mManualExit) {
|
||||
onTermination();
|
||||
}
|
||||
// Temp fix: kill process after 3 seconds to prevent app hanging at next launch
|
||||
// Temp fix: kill process after 3 seconds to prevent app hanging at next launch.
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
|
@ -80,8 +100,12 @@ public class MainActivity extends GameActivity {
|
|||
mActivityDestroyed.set(true);
|
||||
}
|
||||
|
||||
// Called from native code
|
||||
// Called from native code.
|
||||
public void onExit() {
|
||||
// Return if exit was already requested.
|
||||
if (mManualExit) {
|
||||
return;
|
||||
}
|
||||
mManualExit = true;
|
||||
BackgroundService.stop(this);
|
||||
finish();
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
use egui::{Context, Stroke};
|
||||
use egui::os::OperatingSystem;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::screens::Root;
|
||||
use crate::node::Node;
|
||||
|
||||
pub struct PlatformApp<Platform> {
|
||||
pub(crate) app: App,
|
||||
|
@ -132,3 +133,28 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onBackButtonPress(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
_activity: jni::objects::JObject,
|
||||
) {
|
||||
Navigator::back();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
/// Calling on unexpected Android application termination (removal from recent apps).
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onTermination(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
_activity: jni::objects::JObject,
|
||||
) {
|
||||
Node::stop(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,12 +80,9 @@ impl Root {
|
|||
}
|
||||
ui.add_space(16.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
Spinner::new().size(48.0).color(Colors::GRAY).ui(ui);
|
||||
Spinner::new().size(48.0).color(Colors::GOLD).ui(ui);
|
||||
ui.add_space(12.0);
|
||||
ui.label(RichText::new(t!("sync_status.shutdown"))
|
||||
.size(17.0)
|
||||
.color(Colors::TEXT)
|
||||
);
|
||||
ui.label(t!("sync_status.shutdown"));
|
||||
});
|
||||
ui.add_space(10.0);
|
||||
} else {
|
||||
|
@ -103,7 +100,7 @@ impl Root {
|
|||
App::exit(frame, cb);
|
||||
modal.close();
|
||||
} else {
|
||||
Node::stop();
|
||||
Node::stop(true);
|
||||
modal.disable_closing();
|
||||
self.show_exit_progress = true;
|
||||
}
|
||||
|
@ -123,9 +120,9 @@ impl Root {
|
|||
}
|
||||
|
||||
fn show_current_screen(&mut self,
|
||||
ui: &mut egui::Ui,
|
||||
frame: &mut eframe::Frame,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
ui: &mut egui::Ui,
|
||||
frame: &mut eframe::Frame,
|
||||
cb: &dyn PlatformCallbacks) {
|
||||
let Self { screens, .. } = self;
|
||||
for screen in screens.iter_mut() {
|
||||
if Navigator::is_current(&screen.id()) {
|
||||
|
@ -147,15 +144,3 @@ impl Root {
|
|||
(is_panel_open, panel_width)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onBackButtonPress(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
_activity: jni::objects::JObject,
|
||||
) {
|
||||
Navigator::back();
|
||||
}
|
|
@ -25,7 +25,7 @@ use grin_config::config;
|
|||
use grin_core::global;
|
||||
use grin_core::global::ChainTypes;
|
||||
use grin_servers::{Server, ServerStats};
|
||||
use jni::sys::jstring;
|
||||
use jni::sys::{jboolean, jstring};
|
||||
use lazy_static::lazy_static;
|
||||
use log::info;
|
||||
|
||||
|
@ -46,6 +46,8 @@ pub struct Node {
|
|||
restart_needed: AtomicBool,
|
||||
/// Thread flag to stop the server.
|
||||
stop_needed: AtomicBool,
|
||||
/// Flag to check if app exit is needed after server stop.
|
||||
exit_after_stop: AtomicBool
|
||||
}
|
||||
|
||||
impl Default for Node {
|
||||
|
@ -56,14 +58,16 @@ impl Default for Node {
|
|||
starting: AtomicBool::new(false),
|
||||
restart_needed: AtomicBool::new(false),
|
||||
stop_needed: AtomicBool::new(false),
|
||||
exit_after_stop: AtomicBool::new(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node {
|
||||
/// Stop the [`Server`].
|
||||
pub fn stop() {
|
||||
/// Stop the [`Server`] and setup exit flag after if needed.
|
||||
pub fn stop(exit_after_stop: bool) {
|
||||
NODE_STATE.stop_needed.store(true, Ordering::Relaxed);
|
||||
NODE_STATE.exit_after_stop.store(exit_after_stop, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Start [`Server`] with provided chain type.
|
||||
|
@ -190,14 +194,14 @@ impl Node {
|
|||
|
||||
/// Get synchronization status i18n text.
|
||||
pub fn get_sync_status_text() -> String {
|
||||
if Node::is_starting() {
|
||||
return t!("sync_status.initial")
|
||||
};
|
||||
|
||||
if Node::is_stopping() {
|
||||
return t!("sync_status.shutdown")
|
||||
};
|
||||
|
||||
if Node::is_starting() {
|
||||
return t!("sync_status.initial")
|
||||
};
|
||||
|
||||
if Node::is_restarting() {
|
||||
return t!("sync_status.server_restarting")
|
||||
}
|
||||
|
@ -440,11 +444,13 @@ pub extern "C" fn Java_mw_gri_android_BackgroundService_getSyncTitle(
|
|||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
/// Calling on unexpected Android application termination (removal from recent apps).
|
||||
pub extern "C" fn Java_mw_gri_android_MainActivity_onTermination(
|
||||
/// Check if app exit is needed after node stop.
|
||||
pub extern "C" fn Java_mw_gri_android_BackgroundService_exitAppAfterNodeStop(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
_activity: jni::objects::JObject,
|
||||
) {
|
||||
Node::stop();
|
||||
) -> jboolean {
|
||||
let exit_after_stop = NODE_STATE.exit_after_stop.load(Ordering::Relaxed);
|
||||
let is_app_exit_needed = !Node::is_running() && exit_after_stop;
|
||||
return is_app_exit_needed as jboolean;
|
||||
}
|
Loading…
Reference in a new issue