saneatsu
10/3/2019 - 10:14 AM

Dart/Flutter Tips

はじめかた

1. アプリ作成

$ flutter create appname

2. XcodeのSignining&Capabilities

  • Team: AlgoAge K.K
  • BundleIdentifier: com.algoage.appname

Commands

$ flutter devices -v

$ flutter emulators
Pixel_XL_API_28     • Pixel XL API 28  • Google • android
apple_ios_simulator • iOS Simulator    • Apple  • ios

$ flutter emulators --launch apple_ios_simulator

$ flutter run

実機テスト方法(iOS)

localhost をスマホ実機で確認する方法 iPhone から localhost で起動しているアプリにアクセス

1. エンドポイントの書き換え

assets/json/deep_anime_api.jsonのAPI_URIを以下のように書き換え saneatsuの部分は自身のMacPC名にすること

MacのPCの名前はシステム設定の共有から確認

{
    ...
    "API_URI": "http://saneatsu.local:3000"
}

2. iPhoneのWifi設定

  1. Macでローカルサーバーを立ち上げ
  2. 端末とMacをUSBで接続
  3. MacとiPhoneを同じWifiに接続し
  4. MacのIPアドレスをチェック(システム環境設定 > ネットワーク)
  5. 「設定」アプリから該当Wifiを選択し i マークをタップ
  6. HTTP プロキシ -> プロキシを構成 をタップ
  7. 「手動」を選択
  8. 「サーバー」に PC の IP アドレス (e.g., 192.168.120.95) を入力
  9. 「ポート」に localhost で起動しているアプリのポート (e.g., 3000) を入力
  10. 「保存」をタップ

実機テスト方法(Android)

android端末からPCのローカルサーバにアクセスする方法
Androidアプリ開発中にAndroid実機を認識しなくなった時の対処方法

1. エンドポイントの書き換え

assets/json/deep_anime_api.jsonのAPI_URIを以下のように書き換え

{
    ...
    "API_URI": "http://10.0.2.2:3000" // エミュレーターの場合
}

"http://localhost:3000"だと以下のエラーが発生する "http://192.168.179.5:3000" 実機の場合はMacのIPアドレスにする

SocketException: OS Error: Connection refused, errno = 111, address = localhost, port = 35779 #16

2. ChromeでプライベートIPを直接指定

  1. Macでローカルサーバーを立ち上げ
  2. 端末とMacをUSBで接続
  3. chromeでchrome://inspect/#devicesにアクセス(デバックの許可を求められたら許可する)
  4. 「Port forwarding...」をクリックする
  5. 右欄にローカルサーバのipアドレス+ポート番号を入力、左欄に端末側でサーバアクセスする時のポート番号を入力
  6. 「Enable port forwarding」をクリックして有効化
  7. Doneで終了

3. Androidの開発者向けオプションの設定

  1. 「USBデバッグ」を有効化
  2. 「USB設定を選択」で「ファイル(MTP)」を選択
  3. 「USB使用」で「メディアデバイス(MTP)を選択(通知が来ているのでそこから飛ぶ)

デバイスへアプリをインストール(共通)

コマンド

$ flutter devices
1 connected device:
WAS LX2J • P3PDU18316006143 • android-arm64 • Android 7.0 (API 24)

$ flutter run -d P3PDU18316006143

VSCodeを使っている場合は「Fn + F5」

リリース手順

ipaファイルの作成方法

https://qiita.com/ishihamat/items/a897754eed6b5c1ec6ed

or

https://github.com/flutter/flutter/issues/13065#issuecomment-441802877

cd ios
xcodebuild -workspace Runner.xcworkspace -scheme Runner -sdk iphoneos -configuration Release archive -archivePath $PWD/build/Runner.xcarchive
xcodebuild -allowProvisioningUpdates -exportArchive -archivePath $PWD/build/Runner.xcarchive -exportOptionsPlist exportOptions.plist -exportPath $PWD/build/Runner.ipa

Provisioning Profileの確認方法

方法

$ open ~/Library/MobileDevice/Provisioning\ Profiles/

Finderで開いてスペースで開いてどのファイルか確認

