플러터에서 WidgetBindingObserver 를 이용해 앱이 백그라운드인지 포그라운드인지 등등을 알 수 있다.
하지만 앱이 꺼졌을 때 detach가 감지되지 않았다.
그래서 네이티브단에서 감지하여야 한다.
MethodChannel을 이용해서 앱이 종료되었을 때 플러터로 값을 넘기고 앱이 종료되게 해야한다.
플러터
getx컨트롤러 이용
init부분에 MethodChannel 수신 코드 등록
class MyController extends GetxController {
final MethodChannel _methodChannel = const MethodChannel("my.channel"); // MethodChannel
@override
void onInit() {
super.onInit();
// methodChannel 수신
_methodChannel.setMethodCallHandler((call) async {
if (call.arguments == "onDestroy") {
...
}
if (call.arguments == "applicationWillTerminate") {
...
}
});
}
@override
void onClose() {
super.onClose();
}
}
안드로이드
MethodChannel을 선언하고 configureFlutterEngine부분에 세팅해준다.
앱이 시작되면 configureFlutterEngine부분에서 플러터엔진을 초기화하는 단계를 거치기 때문에 이 메소드를 오버라이드해서 초기 세팅을 해주면 된다.
그리고 onDestory()를 오버라이드하여 MethodChannel을 이용해 앱이 종료될 때 플러터로 값을 던지게 해준다.
class MainActivity: FlutterActivity() {
// MethodChannel 선언
lateinit var methodChannel: MethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
// MethodChannel 세팅
methodChannel = MethodChannel(
flutterEngine.dartExecutor,
"my.channel"
)
// MethodChannel 수신
methodChannel.setMethodCallHandler { call, result ->
result.success("result: ${call.method}")
}
}
override fun onDestroy() {
// 앱 종료 시 플러터로 값 전달
methodChannel.invokeMethod("invokeMethod", "onDestroy")
super.onDestroy()
}
}
하지만 onDestroy()가 실행될 때 플러터로 값이 전달되지 않았다.
특히 methodChannel이 파괴되어 찾지 못한다는 오류가 떴다. 그래서 쓰레드를 잠시 멈춰주는 코드를 추가하였다.
override fun onDestroy() {
// 앱 종료 시 플러터로 값 전달
methodChannel.invokeMethod("invokeMethod", "onDestroy")
Thread.sleep(2000) // 메인 쓰레드 잠시 멈추기
Log.d("onDestroy","onDestroy")
super.onDestroy()
}
IOS
똑같이 methodChannel을 선언하고 세팅한다.
applicationWillTerminate()이 실행되므로 해당 부분에 값을 보내면 된다.
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var methodChannel: FlutterMethodChannel! // methodChannel 선언
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// FlutterViewController
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
// methodChannel 세팅
methodChannel = FlutterMethodChannel(
name: "my.channel",
binaryMessenger: controller.binaryMessenger
)
// methodChannel 수신
methodChannel.setMethodCallHandler { [weak self] (call, result) in
result("result : \(call.method)")
}
return super.application(
application,
didFinishLaunchingWithOptions: launchOptions
)
}
// 앱 종료
override func applicationWillTerminate(_ application: UIApplication) {
methodChannel.invokeMethod("invokeMethod", arguments: "applicationWillTerminate")
}
}
IOS도 앱 종료 시 채널로 값을 던지지 못한다.
applicationWillTerminate()에 잠시 멈춰주는 코드를 추가해주면 된다.
override func applicationWillTerminate(_ application: UIApplication) {
methodChannel.invokeMethod("invokeMethod", arguments: "applicationWillTerminate")
sleep(2) // 잠시 멈추기
}
+
안드로이드폰의 특성상 백키를 이용해서 앱을 온전히 종료시킬 수 있지만,
가운데 버튼을 클릭하여 백그라운드로 보내고 백그라운드에서 실행되고 있는 앱 리스트에서 종료할 수 있는 방법도 있었다.
이렇게 앱을 강제종료 하는 것은 따로 따로 생명주기가 실행되지 않는다.
비정상적인 앱 종료가 있을 때는 또다르게 처리해줘야하는데 서비스를 이용하는 것이다.
앱이 시작될 때 등록하였다가 서비스가 종료될 때 처리해주면 된다.
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
methodChannel = MethodChannel(
flutterEngine.dartExecutor,
"my.channel"
)
methodChannel.setMethodCallHandler { call, result ->
result.success("result: ${call.method}")
}
// Service 등록
startService(Intent(applicationContext, MyService::class.java))
}
class MyService : Service() {
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onTaskRemoved(rootIntent: Intent) {
super.onTaskRemoved(rootIntent)
// 앱 종료 시 처리
Log.d("MyApp", "앱 종료!")
}
}
'dev > flutter' 카테고리의 다른 글
flutter - firebase 연동 firebase cli, pod repo update 에러 (0) | 2023.06.18 |
---|---|
플러터 차트 (fl_chart) (0) | 2023.06.16 |
플러터 리스트 또는 ListView 위젯 뒤집기 (0) | 2023.06.09 |
플랫폼 통신 BasicMessageChannel (안드로이드, IOS) (0) | 2023.05.31 |
플랫폼 통신 MethodChannel (안드로이드, IOS) (0) | 2023.05.31 |