1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

flutterでアプリ開発する時に最初にすること

Last updated at Posted at 2024-07-06

自分用のメモです。
後々どうせやるけど面倒くさくなりそうな最低限のタスク達。

環境

スペック
pc macbook air
メモリ M2
OS Sonama 14.2
flutter 3.19.6
dart 3.3.4
devtools 2.31.1
xcode 15.3
android studio 2023.3.1 (Jellyfish)

bundle identifier

プロジェクト作る時に
flutter create --org com.your.orgname my_app_nameで作るか、
vscodeのSetting.jsonで自動的に入力するようにしておくと楽。

↓参考
Flutterで作ったプロジェクトのBundleID・PckageNameを変更する方法と対策

画面の回転設定

Flutter でアプリの画面を Portrait 固定にするがすごい簡潔でよかった。

ios

Runner > General で設定。回転しないならportraitのみにする。

android

android/app/src/main/AndroidManifest.xmlのactibityタグにandroid:screenOrientation="portrait"を追加する。

共通

スクリーンによる回転の可・不可、回転時のUIの切り替えは【Flutter】画面回転に対応するが参考になりそう(ちゃんと確かめてはない)

エミュレータで確認しておく

ios

1. open -a Simulatorでシミュレータを起動

2. flutter runでアプリを起動

3. -dをつけると何で起動するか選べる
flutter devicesで使えるデバイスを調べる。
機種名の右側の文字列の先頭一文字を指定することで選べる。

iPhone 15 Pro Max (mobile) • 000000000000-000000-000000

だったらflutter run -d 0

android

初回(AVDがない)の場合

Start building Flutter Android apps on macOSに従って進めていく。

1. android studioを立ち上げる。

2. 「Get from VCS」の右隣の3点リーダーの「Virtual Device Manager」を選択。
スクリーンショット 2024-05-04 22.09.25.png

3. +ボタンをクリック。(ホバーすると「Create Virtual Device」が表示される)
スクリーンショット 2024-05-04 22.32.58.png

4. 任意のデバイスを選択して「Next」
スクリーンショット 2024-05-04 22.33.18.png

5. 任意のイメージを選択してダウンロードボタンをクリック。
スクリーンショット 2024-05-04 23.01.28.png
少し待つとインストールが終わるので「Finish」をクリック。

6. インストールされたイメージを選択して「Next」

7. 細かい設定ができるが多分特に何もしなくていいので「Finish」

8. command-line toolsがない場合、android studioのsdk managerのsdk toolsから最新のものをインストールする。アコーディオンメニューのようになってるので、余分なものはしまわないと出てこない。
↓参考
[基礎知識]Android Studio(Cnary6ビルド(Jellyfish))インストール記録

1. エミュレータの一覧を取得

emulator -list-avds

$ANDROID_SDK_ROOT/emulatorにパスを通しておかないとできないので 注意。

2. emulator -avd {avd_name}もしくはemulator @{avd_name}で起動

emulator -avd pixel_8_pro

もしくは

emulator @avd pixel_8_pro

など

↓参考
Android Emulatorのみを起動する

flutter_dotenv

flutter_dotenvを入れておく。
のちのちIDとか管理することになる。

以下公式のドキュメントの引用。

1. pub addpub getで追加。

2. assetsに.envを追加する。

pubspec.yaml
assets:
  - .env

3. プロジェクトのルートディレクトリに.envファイルを作る。

4. main.dartでenvファイルをロードする。
(このステップ以降コードはv5.0.0以降のもの)

main.dart
import 'package:flutter_dotenv/flutter_dotenv.dart';

// DotEnv dotenv = DotEnv() is automatically called during import.
// If you want to load multiple dotenv files or name your dotenv object differently, you can do the following and import the singleton into the relavant files:
// DotEnv another_dotenv = DotEnv()

Future main() async {
  // To load the .env file contents into dotenv.
  // NOTE: fileName defaults to .env and can be omitted in this case.
  // Ensure that the filename corresponds to the path in step 1 and 2.
  await dotenv.load(fileName: ".env");
  //...runapp
}

