Androidでflutterのsign_in_with_appleを使ったときにactivityが起動できない対処法

こんにちは。[virapture株式会社](https://virapture.com)の[もぐめっと](https://mogmet.com)です。
![mogmet.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42234/ce84b8ec-2a7f-2fb0-48b6-561bc0cc32f0.jpeg)

倉庫を使っておしゃれなカフェ空間にしているcafe SoulTreeというところでの一枚です。
空間もおしゃれで、昔、ゆとりですがなにかという番組でも使われていました。
駅から離れているのに結構人気スポットなので二子玉デートに使うといいと思います。

https://cafesoultree.jp/


本日はタイトルの通り、sign in with appleをしようとしたらactivityが起動できなくて困ったことがあったので対処法を記載しておきます。

実装方法に関しては下記記事を参考に実装しました。

https://medium.com/flutter-jp/sign-in-with-apple-d0d123cbbe17

## どんなエラー

Sign in with appleでログイン完了後、アプリに戻ってActivityを起動しようとすると下記のようなエラーが発生しました。

```log
D/AndroidRuntime(29534): Shutting down VM
E/AndroidRuntime(29534): FATAL EXCEPTION: main
E/AndroidRuntime(29534): Process: com.mogmet, PID: 29534
E/AndroidRuntime(29534): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mogmet/com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Intent.toString()' on a null object reference
E/AndroidRuntime(29534): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2822)
E/AndroidRuntime(29534): 	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2897)
E/AndroidRuntime(29534): 	at android.app.ActivityThread.-wrap11(Unknown Source:0)
E/AndroidRuntime(29534): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1598)
E/AndroidRuntime(29534): 	at android.os.Handler.dispatchMessage(Handler.java:105)
E/AndroidRuntime(29534): 	at android.os.Looper.loop(Looper.java:251)
E/AndroidRuntime(29534): 	at android.app.ActivityThread.main(ActivityThread.java:6572)
E/AndroidRuntime(29534): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(29534): 	at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
E/AndroidRuntime(29534): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
E/AndroidRuntime(29534): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Intent.toString()' on a null object reference
E/AndroidRuntime(29534): 	at android.app.Instrumentation.execStartActivity(Instrumentation.java:1581)
E/AndroidRuntime(29534): 	at android.app.Activity.startActivityForResult(Activity.java:4472)
E/AndroidRuntime(29534): 	at android.app.Activity.startActivityForResult(Activity.java:4430)
E/AndroidRuntime(29534): 	at android.app.Activity.startActivity(Activity.java:4791)
E/AndroidRuntime(29534): 	at android.app.Activity.startActivity(Activity.java:4759)
E/AndroidRuntime(29534): 	at com.aboutyou.dart_packages.sign_in_with_apple.SignInWithApplePlugin$onMethodCall$1.invoke(SignInWithApplePlugin.kt:89)
E/AndroidRuntime(29534): 	at com.aboutyou.dart_packages.sign_in_with_apple.SignInWithApplePlugin$onMethodCall$1.invoke(SignInWithApplePlugin.kt:84)
E/AndroidRuntime(29534): 	at com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback.onCreate(SignInWithApplePlugin.kt:168)
E/AndroidRuntime(29534): 	at android.app.Activity.performCreate(Activity.java:6975)
E/AndroidRuntime(29534): 	at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
E/AndroidRuntime(29534): 	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2775)
E/AndroidRuntime(29534): 	... 9 more
```

なぜかintentがないって言われちゃっています。なんでやねん。

## 解決法結論

結論からいうと、twitterログインのためにschemeを定義していたのですが、こいつが原因でした

```AndroidManifest.xml
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Registered Callback URL for twitter login -->
                <data android:scheme="twitter" /> ← こいつ！！
            </intent-filter>
        </activity>
```

そのためintent-filterを分けて書くことで解決できました。

```AndroidManifest.xml
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Registered Callback URL for twitter login -->
                <data android:scheme="twitter" />
            </intent-filter>
        </activity>

```

## 結論に至るまでの結論

ここからはきっと誰も読まないと思われるが念の為に残しておく解決法に至った顛末を記載します。

まず、ログを読み解くと、最後はここでエラーが発生していることがわかりました。

```
E/AndroidRuntime(29534): 	at com.aboutyou.dart_packages.sign_in_with_apple.SignInWithApplePlugin$onMethodCall$1.invoke(SignInWithApplePlugin.kt:89)
```

実際にこのソースをたどると、packageManager.getLaunchIntentForPackageを使ってintentを引っ張ってactivityを起動していることがわかりました。

https://github.com/aboutyou/dart_packages/blob/753e2c4872fb7878858f9cce379821fa19a0d265/packages/sign_in_with_apple/android/src/main/kotlin/com/aboutyou/dart_packages/sign_in_with_apple/SignInWithApplePlugin.kt#L84-L90

```SignInWithApplePlugin.kt
        triggerMainActivityToHideChromeCustomTab = {
          val notificationIntent = _activity.packageManager.getLaunchIntentForPackage(_activity.packageName);
          notificationIntent?.setPackage(null)
          // Bring the Flutter activity back to the top, by popping the Chrome Custom Tab
          notificationIntent?.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP;
          _activity.startActivity(notificationIntent)
        }
```

どうやらnotificationIntentがnullになっていて起動に失敗しているようでした。

サンプルだと問題ないのになんで自分のアプリのpackageNameからひっぱってこれないねん！というところで考えたところ、そもそもいつのまにかこのアプリをビルドしたときにホーム画面にアプリのアイコンが表示されていないことを思い出し、このあたりでflutterではなくandroid側に、問題があるということを考えました。

おそらく、packageManager.getLaunchIntentForPackageでとってこれないということはアプリ情報がなにかおかしいということなので、AndroidManifest.xmlの何かがおかしいと狙いを定めます。

そこであちこちAndroidManifest.xmlの情報を消したりしてみていった結果、アプリアイコンが表示されるようになりました。
その原因となったのが結論でも書いた、twitterログインのときに追加したscheme情報が原因ということがわかりました。

## まとめ

schemeを追加するときは気をつけよう！！！
また、intent-filterの追加にも気をつけよう！！

原因がわかると本当に些細な問題なのですが、これに至るまでがなかなか大変だったりするので開発は常に調査との戦いになるので実質調査兵団の団員といっても過言ではないです。

最後に、[ワンナイト人狼オンライン](https://online.1nite-jinro.com/link/blog)というゲームを作ってます！よかったら遊んでね！

https://online.1nite-jinro.com/link/blog

他にも[Camecon](https://camecon.me/)や[Offcha](https://offcha.com/)といったサービスも作ってるのでよかったら使ってね！

https://camecon.me/

https://offcha.com/

また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。

https://virapture.com/