diff --git a/README.md b/README.md index 68cfe2e..85411ea 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,32 @@ -# MaizeBus +github_header + +# Quickstart (Recommended) +## Create an API key for Google Maps +**Keep your API key secret!** Your Google Maps API key is just for your local build of Maizebus (we'll use a different one when publishing to the app store). Our GitHub repository is configured to ignore `android/local.properties` and `ios/Flutter/gmap.xcconfig` so you're safe to commit as usual. + +You have two options for getting your API key: either use a Maps Demo Key or get an API key through Google Cloud. The Maps Demo key doesn't require a credit card but is newer and might have stricter usage limits. Google Cloud requires you to have a credit card on file, but our usage stays in the free tier (we're using the "Maps SDK", which has [unlimited free usage](https://developers.google.com/maps/billing-and-pricing/pricing#map-loads-pricing)). I would recommend getting your API key from Google Cloud since it's more stable. + +1. Option A: Use a Maps Demo Key (no credit card required) + 1. Visit the [Maps Demo Key page](https://mapsplatform.google.com/maps-demo-key/?utm_experiment=13103221) + 2. Click "Try for free" and sign in with your Google Account + 3. Agree to the terms, and you should see your Maps Demo Key! +2. Option B: Create an API key through Google Cloud + 1. Open the [Google Cloud Console](https://console.cloud.google.com/google/maps-apis/overview). Create an account if you don't already have one + 2. In the toolbar you should see the Project Picker (right next to "Google Cloud"). Click it and create a new project. Call it whatever you like (such as "Local-Maizebus-Testing") + 3. In the sidebar, click "APIs & Services" and enable "Maps SDK for Android" and "Maps SDK for iOS" + 4. Now click on "Keys & Credentials" in the sidebar + 5. Click on the "Maps Platform API Key" under "API Keys", then click "Show key" + +## Run automatic setup +1. Make sure Flutter is installed on your computer (see [this guide](https://docs.flutter.dev/install) for how to do this) +2. Open a terminal (Mac) or WSL terminal (Windows) in the project folder. Run `./setup.sh` to start the setup process +3. Paste your Google Maps API key into the setup script when prompted. The setup script will add your API key to the project +4. Launch an emulator and click the green Run button in VSCode to build and run the project! Alternatively you can run `flutter run` in your terminal + +**Note:** `setup.sh` disables Firebase by default and creates dummy configuration files. Most frontend developers probably won't work on the notification system, so we're saving you all the pain of having to get a Firebase API key and configure flutterfire. If you'd like to configure Firebase properly, see the section below. + + +# Manual Setup ## Google Maps Setup (iOS) diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart index 45a8ab9..30d0a32 100644 --- a/lib/services/notification_service.dart +++ b/lib/services/notification_service.dart @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +const useFirebase = bool.fromEnvironment('USE_FIREBASE', defaultValue: kReleaseMode); class NotificationService { static final _localNotificationsPlugin = FlutterLocalNotificationsPlugin(); static bool _listeningForFcmUpdates = false; @@ -22,10 +23,12 @@ class NotificationService { /// e.g. call it asap if notifications were previously used, otherwise wait for /// the user to trigger a feature that requires notifications static Future initPlugin() async { - await Firebase.initializeApp( - name: "[DEFAULT]", - options: DefaultFirebaseOptions.currentPlatform, - ); + if (useFirebase) { + await Firebase.initializeApp( + name: "[DEFAULT]", + options: DefaultFirebaseOptions.currentPlatform, + ); + } // prepare local notifications const AndroidInitializationSettings androidSettings = @@ -69,6 +72,8 @@ class NotificationService { // Currently this function must be called even if permission is already granted, // as it sets up some important listeners static Future requestPermission() async { + if (!useFirebase) return; // If Firebase is disabled for development skip all this + // todo: add back in if needed final notificationSettings = await FirebaseMessaging.instance .requestPermission(); diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..a76fcf1 --- /dev/null +++ b/setup.sh @@ -0,0 +1,118 @@ +#!/bin/bash +set -Eeuo pipefail + +BLACK="\e[30m"; +RED="\033[31m"; +GREEN="\033[32m"; +YELLOW="\033[33m"; +BLUE="\033[34m"; +MAGENTA="\033[35m"; +CYAN="\033[36m"; +WHITE="\033[37m"; +RESET="\033[0m"; + +if flutter --version; then + echo "Found Flutter installation!" +else + echo "Error: Could not find Flutter" + exit 1 +fi + +flutter doctor + +echo "Please paste in your Google Maps API key: " + +read gmaps_apikey + +touch ios/Flutter/gmap.xcconfig +sed -E 's/^GMapApiKey=([A-Za-z0-9]+)//' ios/Flutter/gmap.xcconfig # Remove all old API keys from gmap.xcconfig +echo "GMapApiKey=$gmaps_apikey" > ios/Flutter/gmap.xcconfig # Add API key to gmap.xcconfig +touch android/local.properties +grep -v '^GOOGLE_MAPS_API_KEY=' android/local.properties > android/local.properties.tmp || true # Remove all old API keys from local.properties +mv android/local.properties.tmp android/local.properties +printf "\nGOOGLE_MAPS_API_KEY=$gmaps_apikey" >> android/local.properties # Add API key to local.properties + +flutter pub get + +if [ ! -f lib/firebase_options.dart ]; then +touch lib/firebase_options.dart +> lib/firebase_options.dart # Clear the file +cat > lib/firebase_options.dart << 'EOF' +// Dummy Firebase config file. WILL NOT CONNECT TO FIREBASE OR RECEIVE NOTIFICATIONS +// To set the app up to use Firebase notifications, follow this tutorial: https://firebase.google.com/docs/flutter/setup +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +// If you're seeing a compile error here, you're making a release build with the +// dummy Firebase config. Set up the real one: https://firebase.google.com/docs/flutter/setup +// ignore: unused_element +const _noReleaseWithDummyFirebase = 1 ~/ (bool.fromEnvironment('dart.vm.product') ? 0 : 1); + + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + throw UnsupportedError("Firebase hasn't been configured for this project! Please delete firebase_options.dart and follow the tutorial at https://firebase.google.com/docs/flutter/setup"); + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'dummy-api-key', + appId: 'dummy-app-id', + messagingSenderId: 'dummy-sender-id', + projectId: 'dummy-project-id', + storageBucket: 'dummy-project-id.appspot.com', + ); +} +EOF +else + printf "${YELLOW}Note: lib/firebase_options.dart already exists and was not overwritten $RESET\n" + printf " If you'd like to replace firebase_options.dart with the dummy version,\n" + printf " remove it and run this script again\n" +fi + +if [ ! -f android/app/google-services.json ]; then +cat > android/app/google-services.json << 'EOF' +{ +"project_info": { + "project_number": "000000000000", + "project_id": "dummy-project-id", + "storage_bucket": "dummy-project-id.appspot.com" +}, +"client": [ + { + "client_info": { + "mobilesdk_app_id": "1:000000000000:android:0000000000000000000000", + "android_client_info": { + "package_name": "com.ishankumar.maizebus" + } + }, + "oauth_client": [], + "api_key": [{ "current_key": "dummy-api-key" }], + "services": { "appinvite_service": { "other_platform_oauth_client": [] } } + } +], +"configuration_version": "1" +} +EOF +else + printf "${YELLOW}Note: android/app/google-services.json already exists and was not overwritten$RESET\n" + printf " If you'd like to replace google-services.json with the dummy version,\n" + printf " remove it and run this script again\n" +fi + +# npm i -g firebase-tools # Install Firebase tools + + +# dart pub global activate flutterfire_cli +