flutter_blocを使用したFlutterでのマルチフレーバー認証

このチュートリアルでは、制作のさまざまな段階の定義と、開発におけるそれらの重要性について学習します。また、さまざまな環境でさまざまなFirebase構成を使用する方法についても説明します。さらに、ブロックウィジェットと、Flutterアプリケーションで状態を管理する際のウィジェットの機能についても学習します。

テスト用にデバイス上で同じアプリケーションのさまざまなビルドを使用できるように、さまざまなフレーバーのGoogle認証を実装するFlutterプロジェクトを作成します。

さまざまな段階

大規模なテクノロジー企業では、プロジェクトは通常、開発、ステージング、生産の3つの段階で完了します(ただし、これらの段階は企業ごとに異なる場合があります)。

これらのさまざまな段階で、製品はバグに対処するために徹底的にテストされ、高品質のソフトウェア製品を消費者に出荷できるようになります。

発達

この段階では、UIの初期構築と、APIとバックエンドの統合が開発環境で行われます。この環境で使用するデータは通常、テストAPIまたはテストデータベースであり、実際のデータはありません。リリース後に新しい機能をアプリケーションに追加する場合は、最初に開発環境から実装されます。

この段階では、コードが完全に機能し、アプリが効率的に実行されることを確認するために、多くのコードテストが行​​われます。この段階で実行されるテストのタイプは、と呼ばれunit testingます。

演出

ステージング環境では、選択したユーザーを連れてアプリをテストできます。これにより、実際のデータとやり取りできるため、アプリが公開された後の動作を把握できます。ステージング環境は本番環境を模倣しようとするため、大きな欠陥があり、システムが故障した場合でも、本番環境をシャットダウンする必要はありません。

すべてのデータベース移行は、この段階でテストされます。新しい機能が追加されたときに、最悪のシナリオをチェックするために機能もプッシュされます。プッシュされたときに新機能が壊れた場合、バグが発見されて修正されます。

WhatsApp Webを使用したことがある場合は、新しい機能が正式に公開される前に、テストプログラムに参加して新しい機能をテストするように求められた可能性があります。これは、ベータテストとして知られているものの例です。

製造

これは、ユーザーが試してみるためにアプリが公開される段階です。これは、会社またはクライアントにとって最も重要なフェーズです。実稼働段階では、ユーザーを失う可能性があるため、ユーザーに大きなバグに気付かせたくないでしょう。理想的には、ソフトウェアの主要なバグのほとんどは、この時点までに前の段階で対処されているはずです。

一般的な開発のヒント:ソフトウェアのすべての機能を一度に展開する必要はありません。新しい機能をプッシュする前に、問題をチェックし、現在の機能が安定していることを確認することを優先します。

Flutterアプリケーションの構築

Flutterアプリケーションでフレーバーを設定するには、手動で構成する必要があります。つまり、さまざまなディレクトリにある多くのファイルを操作する必要があります。これは非常に混乱する可能性がありますが、very_good_cliを使用すると、作業がはるかに簡単になります。

設定

新しいFlutterプロジェクトを作成するには、very_good_cliというDartパッケージを使用します。このパッケージは、標準構造を作成し、iOSとAndroidの両方のアプリケーションで必要なすべての環境をセットアップするのに役立ちます。

ツールをインストールするには、ターミナルで次のコマンドを入力します。dart pub global activate very_good_cli

very_good_cliをインストールしてアクティブ化した後、次のコマンドを使用してFlutterプロジェクトを作成できます。very_good create my_app --desc "My new Flutter app" --org "com.custom.org"

YAMLファイルのコンテンツを次のように置き換えます。

name: googlesigninwithflavor
description: A Very Good Project created by Very Good CLI.
version: 1.0.0+1
publish_to: none
environment:
  sdk: ">=2.16.0 <3.0.0"
dependencies:
  bloc: ^8.0.3
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.1
  intl: ^0.17.0
  google_sign_in: ^5.2.4
  equatable: ^2.0.3
  firebase_core: ^1.14.0
  firebase_auth: ^3.3.13
dev_dependencies:
  bloc_test: ^9.0.3
  flutter_test:
    sdk: flutter
  mocktail: ^0.3.0
  very_good_analysis: ^2.4.0
flutter:
  uses-material-design: true
  generate: true
  assets:
    - asset/

ファイル構造

