π App Introduction: Mobile app for finding nearby places using Naver Local Search API and GPS location services
π Duration: April 20, 2025 ~ April 22, 2025 (3 days)
π± Platform: Flutter cross-platform app (iOS, Android)
π₯ Team Size: 1 developer (Personal project)
πΌ Role: Entire app UI/UX design & development, API integration
π οΈ Key Technologies: Flutter Dart Naver Local API VWorld API Riverpod Geolocator InAppWebView URL Launcher Dio
π GitHub: daehan-lim/flutter-place-finder
  
  
  
  
  
  
  
  
  
PlaceFinder helps users discover nearby places by searching by place names or addresses. The app uses Naver Local Search API and VWorld API to provide GPS-based location search and supports seamless redirection to popular map applications. Users can quickly explore local businesses, restaurants, and points of interest while accessing detailed information through in-app web view integration.
βββ app/                               # App configuration and setup files
β   βββ constants/                     # App-wide constant definitions
β   β   βββ app_colors.dart            # Color constants
β   β   βββ app_constants.dart         # General app constants
β   β   βββ app_styles.dart            # Style definitions
β   βββ app_providers.dart             # Riverpod provider setup
β   βββ theme.dart                     # App theme configuration
β
βββ core/                              # Core functionality and common utilities
β   βββ exceptions/                    # App-wide exception classes
β   β   βββ data_exceptions.dart       # Data-related exception classes
β   βββ services/                      # External service integrations
β   β   βββ map_launcher_service.dart
β   βββ utils/                         # Helper functions and utility classes
β       βββ geolocator_util.dart
β       βββ snackbar_util.dart
β       βββ string_format_utils.dart
β
βββ data/                              # Data layer and data access
β   βββ dto/                           # Data Transfer Objects
β   β   βββ naver_place_dto.dart
β   β   βββ vworld_district_dto.dart
β   βββ model/                         # Data models
β   β   βββ place.dart
β   βββ network/                       # Network communication
β   β   βββ dio_clients.dart
β   βββ repository/                    # Repository implementations
β       βββ location_repository.dart
β
βββ ui/                                # User interface
β   βββ pages/                         # App screens
β   β   βββ home/                      # Home screen
β   β   β   βββ home_page.dart
β   β   β   βββ home_view_model.dart
β   β   β   βββ widgets/
β   β   β       βββ home_list_item.dart
β   β   βββ web/                       # WebView screen
β   β       βββ place_web_page.dart
β   β       βββ place_web_page_view_model.dart
β   βββ widgets/                       # Common widgets
β       βββ error_layout.dart
β
βββ main.dart                          # App entry point
Geolocator for GPS coordinate acquisition with VWorld API to automatically identify userβs current administrative districtBearer Token authentication and Dio HTTP clientBaseOptions for consistent HTTP settings with 10-second connection/reception timeout and debug logging through LogInterceptorGeo URI scheme allowing users to choose from installed map apps (Google Maps, Naver Map, KakaoMap)URL Launcher integration for smooth transitions to map applicationsCustom User Agent configurationInAppBrowserView mode for Naver search integrationApiException, NetworkException, EnvFileException for specific scenariosTooltip for long addressesInkWell effects and shadowsGestureDetector for better user convenienceProvider pattern and dependency injectionAsyncValueDTO and Modelflutter_dotenv.env.example file to guide development environment configurationHomeListItem, MessageLayoutStringFormatUtils, SnackbarUtiliOS Map App Integration Silent Failure
Problem
On iOS, when Naver Map is not installed and launchUrl() is called with the nmap:// custom scheme, it fails silently without any response. The Apple Maps fallback configured with try/catch never executes, leaving users with no feedback or alternative action.
canLaunchUrl() in the Android implementation. It would return false even for executable geo: URIs:if (await canLaunchUrl(Uri.parse('geo:0,0?q=$encoded'))) {
  // Would return false despite being executable
}
canLaunchUrl() would be equally unreliable on iOS, so I used try/catch for failure handling on both platforms
static Future<void> openInMap(String queryAddress) async {
  if (Platform.isIOS) { 
    try {
      await launchUrl(naverUri, mode: LaunchMode.externalApplication);
    } catch (e) {
      // This catch block never executes on iOS
      final appleUri = Uri.parse('http://maps.apple.com/?q=$encoded');
      await launchUrl(appleUri, mode: LaunchMode.externalApplication);
      
    }
  }
}
The approach failed because iOS launchUrl() doesnβt throw exceptions for unavailable apps - it just silently does nothing, so the catch block never executes and Apple Maps never launches.
canLaunchUrl()geo:Final Solution
Implemented platform-specific handling that works with each OSβs characteristics:
static Future<void> openInMap(String queryAddress) async {
  if (Platform.isIOS) { 
    final naverUri = Uri.parse('nmap://search?query=$encoded&appname=$appName');
    if (await canLaunchUrl(naverUri)) {
      await launchUrl(naverUri, mode: LaunchMode.externalApplication);
    } else {
      // Naver Map unavailable, use Apple Maps
      final appleUri = Uri.parse('http://maps.apple.com/?q=$encoded');
      if (await canLaunchUrl(appleUri)) {
        await launchUrl(appleUri, mode: LaunchMode.externalApplication);
      }
    }
  } else {
    // Android: Keep try/catch approach for geo URIs
    try {
      await launchUrl(geoUri, mode: LaunchMode.externalApplication);
    } catch (e) {
      log('Could not launch map: $e');
    }
  }
}