5. 環境変数にアクセスする

import 'package:flutter_dotenv/flutter_dotenv.dart';
dotenv.env['VAR_NAME'];

アプリアイコン

flutter_launcher_iconsを追加

任意のフォルダに画像を保存 e.g.) assets/images

pubspec.yaml
assets:
    - assets/
    - assets/images/
    - assets/images/launcher/
    - assets/images/splash/

アイコンの設定を追記

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter

# アイコンの設定
flutter_launcher_icons:
  ios: true
  image_path: "assets/images/launcher/icon.png"
  remove_alpha_ios: true
  android: true;
  adaptive_icon_background: "assets/images/launcher/icon_android_background.png"
  adaptive_icon_foreground: "assets/images/launcher/icon_android_foreground.png"

アイコンに使用する画像ファイルの名前には'-'は使えないので注意が必要。

flutter_launcher_iconsを実行する。

dart run flutter_launcher_icons

シミュレーターでアプリ走ってる場合は再起動orシミュレータからアプリを削除して再度run。

↓参考
【Flutter】アプリアイコンに必要な画像と追加方法(flutter_launcher_icons,Figma)

画像が見切れてるアイコンを生成したい時

↓みたいな画像
app-icon-ios.PNG

iosではこのままの画像を用意するだけ。しかしandroidのadaptive iconは勝手に画像をマスクしにくるので工夫が必要。

何もせずにios用に用意した画像をそのまま使うと↓みたいな感じになる(pixel 8 proのエミュレーターで検証)。
無題58_20240506185044.PNG

以下解決策
1. andorid用に画像を用意。機種によってアイコンの形が変わり、それによってマスクの仕方が変わる(っぽい?)ので、余裕を持たせてios用のものよりも画像が見える範囲を少し広めにしておいた方がいいかもしれない。ただし、四角くマスクされる場合もあるので要検討。
(検証できてないけど108x108のサイズで作っておいた方が良さそう。)

2. 1で用意した画像をadaptive_icon_backgroundに割り当てる。そうすることでマスクされるのを回避する。

3. adaptive_icon_foregroundには透明なだけの透過画像を割り当てる。この画像は透明にする以外特に工夫は要らなそう。

3のforegroundの画像になんか書いたら遊び心があっていい感じのアイコンが作れるかもしれない。けどどっちにしろiosには適用できなさそう(?)

スプラッシュ画面

スプラッシュ画面作成

flutter_native_splashを追加。

アイコン同様に画像を配置。

androidに対応するため画像は直径768pxの円に収まるものを用意しておくと楽

設定を追記。

pubspec.yaml
# アイコンの設定
flutter_launcher_icons:
  ios: true
  image_path: "assets/images/launcher/icon.png"
  remove_alpha_ios: true
  android: true;
  adaptive_icon_background: "assets/images/launcher/icon_android_background.png"
  adaptive_icon_foreground: "assets/images/launcher/icon_android_foreground.png"

# スプラッシュ画面の設定
flutter_native_splash:
  image: "assets/images/splash/splash.png"
  color: "#f5f5f5"
  android: true
  ios: true
  fullscreen: true
  android_12:
    image: "assets/images/splash/splash.png"
    color: "#f5f5f5"

flutter_native_splash:createを実行する。

dart run flutter_native_splash:create

アイコン同様再起動。

↓参考
【Flutter】コマンド一発でスプラッシュ画面を実装する【flutter_native_splash】

アプリ内での処理

main.dartのmain関数内にコードを追記。
スプラッシュ画面を正常に表示する。

void main() {
  // 追記
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  
  // 追記
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);

  runApp(const MyApp());
}

任意の位置(initStateとか)にコードを追記。
データのロードなどの処理を行った後など適切なタイミングでスプラッシュ画面を終了する。
flutter_native_splashをフルスクリーンで表示すると、終了後ステータスバー(画面上部の時間とか表示する領域)が表示されなくなったりするので、表示する処理を記述する。

// スプラッシュ画面終了
FlutterNativeSplash.remove();