lib                                   
├─ app                                
│  ├─ bloc                            
│  │  ├─ google_sign_in_bloc.dart     
│  │  ├─ google_sign_in_event.dart    
│  │  └─ google_sign_in_state.dart    
│  ├─ view                            
│  │  ├─ app.dart                     
│  │  └─ google_sign_in_view.dart     
│  └─ app.dart                        
├─ dashboard                          
│  └─ dashboard.dart                  
├─ repository                         
│  └─ authentication_repository.dart  
├─ bootstrap.dart                     
├─ generated_plugin_registrant.dart   
├─ main_development.dart              
├─ main_production.dart               
└─ main_staging.dart                  

プロジェクトを作成すると、制作の3つの段階に応じて名前が付けられた3つの異なるメインファイルが表示されます。これらの各ファイルは、本番の特定の段階で必要に応じて異なる設定を持つことができます。

main_development.dart              
main_production.dart               
main_staging.dart  

次の引数をターミナルに渡すことで、任意のフレーバーを実行できます。

# For Development
flutter run --flavor development --t lib/main_development.dart
# For Staging
flutter run --flavor development --t lib/main_staging.dart
# For Production
flutter run --flavor development --t lib/main_production.dart

Androidの場合、さまざまなフレーバーのセットアップ中に通常処理するbuild.gradleファイルは、Androidディレクトリ内のファイルです。

iOSの場合、使用するファイルはXcodeスキームです。ただし、very_good_cliによって既に生成されているため、これを行う必要はありません。

さまざまな環境向けにFirebaseを設定する

最近、FirebaseはFirebase CLIを導入しました。これにより、Firebaseプロジェクトの構成が簡単かつシームレスになりました。ただし、アナリティクスやGoogleログインなど、まだサポートされていない機能がいくつかあります。Googleログインを使用するため、Firebaseを手動で設定する必要があります。そのため、Firebaseプロジェクトを手動で設定します。

Firebaseコンソールでは、次の3つの異なるプロジェクトを作成します。

  • flavor dev
  • flavor stg
  • flavor prodマルチフレーバーFirebaseプロジェクト

FlutterプロジェクトをFirebaseに登録するときは、Androidパッケージ名.devに、、、を追加する.stg必要があります。.prd

