【Flutter】クレデンシャル情報を.envファイルで取得し、ネイティブファイルで利用する方法【GoogleMap】
アプリ開発をする際に、API Keyなどの第三者に知られてはいけない情報(クレデンシャル情報)を扱う場面があるかと思います。
このようなクレデンシャル情報は、プログラムにハードコーディングするのではなく、.envなどの環境設定ファイルから読み込んで使用することがアプリ開発の鉄則です。
もしハードコーディングしてそのままGitにコミットしてしまった日には地獄を見ます。笑
Gitの履歴を見れば誰でもクレデンシャル情報が知れてしまうので。笑
ということで今回は、FlutterでGoogleMapを実装するケースを想定し、API Keyを.envファイルから読み込みMapを表示してみたいと思います。
GoogleMapをFlutterで実装する際、iOSやAndroidのネイティブファイルにAPI Keyを入力する必要がありますが、この際にFlutterの.envライブラリから取得した情報を使用する方法をご紹介します。
ソースコード
こちらにソースコードを載せています。もし必要であればご覧ください〜
この記事を読んでわかること
- Flutterで.envファイルからクレデンシャル情報を取得し、ネイティブファイルで使用する方法
使用するライブラリ
- flutter_config
- google_maps_flutter(google_maps_flutterの詳しい使用方法はここでは紹介しません)
flutter_configのほかにflutter_dotenvというライブラリが有名ですが、今回はネイティブファイルで.envファイルを読み込むという要件があるため、flutter_configを採用します。
(もし要望があればflutter_dotenvの使い方記事も書こうかな)
ライブラリをインストール
flutter_config
flutter pub add flutter_config
GoogleMapライブラリ
flutter pub add google_maps_flutter
GoogleMapWidget作成
main.dartにGoogleMapWidgetを作成
class GoogleMapWidget extends StatefulWidget {
const GoogleMapWidget({super.key});
State<GoogleMapWidget> createState() => _GoogleMapWidgetState();
}
class _GoogleMapWidgetState extends State<GoogleMapWidget> {
final Completer<GoogleMapController> _controller =
Completer<GoogleMapController>();
static const CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(35.68126232447219, 139.76712479827628),
zoom: 15,
);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Google Map Flutter Config'),
),
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
);
}
}
ルートディレクトリに.env作成、環境変数設定
.env
IOS_MAP_API_KEY=YOUR IOS API KEY HERE
ANDROID_MAP_API_KEY=YOUR ANDROID API KEY HERE
iOS側の設定
AppDelegate.swift変更
ios/Runner/AppDelegate.swift
import UIKit
import Flutter
import GoogleMaps
import flutter_config // ここ追記
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey(FlutterConfigPlugin.env(for: "IOS_MAP_API_KEY")) // ここ追記
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Android側の設定
AndroidManifest.xml変更
android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flutter_config_google_map">
<application
android:label="flutter_config_google_map"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
...
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="@string/ANDROID_MAP_API_KEY"/> // ここ追記
</application>
</manifest>
build.gradle変更
android/app/build.gradle
...
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply from: project(':flutter_config').projectDir.getPath() + "/dotenv.gradle" // ここ追記
...
最終的なソースコード
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: GoogleMapWidget(),
);
}
}
class GoogleMapWidget extends StatefulWidget {
const GoogleMapWidget({super.key});
State<GoogleMapWidget> createState() => _GoogleMapWidgetState();
}
class _GoogleMapWidgetState extends State<GoogleMapWidget> {
final Completer<GoogleMapController> _controller =
Completer<GoogleMapController>();
static const CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(35.68126232447219, 139.76712479827628),
zoom: 15,
);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Google Map Flutter Config'),
),
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
);
}
}
結果
iOS、Androidともに.envファイルからAPI Keyを読み込み、GoogleMapを表示することができました。
実際に使用する際は、.envファイルを.gitignore対象にしてGitの管理対象から外すようにしてください。
Discussion
素晴らしい記事をありがとうございます。
ios, androidと同様に、
~/web/index.html
にもAPIキーを設定することが可能だと思います。(参考)このhtmlファイル内に記載するAPIキーを.envから読み取る方法については、何かお考えがあるかお聞きしたいです。よろしくお願いたします。