こんにちは。
前回の記事でFlutterアプリでGoogleログインをしましたので、今日はSpreadsheet作成して適当なデータを入れたいと思います。今日は②Spreadsheet作成編するです。
- Googleにログインする
- GoogleDriveにSpreadsheetを作成してデータを入れる
前回の記事はこちらになります。

今回の記事ではUpload用のボタンを用意した画面を表示し、Uploadボタンで押下GoogleDriveにSpreadsheetを作成します。
作成したSpreadsheetです。
プラグインインストール
必要なプラグインは次のとおりです。
googleapis | GoogleCloudAPIを使用するFlutterプラグイン |
pubspec.yamlに以下を追加します。
dependencies: ・・・ googleapis: ^6.0.0
そして「flutter pub get」でインストールします。
GoogleCloudAPIの設定
「Google Drive API」と「Google Sheets API」を利用出来るようにします。
Google Cloud Consoleで[APIとサービス]から[ライブラリ]を選択します。
「Google Drive」などのキーワードを入れて検索します。
「Google Drive API」を有効にします。
同じように「Google Sheets API」も有効にします。
GoogleAPIのOAuth2.0スコープ設定
アプリがAPIを使用してGoogleユーザーのデータにアクセスする場合、そのスコープ(範囲)をユーザに同意してもらう必要があります。その認証にOAuth2.0認証を使用します。
先ほど有効にした「Google Drive API」と「Google Sheets API」のスコープを決めます。今回はGoogleDriveにSheetsファイルを作成し、Sheetsファイルのデータに書き込みを行うのが目的です。
GoogleAPIのOAuth2.0スコープを参照します。
上記赤枠のスコープをOAuth同意画面に登録します。ここに登録する事でアプリにスコープに対する同意画面がユーザーに表示されるようになります。
[OAuth同意画面]から[アプリを編集]を選択します。
①OAuth同意画面から表示されるので適切に入力し、②スコープまで進めます。
[スコープを追加または削除]を選択します。
手動追加にて、以下を追加します。
https://www.googleapis.com/auth/drive.file
https://www.googleapis.com/auth/spreadsheets
③④は必要に応じて入力します。
ログイン用ソースコード(修正)
前回の記事のログイン用ソースコードを少し修正します。
google_login.dartのsignIn()の中を変更します。
変更前
GoogleSignIn googleSignIn = GoogleSignIn();
変更後
GoogleSignIn googleSignIn = GoogleSignIn(scopes: [ 'https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/spreadsheets', ]);
もう一か所、GoogleLoginInfoクラスを次の章で作成するGoogleSheetsクラスに変更します。
変更前
MaterialPageRoute( builder: (context) => GoogleLoginInfo( user: user, ), ),
変更後
MaterialPageRoute( builder: (context) => GoogleSheets( user: user, ), ),
Spreadsheet作成ソースコード
google_sheets.dartを作成します。
import 'package:flutter/material.dart'; import 'package:http/io_client.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:googleapis/drive/v3.dart' as drive; import 'package:googleapis/sheets/v4.dart' as sheets; import 'package:http/http.dart'; import 'package:google_sign_in/google_sign_in.dart'; import 'package:tracer/routes/google_login.dart'; import '../baseappbar.dart'; class Category { late int id; late String title; Category( this.id, this.title, ); } class GoogleHttpClient extends IOClient { Map<String, String> _headers; GoogleHttpClient(this._headers) : super(); @override Future<IOStreamedResponse> send(BaseRequest request) => super.send(request..headers.addAll(_headers)); @override Future<Response> head(Uri url, {Map<String, String>? headers}) => super.head(url, headers: headers!..addAll(_headers)); } class GoogleSheets extends StatefulWidget { final User user; const GoogleSheets({ Key? key, required this.user, }) : super(key: key); @override _GoogleSheetsState createState() => _GoogleSheetsState(); } class _GoogleSheetsState extends State<GoogleSheets> { late User _user; GoogleHttpClient? authenticateClient; Future? _future; bool _isSigningOut = false; String _sheetId = ''; List<Category> list= [ Category(0,'sentiment'), Category(1,'food'), Category(2,'sports'), Category(3,'hardware'), Category(4,'vehicle'), ]; @override void initState() { _user = widget.user; _future = initAuth(); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( resizeToAvoidBottomInset : false, appBar: TransAppBar( title: 'GoogleSpreadSheets', appBar: AppBar(), ), body: FutureBuilder( future: _future, builder: (context, snapshot) { switch (snapshot.connectionState) { case ConnectionState.waiting: return const Center( child: CircularProgressIndicator(), ); default: if (snapshot.hasError) { print(snapshot.error); return Text('Error: ${snapshot.error}'); } else { return createGSheets(); } } } ) ); } createGSheets() { return SafeArea( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Row(), _user.photoURL != null ? ClipOval( child: Material( color: Colors.white60, child: Image.network( _user.photoURL!, fit: BoxFit.fitHeight, ), ), ) : const ClipOval( child: Material( color: Colors.black12, child: Padding( padding: EdgeInsets.all(16.0), child: Icon( Icons.person, size: 60, color: Colors.deepOrange, ), ), ), ), const SizedBox(height: 16.0), OutlinedButton( child: const Text('Upload'), onPressed: () async { if (authenticateClient == null) { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => const GoogleLogin(), ), ); } String? sheetId = await createSheet(); if(sheetId != null) { await insertSheet(sheetId); showDialog( context: context, builder: (context) { return AlertDialog( content: const Text('Googleスプレッドシートを作成しました。'), actions: [ ElevatedButton( onPressed: () => Navigator.pop(context, 'OK'), child: const Text('OK'), ), ], ); }, ); } }, ), _isSigningOut ? const CircularProgressIndicator() : OutlinedButton( child: const Text('Sign Out'), onPressed: () async { setState(() { _isSigningOut = true; }); await signOut(); setState(() { _isSigningOut = false; }); Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => const GoogleLogin(), ), ); } ) ], ), ); } Future<GoogleHttpClient?> initAuth() async { GoogleSignInAccount? googleSignInAccount = await GoogleSignIn().signInSilently(); if (googleSignInAccount == null) { return null; } authenticateClient = GoogleHttpClient(await googleSignInAccount.authHeaders); return authenticateClient; } Future<String?> createSheet() async { GoogleSignInAccount? googleSignInAccount = await GoogleSignIn().signInSilently(); if (googleSignInAccount == null) { return null; } authenticateClient = GoogleHttpClient(await googleSignInAccount.authHeaders); final driveApi = drive.DriveApi(authenticateClient!); var driveFile = drive.File(); driveFile.name = 'FlutterApp'; driveFile.mimeType = 'application/vnd.google-apps.spreadsheet'; final result = await driveApi.files.create(driveFile); String sheetId = result.id!; return sheetId; } Future<void> insertSheet(String sheetId) async { final sheetsApi = sheets.SheetsApi(authenticateClient!); List<dynamic> inputData = []; for (int i = 0; i < list.length; i++) { List<dynamic> row = []; row.add(list[i].id); row.add(list[i].title); inputData.add(row); } sheets.ValueRange vr = sheets.ValueRange.fromJson({ 'values': inputData }); await sheetsApi.spreadsheets.values .append(vr, sheetId, 'A:B', valueInputOption: 'USER_ENTERED') .then((sheets.AppendValuesResponse r) { }); return; } Future<void> signOut() async { final GoogleSignIn googleSignIn = GoogleSignIn(); await googleSignIn.signOut(); await FirebaseAuth.instance.signOut(); } }
コメント