yasutomogのブログ

Software Engineerの雑記

Flutterで環境別のGoogleMap API Keyを設定する方法(dart-define-from-file)

概要

FlutterでGoogleMapを利用するとき、API KeyはOS毎に以下のファイルで設定する必要があります。

テスト環境と本番環境にそれぞれ発行したGoogleMap API Keyを、 ビルド(ipaまたはaabファイルの生成)時に、 dart-define-from-file オプションから設定する方法を記載します。

前提

Flutterで環境ごと設定値を分けるには、元々、Flutterビルドコマンドオプションの dart-define を使ってましたが、 dart-define-from-file オプションによって設定値をファイルにまとめることができるようになりました。
その方法については、以下の記事が大変参考になるので、こちらでは割愛した内容を記載します。

zenn.dev

dart-define-from-fileからの設定

dart_defines/dev.jsondart_defines/prod.json は既に用意している前提で、GoogleMap API Keyをそれぞれのjsonに追加します。

"iOSGoogleMapApiKey": "hoge"
"androidGoogleMapApiKey": "fuga"

iOS

  • ios/Runner/Info.plist に以下を追加し、swiftからdart-defineのjsonにアクセスできるように設定。
  <key>DART_DEFINES</key>
  <string>$(DART_DEFINES)</string>
  • ios/Runner/AppDelegate.swift を以下のように編集して、jsonファイルの内容を取得して使用することが可能。
import UIKit
import Flutter
import GoogleMaps

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    // - Setup dart-define(dart-defineの値) 
    let dartDefinesString = Bundle.main.infoDictionary!["DART_DEFINES"] as! String
    var dartDefinesDictionary = [String:String]()
    for definedValue in dartDefinesString.components(separatedBy: ",") {
        let decoded = String(data: Data(base64Encoded: definedValue)!, encoding: .utf8)!
        let values = decoded.components(separatedBy: "=")
        dartDefinesDictionary[values[0]] = values[1]
    }

    GMSServices.provideAPIKey(dartDefinesDictionary["iOSGoogleMapApiKey"]!)
    // self.window.makeSecure()
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

extension UIWindow {
  func makeSecure() {
    let field = UITextField()
    field.isSecureTextEntry = true
    self.addSubview(field)
    field.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
    field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
    field.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
    self.layer.superlayer?.addSublayer(field.layer)
    field.layer.sublayers?.first?.addSublayer(self.layer)
  }
}

参考URL medium.com

Android

  • android/app/build.gradle の defaultConfig に以下を追加し、dart-defineの値をAndroidManifest.xmlで利用できるように設定
    defaultConfig {
         manifestPlaceholders["googleApiKey"] = androidGoogleMapApiKey
     }
  • android/app/src/main/AndroidManifest.xml で上記の manifestPlaceholders に指定したKEYを使い設定
         <meta-data android:name="com.google.android.geo.API_KEY" android:value="${googleApiKey}"/>

参考URL

developer.android.com

Androidで正しく設定できているかどうかを確認する方法(値が正しく渡せているかを確認する)

apkファイルの拡張子をzipに変更して解凍することで、AndroidManifest.xml を見つけることはできるが、そのまま開いてもバイナリ形式にエンコードされているため確認することができない。

code.google.com

上記から AXMLPrinter2.jar をダウンロードし、以下のようなコマンドで確認用のAndroidManifest.xmlを生成することが可能。

 java -jar AXMLPrinter2.jarのPath AndroidManifest.xmlのPath > check_AndroidManifest.xml