Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

【Mac不要】FlutterアプリにFirebase Crashlyticsを組み込んでiOSとAndroidに実機配備する手順 - Codemagic編

はじめに

※この記事は、以下の記事の続編です。

【Mac不要】FlutterアプリにFirebase SDKを組み込んでiOSとAndroidに実機配備する手順 - Codemagic編

この記事ではその後、FlutterアプリにFirebase Crashlyticsを組み込み、iOS, Androidの両端末のクラッシュ情報をFirebaseコンソールに連携できるようになるまでの手順を説明します。

では早速始めてみましょう。

謝辞

Firebase Crashlytics - Android

Android向けの作業を進めるにあたっては、以下の記事がとても助けになりました。ありがとうございます。

Firebase Crashlytics - iOS

iOS向けの作業を進めるにあたっては、以下の記事がとても助けになりました。
ありがとうございます。

前提

この記事は、以下に当てはまる人向けの iOS/Android 対応アプリにFirebase Crashlyticsを組み込む手順を紹介します。

  • 開発機はWindowsだ
  • Macを持っていない
  • Flutterで開発したい
  • Apple Developer Programに既に登録している。

開発環境の前提

以下の2本の記事の手順に沿ってFlutterアプリをCodemagicでビルドし、さらに自身のiOS端末/Android端末のアプリの利用状況(Analytics)がFirebaseに連携されている状態にしておいてください。

  1. 【Mac不要】開発中のFlutter製アプリをiOSとAndroidに実機配備する手順 - Codemagic編
  2. 【Mac不要】FlutterアプリにFirebase SDKを組み込んでiOSとAndroidに実機配備する手順 - Codemagic編

ソースコードの公開

この記事の手順で作成したソースコードはGithubで公開しています。併せてご参照ください。
https://github.com/atsuteru/flutter_firebase_0507/tree/Qiita-FirebaseCrashlytics-v1.0

本文

FlutterアプリにFirebase Crashlyticsを組み込む

FlutterにFirebase Crashlyticsを組み込むために、まずはライブラリのページを確認するようにしましょう。Google検索のキーワードはFlutter Firebase Crashlyticsで大丈夫。以下のページが見つかればOKです。

firebase_crashlytics | Flutter Package - Dart Pub

なぜページを確認するかというと、次の2点です。

  • 最新バージョンのバージョン番号を調べる。
  • 最新バージョンの導入方法を学ぶ。

バージョン番号は、タイトルに記載されています。
2020/5/11時点のタイトルは次のようになっていました。

firebase_crashlytics 0.1.3+3

つまり最新バージョンは 0.1.3+3 だということ。※最後の+3までがバージョン番号です。

またそのページの説明の中に、以下の見出しがありますので、それを読み解いて作業を進めることになります。

  • Usage ・・・ ライブラリの使い方
  • Import the firebase_crashlytics plugin ・・・ Flutterアプリへの組み込み手順
  • Android integration ・・・ Androidで動作させるための追加の手順
  • iOS Integration ・・・ iOSで動作させるための追加の手順
  • Use the plugin ・・・ ライブラリを利用する実装方法

ではこれでもうできましたね!お疲れ様ですっ。

・・・