$ curl -O https://raw.githubusercontent.com/InderKumarRathore/ListProvisioningProfileName/master/list-provisioning-profile-name.sh
$ chmod +x list-provisioning-profile-name.sh
$ bash list-provisioning-profile-name.sh
saneatsuwakana at saneatsu in ~
$ bash list-provisioning-profile-name.sh
Provisioning Profile Folder: cd ~/Library/MobileDevice/Provisioning\ Profiles/
020be5e2-7782-4797-832a-74664f422d79.mobileprovision    chatbot_mobile
256ab240-7594-47ce-a5bd-7a567603e6f1.mobileprovision    poseandclassification
58d6d6ae-5b9f-4eb0-8802-9bbf592569e1.mobileprovision    ios team provisioning profile: com.algoage.deepanime
711389b8-8995-425f-8d33-f81170a77127.mobileprovision    ios team provisioning profile: *
75497611-94ba-4871-8546-1c599b960b78.mobileprovision    deepanime  ← これ!
782a89d3-c369-470f-b68c-6a2730ae05b7.mobileprovision    ios team provisioning profile: net.algoage.chatbotmobile
78702b93-d067-4d98-9673-61a0b540a60b.mobileprovision    poseandclassificationdemotest
a3b4cfb1-5288-46a6-b0e8-f2a25d19b750.mobileprovision    ios team store provisioning profile: com.algoage.deepanime
b03736ff-29c4-4a6c-bf49-f6a1a1255bea.mobileprovision    animeafreco
dcfb0473-e7e1-4f1d-b453-af1350a1998f.mobileprovision    ios team store provisioning profile: net.algoage.chatbotmobile

参考

Dartの文法

Widget解説

Stateクラスのライフサイクル

    1. createState
    1. initState
    1. didChangeDependencies
    • Widgetツリーの変更を要素に通知する
    • contextにアクセスが必要なInheritedWidget由来のinheritFromWidgetOfExactTypeにアクセス可能

Flutterの基礎

didChangeDependencies

アニメーション

デザイン、UI

アーキテクチャ

BLoV, Provider

App内課金

https://developer.apple.com/account/#/overview/QL469279ML このページから契約内容に同意する。

BottomNavigationBar

アニメーション

onTapをWidgetに追加する方法

  • GestureDetector
    • 子にTextとかがあるとその文字をタップしないと反応してくれない
  • InkWell
    • 子Widget全体が反応する

参考

await処理松

mapのループ色々

https://www.codevscolor.com/dart-iterate-map/

リストをループしてWidgetを作る

この方法はワンライナーでなくちゃいけないので注意。 Text以外にも入れ子のWidgetを使いたい場合は別に関数としてWidgetを定義すること

Subscription

全体

iOS

App Store Connect

Android

Google Play Console

unix timestamp

final int timestamp = (DateTime.now().millisecondsSinceEpoch / 1000).round();

リストの使い方いろいろ

Top 10 Array utility methods you should know (Dart) 🎯

Buttonを非活性化

How do I disable a Button in Flutter?

リストをmap()で回す時にindexも渡す

List _sample = ['a','b','c'];
_sample.asMap().forEach((index, value) => f);

Enumerate or map through a list with index and value in Dart

Firestoreの特定のフィールドをとることは出来ない

How to get value of some field in firebase firestore android?

Firebase Analytics

サイズの取得方法色々

// full screen width and height
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;

// height without SafeArea
var padding = MediaQuery.of(context).padding;
double height1 = height - padding.top - padding.bottom;

// height without status bar
double height2 = height - padding.top;

// height without status and toolbar
double height3 = height - padding.top - kToolbarHeight;

HEICをJPGに変換

下の方法もあるが、deep_anime_mobileではMultiImagePickerを利用してbyteDataをとってきてそれを変換した。

https://github.com/flutter/flutter/issues/20522#issuecomment-520175936

try {
  selectedImages = await MultiImagePicker.pickImages(
    maxImages: 3,
    enableCamera: true,
  );
  for (var image in selectedImages) {
    ByteData byteData = await image.getByteData();
    imageFiles.add(
      byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes)
    );
  }
  
  List images = [];
  for (int i=0; i<selectedImages.length; i++) {
    images.add(
      UploadFileInfo.fromBytes(
        selectedImages[i],
        'image_$i.png',
        contentType: ContentType('image', 'png')
      )
    );
  }
} catch (e) {
  print(e.message);
}


パスからファイル名だけを取得

pathというデフォルトで用意されているライブラリを使う。 拡張子だけ撮ってくるときにも使える便利。

import 'package:path/path.dart' as p;

String extension = p.extension(image.name);

https://stackoverflow.com/questions/50439949/flutter-get-the-filename-of-a-file

StringをEnumに変換

enum Fruit { apple, banana }

// Convert to string
String str = Fruit.banana.toString();

// Convert to enum
// Fruit f = Fruit.values.firstWhere((e) => e.toString() == str);
Fruit f = Fruit.values.firstWhere((e) => e.toString() == 'Fruit.' + str);
assert(f == Fruit.banana);  // it worked

https://stackoverflow.com/questions/27673781/enum-from-string

シリアライズ方法

Dartのコンストラクタ

  1. 生成的コンストラクタ
  2. ファクトリ
  3. 定数コンストラクタ

https://makicamel.hatenablog.com/entry/2019/03/14/213933

Bing API

PageTransitionいろいろ

Image.networkでローディングを表示する

アップロード中にButtonをdisableにする

レイアウト

全般

GridView

Textfieldの検索窓

実機をUSBでつないでlocalhostにアクセス

/var/mobile/Containers/Data/Application/(XXX)/Documents/

https://qiita.com/nambara/items/bc0649b5c2d955bff220