Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/bridge/web_view_bridge_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:logger/logger.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:app/utils/url_restore_manager.dart';

class WebViewBridgeHandler {
final BuildContext context;
Expand Down Expand Up @@ -219,6 +220,13 @@ class WebViewBridgeHandler {
}

try {
// Android에서 카메라 호출 전 현재 URL 저장 (앱이 kill될 경우 복원용)
final currentUrl = await controller.getUrl();
if (currentUrl != null) {
await UrlRestoreManager.saveUrlBeforeCamera(currentUrl.toString());
logger.d('카메라 호출 전 URL 저장: $currentUrl');
}

onShowLoading?.call('사진 촬영 중...');
final ImagePicker picker = ImagePicker();
final XFile? image = await picker.pickImage(
Expand All @@ -235,9 +243,14 @@ class WebViewBridgeHandler {
source: "openAlbum('data:image/png;base64,$base64Image')",
);
}

// 정상 복귀 시 저장된 URL 삭제 (앱이 kill되지 않았으므로)
await UrlRestoreManager.clearSavedUrl();
onHideLoading?.call();
} catch (e) {
logger.e('Error taking image: $e');
// 에러 시에도 저장된 URL 삭제
await UrlRestoreManager.clearSavedUrl();
onHideLoading?.call();
}
}
Expand Down
50 changes: 35 additions & 15 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:app/permissions/FirebaseConfig.dart';
import 'package:app/ui/loading_widget.dart';
import 'package:app/utils/env/env.dart';
import 'package:app/utils/url_restore_manager.dart';
import 'package:app/web_view/web_view.dart';
import 'package:flutter/material.dart';
import 'package:kakao_flutter_sdk/kakao_flutter_sdk_template.dart';
Expand Down Expand Up @@ -142,25 +143,44 @@ class SplashScreen extends StatefulWidget {
}

class _SplashScreenState extends State<SplashScreen> {
String? _restoredUrl;

@override
void initState() {
super.initState();
_initializeAndNavigate();
}

Future.delayed(const Duration(seconds: 3), () {
Navigator.of(context).pushReplacement(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
const BottleNoteWebView(),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: animation,
child: child,
);
},
transitionDuration: const Duration(milliseconds: 1000),
),
);
});
Future<void> _initializeAndNavigate() async {
try {
// Android에서 카메라 호출 후 앱이 kill된 경우 복원할 URL 확인
final restoredUrl = await UrlRestoreManager.consumeRestoredUrl();
if (restoredUrl != null) {
logger.d('복원할 URL 발견: $restoredUrl');
_restoredUrl = restoredUrl;
}

// 최소 3초 대기 (기존 동작 유지)
await Future.delayed(const Duration(seconds: 3));
} catch (e) {
logger.e('스플래시 초기화 중 오류 발생: $e');
}

if (!mounted) return;

Navigator.of(context).pushReplacement(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) =>
BottleNoteWebView(initialUrl: _restoredUrl),
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: animation,
child: child,
);
},
transitionDuration: const Duration(milliseconds: 1000),
),
);
}

@override
Expand Down
57 changes: 57 additions & 0 deletions lib/utils/url_restore_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'dart:io' show Platform;
import 'package:shared_preferences/shared_preferences.dart';

/// Android에서 카메라 호출 후 앱이 kill되었을 때 URL을 복원하기 위한 매니저
class UrlRestoreManager {
static const String _pendingUrlKey = 'pending_restore_url';
static const String _timestampKey = 'pending_restore_timestamp';

/// URL 복원 유효 시간 (5분)
static const int _validDurationMinutes = 5;

/// 카메라 호출 전 현재 URL 저장 (Android 전용)
static Future<void> saveUrlBeforeCamera(String url) async {
if (!Platform.isAndroid) return;

final prefs = await SharedPreferences.getInstance();
await prefs.setString(_pendingUrlKey, url);
await prefs.setInt(_timestampKey, DateTime.now().millisecondsSinceEpoch);
}

/// 저장된 URL 가져오기 및 삭제 (Android 전용)
/// 유효 시간이 지났거나 URL이 없으면 null 반환
static Future<String?> consumeRestoredUrl() async {
if (!Platform.isAndroid) return null;

final prefs = await SharedPreferences.getInstance();
final savedUrl = prefs.getString(_pendingUrlKey);
final savedTimestamp = prefs.getInt(_timestampKey);

// 저장된 URL이 없으면 null
if (savedUrl == null || savedTimestamp == null) {
return null;
}

// 유효 시간 체크 (5분 초과시 무효)
final now = DateTime.now().millisecondsSinceEpoch;
final elapsed = now - savedTimestamp;
if (elapsed > _validDurationMinutes * 60 * 1000) {
// 만료된 데이터도 정리
await clearSavedUrl();
return null;
}

// 정상적으로 복원된 경우 사용 후 삭제
await clearSavedUrl();
return savedUrl;
}

/// 저장된 URL 삭제 (정상 카메라 복귀 시 호출)
static Future<void> clearSavedUrl() async {
if (!Platform.isAndroid) return;

final prefs = await SharedPreferences.getInstance();
await prefs.remove(_pendingUrlKey);
await prefs.remove(_timestampKey);
}
}
8 changes: 6 additions & 2 deletions lib/web_view/web_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import '../actions/back_action_handler.dart';

class BottleNoteWebView extends StatefulWidget {
final VoidCallback? onLoaded;
const BottleNoteWebView({super.key, this.onLoaded});
final String? initialUrl;

const BottleNoteWebView({super.key, this.onLoaded, this.initialUrl});

@override
State<BottleNoteWebView> createState() => BottleNoteWebViewState();
Expand Down Expand Up @@ -113,7 +115,9 @@ class BottleNoteWebViewState extends State<BottleNoteWebView>
final content = Stack(
children: [
InAppWebView(
initialUrlRequest: URLRequest(url: WebUri(Env.webViewUrl)),
initialUrlRequest: URLRequest(
url: WebUri(widget.initialUrl ?? Env.webViewUrl),
),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
useShouldOverrideUrlLoading: true,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ packages:
source: hosted
version: "4.1.0"
shared_preferences:
dependency: transitive
dependency: "direct main"
description:
name: shared_preferences
sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a"
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dependencies:
flutter_svg: ^2.0.10+1
svg_path_parser: ^1.1.2
flutter_native_splash: ^2.4.6
shared_preferences: ^2.5.2

dev_dependencies:
flutter_test:
Expand Down