となればいいのですが、何かと上手くいかなかったりします。それだけ進化のスピードが速いということですね!(ポジティブ

というわけで、以下、私がいろいろ試した中で、うまくいった最短の手順を紹介します。

FlutterアプリにFirebase Crashlyticsを組み込む

この手順はライブラリのinstallingの手順に沿ってます。

Flutterにライブラリを組み込むには、pubspec.yamlを編集します。dependenciesに最新のバージョンfirebase_crashlytics: ^0.1.3+を追記しましょう。追記する箇所はflutter,firebase_coreよりも後にしないと、私はうまくいきませんでした。

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^0.4.4+3
  firebase_crashlytics: ^0.1.3+3

Flutterアプリに、FirebaseコンソールのCrashlyticsと連携するためのコードを追加する

この手順はライブラリのUse the pluginの手順に沿っています。

Flutterアプリが実行中にクラッシュしたことを検出し、FirebaseコンソールのCrashlyticsに連携できるようにするために、以下のコードを追加します。

あと、「▼▼▼」「▲▲▲」などが付いたコメントは、この記事での説明用ですので、あなたのコードには書かないでください。念のため(^^;

2020/06/04 修正
runZonedのonError引数がdeprecatedとしてマークされていたため、ソースコードを更新しました。参考: Migrate runZoned calls to runZonedGuarded

lib/main.dart
//▼▼▼ 以下、修正前のコード ▼▼▼
//import 'package:flutter/material.dart';
//void main() => runApp(MyApp());
//▼▼▼ 以下、修正後のコード ▼▼▼
import 'dart:async';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart';
void main() {
  Crashlytics.instance.enableInDevMode = true;
  FlutterError.onError = Crashlytics.instance.recordFlutterError;
  runZonedGuarded(() async {
    runApp(MyApp());
  }, (e, s) async => await Crashlytics.instance.recordError(e, s));
}

上記の各コードの説明は、ライブラリのページに書いてありますので、割愛します。

Flutterアプリに、Crashlyticsとの連携を試すためのテストコードを追加する

この手順は任意ですが、もしここまでを私の記事に沿って作ってこられた場合は、ぜひやってみてください。

この手順は、ライブラリのExampleで公開されているサンプルコードを取り入れるものです。

以下の「追加ココカラ」「追加ココマデ」の間の部分を、実装しましょう。この実装はFirebase Crashlyticsライブラリのいろんな機能を実験できるボタンを画面に表示します。

lib/main.dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
//▼▼▼ 追加ココカラ ▼▼▼
            Text(
              'Firebase Crashlytics Tests:',
            ),
            FlatButton(
                child: const Text('Key'),
                onPressed: () {
                  Crashlytics.instance.setString('foo', 'bar');
                }),
            FlatButton(
                child: const Text('Log'),
                onPressed: () {
                  Crashlytics.instance.log('baz');
                }),
            FlatButton(
                child: const Text('Crash'),
                onPressed: () {
                  // Use Crashlytics to throw an error. Use this for
                  // confirmation that errors are being correctly reported.
                  Crashlytics.instance.crash();
                }),
            FlatButton(
                child: const Text('Throw Error'),
                onPressed: () {
                  // Example of thrown error, it will be caught and sent to
                  // Crashlytics.
                  throw StateError('Uncaught error thrown by app.');
                }),
            FlatButton(
                child: const Text('Async out of bounds'),
                onPressed: () {
                  // Example of an exception that does not get caught
                  // by `FlutterError.onError` but is caught by the `onError` handler of
                  // `runZoned`.
                  Future<void>.delayed(const Duration(seconds: 2), () {
                    final List<int> list = <int>[];
                    print(list[100]);
                  });
                }),
            FlatButton(
                child: const Text('Record Error'),
                onPressed: () {
                  try {
                    throw 'error_example';
                  } catch (e, s) {
                    // "context" will append the word "thrown" in the
                    // Crashlytics console.
                    Crashlytics.instance
                        .recordError(e, s, context: 'as an example');
                  }
                }),
//▲▲▲ 追加ココマデ ▲▲▲
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

Android向けの追加の導入手順を実施する

Android向けには、以下の手順が必要です。

この手順はライブラリのAndroid integrationの手順に沿っています。

1) Android向けのライブラリの組み込みを定義する

以下の「追加ココカラ」「追加ココマデ」の間の部分を、追加しましょう。

android/build.gradle
buildscript {
    repositories {
        google()
        jcenter()
//▼▼▼ 追加ココカラ ▼▼▼
        maven {
            url 'https://maven.fabric.io/public'
        }
//▲▲▲ 追加ココマデ ▲▲▲
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath 'com.google.gms:google-services:4.3.3'
//▼▼▼ 追加ココカラ ▼▼▼
        classpath 'io.fabric.tools:gradle:1.26.1'
//▲▲▲ 追加ココマデ ▲▲▲
    }
}

allprojects {
    repositories {
        google()
        jcenter()
//▼▼▼ 追加ココカラ ▼▼▼
        maven {
            url 'https://maven.fabric.io/public'
        }
//▲▲▲ 追加ココマデ ▲▲▲
    }
}

2) Android向けのプラグインの読み込みを定義する

apply pluginの箇所は、com.google.gms.google-servicesよりも前であることに注意してください。

android/app/build.gradle
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
//▼▼▼ 追加ココカラ ▼▼▼
apply plugin: 'io.fabric'
//▲▲▲ 追加ココマデ ▲▲▲
apply plugin: 'com.google.gms.google-services'

//▲▼▲(中略)▲▼▲