// splash screen 終了後にステータスバーを表示する
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
    overlays: SystemUiOverlay.values);

↓の2つをインポートしなきゃいけない。

import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:flutter/services.dart';

services.dartSystemChromeを使うため。

環境切り替え

とにかく↓の記事通り進めていく。

↓のコマンドで実行(buildも)することで切り替わる。

flutter run --dart-define-from-file=path/filename

この設置をした後xcodeでビルドしようとすると、product bundle identifireがないと言われて失敗することがある。

ターミナルなどで一度--dart-define-from-fileをつけてビルドしなきゃいけない。
(product bundle identifierが、環境ファイルに書かれたもので上書きされる。)

firebase

firebase初めての時はcliをインストトール

Firebase CLI リファレンスに従って進める

1. mac or linuxなら

curl -sL https://firebase.tools | bash

npmを使ってるなら

npm install -g firebase-tools

でインストールするのが良さそう。

どちらにも当てはまらないならバイナリをダウンロードして頑張ってパスを通す。

2. 正しくインストールできたか確かめる。

firebase --version

3. firebaseにログインする

firebase login

firebaseのサイトに飛ばされるので、任意のアカウントでログイン。

プロジェクトを作る

firebaseにログインして、「プロジェクトを追加」から作成。
プロジェクト名を入力して進む。
プロジェクトIDは重複がある場合適当に割り振られるorいい感じのものをつける。

プロジェクトは環境の数だけ作る。dev, stg, prdがあるなら、appname-dev, appname-stg, appname-prdを作る。

それぞれのプロジェクトで、androidとiosのアプリを作る。

flutterにfirebaseを追加

android/app/src/ios/に環境分のディレクトリを作って、firebase sdkの構成ファイルを配置する。
androidとiosでそれぞれ環境に応じて構成ファイルを参照できるようにする。

を参考にする。
というか完全に↓(同記事)を参考にしたらいい。

flutterにfirebaseを使うためのプラグインを追加する。

flutter pub add firebase_core

この段階でiosのビルドをしようとすると、pod installしろと言われる場合がある。

Specs satisfying the `firebase_core (from `.symlinks/plugins/firebase_core/ios`)` dependency were found, but they required a higher minimum deployment target.

と言われた場合はビルドターゲットのバージョンが低い。firebaseは2024/7/24時点では13以上が必要っぽい。ios/Podfileの先頭に↓を追記する。

platform :ios, '13.0'

podを更新する

pod install --repo-update

flutterfire_cliの追加

dart pub global activate flutterfire_cli

(※flutter pubとは異なるコマンド)

↓参考

追加しただけではflutterfireコマンドは使えないので注意。
コンソールに出てくるexport PATH="$PATH":"$HOME/.pub-cache/bin"でパスを通す。

環境毎にflutterfire configureする

次項のfirebaseの初期化に用いられるfirebase_optionsが、環境によって適切に使われるようにしたい。
例えば開発環境なら、firebase_options_dev.dartを使う。

flutterfire configureで毎にファイルを生成する。この時生成されるfirebase_optionsファイルは特に書き換えたりしない。
project idはfirebase projects:listで確認できる。

# dev環境
flutterfire configure --project=<firebase-dev-project-id> --out=lib/firebase_options_dev.dart
# stg環境
flutterfire configure --project=<firebase-stg-project-id> --out=lib/firebase_options_stg.dart
# prd環境
flutterfire configure --project=<firebase-prd-project-id> --out=lib/firebase_options_prd.dart

firebase.jsonを編集して環境毎のアプリidを記述する。
プロジェクトidはflutterfire configureの時のものと同じ。アプリidは、firebaseのコンソールから「プロジェクトの設定」を開き、下の方の「マイアプリ」のところに書いてある「アプリID」をコピペする。
"default"はどの環境を書いても(多分)大差ないので適当に書いておく。

