Slide 1

Slide 1 text

FirebaseͰ θϩ͔ΒΞϓϦΛ࡞Δ   Flutter Meetup Tokyo #4  pixiv.inc @consomme72 / Tadashi Yamazaki

Slide 2

Slide 2 text

ࣗݾ঺հ   ࢁ࡚ ਖ਼ / Tadashi Yamazaki Twitter: @consomme72 ϐΫγϒגࣜձࣾ ΫϦΤΠλʔࣄۀ෦ AndroidΞϓϦΤϯδχΞ

Slide 3

Slide 3 text

BOOTH   ಉਓࢽɺάοζɺ ΞΫηαϦʔͳͲΛ खܰʹൢചͰ͖ΔαʔϏε ※ٕज़ॻଟ਺ൢചதʂ

Slide 4

Slide 4 text

  ࠷ۙձࣾͰ FlutterΛ࢖͍ͬͯΔͷͰ ஌ݟڞ༗

Slide 5

Slide 5 text

  Flutter x Firebase

Slide 6

Slide 6 text

https://github.com/flutter/plugins/blob/master/FlutterFire.md  

Slide 7

Slide 7 text

  ؆қTumblrతΞϓϦΛ࡞Δ

Slide 8

Slide 8 text

  Setup Firebase

Slide 9

Slide 9 text

  ͍͍ͩͨެࣜʹॻ͍ͯ͋ΔͷͰ ཁ఺͚ͩ https://codelabs.developers.google.com/codelabs/flutter-firebase/

Slide 10

Slide 10 text

https://console.firebase.google.com/  

Slide 11

Slide 11 text

iOS/Android྆ํͷઃఆΛߦ͏  

Slide 12

Slide 12 text

Android   ΞϓϦΛొ࿥͢Δࡍʹ σόοάkeystoreͷSHA-1Λొ࿥ ʢGoogleAuthͰඞཁʣ

Slide 13

Slide 13 text

Android   google-services.jsonɹΛ appҎԼʹ഑ஔ

Slide 14

Slide 14 text

Android   app/build.gradle build.gradle buildscript { … dependencies { … classpath 'com.google.gms:google-services:3.2.1' … } } apply plugin: 'com.google.gms.google-services'

Slide 15

Slide 15 text

iOS   ී௨ʹόϯυϧIDΛهೖ

Slide 16

Slide 16 text

iOS   $ open ios/Runner.xcworkspace ͰXCodeΛىಈͯ͠ RunnerσΟϨΫτϦʹ GoogleService-Info.plistɹΛ഑ஔ

Slide 17

Slide 17 text

• Firebase AuthenticationʢϢʔβʔೝূʣ • Google AuthenticationʢGoogleೝূʣ • Cloud Firestoreʢσʔλϕʔεʣ • Cloud Storageʢը૾อଘʣ   ࠓճ࢖͏ػೳ

Slide 18

Slide 18 text

  flutter: sdk: flutter # For Firebase firebase_auth: ^0.5.19 google_sign_in: ^3.0.5 cloud_firestore: ^0.7.4 firebase_storage: ^1.0.1 pubspec.yaml

Slide 19

Slide 19 text

  Firebase Authentication

Slide 20

Slide 20 text

  Firebase Console Ͱ ࢖͍͍ͨೝূํࣜΛ ༗ޮʹ͓ͯ͘͠ ࣄલઃఆ

Slide 21

Slide 21 text

  CFBundleURLTypes CFBundleTypeRole Editor CFBundleURLSchemes com.googleusercontent.apps.${hoge} iOS : Info.plist ʹ௥ه

Slide 22

Slide 22 text

  … REVERSED_CLIENT_ID com.googleusercontent.apps.${hoge} … GoogleServices-Info.plist ͔Βίϐϖ

Slide 23