パッケージ名はandroid/app/build.gradleファイルにあります。以下に示すように、として表示さapplicationIdれます。

 defaultConfig {
        applicationId "com.example.verygoodcore.googlesigninwithflavor"
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
    flavorDimensions "default"
    productFlavors { 
        production {
            dimension "default"
            applicationIdSuffix ""
            manifestPlaceholders = [appName: "Googlesigninwithflavor"]
        }
        staging {
            dimension "default"
            applicationIdSuffix ".stg"
            manifestPlaceholders = [appName: "[STG] Googlesigninwithflavor"]
        }        
        development {
            dimension "default"
            applicationIdSuffix ".dev"
            manifestPlaceholders = [appName: "[DEV] Googlesigninwithflavor"]
        }
    }

iOSの場合

iOSに登録するときは、正しいバンドルIDも入力する必要があります。ただし、Xcodeの使用経験がない場合、Xcodeの操作は難しい場合があります。次の手順に従って、バンドルIDを見つけることができます。

Xcodeを開くXcodeを開いたときに表示されるもの

をクリックしOpen a project or fileます。

Flutterプロジェクトに移動し、iOSディレクトリを開きます。ディレクトリを選択しRunner.xcworkspaceます。

次に、[ランナー]ドロップダウンをクリックします。[全般表示]タブで、を選択するBuild Settingsと、そこにアプリバンドルが表示されます。

すべてのFirebaseプロジェクトでこれらの手順を繰り返します。登録後、Android用とiOS用のgoogle-services.jsonファイルをダウンロードできます。GoogleService-Info.plist

google-services.jsonファイルはに移動されますandroid/app/src/{respective environment}。iOSの場合、環境のサブディレクトリを持つ新しい構成ディレクトリを作成GoogleService-Info.plistし、さまざまな環境に追加します。このファイルをRunnerXcodeのに追加します。詳細については、このFirebaseガイドをお読みください。

Google認証を実装するためのセットアップ

アプリケーションでGoogle認証を使用するには、次の手順でGoogleプロバイダーを有効にする必要があります。開発環境でGoogleプロバイダーを有効にします。

Firebaseに移動します。このチュートリアルでは、開発プロジェクトから始めます。

メインナビゲーションバーで、[認証]を選択します。次のように表示されます。認証を有効にする

次に、をクリックしSet up sign-in methodます。プロバイダーのリストが表示されます。[Googleログイン]を選択すると、次のように表示されます。Googleサインイン

Enable次の画像に示すように、オンに切り替えて、プロジェクトのサポートメールを追加します。次に、設定を保存します。プロジェクトサポートメールを追加

ナビゲーションバーで、設定アイコンをクリックProject settingsし、ドロップダウンから選択します。次に、ページの一番下までスクロールします。プロジェクトからSHA-1 keyとを追加する必要があります。SHA-256 key

SHAキーまたは指紋を追加するには、プロジェクトに戻り、Androidフォルダーを右クリックして、をクリックしますOpen in an integrated terminal。これにより、VSCode環境で新しいターミナルが開きます。

端末で、コマンド./gradlew signingReportを使用してキーを取得します。このコマンドを実行すると、環境が複数あるため、さまざまな署名キーを取得する必要があります。端末で開発デバッグSHA-1キーを使用します。

別の方法:コードエディタのターミナルで、ディレクトリをAndroidフォルダに変更してコマンドを実行できます。指紋/SHAキー

保存ボタンをクリックして、更新されたgoogle-services.jsonファイルをダウンロードします。google-services.json開発環境でファイルを置き換えます。この場合、開発環境に追加します。

注: Googleサインインを正しく機能させるには、FirebaseでSHA-1キーが必要です

Google認証を有効にしました。次のセクションで実装します。

FlutterプロジェクトにGoogle認証を実装する

状態管理にはブロックを使用します。Blocは、によって追加された状態マネージャーvery_good_cliです。

リポジトリの作成

リポジトリは、UIレイヤーに送信する必要のあるデータをブロックに提供するサービスのようなものです。リポジトリは、ブロックの要求に応じて直接API呼び出しを行う責任があります。リポジトリを次のように実装します。

import 'dart:developer';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class AuthenticationRepository {
  Future<bool> signInWithGoogle() async {
    try {
      final user = GoogleSignIn().currentUser ?? await GoogleSignIn().signIn();
      if (user != null) {
        await GoogleSignIn().signOut();
      }
      final googleAuth = await user?.authentication;
      final credential = GoogleAuthProvider.credential(
        accessToken: googleAuth?.accessToken,
        idToken: googleAuth?.idToken,
      );
      await FirebaseAuth.instance.signInWithCredential(credential);
      return true;
    } catch (e) {
      log('An Error Occurred $e');
      return false;
    }
  }
  
  Future<void> handleSignOut() => GoogleSignIn().disconnect();
  // Future<void> signOut() async {
  //   final _googleSignIn = GoogleSignIn();
  //   _googleSignIn.disconnect();
  // }
}

ブロックイベント

私たちのプロジェクトでは、2つのイベントが必要にGoogleSignInRequestedなりGoogleSignOutRequestedます。これは、次の方法で実装できます。

part of 'google_sign_in_bloc.dart';
abstract class GoogleSignInEvent extends Equatable {
  const GoogleSignInEvent();
  @override
  List<Object> get props => [];
}
class GoogleSignInRequested extends GoogleSignInEvent {}
class GoogleSignOutRequested extends GoogleSignInEvent {}

ブロック状態の作成

また、2つの状態が必要になります。1つはユーザーがいるAuthenticated場合、もう1つはユーザーがいる場合ですUnAuthenticated

part of 'google_sign_in_bloc.dart';
abstract class GoogleSignInState extends Equatable {
  @override
  List<Object?> get props => [];
}
class UnAuthenticated extends GoogleSignInState {}
class Authenticated extends GoogleSignInState {}

ブロックを作成する

Authenticatedブロックは、ユーザーがログインしたUnAuthenticatedときとユーザーがダッシュボードからログアウトしたときの2つの状態をUIに公開します。

これを次のように実装します。

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:googlesigninwithflavor/repository/authentication_repository.dart';
part 'google_sign_in_event.dart';
part 'google_sign_in_state.dart';
class GoogleSignInBloc extends Bloc<GoogleSignInEvent, GoogleSignInState> {
  GoogleSignInBloc({required this.authenticationRepository})
      : super(UnAuthenticated()) {
    on<GoogleSignInRequested>(_onGoogleSignInPressed);
    on<GoogleSignOutRequested>(_onGoogleSignOutPressed);
  }
  final AuthenticationRepository authenticationRepository;
  Future<void> _onGoogleSignInPressed(
    GoogleSignInRequested event,
    Emitter<GoogleSignInState> emit,
  ) async {
    final response = await authenticationRepository.signInWithGoogle();
    if (response) {
      emit(Authenticated());
    }
  }
  void _onGoogleSignOutPressed(
    GoogleSignOutRequested event,
    Emitter<GoogleSignInState> emit,
  ) {
    authenticationRepository.handleSignOut();
    emit(UnAuthenticated());
  }
}

UIの構築

私たちのapp.dartクラスは、ホーム画面を次のようにレンダリングします。

import 'package:flutter/material.dart';
import 'package:googlesigninwithflavor/app/view/google_sign_in_view.dart';
class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        appBarTheme: const AppBarTheme(color: Color(0xFF13B9FF)),
        colorScheme: ColorScheme.fromSwatch(
          accentColor: const Color(0xFF13B9FF),
        ),
      ),
      home: const GoogleSignInView(),
    );
  }
}