{
	"flutter": {
		"platforms": {
			"android": {
				"default": {
					"projectId": "{プロジェクトid}",
					"appId": "{アプリid}",
					"fileOutput": "android/app/google-services.json"
				}
			},
			"ios": {
				"default": {
					"projectId": "{プロジェクトid}",
					"appId": "{アプリid}",
					"uploadDebugSymbols": false,
					"fileOutput": "ios/Runner/GoogleService-Info.plist"
				}
			},
			"dart": {
				"lib/firebase_options_dev.dart": {
					"projectId": "{プロジェクトid}",
					"configurations": {
						"android": "{アプリid}",
						"ios": "{アプリid}"
					}
				},
				"lib/firebase_options_stg.dart": {
					"projectId": "{プロジェクトid}",
					"configurations": {
						"android": "{アプリid}",
						"ios": "{アプリid}"
					}
				},
				"lib/firebase_options_prd.dart": {
					"projectId": "{プロジェクトid}",
					"configurations": {
						"android": "{アプリid}",
						"ios": "{アプリid}"
					}
				}
			}
		}
	}
}

firebaseのapiキーは公開されても大丈夫らしい。

参考
Firebaseのセキュリティについて - そのAPI キー本当に公開しても大丈夫ですか?

firebaeを初期化

firebase_coreとそれぞれのfirebase_opsionsをインポート。使い分けられるように

main.dart
import 'package:firebase_core/firebase_core.dart';

import 'firebase_options_dev.dart' as dev_default_firebase_options;
import 'firebase_options_stg.dart' as stg_default_firebase_options;
import 'firebase_options_prd.dart' as prd_default_firebase_options;

WidgetsFlutterBinding.ensureInitialized();の後にFirebase.initializeAppを追加して初期化する。この時環境毎に適切なfirebase_optionsを引数に渡す。

main.dart
WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();

const flavor = String.fromEnvironment('flavor');

FirebaseOptions options;
switch (flavor) {
  case "prd":
    options =
        prd_default_firebase_options.DefaultFirebaseOptions.currentPlatform;
    break;
  case "stg":
    options =
        stg_default_firebase_options.DefaultFirebaseOptions.currentPlatform;
    break;
  default:
    options =
        dev_default_firebase_options.DefaultFirebaseOptions.currentPlatform;
}

// firebaseを初期化
await Firebase.initializeApp(
  options: options,
);

chatGPTが教えてくれたので、これがいい方法なのかはわからない。今度リサーチしたい。

flutterに機能を追加

pubspec.yamlに使いたいfirebaseの機能を追加。

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
    
  # 省略
  
  firebase_core: ^2.31.0
  firebase_analytics:
  firebase_crashlytics:

認証を使いたいならfirebase_authなど。

admob(広告)

この記事ではバナー広告だけ扱う。

google_mobile_adsを追加。

info.plistなどに設定の記述がないままpubspec.yamlに追加して実行(コンパイル)しようとするとエラーが出て失敗するので、後で追加するか一旦コメントアウトしておくといい

admobに登録する必要があるが簡単なので割愛。

手順は公式のFlutter アプリに AdMob 広告を追加するで確認するのが良さそう。ただし、最終更新日が2022年なのはちょっと不安。

admobで広告を作成

これも簡単な作業なので一旦割愛。

firebaseとリンク

admobの設定画面の「アプリリンクの管理」からリンク
すでにfirebaseでプロジェクトを作ってる場合は、identifierを入力すると該当のプロジェクトが出てくる。

IDを記述

設定ファイルに色々記述がないと表示ができない。というかそもそもコンパイルできない。

開発時は動作確認用にテスト用の広告を使う。

本番の広告の確認をするにはテストデバイスの登録をする必要がある。テスト広告を有効にするを参考にするといい。

テスト用のアプリIDと広告ユニットIDは3. AdMob アプリと広告ユニットを設定するに書かれている↓の表から持ってくる。
スクリーンショット 2024-05-06 20.30.50.png

ios

ios/Runner/Info.plistを編集
GADApplicationIdentifierにアプリIDを割り当てる。
(↓のコードはテスト用ID)

Info.plist
...
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
...
テスト用アプリID
ca-app-pub-3940256099942544~1458002511
テスト用広告ユニットID(バナー)
ca-app-pub-3940256099942544/2934735716

