［Android］GitHubにAPIキーを上げないようにAPIキーを環境変数に設定する

# はじめに

APIキーをStrings.xmlに書いてしまうとGitHubにファイルを上げたときに見えてしまいます。
そうなるとまずいと思うので、環境変数からAPIキーを読み込むようにしたいと思います。
次のようにTextViewにAPIキーを表示して読み込めているか確認します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79387/392afc6b-0c5d-8b25-7b84-246d69945952.png" height="500"/>

# セットアップした環境
次の環境でセットアップしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79387/74ce6b57-d544-c2f5-16fa-278452836750.png)

# 1.APIキーを環境変数に登録する

次の手順で環境変数にAPIキーを登録していきます。
環境変数の設定方法は利用しているShellによってことなりますので、
自分の環境にあった方法で環境変数の登録を行ってください。

💡本記事ではbashとfishでの手順を記載しているのでそれ以外のShellの場合は自分で検索してください。

## bash

bashだと.bashrcに記載した内容を起動するために実行してくれるので、
.bashrcに環境変数を設定するコマンドを記述します。

### (1) bashrcを開く

```shell
bash-3.2$ vi ~/.bashrc
```

### (2) bashの起動時にAPIキーを環境に登録するように設定する

```shell
export API_KEY="sample-api-key"
```

### (3) bashを再起動する

```shell
bash-3.2$ exit
bash-3.2$
```

### (4) bashに環境変数が設定されているか確認する

```shell
bash-3.2$ echo $API_KEY
```

## fish

fishだとfish.configに記載した内容を起動するたびに実行してくれるので、
fish.configに環境変数を設定するコマンドを記述します。

### (1) fish.configを開く

```shell
» cd ~/.config/fish/fish.config
» vi fish.config
```

### (2) fishの起動時にAPIキーを環境変数に登録するよう設定する

```shell
set -x  API_KEY sample-api-key
```

### (3) fishを再起動する

```shell
» exit

Last login: Tue Oct 22 10:55:15 on ttys000
Welcome to fish, the friendly interactive shell
```

### (4) fishに環境変数が設定されているか確認する

```shell
» echo $API_KEY
```

# 2.環境変数をmeta-dataとして登録する

登録した環境変数をコードから参照できるようにするため、
次の手順でAndroidManifestのmeta-dataに環境変数を登録します。

### (1) Android Studioをshellから起動する

```shell
» open /Applications/Android\ Studio.app/
```

### (2) build.gradle(.app)で環境変数の値を読み込む

```build.gradle(app)

android {
          ︙
    defaultConfig {
          ︙
        manifestPlaceholders = [API_KEY: System.getenv("API_KEY")]
          ︙
    }
    buildTypes {
          ︙
    }
}
```


### (3) AndroidManifest.xmlで環境変数の値を定義する

```AndroidManifest.xml
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    tools:ignore="GoogleAppIndexingWarning">
      ︙
    <meta-data android:name="API_KEY" android:value="${API_KEY}" />
      ︙
</application>
```

## 3. 環境変数を登録したmeta-dataを読み込む

AndroidManifestに登録したmeta-dataをActivityで
取得してTextViewに表示してみます。

### (1) meta-dataを取得する

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val appInfo = getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA)
        val apiKey = appInfo.metaData.getString("API_KEY")
    }
}
```

### (2) meta-dataを表示するViewを定義する

```activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/meta_value_textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

### (3) meta-dataをViewにセットする

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val appInfo = getPackageManager().getApplicationInfo(packageName, PackageManager.GET_META_DATA)
        val apiKey = appInfo.metaData.getString("API_KEY")

        val textView = findViewById<TextView>(R.id.meta_value_textview)
        textView.text = apiKey
    }
}
```


# おわりに

次のようにTextViewに環境変数に設定した値が表示できました。
TextViewに値を設定しましたが、実際はAPIサービスの引数に指定する形になると思います。
あとこのサンプルですが環境変数の値を変更すれば表示も変わりますので試して見てください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79387/6535920b-6de9-7b0d-5c3e-9ecfac4febb3.png" height="500"/>

次にサンプルを公開しています。
何か不明点などあれば次のサンプルをご覧ください。

| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79387/9ac9e6cb-a49e-5896-4729-28a27037e8e9.png)| [Kaleidot725 => android-mylab => InjectBuildBariablesSample](https://github.com/kaleidot725/android-mylab/tree/master/InjectBuildVariablesSample) |
| ------- | ------- |

## 参考
- [fish | Frequently Asked Questions](https://fishshell.com/docs/2.2/faq.html)
- [Inject build variables into the manifest | Android | Google Developers](https://developer.android.com/studio/build/manifest-build-variables)
- [meta-data | Android | Google Developers](https://developer.android.com/guide/topics/manifest/meta-data-element)