google_sign_in_view.dartホーム画面とサインインボタンの実装を保持します。

class GoogleSignInView extends StatelessWidget {
  const GoogleSignInView({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return RepositoryProvider(
      create: (context) => AuthenticationRepository(),
      child: BlocProvider(
        create: (context) => GoogleSignInBloc(
          authenticationRepository: RepositoryProvider.of(context),
        ),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Sign In With Google'),
          ),
          body: const ShowSignInButton(),
        ),
      ),
    );
  }
}

上記のコードでは、RepositoryProviderウィジェットを使用してリポジトリのインスタンスと、を介してリポジトリにアクセスできるようにする子を作成しましたRepositoryProvider.of(context)

また、BlocProviderウィジェットを使用してインスタンスを作成Blocし、サブツリーまたは子ウィジェットからアクセスできるようにしました。

次に、次のように子ウィジェットでブロックを使用します。

class ShowSignInButton extends StatelessWidget {
  const ShowSignInButton({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return BlocListener<GoogleSignInBloc, GoogleSignInState>(
      listener: (context, state) {
        if (state is Authenticated) {
          Navigator.push<Type>(
            context,
            MaterialPageRoute(builder: (_) => const DashBoard()),
          );
        }
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Image.asset(
              'asset/google2.png',
              height: 60,
            ),
          ),
          ElevatedButton(
            onPressed: () {
              context.read<GoogleSignInBloc>().add(GoogleSignInRequested());
            },
            child: const Text('Sign In With Google'),
          ),
        ],
      ),
    );
  }
}

ここでは、を使用しBlocListnerて、ブロックによって放出された状態に基づいて別の画面に移動しました。

GoogleSignInRequestedまた、イベントをに渡しましたElevatedButton。そのため、ユーザーがボタンをクリックしてGoogleにログインすると、イベントがブロックに渡され、GoogleSignInAPIにリクエストが送信されます。

認証されたユーザーの詳細を表示するダッシュボード画面も実装しましょう。これを実装するには、FirebaseAuthインスタンスを呼び出して現在のユーザーの詳細にアクセスする必要があります。BlocListnerまた、ウィジェットを使用してユーザーをサインイン画面に戻すログアウトボタンを作成します。

class DashBoard extends StatelessWidget {
  const DashBoard({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return RepositoryProvider(
      create: (context) => AuthenticationRepository(),
      child: BlocProvider(
        create: (context) => GoogleSignInBloc(
          authenticationRepository: RepositoryProvider.of(context),
        ),
        child: DashBoardDetails(),
      ),
    );
  }
}
class DashBoardDetails extends StatelessWidget {
  DashBoardDetails({
    Key? key,
  }) : super(key: key);
  final user = FirebaseAuth.instance.currentUser!;
  @override
  Widget build(BuildContext context) {
    return BlocListener<GoogleSignInBloc, GoogleSignInState>(
      listener: (context, state) {
        if (state is UnAuthenticated) {
          Navigator.of(context).pushAndRemoveUntil<Type>(
            MaterialPageRoute(builder: (context) => const GoogleSignInView()),
            (route) => false,
          );
        }
      },
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Very Good Codemagic'),
        ),
        body: BlocBuilder<GoogleSignInBloc, GoogleSignInState>(
          builder: (context, state) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Center(
                  child: Text('Welcome to your Dashboard'),
                ),
                Text('${user.displayName}'),
                if (user.photoURL != null)
                  Image.network('${user.photoURL}')
                else
                  Container(),
                ElevatedButton(
                  onPressed: () {
                    context
                        .read<GoogleSignInBloc>()
                        .add(GoogleSignOutRequested());
                  },
                  child: const Text('Sign Out'),
                )
              ],
            );
          },
        ),
      ),
    );
  }
}

やあ!🎉開発、ステージング、本番環境用のGoogleログイン認証を正常に作成しました。

 このストーリーは、もともとhttps://blog.codemagic.io/multi-flavored-authentication-in-flutter/で公開されました

#flutter #authentication #google 

What is GEEK

Buddha Community

