DeployGateを使って特定の端末やユーザー以外では起動できないアプリを作る(Kotlin編）

# アプリを起動できる端末を制御したい

公開前のアプリや開発中のバージョンのアプリ、社外秘や業務用のアプリなどを、特定のユーザーや、特定の管理している端末以外では**そもそも起動されたくない、起動されては困る**という場合がしばしばあります。

特にAndroidの場合はアプリの実行バイナリであるAPKファイルを端末から**容易にぶっこ抜ける**ということもあり、アプリの配布やインストールを管理したり制御しても、悪意を持ってAPKファイルを抜かれてしまうと再配布や流出させてしまうことが簡単にできてしまいます。また、**未公開のアプリがインストールされた端末を紛失**してしまったり、開発メンバーが**退職**したり、個人の端末でテストを行ってもらったあとに**確実にテスト版のアプリを削除してもらいたい**場合も、そもそもアプリの**起動権限を遠隔から剥奪**することができればさらに安心です。

このような**アプリの起動権限の遠隔制御**は、[DeployGate SDK](https://docs.deploygate.com/docs/android-sdk)が提供している[ユーザ認証機能](https://docs.deploygate.com/docs/android-user-auth)を使用すると、簡単に実現することができます。

ここでは実際に、Kotlinを使って特定のDeployGateユーザのAndroid端末でしか起動することが出来ないアプリを作ってみようと思います。

# DeployGate SDK の導入
[DeployGate](https://deploygate.com/)はアプリを特定の人だけに配布するための開発用配信サービスです。配布対象の制御だけであればSDKのインストールは不要でAPKファイルをアップロードするだけで使用できますが、提供するSDKを導入すると、今回使用するユーザ認証機能に加えて、リモートでのログ収集をはじめとした様々な便利機能を利用することができます。

DeployGate SDKの導入はGradleから行います。

![40c478d292032b698c11a8622fb641c2.png](https://qiita-image-store.s3.amazonaws.com/0/956/70e95f57-22a7-f8e7-9227-c9f2017b83ab.png)

AndroidStudioのプロジェクトビューから`build.gradle`を選択し、`depensencies`の項目に以下の行を追加します。

```gradle
    compile 'com.deploygate:sdk:4.0.0'
```
ファイルを編集後、エディタ上部に表示される案内に従って`Sync Now`を押して変更を反映させます。SDKの導入はこれだけで完了です！

# アプリの起動権限制御を実装

次に、DeployGate SDKの提供するユーザ認証機能を使い、アプリの起動時に起動権限を確認し、もしDeployGateでのアクセス権限の無いアプリ（= 起動権限の無いアプリ）だった場合にアクティビティを強制終了するコードを実装します。といっても、アクティビティの`onCreate`内の`super.onCreate(savedInstanceState)`の後に以下のように確認処理を書き足すだけです。
(MainActivityの名称は適切に読み替えてください)

```kotlin

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        //DeployGateによる起動権限の確認
        DeployGate.registerCallback(object: DeployGateCallback{
            override fun onStatusChanged(isManaged: Boolean, isAuthorized: Boolean, loginUsername: String?, isStopped: Boolean) {
                if(!isAuthorized){
                    Toast.makeText(this@MainActivity, "You are not authorized to launch this app", Toast.LENGTH_LONG).show()
                    finish()
                }
            }
            override fun onUpdateAvailable(revision: Int, versionName: String?, versionCode: Int) {}
            override fun onInitialized(isServiceAvailable: Boolean) {}
        }, true)


        setContentView(R.layout.activity_main)
    }
}
```

これで、もし起動権限のない人がアプリを立ち上げてアクティビティを起動しようとした場合、Toastにエラーを表示して自身のアクティビティを強制終了させることができます。

# アプリ立ち上げてみよう
それでは実際にアプリを立ち上げてみたいと思います。DeployGateのクライアントがインストールされていなかったり、ログインをしていなかったり、自分のアクセス権が無いアプリだった場合は場合は、Toastで「You are not authorized to launch this app」とエラーが表示されActivityを起動することができません。

<img src="https://qiita-image-store.s3.amazonaws.com/0/956/f482c3d0-328f-e016-08ea-e1d43e63d9ee.png" width="350px" />

DeployGateクライアントをインストールしてログインした状態で、アクセス権限のあるアプリを起動した場合は、通常通りアクティビティが起動します。

<img src="https://qiita-image-store.s3.amazonaws.com/0/956/316e704a-481d-b6ce-6b21-2edd267592b0.png" width="350px" />

なお、アプリ（アクティビティ）起動中や起動後であっても、その間にDeployGateクライアントからログアウトする操作を行ったり、遠隔で端末からDeployGateクライアントログアウトさせたりした場合は、そのイベントを検知して**すぐにアクティビティが強制終了**します。

また、ユーザー認証は**DeployGateで管理されているバージョンのアプリのみに対して有効**なので、同じパッケージ名であっても、変更後にUSBケーブルなどから上書き転送したものは起動する事ができません。具体的には、アプリのパッケージ名とタイムスタンプ、md5を元に判定されます。

デバックを容易にするために、プラグイン経由で毎回DeployGateにアップロードするか、特定のproductFlavor(BUILD_TYPE)だけ認証を有効にするなど工夫すると良いでしょう。

```kotlin
// 例
if (BuildConfig.BUILD_TYPE == "stagingDebug") {
    DeployGate.registerCallback(...)
}
```



# テスターやグループのメンバーの起動権限を剥奪する
ユーザ認証機能はDeployGate上のアプリへのアクセス権限に基づいて機能します。起動権限を外したい場合は、DeployGateで管理しているアプリにアクセスできるメンバーから対象ユーザー外してください。

# インストールされている端末の起動権限を遠隔から剥奪する
自アカウントが保有する特定の端末からの起動権限を剥奪する場合は、自分のアカウントに紐づく端末の登録を削除します。DeployGateのダッシュボードの左サイドバーの最下部にある「利用中の端末」かた起動権限を剥奪したい端末を選び**「リモートでログアウトさせる」**を選んで、遠隔から対象端末のDeployGateクライアントをログアウトさせてください。

<img width="689" alt="30ebab4aa3aa282f39cdde0c20b0dcaf.png" src="https://qiita-image-store.s3.amazonaws.com/0/956/c8b89bf0-ab2c-f0c7-879b-7a5a8d4984cf.png">

# まとめ
DeployGateとDeployGate SDKをつかって特定のアカウントや端末でしか起動できないアプリをKotlinで作る方法をご紹介しました。起動権限を確認するフローを簡単に入れておくだけで、配布後も流出リスクを抑えた安心でストレスフリーな開発を行うことができます。ぜひお試しください！