Skip to content

Commit

Permalink
Merge pull request #256 from privacybydesign/ios-call-irmagobridge-stop
Browse files Browse the repository at this point in the history
Fix: irmagobridge's Stop method not called on iOS
  • Loading branch information
ivard authored Nov 22, 2023
2 parents 545cd73 + 53a634f commit 7ecf89f
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Fixed
- irmagobridge's Stop method is not called on iOS when the app is terminated

## [7.5.3] - 2023-11-16
### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ public class MainActivity extends FlutterActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
// We do both these steps before calling parent, to ensure that this always happens before starting the flutter
// engine and attaching its plugins
// We do both these steps before calling parent, to ensure that this always
// happens before starting the flutter engine and attaching its plugins

// Initialize the Go binding here by calling a seemingly noop function
Irmagobridge.prestart();

// Capture initial url only during onCreate, for use during first engine instantiation
// Capture initial url only during onCreate, for use during first engine
// instantiation
this.initialURL = getIntent().getData();

// Hand of to parent
Expand All @@ -48,7 +49,9 @@ public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
flutterEngine.getPlugins().add(new IIABPlugin());

// Start up the irmamobile bridge
MethodChannel channel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "irma.app/irma_mobile_bridge");
MethodChannel channel = new MethodChannel(
flutterEngine.getDartExecutor().getBinaryMessenger(),
"irma.app/irma_mobile_bridge");
bridge = new IrmaMobileBridge(this, this, channel, initialURL);
channel.setMethodCallHandler(bridge);
initialURL = null; // Ensure we only use the initialURL once
Expand All @@ -58,12 +61,16 @@ public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (bridge != null) bridge.onNewIntent(intent);
if (bridge != null) {
bridge.onNewIntent(intent);
}
}

@Override
protected void onDestroy() {
Irmagobridge.stop();
if (bridge != null) {
bridge.stop();
}
super.onDestroy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,8 @@ public void debugLog(String message) {
if (debug)
System.out.printf("[IrmaMobileBridgePlugin] %s\n", message);
}

public void stop() {
Irmagobridge.stop();
}
}
1 change: 1 addition & 0 deletions ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@
PRODUCT_BUNDLE_IDENTIFIER = foundation.privacybydesign.irmamob.alpha;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "Local development profile";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = On;
Expand Down
20 changes: 12 additions & 8 deletions ios/Runner/IrmaMobileBridgePlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class IrmaMobileBridgePlugin: NSObject, IrmagobridgeIrmaMobileBridgeProtocol, Fl
private var nativeError: String?
private var appReady: Bool


/// Private constructor. This constructor is called indirectly via register (see below).
/// - Parameters:
/// - channel: Channel to send messages to the Flutter side
Expand All @@ -21,7 +20,6 @@ class IrmaMobileBridgePlugin: NSObject, IrmagobridgeIrmaMobileBridgeProtocol, Fl
super.init()
}


/// Calls the Start method of irmagobridge.
private func start() {
let bundlePath = Bundle.main.bundlePath
Expand Down Expand Up @@ -54,7 +52,12 @@ class IrmaMobileBridgePlugin: NSObject, IrmagobridgeIrmaMobileBridgeProtocol, Fl

IrmagobridgeStart(self, libraryPath, bundlePath, TEE(), aesKey)
}


/// Calls the Stop method of irmagobridge.
private func stop() {
debugLog("Stopping irmago")
IrmagobridgeStop()
}

/// Implements the register method of the FlutterPlugin interface. This method is called by Flutter to bootstrap the plugin.
/// - Parameter registrar: Registration context of the Flutter plugin
Expand All @@ -68,8 +71,7 @@ class IrmaMobileBridgePlugin: NSObject, IrmagobridgeIrmaMobileBridgeProtocol, Fl
registrar.addMethodCallDelegate(instance, channel: channel)
registrar.addApplicationDelegate(instance)
}



/// Implements the handle method of the FlutterPlugin interface. This method is called when invokeMethod is called on the plugin's method channel in Flutter/Dart.
/// - Parameters:
/// - call: Object that specifies the method that should be handled and the corresponding arguments
Expand All @@ -94,18 +96,16 @@ class IrmaMobileBridgePlugin: NSObject, IrmagobridgeIrmaMobileBridgeProtocol, Fl
result(nil)
}


/// Implements the DebugLog method of the IrmaMobileBridge interface.
/// - Parameter message: Message to be logged
func debugLog(_ message: String?) {
#if DEBUG
if message != nil {
NSLog("[IrmaMobileBridgePlugin] \(message)")
NSLog("[IrmaMobileBridgePlugin] \(message!)")
}
#endif
}


/// Implements the DispatchFromGo method of the IrmaMobileBridge interface.
/// - Parameters:
/// - name: name of the method being invoked
Expand Down Expand Up @@ -160,4 +160,8 @@ extension IrmaMobileBridgePlugin: FlutterApplicationLifeCycleDelegate {
}
return false
}

public func applicationWillTerminate(_ application: UIApplication) {
stop()
}
}
6 changes: 5 additions & 1 deletion lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,11 @@ class AppState extends State<App> with WidgetsBindingObserver {
),
builder: (context, snapshot) {
if (!snapshot.hasData || !_privacyScreenLoaded) {
return const SplashScreen();
// Delay the loading indicator a bit, so it doesn't flash on screen.
return FutureBuilder(
future: Future.delayed(const Duration(seconds: 3), () => true),
builder: (context, isLoading) => SplashScreen(isLoading: isLoading.data ?? false),
);
}

final displayRootedWarning = snapshot.data!.a;
Expand Down
36 changes: 23 additions & 13 deletions lib/src/screens/loading/loading_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,28 @@ class _LoadingScreenState extends State<LoadingScreen> {
}

@override
Widget build(BuildContext context) => StreamBuilder<ErrorEvent>(
stream: IrmaRepositoryProvider.of(context).getFatalErrors(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final error = snapshot.data;
return ErrorScreen.fromEvent(
error: error!,
);
}
return const SplashScreen(
isLoading: true,
Widget build(BuildContext context) {
final repo = IrmaRepositoryProvider.of(context);
return StreamBuilder<ErrorEvent>(
stream: repo.getFatalErrors().timeout(
const Duration(seconds: 15),
onTimeout: (_) => repo.dispatch(ErrorEvent(
exception: 'Timeout: enrollment status could not be determined within 15 seconds',
stack: '',
fatal: true,
)),
),
builder: (context, snapshot) {
if (snapshot.hasData) {
final error = snapshot.data;
return ErrorScreen.fromEvent(
error: error!,
);
},
);
}
return const SplashScreen(
isLoading: true,
);
},
);
}
}

0 comments on commit 7ecf89f

Please sign in to comment.