flutter_blocを使用したFlutterでのマルチフレーバー認証

flutter_blocを使用したFlutterでのマルチフレーバー認証

このチュートリアルでは、制作のさまざまな段階の定義と、開発におけるそれらの重要性について学習します。また、さまざまな環境でさまざまなFirebase構成を使用する方法についても説明します。さらに、ブロックウィジェットと、Flutterアプリケーションで状態を管理する際のウィジェットの機能についても学習します。

テスト用にデバイス上で同じアプリケーションのさまざまなビルドを使用できるように、さまざまなフレーバーのGoogle認証を実装するFlutterプロジェクトを作成します。

さまざまな段階

大規模なテクノロジー企業では、プロジェクトは通常、開発、ステージング、生産の3つの段階で完了します(ただし、これらの段階は企業ごとに異なる場合があります)。

これらのさまざまな段階で、製品はバグに対処するために徹底的にテストされ、高品質のソフトウェア製品を消費者に出荷できるようになります。

発達

この段階では、UIの初期構築と、APIとバックエンドの統合が開発環境で行われます。この環境で使用するデータは通常、テストAPIまたはテストデータベースであり、実際のデータはありません。リリース後に新しい機能をアプリケーションに追加する場合は、最初に開発環境から実装されます。

この段階では、コードが完全に機能し、アプリが効率的に実行されることを確認するために、多くのコードテストが行​​われます。この段階で実行されるテストのタイプは、と呼ばれunit testingます。

演出

ステージング環境では、選択したユーザーを連れてアプリをテストできます。これにより、実際のデータとやり取りできるため、アプリが公開された後の動作を把握できます。ステージング環境は本番環境を模倣しようとするため、大きな欠陥があり、システムが故障した場合でも、本番環境をシャットダウンする必要はありません。

すべてのデータベース移行は、この段階でテストされます。新しい機能が追加されたときに、最悪のシナリオをチェックするために機能もプッシュされます。プッシュされたときに新機能が壊れた場合、バグが発見されて修正されます。

WhatsApp Webを使用したことがある場合は、新しい機能が正式に公開される前に、テストプログラムに参加して新しい機能をテストするように求められた可能性があります。これは、ベータテストとして知られているものの例です。

製造

これは、ユーザーが試してみるためにアプリが公開される段階です。これは、会社またはクライアントにとって最も重要なフェーズです。実稼働段階では、ユーザーを失う可能性があるため、ユーザーに大きなバグに気付かせたくないでしょう。理想的には、ソフトウェアの主要なバグのほとんどは、この時点までに前の段階で対処されているはずです。

一般的な開発のヒント:ソフトウェアのすべての機能を一度に展開する必要はありません。新しい機能をプッシュする前に、問題をチェックし、現在の機能が安定していることを確認することを優先します。

Flutterアプリケーションの構築

Flutterアプリケーションでフレーバーを設定するには、手動で構成する必要があります。つまり、さまざまなディレクトリにある多くのファイルを操作する必要があります。これは非常に混乱する可能性がありますが、very_good_cliを使用すると、作業がはるかに簡単になります。

設定

新しいFlutterプロジェクトを作成するには、very_good_cliというDartパッケージを使用します。このパッケージは、標準構造を作成し、iOSとAndroidの両方のアプリケーションで必要なすべての環境をセットアップするのに役立ちます。

ツールをインストールするには、ターミナルで次のコマンドを入力します。dart pub global activate very_good_cli

very_good_cliをインストールしてアクティブ化した後、次のコマンドを使用してFlutterプロジェクトを作成できます。very_good create my_app --desc "My new Flutter app" --org "com.custom.org"

YAMLファイルのコンテンツを次のように置き換えます。

name: googlesigninwithflavor
description: A Very Good Project created by Very Good CLI.
version: 1.0.0+1
publish_to: none
environment:
  sdk: ">=2.16.0 <3.0.0"
dependencies:
  bloc: ^8.0.3
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.1
  intl: ^0.17.0
  google_sign_in: ^5.2.4
  equatable: ^2.0.3
  firebase_core: ^1.14.0
  firebase_auth: ^3.3.13
dev_dependencies:
  bloc_test: ^9.0.3
  flutter_test:
    sdk: flutter
  mocktail: ^0.3.0
  very_good_analysis: ^2.4.0
flutter:
  uses-material-design: true
  generate: true
  assets:
    - asset/

ファイル構造