android

android/app/src/main/AndroidManifest.xmlを編集
ios同様アプリIDを割り当てる。
(↓のコードはテスト用ID)

AndroidManifest.xml
<manifest>
    ...
    <application>
       ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/>
    </application>

</manifest>
テスト用アプリID
ca-app-pub-3940256099942544~3347511713
テスト用広告ユニットID(バナー)
ca-app-pub-3940256099942544/6300978111
ユニットID

ad_helper.dartにユニットIDを記述しておく。(名前はなんでもいい)

デバッグビルドとリリースビルドで返すIDを切り替えるようにしておくと便利。

ad_helper.dart
import 'dart:io';

import 'package:flutter_dotenv/flutter_dotenv.dart';

class AdHelper {
  static String get BanneradUnitId {
    bool isDebug = false;

    // debug時のみ実行
    assert(isDebug = true);

    if (isDebug) {
      // デバッグ時
      if (Platform.isAndroid) {
        return "a-app-pub-3940256099942544/6300978111";
      } else if (Platform.isIOS) {
        return "ca-app-pub-3940256099942544/2934735716";
      } else {
        throw UnsupportedError("Unsupported platform");
      }
    } else {
      // リリース時
      if (Platform.isAndroid) {
        return dotenv.env['ANDROID_UNIT_ID']!;
      } else if (Platform.isIOS) {
        return dotenv.env['OS_UNIT_ID']!;
      } else {
        throw UnsupportedError("Unsupported platform");
      }
    }
  }
}

広告のロード

広告を表示するwidgetを作って、initState内で広告をロードする。
ロードが成功した時のみバAdWidgetを生成する。

使われなくなったバナーはdispose()でリリースする。

@override
  void dispose() {
    adState.banner.dispose();

    super.dispose();
  }
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

import 'package:path/to/ad_helper.dart';

class BannerAdContainer extends StatefulWidget {
  const BannerAdContainer({super.key});

  @override
  State<BannerAdContainer> createState() => _BannerAdContainerState();
}

class _BannerAdContainerState extends State<BannerAdContainer> {
  BannerAd? banner;

  @override
  void initState() {
    super.initState();

    BannerAd(
      size: AdSize.banner,
      adUnitId: AdHelper.BanneradUnitId,
      listener: BannerAdListener(
        onAdLoaded: (ad) {
          debugPrint('Ad loaded: ${ad.adUnitId}');
          setState(() {
            banner = ad as BannerAd;
          });
        },
        onAdClosed: (ad) {
          debugPrint('Ad closed: ${ad.adUnitId}');
        },
        onAdFailedToLoad: (ad, error) {
          debugPrint('Ad failed to load: ${ad.adUnitId}, $error');
          ad.dispose();
        },
        onAdOpened: (ad) {
          debugPrint('Ad opened: ${ad.adUnitId}');
        },
        onAdClicked: (ad) {
          debugPrint('Ad clicked: ${ad.adUnitId}');
        },
        onAdImpression: (ad) {
          debugPrint('Ad impressed: ${ad.adUnitId}');
        },
        onAdWillDismissScreen: (ad) {
          debugPrint('Ad screen dismissed: ${ad.adUnitId}');
        },
      ),
      request: const AdRequest(),
    ).load();
  }

  @override
  void dispose() {
    banner?.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey,
      height: 100,
      child: Center(
        child: banner != null
            ? AdWidget(ad: banner!)
            : const Text(
                '広告',
                style: TextStyle(color: Colors.white),
              ),
      ),
    );
  }
}

google mobile adsを初期化

広告をロードする前の適当なところで初期化処理を行う。
とりあえずmainでやっておけばいい。

main.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  MobileAds.instance.initialize();
  runApp(MyApp());
}

広告を表示

適当なところに表示する。バナーを画面上部か下部に表示するならColumn使っとく。

 body: Column(
        children: [
          Expanded(
            // 省略
          ),
          const BannerAdContainer(),
        ],
      ),

テストデバイスの設定

