flutter トラブルシュート 覚書
Text がはみ出る (Overflow)
Text(
'over flowed text',
overflow: TextOverflow.fade, // fade, clip, etc...
);
それでも用意した領域からはみ出る
Text(
'over flowed text',
overflow: TextOverflow.fade,
softWrap: false,
);
トップページへ戻り、そこからは戻れないようにしたい
ユーザーを切り替えた時など、普通にトップページに戻ると過去のユーザーに表示していたページが残る。
Navigator.of(context).pushNamedAndRemoveUntil(
'/home',
(r) => false,
);
RemoveUntil
系はコールバックの返り値がtrue
になるまで繰り返しNavigatorに残るページを削除する。
タブを移動するたびにページを生成をやり直したくない
ページ生成のために通信したりしていると特に。
AutomaticKeepAliveClientMixin
を使ったやり方がすごく楽。
class PageState extends State<Page> with AutomaticKeepAliveClientMixin { // ←追加
bool get wantKeepAlive => true; // ←追加
Widget build(BuildContext context) {
super.build(context); // ←追加
}
}
これ追加するだけ
Listの最後に来た時に追加データをロードしたい
ListTileのtrailingのRowがはみ出す
Row(
mainAxisSize: MainAxisSize.min,
)
Firebase Analytics データが来ない
どうもデータ送信は纏めて行っている様子
- iOSは操作したあと、iPhoneホームに戻ると送信されやすい
- Androidは(シミュレーターのみ確認)操作したあと、シミュレーターを終了させるときに送信されやすい
Firebase Crashlytics データが来ない
ドキュメント手順に補足
- Firebaseで有効化
- SDKをプロジェクトに含めてシミュレータへビルドしてインストール。最初のクラッシュを発生
- クラッシュしたら(多分ビルド/インストールをしなおさず)アプリを再起動。→送信される
dSYM
localization でのエラー
app_localizations.dart
やそのディレクトリなどが生成されなかった時は
flutter gen-l10n
を実行する
その後
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
の追加でdoesn't exist
と言われましたが、VSCodeの再起動で消えます。
ただしAppLocalization
クラス"自体"の補完は効かないみたい。
おまけ
出典元の2つ目の回答にありますが、上記を行った上であればlocalizationsDelegates:
やsupportedLocales:
はAppLocalizationが自動生成してくれるので、公式docのようにわざわざ列挙する必要はもうないみたいです。
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
+ localizationsDelegates: AppLocalizations.localizationsDelegates,
- localizationsDelegates: [
- GlobalMaterialLocalizations.delegate,
- GlobalWidgetsLocalizations.delegate,
- GlobalCupertinoLocalizations.delegate,
- ],
+ supportedLocales: AppLocalizations.supportedLocales,
- supportedLocales: [
- const Locale('en', ''),
- const Locale('jp', ''),
- ],
title: 'My app',
home: ... ,
);
}
}
出典
List<dynamic> to List<String>
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<String>'
jsonDecode後によく困るやつ
List<dynamic> data = ["aaa", "bbb", "ccc"];
List<String> strings = data.cast<String>().toList();
AppStoreの短縮URLが欲しい
数年前の情報が沢山出てきて、appleのマーケティング用のサイトから短縮URLが取得できるような案内が多いが、現在は提供していない様子。
↓
bitlyでappstoreのURLを短縮しようとするとapple.co/...
となります。
正規ではないんでしょうが見栄えは○
Flutter × Firebase アナリティクスから自分を除外したい
Firebaseの作るGAでは「ビュー」が作成されない設定っぽいのでipでのフィルタリング等ができない。
なのでプログラム上でAnalyticsをdisableにする方法を取る
除外したい開発用のデバイスのIDを取得
Future<String> _getDeviceId() async {
if (Platform.isIOS) {
final info = await DeviceInfoPlugin().iosInfo;
return (info.identifierForVendor!);
} else {
final info = await DeviceInfoPlugin().androidInfo;
return (info.androidId!);
}
}
これをprint()
するなどして自分のデバイスIDを取得して、どこか参照できる場所に置いておく。
Analyticsをdisable
ハードコードを避けるために下の例ではflutter_dotenvでTEST_DEVICE_ID
という名前にカンマ区切りで除外したいデバイスのIDを置いている。
void main() async {
await Firebase.initializeApp();
final excludeIds = dotenv.env['TEST_DEVICE_ID']!.split(',');
if (kDebugMode || excludeIds.contains(await _getDeviceId())) {
FirebaseAnalytics().setAnalyticsCollectionEnabled(false);
}
runApp(MyApp());
}
本当はコード外でやりたいけどね😩
カスタムURLスキームを設定したらAndroid側でアプリアイコンが消え開けなくなった
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="カスタムスキーム" />
</intent-filter>
intent-filter
は分けないといけない
firebase hosting でデプロイしたapp-ads.txtが認識されない
- Admobで見ると「robots.txtが原因でクロールできない」と言われる。
- 「詳細」か何かのリンクを押すとどんなrobots.txtを設定すればいいか書いてある。
- robots.txtを設置しても「robots.txtが原因でクロールできない」が変わらない
- ブラウザやUAをクロールbotにしたcurlでアクセスしてもちゃんと取得できるのに
解決
robots.txtを設置してから5日くらい放置したら認識された。
Admobで手動更新できるけど、更新されたrobots.txtが反映されてadmobが認識するまでは時間がかかるっぽい。時間返して!
share_plus
で画像を保存しようとしたときに落ちる
OSの共有メニューを呼び出してくれるPackage: share_plus
公式の説明が不足していて設定が足りてないことに気づかずハマった。
類似Packageのshare_extendには書いてあったのでそちら参照。
以下の設定を付け足すと正常に動作する
iOS
<project root>/ios/Runner/Info.plist
<key>NSPhotoLibraryAddUsageDescription</key>
<string>describe why your app needs access to write photo library</string>
Android
<project root>/android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
READは要らない気もするが?
String.fromEnvironment
で値が取得できない
「String.fromEnvironment
はconst
を付けたときしか正しい動作が保証されない」と、コード内コメントでも説明されていたのに気付かなかった。
This constructor is only guaranteed to work when invoked as const. It may work as a non-constant invocation on some platforms which have access to compiler options at run-time, but most ahead-of-time compiled platforms will not have this information.
つまり、以下のようにアクセサを作って使うことが出来ない
enum EnvDef {
flavor,
appName,
appIdSuffix,
;
String get value => String.fromEnvironment(name);
toString() => value;
}