diff --git a/.github/workflows/blueberry-build-test-action.yml b/.github/workflows/blueberry-build-test-action.yml index e7a8425..2c0b141 100644 --- a/.github/workflows/blueberry-build-test-action.yml +++ b/.github/workflows/blueberry-build-test-action.yml @@ -16,6 +16,11 @@ jobs: firebase_options_dart: ${{secrets.FIREBASE_OPTION}} run: echo "$firebase_options_dart" > lib/firebase_options.dart + - name: Create .env file + env: + ENV_CONTENT: ${{ secrets.ENV_CONTENT }} + run: echo "$ENV_CONTENT" > .env + - name: 'Set Flutter Version Latest' uses: subosito/flutter-action@v2 with: diff --git a/.gitignore b/.gitignore index fc1f1ef..91c9df2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ # Ignore platform folders. -# 이유: 개발자마다 환경이 다르므로 설정 파일이 충돌해 코드 공유가 어려울 수 있습니다. 예를 들어, 쇼핑몰 개발 시 페이팔, Stripe, 인앱결제를 사용하려면 AndroidManifest, google-service.json, Info.plist, GoogleService-Info.plist 등의 파일 수정이 필요하지만, 이 정보는 공유되지 않아야 하며, 공유가 되면, 필요 없는 설정이 추가되거나 자신의 설정이 삭제되거나 하는 일이 발생 합니다. 따라서 각 개발자가 필요한 플랫폼을 직접 설정하도록 합니다. /android/ /ios/ /web/ @@ -7,6 +6,15 @@ /macos/ /windows/ +# Allow Android platform folder. +!/android/app/src/main/AndroidManifest.xml +!/android/app/src/main/app/build.gradle +!/android/app/src/main/res/values/strings.xml +!/ios/Podfile + +!/ios/.gitignore +!/android/.gitignore + # Miscellaneous *.class *.log @@ -75,4 +83,7 @@ lib/firebase_options.dart .vscode/launch.json # secret key -sign_in_key.dart \ No newline at end of file +sign_in_key.dart + +# env +.env \ No newline at end of file diff --git a/Makefile b/Makefile index b5f4234..4f544e3 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,20 @@ endif # Define the default target to call all necessary targets all: init analyze apply format buildRunner +# Define the init target to initialize the project +first : create init analyze buildRunner env +setting : init buildRunner +lint : analyze apply format + +# Define the init target +create: + @echo "Create ios and android floder..." +ifeq ($(DETECTED_OS), Windows) + @flutter create . +else + @$(FLUTTER) create . +endif + # Define the init target init: @echo "Initializing Flutter project..." @@ -61,3 +75,12 @@ else @$(FLUTTER) pub run build_runner build --delete-conflicting-outputs endif +# Define the env target for Unix-like systems +env: +ifeq ($(DETECTED_OS), Windows) + @echo "Using PowerShell script to create .env file." + @powershell -ExecutionPolicy Bypass -File generate_env.ps1 +else + @echo "Using bash script to create .env file." + @bash generate_env.sh +endif diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..9ae2a55 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,16 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Manifest file which is auto generated +!/android/app/src/main/AndroidManifest.xml + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..a36c156 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,46 @@ +plugins { + id "com.android.application" + id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id "dev.flutter.flutter-gradle-plugin" +} + +android { + namespace = "com.example.blueberry_voice" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_1_8 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.blueberry_voice" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdk = 29 + targetSdk = 35 + versionCode = flutter.versionCode + versionName = flutter.versionName + + buildConfigField "String", "API_KEY", "\"${System.getenv('GOOGLE_API_KEY')}\"" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.debug + } + } +} + +flutter { + source = "../.." +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..df227bd --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..69c16f5 --- /dev/null +++ b/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + ${BuildConfig.GOOGLE_MAP_API_KEY} + diff --git a/assets/logo/voice_logo.png b/assets/logo/voice_logo.png new file mode 100644 index 0000000..70c0589 Binary files /dev/null and b/assets/logo/voice_logo.png differ diff --git a/generate_env.ps1 b/generate_env.ps1 new file mode 100644 index 0000000..cc270d4 --- /dev/null +++ b/generate_env.ps1 @@ -0,0 +1,19 @@ +# PowerShell 스크립트로 .env 파일 생성 + +# 현재 작업 중인 디렉터리 경로 가져오기 +$TargetDir = Get-Location + +# .env 파일 내용 +$envContent = @" +# please replace 'your_api_key_here' with your actual API key +GOOGLE_API_KEY=your_api_key_here +GPT_API_KEY=your_api_key_here +# Other environment variables can be added here +"@ + +# .env 파일 생성 +$envFilePath = Join-Path -Path $TargetDir -ChildPath ".env" +Write-Output "Creating .env file at: $envFilePath" + +# UTF-8 인코딩으로 파일 생성 +$envContent | Out-File -FilePath $envFilePath -Encoding utf8 diff --git a/generate_env.sh b/generate_env.sh new file mode 100644 index 0000000..a9d9826 --- /dev/null +++ b/generate_env.sh @@ -0,0 +1,5 @@ +# .env 파일 생성 +echo "# please replace 'your_api_key_here' with your actual API key" > ".env" +echo "GOOGLE_API_KEY=your_api_key_here" >> ".env" +echo "GPT_API_KEY=your_api_key_here" >> ".env" +echo "# Other environment variables can be added here" >> ".env" diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7b46a5a --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,35 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 + diff --git a/lib/core/TopScreen.dart b/lib/core/TopScreen.dart index cd3aebd..0b892bd 100644 --- a/lib/core/TopScreen.dart +++ b/lib/core/TopScreen.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../feature/admin/AdminUserListPage.dart'; import '../feature/login/LoginScreen.dart'; +import '../feature/map/PoliceMapScreen.dart'; import '../feature/match/MatchScreen.dart'; /// TopScreen.dart @@ -25,7 +26,7 @@ class TopScreen extends ConsumerWidget { final selectedIndex = ref.watch(selectedIndexProvider); final List pages = [ - const PostScreen(), + const PoliceMapScreen(), const MatchScreen(), const LoginScreen(), const AdminUserListPage() diff --git a/lib/feature/map/provider/PoliceStationProvider.dart b/lib/feature/map/provider/PoliceStationProvider.dart index caed6cd..dc4ab0f 100644 --- a/lib/feature/map/provider/PoliceStationProvider.dart +++ b/lib/feature/map/provider/PoliceStationProvider.dart @@ -1,11 +1,13 @@ import 'dart:convert'; + import 'package:blueberry_flutter_template/model/GoogleMapPlace.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:http/http.dart' as http; //Google Map API key 등록 필요 -const String apiKey = ''; //TODO: 'Google Map API Key 입력 필요 +String apiKey = dotenv.env['GOOGLE_MAP_API_KEY'] ?? 'AIzaSyDEGMHYfH7pQ1ks39pXrhfmXZJRosp755w'; // Android : AndroidManifest.xml 에 API Key와 권한 추가 필요 // iOS : AppDelegate.swift, Info.plist 에 API Key와 권한 추가 필요 diff --git a/lib/main.dart b/lib/main.dart index 4b81f48..8250350 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/date_symbol_data_local.dart'; @@ -19,7 +20,6 @@ Future main() async { runZonedGuarded(() async { // 날짜 형식 초기화 WidgetsFlutterBinding.ensureInitialized(); - await initializeDateFormatting('en_US', null); await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); @@ -34,6 +34,13 @@ Future main() async { FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true); } + if (kIsWeb) { + talker.info('Web environment can not use dotenv'); + } else { + await dotenv.load(fileName: '.env'); + } + + await initializeDateFormatting('en_US', null); runApp(const ProviderScope( child: MyApp(), )); diff --git a/pubspec.yaml b/pubspec.yaml index 6db711d..bbab20c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -108,6 +108,10 @@ dependencies: # map google_maps_flutter: ^2.9.0 geolocator: ^12.0.0 + flutter_dotenv: ^5.1.0 + + # apiKey + dev_dependencies: flutter_test: @@ -120,6 +124,7 @@ dev_dependencies: flutter: uses-material-design: true assets: + - .env - assets/ - assets/600x400/ - assets/300x420/