lib                                   
├─ app                                
│  ├─ bloc                            
│  │  ├─ google_sign_in_bloc.dart     
│  │  ├─ google_sign_in_event.dart    
│  │  └─ google_sign_in_state.dart    
│  ├─ view                            
│  │  ├─ app.dart                     
│  │  └─ google_sign_in_view.dart     
│  └─ app.dart                        
├─ dashboard                          
│  └─ dashboard.dart                  
├─ repository                         
│  └─ authentication_repository.dart  
├─ bootstrap.dart                     
├─ generated_plugin_registrant.dart   
├─ main_development.dart              
├─ main_production.dart               
└─ main_staging.dart                  

プロジェクトを作成すると、制作の3つの段階に応じて名前が付けられた3つの異なるメインファイルが表示されます。これらの各ファイルは、本番の特定の段階で必要に応じて異なる設定を持つことができます。

main_development.dart              
main_production.dart               
main_staging.dart  

次の引数をターミナルに渡すことで、任意のフレーバーを実行できます。

# For Development
flutter run --flavor development --t lib/main_development.dart
# For Staging
flutter run --flavor development --t lib/main_staging.dart
# For Production
flutter run --flavor development --t lib/main_production.dart

Androidの場合、さまざまなフレーバーのセットアップ中に通常処理するbuild.gradleファイルは、Androidディレクトリ内のファイルです。

iOSの場合、使用するファイルはXcodeスキームです。ただし、very_good_cliによって既に生成されているため、これを行う必要はありません。

さまざまな環境向けにFirebaseを設定する

最近、FirebaseはFirebase CLIを導入しました。これにより、Firebaseプロジェクトの構成が簡単かつシームレスになりました。ただし、アナリティクスやGoogleログインなど、まだサポートされていない機能がいくつかあります。Googleログインを使用するため、Firebaseを手動で設定する必要があります。そのため、Firebaseプロジェクトを手動で設定します。

Firebaseコンソールでは、次の3つの異なるプロジェクトを作成します。

  • flavor dev
  • flavor stg
  • flavor prodマルチフレーバーFirebaseプロジェクト

FlutterプロジェクトをFirebaseに登録するときは、Androidパッケージ名.devに、、、を追加する.stg必要があります。.prd