テストデバイスを設定して安全に本番広告を配信する。

admobにログインして、設定 > テストデバイスからテストデバイスを追加する。

↓参考

app idを切り替える

環境切り替えの要領で切り替える。

dev.json, stg.json, prd.jsonにそれぞれapp idを追加する。
prd.jsonだけ(場合によってはstg.jsonも)idを本番用idにする。
(↓はテスト用app id)

dev.json
{
    // 省略
    "admobAppIdIos": "ca-app-pub-3940256099942544~1458002511",
    "admobAppIdAndroid": "ca-app-pub-3940256099942544~3347511713"
}

prd.jsonは必ず.gitignoreに追加する!!!!
先にprd.jsonがpushされている場合などはgitignore後で追加した時の方法で削除する。

本当はprd.jsonに直接idを書きたくなかったけど、これ以外のいい方法がわからなかったので何か他にあったら知りたい。

ios

info.plistのGADApplicationIdentifierの値を↓のように変更する。

info.plist
		<key>GADApplicationIdentifier</key>
		<string>$(admobAppIdIos)</string>
  	</dict>
</plist>

これでiosのapp idが切り替わる

android

android/app/build.gradleのdefaultConfigresValueを追加する。

build.gradle
    defaultConfig {
        // 省略
        applicationId "${dartDefines.appId}"
        resValue "string", "app_name", "${dartDefines.appName}"

        // ↓追加
        resValue "string", "admob_app_id_android", "${dartDefines.admobAppIdAndroid}"
    }

android/app/src/main/AndroidManifest.xmlのcom.google.android.gms.ads.APPLICATION_IDの値を@string/admob_app_id_androidに書き換える。

AndroidManifest.xml
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="@string/admob_app_id_android"/>
    </application>

これでandroidのapp idが切り替わる。

実機デバイス用の広告リクエス設定

このままではデバイスIDを設定したスマホでテストモードの本番広告(正式な名称がわからない)を表示することが出来ない。
test device identifier(デバイスIDをハッシュ化したもの?)をコード上で設定してやらなければいけない。
(xcodeでログを見た時に初めて気づいたので、実機で広告を表示するのに随分時間がかかった。)

<Google> To get test ads on this device, set: 
Objective-C
	GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ @"00000000000000000000000000000" ];
Swift
	GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = [ "000000000000000000000000000000" ]

デバイスIDを取得する

import 'package:device_info_plus/device_info_plus.dart';

DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
String? testDeviceId;

if (Platform.isIOS) {
  IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
  testDeviceId = iosInfo.identifierForVendor;
} else if (Platform.isAndroid) {
  AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
  testDeviceId = androidInfo.id;
}

debugPrint('Test Device ID: $testDeviceId');

identifierを設定する

// デバイスIDをMD5でハッシュ化
var bytes = utf8.encode(testDeviceId);
var digest = md5.convert(bytes);
var id = digest.toString();
RequestConfiguration requestConfiguration = RequestConfiguration(
  testDeviceIds: [id],
);
await MobileAds.instance
    .updateRequestConfiguration(requestConfiguration);

これだけだと、設定が終わる前にロードしてしまって失敗するので、非同期に制御してあげた方がいい。

ステータスバーの色を変更する(android)

(特にこだわりが無ければやらなくてもいい。けどiosとデザイン変わってしまうのでやった方がいいかも。)

androidは自分でステータスバーの色を変えてあげなきゃいけない(っぽい)

Platformを使うためdart:ioをインポート。

import 'dart:io';

// 省略

void main() {
  // 省略

  if (Platform.isAndroid) {
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.white, // ステータスバーの背景色を設定
    ));
  }

  runApp(const MyApp());
}

番外編

gitignore後で追加した時

.gitignoreにignoreしたいものを追加する。

git rm --cached ファイル名

or

git rm --cached -r ディレクトリ名

で削除。
commit & push するとリモートからgitignoreしたいものが消える。

↓参考

admobログイン

なぜかarcではページを読み込めないのでchromeとかでログインする。
(↑これマジでなんで?)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?