Firebase Cloud FunctionsでJsonを返す
Cloud FunctionsからJsonを返す方法
下の実装では別のAPIを叩いて受け取った結果をjsonにして返却している。
const functions = require('firebase-functions'); const request = require('request'); exports.onBooksGenre = functions.https.onRequest((req, res) => { var headers = { 'Content-Type':'application/json' } var options = { url: "URL", method: 'GET', headers: headers, json: true } return request(options, (error, response, body) => { if (error || response.statusCode !== 200) { res.json(error).end(); return; } res.json(body).end(); }); });
FlutterでのAppBar3選
FlutterのAppbarについて3つ動画にして紹介しました。
Goでhttpリクエストしてjsonを受け取ってコマンドラインに出力する
下記のコードでいけた
package main import ( "fmt" "io/ioutil" "net/http" ) func main() { client := &http.Client{} req, err := http.NewRequest("GET", "リクエストURL", nil) if (err != nil) { fmt.Println("error occur") } resp, err := client.Do(req) if(err != nil) { fmt.Println("error occur") } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if(err != nil) { fmt.Println("error occur") } fmt.Println(string(body)) }
RecyclerViewでアイテムのクリックイベントを受け取る
フラグメントにinterfaceを実装する。
interface ItemListEventListener { fun onTapItem(view: View, id: Int) }
fragmentでimplementして実装を書く
ここではinterfaceの実装と、adapterにイベントリスナーの実装を渡している
class ItemListFragment : Fragment(), ItemListEventListener { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = FragmentItemListBinding.inflate(inflater, container, false) setupLayout() return binding.root } override fun onTapItem(view: View, id: Int) { // タップイベントがあるとここが呼ばれる } private fun setupLayout() { itemAdapter = ItemListAdapter(this) val manager = ItemLayoutManager(itemAdapter, requireContext()) binding.productList.run { layoutManager = manager adapter = itemAdapter } } }
adapterで引数として受け取る
class ItemListAdapter(private val eventListener: ItemListEventListener) : ListAdapter<ProductListItem, RecyclerView.ViewHolder>(DiffUtilCallback) { // なんかの実装
adapter側でタップイベントを設定してリスナーとして渡す
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if (holder is ProductItemHolder) { val item = getItem(position) holder.binding.model = item holder.binding.productItem.setOnClickListener { eventListener.onTapItem(it, item.id) } } }
これでタップイベントを受け取れる
参考
AndroidのNavigationを使って遷移先にパラメーターを渡す
Navigationについてはこちら
渡す側
渡す側はbundleに引数を設定して、画面遷移するときに渡す
val bundle = Bundle() bundle.putInt("id", id) Navigation.findNavController(view).navigate(R.id.action_item_list, bundle)
受け取る側
受け取る側は onActivityCreated
で受け取るのがいい
override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) val id = arguments?.getInt("id") print(id) }
参考
FlutterとFirebase Authを使ってメールアドレス認証をする
FirebaseとFlutterの接続方法は下記
下記のプラグインを導入
導入したら下記のコードでログインできる
Future<FirebaseUser> _handleSignUp(String email, String password) async { final FirebaseAuth _auth = FirebaseAuth.instance; final FirebaseUser user = await _auth.createUserWithEmailAndPassword( email: email, password: password); return user; }
FlutterでBottom Sheetを出す
FlutterのBottom Sheet🧐 pic.twitter.com/8yh2csgrPA
— shogo.yamada@Flutterマン (@yshogo87) March 10, 2019
下記の方法で行けた
_showUserInfo(User user, BuildContext context) { showModalBottomSheet( context: context, builder: (_) { return Container( width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.min, children: <Widget>[ ListTile( title: const Text( "Kyat app", style: const TextStyle(fontWeight: FontWeight.bold), ), trailing: CupertinoButton( onPressed: () { Navigator.pop(context); }, child: const Text("cancel")), ), Container( width: 100, height: 100, child: CachedNetworkImage( imageUrl: user.iconUrl, ), ), const SizedBox( height: 20, ), Center(child: Text(user.name)), Container( margin: const EdgeInsets.all(10), child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[], ), ), ], ), ); }); }
Flutterでドロワーを出す
drawer: Drawer() っていう一行でドロワーが出せるようになるFlutterすごすぎないか、、、
— shogo.yamada@Flutterマン (@yshogo87) March 5, 2019
しかも、iOS、Android両方動くって、、、
爆速でアプリ作れる。 pic.twitter.com/96eHeCCvV1
ドロワーを出すだけなら1行でいけます。
return Scaffold( appBar: _appbar(), drawer: Drawer(), )
Flutterのドロワーの実装が簡単すぎてすごい。
— shogo.yamada@Flutterマン (@yshogo87) March 5, 2019
昔のGmailアプリみたいなドロワーこれだけのコードで実装できる。
しかもiOS、Android両方一つのコードで動く。 pic.twitter.com/ssDYceDy2A
上の記事のような昔のGmailみたいなドロワーは下記のコードで出せる
Widget _drawerHeader() { return Drawer( child: ListView( children: <Widget>[ UserAccountsDrawerHeader( accountName: const Text( "shogo.yamada", style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), accountEmail: const SizedBox(), currentAccountPicture: CircleAvatar( child: Text( "A", style: TextStyle(fontSize: 40.0), ), ), ), ], ), ); }
FlutterでBLoCのテストを書く
FlutterでBLoCのテストを書く方法について
BLoCって何?って方は下記の記事をご参照ください。
BLoCクラス
まずはBlocクラス
class HomeBloc { final UserRepositoryInterface userRepository; HomeBloc({ @required this.userRepository, }) { _getUserInfo(); } StreamController<User> _userController = StreamController<User>(); StreamSink<User> get _userSink => _userController.sink; Stream<User> get userStream => _userController.stream; void dispose() { _userController.close(); } _getUserInfo() async { _userSink.add(await userRepository.getUser()); } }
このクラスからRepositoryを設定されているとき userRepository
からデータが返ってきた時に userStream
にデータがaddされるかテストするコードを書きます。
テストを書く
今回はRepositoryをモック化しています。
void main() { UserRepositoryInterface repository; setUp(() { repository = FakeUserRepository(); }); HomeBloc createBloc() { return HomeBloc( userRepository: repository); } test("user stream test", () async { User user = await repository.getUser(); HomeBloc bloc = createBloc(); bloc.userStream.listen((User result) { expect(result.uid, user.uid); }); });
bloc.userStream
にデータがくるのを listen
してデータがきたら結果が正しいかチェックしています。
FlutterにFirebase Crashlyticsを導入する (Android編)
FlutterにFirebase プロジェクトを追加
下記の手順で導入しましょう。
gradleを編集
android/build.gradle
に下記を追加
buildscript { ext.kotlin_version = '1.3.20' repositories { google() jcenter() // ↓追加 maven { url 'https://maven.fabric.io/public' } } dependencies { // ↓追加 classpath 'io.fabric.tools:gradle:1.27.1' classpath 'com.android.tools.build:gradle:3.3.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.2.0' } } allprojects { repositories { google() jcenter() ↓追加 maven { url 'https://maven.google.com/' } } }
app/build.gradleを編集
app/build.gradle
に下記を追加
apply plugin: 'io.fabric'
これで動くはずです。
動かない時
動かない時は下記をご確認ください。
FlutterでCrashlyticsが動かない時
FlutterでFirebase Crashlyticsがビルドエラーになって動かなかったが下記の方法で解決した。
android/gradle/gradle-wrapper.properties
に下記を追加すると直る。
#Sat Mar 02 00:07:33 JST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists // ↓を追加する distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
Incompatible types: ○ and △ がでるとき
sealed
を使って型の確認をするときに下記のエラーで表示できなくなった。
Incompatible types: ○ and △
みたいなエラーがでるときは下記の方法で使える ちゃんと継承させれば解決できる
sealed class ListItem { data class ItemList( val list: List<ProductItem> ) : ListItem() object Title: ListItem() object Progress : ListItem() }
Androidでテキストを太字にする
下記の方法でいけた
簡単にいうと、 android:textStyle="bold"
を設定するだけで太字になった。
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="@string/item_list_title" android:textStyle="bold" android:textSize="20sp" />
Firebaseのコンソールでユーザーを招待する
ユーザーの招待は下記の方法でできる。
コンソールに移動 ↓
下記のボタンをタップ
そこから「ユーザーと権限」ボタンをタップすればできる。
Flutter(Dart)でシングルトン
class AnalyticsUtil { static FirebaseAnalytics _analytics; static FirebaseAnalytics getInstance() { if (_analytics == null) { return FirebaseAnalytics(); } return _analytics; } }