dependencies {
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
    implementation 'com.google.firebase:firebase-analytics:17.2.2'
//▼▼▼ 追加ココカラ ▼▼▼
    implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
//▲▲▲ 追加ココマデ ▲▲▲

ちなみに、fabricは、Firebase Crashlyticsの旧サービスです。現在はFirebase Crashlyticsに移行が進められていますが、内部的にはまだfabricのライブラリを利用しているということですね。

iOS向けの追加の導入手順を実施する

次はiOS向けの導入手順ですが・・・

結論から言うと、iOS向けには追加のライブラリの導入手順は不要です。

なぜならば、FlutterにFirebase関連のパッケージを組み込んだ状態でのiOS向けビルドは、その組み込み情報をもとにPodfileを自動生成し、iOS向けのライブラリの組み込みまでを自動的にやってくれるから、です。

なのでこれは蛇足ですが、iOSディレクトリ直下にPodfileをコミットしようものなら、上記の自動生成がスキップされてしまい、ビルドが通らなくなりますのでご注意を。

なお・・・Podfileとは、iOSアプリのライブラリを管理できるCocoaPodsというツールの設定ファイルで、ios/Runner.xcodeproj/project.pbxprojの書き換えをやってくれるものです。WindowsでCocoaPodsを動作させるのはいばらの道ですので、Macを持たない我々は、FirebaseがCodemagic上でそれを自動的にやってくれるという恩恵にあずかりましょう。。。

iOS向けに不要になったコードを削除する

とは言いつつ1つだけ、iOS向けにやっておかないといけない手順があります。

以下のように、コードを2行削除してください。(「この行を消す!」の2行)

ios/Runner/AppDelegate.m
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"

//@import Firebase; ←この行を消す!

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // [FIRApp configure]; ←この行を消す!
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

@end

私の記事の手順に沿ってやってこられた方はお気づきだと思いますが、これは「Firebase SDK」の組み込みの手順として追加した2行です。

今回、Firebase CrashlyticsをFlutterに組み込んだことによって、不要となったようです。(私はこれを削除しないとうまくいかなかった)

FilebaseコンソールでCrashlyticsと連携できたことを確認する

連携前にFilebaseコンソールでアプリのCrashlyticsページを覗いてみると、次の画面が表示されました。

flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_11 22_45_25.png

SDKの組み込みは先程までの手順で終えているので、ソースコードをpushし、Codemagicによるリリースビルドの結果を待ちましょう。

・・・ビルドが通りましたね!
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_11 23_31_54.png

Androidでの確認

Codemagicから届いたビルド成功の通知メールから、再インストールしました。

そしてFirebaseコンソールに戻ると・・・「インストールが完了しました」の表示が!ちゃんと連携できましたね。
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_11 23_35_08.png

Crashlyticsダッシュボードに移動してみましょう。
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_11 23_35_37.png

クラッシュはまだありませんね。

ここで一つ注意です!

このページはデフォルトで、アプリが異常終了したレベルのクラッシュだけを表示するようにフィルタされています。青いラベル「イベントの種類"クラッシュ"」の「×」を押して、フィルタを解除しておきましょう。

では、実際に"クラッシュ!"・・・はできませんが、仕込んでおいたボタンでアプリでエラーを起こしてみましょう。

アプリは一度終了し、起動しなおしてください。(初回起動のみ、うまく連携されないようです)

そしてアプリの画面の「Key」「Log」「Crash」「Throw Error」「Async out of bounds」「Record Error」をガンガンタップしてみましょう。

すると数分もたたないうちに・・・Crashlyticsページに連携されましたね!
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_11 23_50_37.png

エラーの詳細も、このように確認することができます。
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_11 23_52_04.png

iOSでの確認

Codemagicから届いたビルド成功の通知メールから、再インストールしましょう。

※iOSアプリは、TestFlightの手順(記事:【Mac不要】開発中のFlutter製アプリを仲間のiOS端末に実機配備する手順 - Codemagic&TestFlight編)をすでに実施している場合は、TestFlightから「Update」することでこのバージョンをインストールしましょう。それ以外はの方はCodemagicから届くメールからインストールしてください。

unnamed(3).jpg

iOSアプリでも同じように、アプリの画面の「Key」「Log」「Crash」「Throw Error」「Async out of bounds」「Record Error」をガンガンタップしてみましょう。

私の場合は少し時間がかかりましたが・・・Crashlyticsページに連携されましたね!
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_12 0_22_00.png

iOSの場合の詳細ページはこんな感じです。
flutter-firebase-0507 - Firebase コンソール - Google Chrome 2020_05_12 0_25_36.png

おわりに

これで、本記事の目的は達成できました。しかし、これでやっと開発のスタートラインに立ったにすぎません。

この記事の続編として、あと1本を予定しているので、乞うご期待!

  • Google Photo APIと連携し、利用者のフォトアルバムにアクセスする

最後に、この記事がFlutterを始められる方にとって少しでも助けになれば、幸いです。

kami_teru
SIを楽しむプログラマです。いろんなものを作るのが好き。
peoplesoftware
主にJavaやC#を使った受託開発や、BaaSなどのクラウドサービス、スマホアプリの自社開発を行っている会社です。※各記事の内容は個人の見解であり、所属する会社の公式見解ではありません。
http://www.pscsrv.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away