パッケージ名はandroid/app/build.gradleファイルにあります。以下に示すように、として表示さapplicationIdれます。

 defaultConfig {
        applicationId "com.example.verygoodcore.googlesigninwithflavor"
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
    flavorDimensions "default"
    productFlavors { 
        production {
            dimension "default"
            applicationIdSuffix ""
            manifestPlaceholders = [appName: "Googlesigninwithflavor"]
        }
        staging {
            dimension "default"
            applicationIdSuffix ".stg"
            manifestPlaceholders = [appName: "[STG] Googlesigninwithflavor"]
        }        
        development {
            dimension "default"
            applicationIdSuffix ".dev"
            manifestPlaceholders = [appName: "[DEV] Googlesigninwithflavor"]
        }
    }

iOSの場合

iOSに登録するときは、正しいバンドルIDも入力する必要があります。ただし、Xcodeの使用経験がない場合、Xcodeの操作は難しい場合があります。次の手順に従って、バンドルIDを見つけることができます。

Xcodeを開くXcodeを開いたときに表示されるもの

をクリックしOpen a project or fileます。

Flutterプロジェクトに移動し、iOSディレクトリを開きます。ディレクトリを選択しRunner.xcworkspaceます。

次に、[ランナー]ドロップダウンをクリックします。[全般表示]タブで、を選択するBuild Settingsと、そこにアプリバンドルが表示されます。

すべてのFirebaseプロジェクトでこれらの手順を繰り返します。登録後、Android用とiOS用のgoogle-services.jsonファイルをダウンロードできます。GoogleService-Info.plist

google-services.jsonファイルはに移動されますandroid/app/src/{respective environment}。iOSの場合、環境のサブディレクトリを持つ新しい構成ディレクトリを作成GoogleService-Info.plistし、さまざまな環境に追加します。このファイルをRunnerXcodeのに追加します。詳細については、このFirebaseガイドをお読みください。

Google認証を実装するためのセットアップ

アプリケーションでGoogle認証を使用するには、次の手順でGoogleプロバイダーを有効にする必要があります。開発環境でGoogleプロバイダーを有効にします。

Firebaseに移動します。このチュートリアルでは、開発プロジェクトから始めます。

メインナビゲーションバーで、[認証]を選択します。次のように表示されます。認証を有効にする

次に、をクリックしSet up sign-in methodます。プロバイダーのリストが表示されます。[Googleログイン]を選択すると、次のように表示されます。Googleサインイン

Enable次の画像に示すように、オンに切り替えて、プロジェクトのサポートメールを追加します。次に、設定を保存します。プロジェクトサポートメールを追加

ナビゲーションバーで、設定アイコンをクリックProject settingsし、ドロップダウンから選択します。次に、ページの一番下までスクロールします。プロジェクトからSHA-1 keyとを追加する必要があります。SHA-256 key

SHAキーまたは指紋を追加するには、プロジェクトに戻り、Androidフォルダーを右クリックして、をクリックしますOpen in an integrated terminal。これにより、VSCode環境で新しいターミナルが開きます。

端末で、コマンド./gradlew signingReportを使用してキーを取得します。このコマンドを実行すると、環境が複数あるため、さまざまな署名キーを取得する必要があります。端末で開発デバッグSHA-1キーを使用します。

別の方法:コードエディタのターミナルで、ディレクトリをAndroidフォルダに変更してコマンドを実行できます。指紋/SHAキー

保存ボタンをクリックして、更新されたgoogle-services.jsonファイルをダウンロードします。google-services.json開発環境でファイルを置き換えます。この場合、開発環境に追加します。

注: Googleサインインを正しく機能させるには、FirebaseでSHA-1キーが必要です

Google認証を有効にしました。次のセクションで実装します。

FlutterプロジェクトにGoogle認証を実装する

状態管理にはブロックを使用します。Blocは、によって追加された状態マネージャーvery_good_cliです。

リポジトリの作成

リポジトリは、UIレイヤーに送信する必要のあるデータをブロックに提供するサービスのようなものです。リポジトリは、ブロックの要求に応じて直接API呼び出しを行う責任があります。リポジトリを次のように実装します。

import 'dart:developer';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class AuthenticationRepository {
  Future<bool> signInWithGoogle() async {
    try {
      final user = GoogleSignIn().currentUser ?? await GoogleSignIn().signIn();
      if (user != null) {
        await GoogleSignIn().signOut();
      }
      final googleAuth = await user?.authentication;
      final credential = GoogleAuthProvider.credential(
        accessToken: googleAuth?.accessToken,
        idToken: googleAuth?.idToken,
      );
      await FirebaseAuth.instance.signInWithCredential(credential);
      return true;
    } catch (e) {
      log('An Error Occurred $e');
      return false;
    }
  }
  
  Future<void> handleSignOut() => GoogleSignIn().disconnect();
  // Future<void> signOut() async {
  //   final _googleSignIn = GoogleSignIn();
  //   _googleSignIn.disconnect();
  // }
}

ブロックイベント

私たちのプロジェクトでは、2つのイベントが必要にGoogleSignInRequestedなりGoogleSignOutRequestedます。これは、次の方法で実装できます。

part of 'google_sign_in_bloc.dart';
abstract class GoogleSignInEvent extends Equatable {
  const GoogleSignInEvent();
  @override
  List<Object> get props => [];
}
class GoogleSignInRequested extends GoogleSignInEvent {}
class GoogleSignOutRequested extends GoogleSignInEvent {}

ブロック状態の作成

また、2つの状態が必要になります。1つはユーザーがいるAuthenticated場合、もう1つはユーザーがいる場合ですUnAuthenticated

part of 'google_sign_in_bloc.dart';
abstract class GoogleSignInState extends Equatable {
  @override
  List<Object?> get props => [];
}
class UnAuthenticated extends GoogleSignInState {}
class Authenticated extends GoogleSignInState {}

ブロックを作成する

Authenticatedブロックは、ユーザーがログインしたUnAuthenticatedときとユーザーがダッシュボードからログアウトしたときの2つの状態をUIに公開します。

これを次のように実装します。

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:googlesigninwithflavor/repository/authentication_repository.dart';
part 'google_sign_in_event.dart';
part 'google_sign_in_state.dart';
class GoogleSignInBloc extends Bloc<GoogleSignInEvent, GoogleSignInState> {
  GoogleSignInBloc({required this.authenticationRepository})
      : super(UnAuthenticated()) {
    on<GoogleSignInRequested>(_onGoogleSignInPressed);
    on<GoogleSignOutRequested>(_onGoogleSignOutPressed);
  }
  final AuthenticationRepository authenticationRepository;
  Future<void> _onGoogleSignInPressed(
    GoogleSignInRequested event,
    Emitter<GoogleSignInState> emit,
  ) async {
    final response = await authenticationRepository.signInWithGoogle();
    if (response) {
      emit(Authenticated());
    }
  }
  void _onGoogleSignOutPressed(
    GoogleSignOutRequested event,
    Emitter<GoogleSignInState> emit,
  ) {
    authenticationRepository.handleSignOut();
    emit(UnAuthenticated());
  }
}

UIの構築

私たちのapp.dartクラスは、ホーム画面を次のようにレンダリングします。

import 'package:flutter/material.dart';
import 'package:googlesigninwithflavor/app/view/google_sign_in_view.dart';
class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        appBarTheme: const AppBarTheme(color: Color(0xFF13B9FF)),
        colorScheme: ColorScheme.fromSwatch(
          accentColor: const Color(0xFF13B9FF),
        ),
      ),
      home: const GoogleSignInView(),
    );
  }
}