Slide 23 text

  class _AuthScreenState extends State { final GoogleSignIn _googleSignIn = new GoogleSignIn( scopes: [ 'email' ] ); final FirebaseAuth _firebaseAuth = FirebaseAuth.instance; Future _signIn() async { GoogleSignInAccount account = await _googleSignIn.signIn(); GoogleSignInAuthentication authentication = await account.authentication; FirebaseUser user = await _firebaseAuth.signInWithGoogle( accessToken: authentication.accessToken, idToken: authentication.idToken, ); return user; }

Slide 24

Slide 24 text

  child: new FlatButton( child: const Text('Sign in'), color: Colors.blue, textColor: Colors.white, onPressed: () { _signIn() .then((user) { Navigator.pushReplacement(context, new MaterialPageRoute( builder: (context) => new TimelineScreen() )); } ) .catchError((e) => Scaffold.of(context).showSnackBar(new SnackBar( content: new Text(e.toString()), ))); },

Slide 25

Slide 25 text

  Firebase Cloud Storage

Slide 26

Slide 26 text

  Future _send(String body) async { Uri imageUrl; int time = DateTime.now().millisecondsSinceEpoch; String uuid = Uuid().v4(); if (_image != null) { StorageUploadTask uploadTask = FirebaseStorage.instance .ref() .child('image') .child(uuid + '-' + time.toString()) .putFile(_image); imageUrl = (await uploadTask.future).downloadUrl; } … }

Slide 27

Slide 27 text

  Cloud Firestore

Slide 28

Slide 28 text

  import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:sampleboard/model/post.dart'; final CollectionReference postCollection = Firestore.instance.collection('posts'); class FirestoreService { Stream getPostList() { return postCollection.orderBy('order').snapshots(); } … } FirestoreService::getList

Slide 29

Slide 29 text

  Future createPost(String body, String image, int order) { final TransactionHandler handler = (Transaction transaction) async { final DocumentSnapshot snapshot = await transaction.get(postCollection.document()); final Post post = new Post(snapshot.documentID, body, image, order, 0); final Map data = post.toMap(); await transaction.set(snapshot.reference, data); return data; }; return Firestore.instance.runTransaction(handler).then((mapData) { return Post.fromMap(mapData); }); } FirestoreService::createPost

Slide 30

Slide 30 text

  Future updatePost(Post post) { final TransactionHandler handler = (Transaction transaction) async { final DocumentSnapshot snapshot = await transaction.get(postCollection.document(post.id)); await transaction.update(snapshot.reference, post.toMap()); return {'updated': true}; }; return Firestore.instance.runTransaction(handler).then((result) { return result['updated']; }); } FirestoreService::updatePost

Slide 31

Slide 31 text

  StreamSubscription postSubscription; @override void initState() { super.initState(); _posts = new List(); postSubscription?.cancel(); postSubscription = db.getPostList().listen((QuerySnapshot snapshot) { List posts = snapshot.documents.map((snapshot) => Post.fromMap(snapshot.data)).toList(); setState(() { _posts = posts; }); }); } getList

Slide 32

Slide 32 text

  Demo

Slide 33

Slide 33 text

  Tips?

Slide 34

Slide 34 text

  υϝΠϯࢦఆͰ Create flutter create —org ${domain} ※Tips -i ͰiOSͷݴޠࢦఆ -a ͰAndroidͷݴޠࢦఆ $ flutter create \ --org "net.pixiv.flutter" \ -i swift \ -a kotlin \ pixiv-flutter

Slide 35

Slide 35 text

  Multidex͕ ඞཁ Firebaseͷplugin͕ ΊͬͪΌϝιου਺ଟ͍ͷͰ MultidexͷઃఆͨͿΜඞਢ android { … defaultConfig { multiDexEnabled true } … }

Slide 36

Slide 36 text

• αʔόΛ༻ҙ͠ͳ͍͍ͯ͘ͷ͸ΞϓϦΤϯδχΞͱָͯ͠ • Plugin͕ἧ͍ͬͯΔͷͰਂ͘ߟ͑ͣʹ࣮૷Ͱ͖Δ • ઃఆΛ๨ΕΔͱϋϚΔͷͰυΩϡϝϯτ͸͔ͬ͠ΓಡΉ • iOSͱAndroidͰผͷઃఆΛ͢Δ৔߹΋ଟ͍ • ΤϥʔϩάͩͱԿ͕͓͔͍͠ͷ͔શવΘ͔Βͳ͍ • ެࣜGithub΍StackOverflowΛۦ࢖͢Δ   ·ͱΊ

Slide 37

Slide 37 text

• Flutter Firestore example - Firebase Firestore CRUD with ListView - grokonez • https://grokonez.com/flutter/flutter-firestore-example-firebase-firestore-crud- operations-with-listview • Flutter Institute — Firebase Firestore • https://flutter.institute/firebase-firestore/   References

Slide 38

Slide 38 text

  Thanks! https://github.com/consomme/sample-board-flutter