🐦
FlutterでTwitterログインを実装する
前提
- Twitter DeveloperのログインAPIを使用するための設定が済んでいる。
ちょっと古めですが参考リンク
- Firebaseプロジェクト作成済
Firebaseの設定
- AuthenticationのプロバイダでTwitterを有効にし、APIキーとAPIシークレットキーをコピペする。
Twitter DeveloperにリダイレクトURIにスキーマを設定
今回は「twitterauth://」で設定します。
設定先は以下の記事が参考になります。
iOS側の設定
info.plist
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>Bundle ID</string>
<key>CFBundleURLSchemes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
</array>
</dict>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb$(FACEBOOK_APP_ID)</string>
<!-- Registered Callback URLs in TwitterApp -->
<string>twitterauth</string> // 追加
</array>
</dict>
</array>
Android側の設定
android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hogehoge">
<uses-permission android:name="android.permission.INTERNET" />
<queries>
<provider android:authorities="com.facebook.katana.provider.PlatformProvider" />
</queries>
<application
android:label="${appNamePrefix}アプリ名前"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
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">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data
android:name="flutter_deeplinking_enabled"
android:value="true" />
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="hogehoge.page.link" />
</intent-filter>
// ここから追加
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Registered Callback URLs in TwitterApp -->
<data android:scheme="twitterauth" />
</intent-filter>
// ここまで追加
</activity>
<!-- image croper start -->
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<!-- image croper end -->
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- facebook login start -->
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />
<meta-data
android:name="com.facebook.sdk.ClientToken"
android:value="@string/facebook_client_token"/>
<!-- facebook login end -->
</application>
</manifest>
Flutter側の実装
以前書いたFacebookログインの実装と概ね似たような実装です。
APIキーなどの読込にはdot_envを使用しています。(詳しい説明は割愛)
.env
TWITTER_API_KEY=**********************
TWITTER_SECRET_KEY=***********************
TWITTER_REDIRECT_SCHEMA=twitterauth://
twitter_auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:twitter_login/twitter_login.dart';
import 'package:hogehoge/log.dart';
import 'package:hogehoge/models/sns_login_result.dart';
class TwitterAuth {
TwitterAuth();
Future<TwitterLogin> setKey() async {
return TwitterLogin(
apiKey: dotenv.env['TWITTER_API_KEY'] ?? '',
apiSecretKey: dotenv.env['TWITTER_SECRET_KEY'] ?? '',
redirectURI: dotenv.env['TWITTER_REDIRECT_SCHEMA'] ?? '',
);
}
Future<SNSLoginResult?> login() async {
try {
final twitterAuth = await setKey();
final authResult = await twitterAuth.login();
if (authResult.authToken == null) {
return null;
}
final twitterAuthCredential = TwitterAuthProvider.credential(
accessToken: authResult.authToken!,
secret: authResult.authTokenSecret!,
);
return SNSLoginResult(
name: authResult.user?.name,
credential: twitterAuthCredential,
);
} on Exception catch (e) {
Log.d(e);
rethrow;
}
}
}
final twitterAuthProvider = Provider<TwitterAuth>((ref) {
return TwitterAuth();
});
login_repository.dart
class LoginRepository {
LoginRepository(
this._facebookAuth,
this._firebaseManager,
this._twitterAuth,
);
final FacebookAuth _facebookAuth;
final FirebaseManager _firebaseManager;
final TwitterManager _twitterAuth;
// これをViewModelから呼び出す
Future<Result<SNSLogin?>> twitterLogin() async {
try {
final twitterLoginResult = await _twitterAuth.login();
if (twitterLoginResult == null) {
// キャンセルした場合などはreturn
return const Result.success(null);
}
await _firebaseManager.auth.signInWithCredential(
twitterLoginResult.credential,
);
return Result.success(
SNSLogin(name: twitterLoginResult.name),
);
} on Exception catch (e) {
return Result.failure(convertError(e));
}
}
}
final loginRepositoryProvider = Provider<LoginRepository>((ref) {
final facebook = ref.read(facebookAuthProvider);
final firebase = ref.read(firebaseManagerProvider);
final twitter = ref.read(twitterManagerProvider);
return LoginRepository(facebook, firebase, twitter);
});
あとはLoginRepositoryからtwitterLogin()をViewModelなどで呼び出して終わりです。
Discussion