google_sign_in_view.dartホーム画面とサインインボタンの実装を保持します。

class GoogleSignInView extends StatelessWidget {
  const GoogleSignInView({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return RepositoryProvider(
      create: (context) => AuthenticationRepository(),
      child: BlocProvider(
        create: (context) => GoogleSignInBloc(
          authenticationRepository: RepositoryProvider.of(context),
        ),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Sign In With Google'),
          ),
          body: const ShowSignInButton(),
        ),
      ),
    );
  }
}

上記のコードでは、RepositoryProviderウィジェットを使用してリポジトリのインスタンスと、を介してリポジトリにアクセスできるようにする子を作成しましたRepositoryProvider.of(context)

また、BlocProviderウィジェットを使用してインスタンスを作成Blocし、サブツリーまたは子ウィジェットからアクセスできるようにしました。

次に、次のように子ウィジェットでブロックを使用します。

class ShowSignInButton extends StatelessWidget {
  const ShowSignInButton({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return BlocListener<GoogleSignInBloc, GoogleSignInState>(
      listener: (context, state) {
        if (state is Authenticated) {
          Navigator.push<Type>(
            context,
            MaterialPageRoute(builder: (_) => const DashBoard()),
          );
        }
      },
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: Image.asset(
              'asset/google2.png',
              height: 60,
            ),
          ),
          ElevatedButton(
            onPressed: () {
              context.read<GoogleSignInBloc>().add(GoogleSignInRequested());
            },
            child: const Text('Sign In With Google'),
          ),
        ],
      ),
    );
  }
}

ここでは、を使用しBlocListnerて、ブロックによって放出された状態に基づいて別の画面に移動しました。

GoogleSignInRequestedまた、イベントをに渡しましたElevatedButton。そのため、ユーザーがボタンをクリックしてGoogleにログインすると、イベントがブロックに渡され、GoogleSignInAPIにリクエストが送信されます。

認証されたユーザーの詳細を表示するダッシュボード画面も実装しましょう。これを実装するには、FirebaseAuthインスタンスを呼び出して現在のユーザーの詳細にアクセスする必要があります。BlocListnerまた、ウィジェットを使用してユーザーをサインイン画面に戻すログアウトボタンを作成します。

class DashBoard extends StatelessWidget {
  const DashBoard({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return RepositoryProvider(
      create: (context) => AuthenticationRepository(),
      child: BlocProvider(
        create: (context) => GoogleSignInBloc(
          authenticationRepository: RepositoryProvider.of(context),
        ),
        child: DashBoardDetails(),
      ),
    );
  }
}
class DashBoardDetails extends StatelessWidget {
  DashBoardDetails({
    Key? key,
  }) : super(key: key);
  final user = FirebaseAuth.instance.currentUser!;
  @override
  Widget build(BuildContext context) {
    return BlocListener<GoogleSignInBloc, GoogleSignInState>(
      listener: (context, state) {
        if (state is UnAuthenticated) {
          Navigator.of(context).pushAndRemoveUntil<Type>(
            MaterialPageRoute(builder: (context) => const GoogleSignInView()),
            (route) => false,
          );
        }
      },
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Very Good Codemagic'),
        ),
        body: BlocBuilder<GoogleSignInBloc, GoogleSignInState>(
          builder: (context, state) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Center(
                  child: Text('Welcome to your Dashboard'),
                ),
                Text('${user.displayName}'),
                if (user.photoURL != null)
                  Image.network('${user.photoURL}')
                else
                  Container(),
                ElevatedButton(
                  onPressed: () {
                    context
                        .read<GoogleSignInBloc>()
                        .add(GoogleSignOutRequested());
                  },
                  child: const Text('Sign Out'),
                )
              ],
            );
          },
        ),
      ),
    );
  }
}

やあ!🎉開発、ステージング、本番環境用のGoogleログイン認証を正常に作成しました。

 このストーリーは、もともとhttps://blog.codemagic.io/multi-flavored-authentication-in-flutter/で公開されました

#flutter #authentication #google