20200117のAndroidに関する記事は6件です。

Android アプリのビルド時に GC overhead limit exceeded が出たときに確認すること

概要

macOS を Mojave から Catalina へアップデート後、 Android アプリをビルドすると

GC overhead limit exceeded

というエラーが出るようになってしまいました。。。🤔

原因を突き止めたので書き残しておきます。

原因(ぼくの環境の場合)

いきなり結論を。

Android Studio の Memory Settings が初期化されていたせいでした…

  • Android Studio - Preferences スクリーンショット 2020-01-17 20.19.48.png

赤枠の項目が 空白 になっていました。

こちらを設定したら無事ビルドできるようになりました! 🎉

他に確認したこと

「GC overhead limit exceeded」 で調べるといろいろヒットすると思います🔎

build.gradle に javaMaxHeapSize を定義しているか

build.gradle
android {
    dexOptions {
         javaMaxHeapSize "2g"
    }
}

Android開発中にGC overhead limit exceededで逝く

こちらの記事に詳しく書かれています。

ぼくの build.gradle には既に定義されていました…。

gradle.properties に jvmargs を定義しているか

[stackoverflow] java.lang.OutOfMemoryError: GC overhead limit exceeded on Android 1.4

途方に暮れていたらこちらの stackoverflow にたどり着きました。

gradle.properties
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError

確認してみると定義されていませんでした❗️キタ❗️これでビルドできるー🙌

ウキウキで gradle.properties に追記してビルドボタンぽちっ❗️

ダメでした…。

各値を書き換えてみたりしましたがビルドできずでした。。

おわりに

こちらの記事が誰かの助けになると幸いです🙏

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スマホアプリ開発者のための2019年動向まとめ

はじめに

2019年は新元号「令和」のスタートやラグビーワールドカップなどなんとなくめでたい年でした。年始まで忙しかったので2020年の1月中旬ですが2019年のスマホアプリ業界をこっそりまとめます。

個人的には2019年はAndroidアプリを中心にネイティブアプリ開発保守をしていました。
スマホアプリ開発に携わっていない人もこの記事を見れば2019年のいろいろが分かるかも。
振り返り用に「ふむふむ」「へー」程度に見ていただければ幸いです。

【前年】
スマホアプリ開発者のための2018年動向まとめ
Unityでスマホアプリ(特にプラグイン)を開発している人のための2017年対応まとめ
Unityでスマホアプリ(特にプラグイン)を開発している人のための2016年対応まとめ

通信回線について

約10年に1度の通信回線アップデート、5Gがついにはじまりました。
2019年4月に米Verizonが開始し、9月に米Qualcommが開催した「2019 Future of 5G」では半年以内に30以上の通信事業者が5Gを開始または開始予定としていることが発表されました。

スクリーンショット 2020-01-15 22.01.12.png

https://www.verizon.com/about/our-company/5g
https://www.qualcomm.com/documents/2019-future-5g-presentation

日本ではdocomo、KDDIが2019年9月にプレサービスを開始し、2020年を目処に商用サービス開始予定です。高速、大容量、低遅延、多接続、低消費電力などがキーワードとしてあげられています。

https://www.nttdocomo.co.jp/corporate/technology/rd/tech/5g/
https://www.softbank.jp/biz/5g/
https://biz.kddi.com/5g/

また、3Gの停波のお知らせを公開し、auは2022年、SoftBankは2024年、docomoは2026年に停波となることが決定されました。これによってガラケーやらくらくホンを使用していたシニア層がスマホに大量流入することが予想されます。

https://www.nttdocomo.co.jp/info/news_release/2019/10/29_00.html
https://news.kddi.com/kddi/corporate/newsrelease/2018/11/16/3428.html
https://www.softbank.jp/mobile/network/3g-end/

端末について

Appleからは例年通り9月にiPhone 11, iPhone 11 Pro, iPhone 11 Pro Maxが発売、Googleからは5月にPixel3a, 10月にPixel4が発売されました。
iPhoneもPixelも基本的にはカメラ機能推しで「夜景モード」という言葉は今年浸透した印象です。

2019年は数少ないですがGalaxyやLGから折りたたみ端末(Foldable端末)が発売されました。Microsoftからは「Surface Duo」というAndroid端末が発表され2020年のホリデーシーズンに発売予定です。

5G対応の端末が2019年から発売され2019年12月現在は約30機種に増えました。2020年は対応機種が増え日本からも発売されることが予定されています。

2019年のスマホサービスについて

決済サービスの増加

個人的に大きいと思ったスマホアプリのニュースは2019年2月のPaypay100億円キャンペーンでした。
各店のPOSも多くの決済方法に対応し、生活が一変しました。
非接触方式に比べるとアプリ立ち上げやバーコード提示など不便な印象でしたが、
増税時のキャッシュバックキャンペーンなども後押しし、バーコード/QRコード決済が増えました。
Paypay、LINE Pay、メルペイ、Origami Pay、Kyash、ファミペイ、Origami Pay、楽天ペイ、セブンペイなどいろんなペイの選択肢が増えました(そして消えたサービスもありました)

スマホゲームについて

2019年は日本の大手企業のリリースが多い年でした。
任天堂からはマリオカートツアー、ドクターマリオワールド、ポケモンマスターズと2019年で3本のリリースがありました。
また、ドラゴンクエストウォークなどの位置ゲームに関して世界的にリリースが多く、Googleからゲーム事例の記事が投稿されています。

魅力あるゲーム体験を実現するGoogle Maps Platformの新機能と最新ゲーム事例
https://developers-jp.googleblog.com/2019/12/new-features-contextualized-gameplay-and-new-games-built-google-maps.html

また、ゲームのサービス形態が変化した年でした。Appleからは定額制サービスのApple Arcade、GoogleからはクラウドゲームのStadiaが発表されサービス開始しました。

子供向けプライバシーの保護の強化

スマホに限らずですが、YouTubeで子供向けプライバシー保護の取り扱いが大きく変更されました。
子供向けであると判断された、あるいはそう申告されたすべてのコンテンツについて、視聴者は無条件で子供と見なされるようになりました。

https://youtube.googleblog.com/2019/09/an-update-on-kids.html
https://youtube.googleblog.com/2020/01/better-protecting-kids-privacy-on-YouTube.html

子供向けプライバシー保護の強化はYouTubeのみでなくGoogle Play Serviceにも実施され、
自分が公開している子供向けアプリもGoogle Play Serviceを実装しているという理由で2019年に突然リジェクトされました。(参考: 2019年以降、GooglePlayの子供向けゲームアプリに○○を実装してはいけない)

iOSも例外ではなく9月に「子ども向け」カテゴリガイドラインが更新されました。
2020年3月3日までは対応の猶予期間となっています。

すべての新規Appはこのガイドラインに従う必要があります。また、できるだけ早く既存のAppを更新することをお勧めします。既存のAppにこのガイドラインを適合するのにさらに時間が必要な場合を考慮し、コンプライアンスに準拠させるために2020年3月3日までさらに6か月の猶予期間を設けることにしました。

iOS

iOS13

iOS 13をプレビュー
https://www.apple.com/jp/newsroom/2019/06/apple-previews-ios-13/
iOS 13 Release Notes
https://developer.apple.com/documentation/ios_ipados_release_notes/ios_13_release_notes

2019年9月19日にiOS13の提供が開始されました。
SwiftUI、ダークモード、SF SymbolsなどUI周りが大きく変更されました。
ただしSwiftUIで開発したアプリはiOS13以降のみの対応となるため、完全移行は数年かかりそうです。
iPad向けのOSがiOSからiPadOSになり、iPad用AppをmacOSへ用意に移植できるProject CatalystもWWDC19で発表されました。

Submit Your iOS Apps to the App Store
https://developer.apple.com/news/?id=09102019a&1568158483
Modernizing Your UI for iOS 13
https://developer.apple.com/videos/play/wwdc2019/224/

iOSアップデートにより、要件も更新されました。
2020年4月からiOS13および3rd-genのiPad Pro対応必須となり、同時に以下を要件としています。

  • LaunchScreenのStoryboard化
  • 複数サイズのサポート
  • 分割スクリーンのマルチタスク化

スクリーンショット 2020-01-15 22.19.12.png

参考:

iOSのその他対応

その他にもPUSH通知、UIWebView受付終了の告知がされています。

Apple Push Notification service(APNs)は、2020年11月以降レガシーバイナリプロトコルをサポートしなくなります。

App Storeは、2020年4月からUIWebViewを使った新しいAppの受付を終了し、2020年12月からUIWebViewを使ったAppのアップデートの受付を終了します。

Android

Android10

ようこそ!Android10
https://developers-jp.googleblog.com/2019/09/android-10.html

2019年9月3日にAndroid10の提供が開始されました。
ジェスチャーナビゲーション対応、5G対応、折りたたみ画面対応、セキュリティ強化などが含まれています。

詳細なこちらへ > Android 10対応したので個人的まとめ (RSSリーダーアプリ編)

APIレベル28(Android 9)以上が必須に

2018年までの必須APIレベルは26でしたが今年は28になりました。
APIレベル28の変更点として、デフォルトのネットワークセキュリティ構成がhttps通信のみ許可になりました。
http通信を行うにはドメインをホワイトリストに追加するなどの対応が必要になります。

2019年のターゲットAPIレベル要件の拡大について
https://developers-jp.googleblog.com/2019/03/2019-api.html

AndroidでのTLS採用に関する最新情報
https://developers-jp.googleblog.com/2020/01/android-tls.html

また、2019年8月以降64ビットが必須要件になりました。
Unity5.6以前を使用したゲームの場合は2021年8月までの延長期間が与えられています。

アプリを64ビット要件に対応させましょう
https://developers-jp.googleblog.com/2019/02/get-your-apps-ready-for-64-bit.html

2年連続でAPIレベルが夏から秋にかけてAPIレベルの底上げを行っています。
例年通りだと2020年も行われることが予想されます。
旧サポートライブラリの最終バージョンが28なので、
APIレベル29対応では必然的にAndroidX対応が必要となります。
余裕があるときにAndroidX対応をしていたほうが良さそうです。

Android関連のドキュメントの拡充

2019年1月にAndroidのCodelabが公開されました。
基礎コースと応用コースが用意され、学習が容易になりました。

https://developer.android.com/courses

AndroidXはドキュメントページで最新バージョンがわかるようになった他、
Feedでのバージョン情報提供もはじまりました。
SlackなどでFeedを登録しておけば最新ライブラリの情報がキャッチ可能になります。

https://developer.android.com/jetpack/androidx/versions
https://developer.android.com/feeds/android-release-notes.xml

Androidのその他

2018年末のKotlin1.3でコルーチンが正式対応となり、Google Developers Blogでもコルーチン関連の記事が公開されました。
プロジェクトの動的モジュール化やコード圧縮ツールR8も注目のトピックとしてあげられています。

また、Project Marbleという以前からのAndroid Studio改善の取り組みが反映された、Android Studio 3.5がリリースされました。
詳細はこちら >Android Studio3.5の変更点をもっと詳しく知りたい..!

2020年春に登場するKotlin1.4

Kotlin 1.4の計画および将来的な展望
https://blog.jetbrains.com/jp/2020/01/16/2731

12月に行われたKotlinConf 2019でKotlin1.4の展望が発表されました。
(ちょうど昨日に日本語版blogが更新されました!)
マルチプラットフォーム化やKotlinのSAM変換についての変更などがあります。

Flutter

2019年はFlutter関連のニュースも多くありました。
6月にFlutter for Web発表、12月にはFlutter単独で技術イベントFlutter Interactが行われ注目度は今年も上がっています。

Flutter Interact
https://developers.google.com/events/flutter-interact

Flutterの追い風(?)でDartもバージョンアップが頻繁に行われ、
2018年末の最新バージョンは2.0でしたが2019年末はDart2.7になり、
コレクション機能や拡張メソッド対応など一年で様変わりしました。
DartPadというDartを気軽に試すことができるツールも登場しました。

DartPad
https://dartpad.dev/

Flutterはコンテストも多く開催し、
5月には5KBで作るFlutter Create、11月には時計を作るFlutter Clockを発表しました。
# Flutter Clockの参加締切は2020年1月20日までなのでまだ間に合います。

React NativeやFlutterのUI構築手法

React NativeやFlutterのUI構築手法はネイティブ開発に影響を与え
2019年に「Jetpack Compose」「SwiftUI」が続けて発表されています。
UIはコードベースでプレビューを確認しながら作るという手法が近くに一般化しそうです。

スクリーンショット 2020-01-17 20.31.13.png
SwiftUI

スクリーンショット 2020-01-17 20.31.13.png
Jetpack Compose

Unity

スマホ関係者はUnite 2019の基礎公演、開発者は開発ロードマップ最新情報のYouTube動画を見るのがおすすめです。
基礎公演40:00ではVR/ARや自動運転、アニメーション活用に関して、
非ゲーム分野でシミュレーターとしてのUnity活用概要があります。

Unite 2019 基礎公演
https://youtu.be/zLQ9oY08p84?t=2405

Unity開発ロードマップ最新情報では直近のUnity更新内容が紹介されています。

Unity開発ロードマップ最新情報
https://www.youtube.com/watch?v=o9EJu4LRIdY

DOTS (Data-Oriented Technology Stack)

DOTS - Unity の新しいマルチスレッド対応の Data-Oriented Technology Stack
https://unity.com/ja/dots

UnityはUnityを根幹から変える取り組みが行われており、DOTSに置き換わります。

  • Entity 1.0 (2020.1〜)
  • DOTS NetCode (2020.1〜)
  • DOTS Audio
  • DOTS Physics
  • DOTS Animation

エディタUIも再設計されビジュルスクリプティング機能もベータ公開予定。
映像向けパイプラインにはPythonサポートされます。
その他として、Serializeが進化してリファレンスがSerialize可能になりましたうれしい。

モバイル向けの変更

モバイル向けに以下がロードマップの動画内で発表されています。
Unity as a LibraryはUnityとネイティブアプリの関係性を大きく変化させそうです。

  • Project Tiny: Instant Runのような仕組みを提供。
  • Unity Distribution Portal: Apple, Google以外のプラットフォームにも複数ゲーム配信ハブシステムも提供。
  • Unity as a Library: ネイティブアプリ向けにUnityで作ったアプリをライブラリとして使用できる機能。

まとめ

2019年はだいたい以下のような感じでした(個人の感想です)

  • 2019年のスマホは決済サービスが流行(増税の影響?)
  • 2019年のスマホゲームは最大手参入と新サービス形態(Apple Arcade, Stadio)。
  • 2019年は子供向けプライバシー強化が大きく行われた
  • 2020年はとにかく5Gを中心に変化
  • ネイティブのUI開発は旧手法・新手法(SwiftUI, Jetpack Compose)・別手法(Flutter, React Native)から選択する必要あり。
  • Unityは新手法のDOTSに改装中

告知

2月のDroidKaigi 2020でビジュアルリグレッションテストについて話します。まだ資料できてません。
https://droidkaigi.jp/2020/accepted/

この記事が参考になったら「いいね」を、あとで読む場合は「ストック」を、投げ銭したくなったらPaypayで以下をおねがいします。
PNGイメージ.png

今年もよろしくおねがいいたします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Google Play Console のリリース管理について整理しよう

  • Android アプリのリリースには Google Play Console を使いますが、リリースには複数のバージョンに分けて段階的にリリースして行くことができます。
  • 本記事では Google Play Console の段階リリースについて整理しようと思います。

対象となる方

  • Android アプリ開発者で今後アプリリリースしようと思っている方。

Doc

リリース管理ってなに?

  • Google Play Store のリリースを段階的に行うための方法
  • 公式に、『製品版としてアプリをリリースする前に、テストすることをおすすめします。』と記載
    • いきなりリリース:zap:的なのりはやめておこう

段階的って?

リリース管理の段階として、以下の段階が用意されています。

  • 内部テスト版
  • クローズドテスト版
  • オープンテスト版
  • 製品版

各リリース段階の整理

内部テスト版:robot:

  • 利用ユーザーはGoogle Play Store内の『テスター管理』を利用
  • 最大100名が利用できる
  • 課金アプリの場合、テストユーザーは課金の必要は無し

クローズドテスト版:robot:

  • 利用ユーザーはGoogle Play Store内の『テスター管理』を利用
  • テスト対象のAPKをトラックという単位で作成
    • 1トラック、50リストのテスターリストを登録可能
    • 1リスト、2000人までテスターを登録可能
  • 課金アプリの場合、テストユーザーは課金処理を実施する必要がある
    • PlayStore内でユーザー単位にアプリライセンスを付与できるのでそれによって課金済み状態に擬似的にできる

オープンテスト版:robot:

  • Google Play Store からユーザーが検索して利用することができる
  • 開発元が公開しているオプトインURLから参加する事も可能
  • テスト対象は開発元が上限(最低1000名〜)を決めている場合にはその数に従う
    • 上限がない場合には、制限なしとなる
  • 課金アプリの場合、テストユーザーは課金処理を実施する必要がある
    • PlayStore内でユーザー単位にアプリライセンスを付与できるのでそれによって課金済み状態に擬似的にできる

製品版:ribbon:

  • Google Play Store 一般公開されたバージョン
  • もちろん課金アプリは課金処理が必要

さいごに

  • Android開発をし、世の中に公開するには、Google Play Store での公開が不可欠です!
  • しっかりテストを行い、Bestな状態でリリースして行きましょう:relaxed:

これからも楽しいアプリ開発をしていきましょう:dancer_tone1:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AIDL通信

①IPC通信なので、送信側はMainThreadですけれど、
受信側はMainThreadではなく別すれどである。
②AIDL通信で送受信側のスレッドは別々ですけれど、
AIDL通信は同期処理です。
例えば、APPからServiceの処理を呼んだ時、Serviceの処理が終わるまで、APPがずっと待っている。

image.png

image.png

image.png

image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Flutterまとめ(Dart)

基本的なUI Widget

Container

いわゆるdiv

new Container(
  // padding: EdgeInsets.all(float),
  // .only([direction] :float) もある
  // direction: left,right,top,bottom  
  //EdgeInsets.symmetric(vertical: float)
  //(horizontal: float)もある.
  // marginも同様
  // margin: EdgeInsets.[option](float)
  //decoration: new BoxDecoration(
  //  border: new Border.[option](width: float, color: Color),
  //  option: all,only,symmetric
  //  borderRadius: const 
  //  BorderRadius.[option](const Radius.circular(float)),
  //  color: Color,
  //),
  child: new HogeWidget(),
  //...

)

ListView

読み込みと同時にすべてのリストを描画するため、メニューや設定など要素数が一定&要素数が多すぎないものに利用する.

List<Widget> data = [Widget1,Widget2,Widget3,Widget4,Widget5,...]

new ListView(
  children: data // List
)

ListViewBuilder

使用例

new Listview.builder(
  // itemCount:  int,
  itemBuilder:(BuildContext context, int index){
    // indexがインクリメントする 
    return new HogeWidget()
  }
)

ListViewBuilderを利用して無限リストビュー実装
https://qiita.com/najeira/items/454462c794c35b3b600a

Listのアイテムにクリックイベントを付与

Listのchildrenに渡すWidgetをGestureDetectorでラップすればいい.

new GestureDetector(
  onTap: ()=> _doSomething(),
  // otherEventListeners,
  child: new HogeWidget(),
)

GridView Widget

使用例
タイル状にWidgetを配置するときに使う。
GridView.countで一行当たりの要素数を決めて利用する

new GridView.count(
  crossAxisCount: 5,
 // crossAxisSpacing: 上下のmargin,
  // mainAxisSpasing: 左右のmargin
  children: List.generate(10,(index){
    return /...
  })
)

modal(dialog)を使う

GestureDetector(
  // ...
  onTap: (){
          // open Modal window
          showDialog(
              context: context,
               builder: (_){
                return Modal();
               },
          );
        }
 //...

ModalはAlertDialogsimpleDialogを使うか、それらを継承した独自のWidgetを使う.

Modal内のレイアウトは、singleChildScrollView()の子要素にcolumnやrowを入れてカスタマイズできる.

import 'package:flutter/material.dart';

class Modal extends AlertDialog {
  final String title;
  Modal({this.title});

  @override
  Widget build(BuildContext context){
    return new AlertDialog(

      title:Center(child:Text(title?? "title")),
      content: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            Text("content"),
            //...
          ],

        ),
      ),


      actions: <Widget>[
        RaisedButton(
          child: Text("Cancel"),
          onPressed: (){
            Navigator.pop(context);
          },
        ),
        RaisedButton(
          child: Text("OK"),
          onPressed: (){},
        ),
      ],
    );
  }
}

基本的な操作・挙動の実装

クリックイベント

  • GestureDetector
GestureDetector(
  onTap: () {
    // doSomething
  },
  // onTap: () => _function_name()でも可

  child: ChildWidget,
)

Scaffold

  • appBar
  • drawer(left drawer)
  • endDrawer(right drawer)
  • bottomNavigationBar
  • floatingActionButton
  • persistentFotterButtons
  • bottomSheet

を簡単に実装できる.
内部の要素はchild, childrenで指定する.

new Scafffold(
  appBar: AppBar(
    title: Text("..."),
    //
  ),
  endDrawer: Drawer(
    child: new WidgetA(),
  ),
  body: new HogeWidgetB(),
  persistentFotterButtons: <Widget>[WidgetC, WidgetD,...],
  bottomNavigationBar: BottomAppBar(
    child: new WidgetE(),
  )
)

フォームから値を取得する

1. TextInputField Widgetを使う

class MyFormWidget extends StatefulWidget {
  @override 
  _ChangeFormState createState()=> _ChangeFormState();
}

class _ChangeFormState extends State<MyFormWidget> {
  String _formValue = "";

  void _handleText(String e) {
    setState((){
      _formValue = e;
    });
  }
  Widget build(BuildContext context) {
    return new TextField(
        enabled: true,
        onChanged: _handleText,
        //obscureText: bool, mask input text
        //decoration: const InputDecoration(
        //  icon: Icon(Icons.[identifier]),
        //  hintText:String, (placeholder)
        //  labelText: String, (label)
        //)
       // inputFormatters: <TextInputFormatter>[Obj,Obj,...], 入力値のバリデート

      )
    )
  }
}

2. Form Widgetを使う

TextFormFieldを参照
validator, grouping, save()処理などを提供している

https://flutter.ctrnost.com/basic/interactive/form/textfield/

ページ遷移

Navigationを使ってrouteをつかう.
といっても何のことかわかりにくい.
routeはFlutterのWidgetの一種で、andoridのActivity, iOSのViewControllerに相当するもの

例:二ページ間の遷移
push と popで行き来する場合
以下では、routeをその都度設定する方法で書いている

class FirstRoute extends StatelessWidget {
  @override 
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title: Text("First Page")),
    ),
    body: Container(
      // 省略
      child: Button(
        child:Text("navgate to the other page"),
       onPressed:(){
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => SecondRoute()
            ),
          );
       },
      ),
    ),
  }
}
class SecondRoute extends StatelessWidget {
  @override 
    Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(title: Text("Second Page")),
    ),
    body: Container(
      // 省略
      child: Button(
        child:Text("navgate to the other page"),
       onPressed:(){
          Navigator.pop(context);
          //もとのページに戻る
       },
      ),
    ),
  }

}

任意のpathに遷移する場合

まずMaterialAppにroute関連のパラメタを渡す.
注意点だが、initialRouteパラメタを渡した場合はhome プロパティは指定できない.
以下では、routeを前もって定義する方法で書いている.

MaterialApp(
  initialRoute: "/",// path to somewhere
  routes: {
    "/": (context) => onePage(),
    "/anotehr": (context) => anotherPage(),
    "/theOther": (context) => theOtherPage(),
  }
)

//いろいろ省略
onPressed: (){
  Navigator.pushhNamed(context, "/anoter")
}

変数付きroute

Navigator.push(
  context,
  MaterialPageRoute(
    settings: RouteSettings(name: "/show/<itemId>"),
    builder: (BuildContext context) => ItemDetailPage(itemId)
  ),
);

https://qiita.com/kwmt@github/items/8720e7ab21f8ac12695d

パラメータを画面遷移時に渡す

渡す側

onPressed: () => Navigator.push(
  context,
  MaterialPageRoute(
    builder: (conetxt)=> SenderPage(parameter: 1),
  ),
);

受け取る側

class ReceiverPage extends StatelessWidget {
  final int parameter;
  ReceiverPage({this.parameter});
}

基本的な処理の実装

ライブラリのインポート

import "library-name" as ailias;
import "another-library" show something;
// only import a certain one
import "another-library" hide something;
// import all BUT something 

HTTP リクエスト

ポイント

  • Future, async, await
  • cascading notation
  • JSON.encode()
import "package:flutter/http.dart" as http;
// import A as B が使える

Future<bool> signIn() async {
  var client = new http.Client();
  var req_headers = new Map()
    ..["Content-Type"] = "application/json";
// ..["Content-Type"]はcascading notation と呼ばれる記法
// var req_header = new Map();
// req_headers["Content-Type"]="application/json"と同じ
 var body = new Map()
    ..['name'] = 'John Doe'
    ..['email'] = 'info@example.com';

  var res = await client.post(
    "https://example.com/",
    headers: req_headers,
    body: JSON.encode(body) 
  );
}


ログイン処理

firebase auth

まずGoogleSignIn()のインスタンスとFirebaseAuth.instanceを用意し、_handleGoogleSignIn()メソッドを作る.

final _googleSignIn = new GoogleSignIn();
final _firebaseAuth  = FirebaseAuth.instance;

Future<FirebaseUser> _handleGoogleSignIn() async {
  GoogleSignInAccount googleUser = await _googleSignIn.signIn();
  GoogleSignInAuthentication googleAuth = await googleUser.authentication;
  FirebaseUser user = await _firebaseAuth.signInWithGoogle(
    accessToken: googleAuth.accessToken,
    idToken: googleAuth.idToken,
  );
  return user;
}

次のようにFirebaseUser_handleGoogleSignIn()を定義すする

import "package:firebase_auth/firebase_auth.dart";
import "package:google_sign_in/google_sign_in.dart";

// 現在ログインしているユーザー
FirebaseUser _currentUser;
// ログインしている場合はユーザー情報がセットされる
// ログインしていない場合はnull


_handleGoogleSignIn().then((user){
  // do something
}).catchError((error){
  // do error handling
})
// Googleアカウントでサインインを試みる. 
// errorの場合はエラーハンドリングをする.




サインイン/ログイン画面の破棄

これはof(context).pushReplacement()をつかって、現在の画面を破棄して次の画面に遷移する

Navigator.of(context).pushReplacement(
  MaterialPageRoute(
    settings: RouteSettings(name:"/welcome"),
    builder: (BuildContext context) => WelcomePage(),
  )
)

flutterとdartのわかりにくい記法

context

builder の context

flutter側が自動で受け渡すもっぱら受け取り専用のcontext
意識的に利用するタイミングは少ない

builder(BuildContext context){
 return // some Widget; 
}

@override 
Widget build(BuildContext context){
   return // some widget;
}

SomeWidget.of(context).

context は あるWidgetがWidgetツリーのなかのどこにいるのかをあらわしている.
Widget.of(context)は、contextのもつWidgetツリーの場所から先祖の階層にさかのぼって、最初に見つかるWidgetを返す.

細かい話はこの記事を見ればわかる
https://qiita.com/agajo/items/93d75aafe87bdc7b2026

foo ?? bar

Rubyのnil ガードみたいな仕組み
左辺がnullでない場合はfoo, nullの場合はbarを返す.

int x;

// 省略
// 何らかの処理でxにnullが入っている場合は, 0がyに代入されるのでnullのエラーを避けられる,

int y = x ?? 0;

メンバー変数の初期化

  • メンバー変数

起こりうるエラー

Error: Final field "hoge" is not initialized. Try to initialize the field ....

対処

class Product {
  final String name;
  final int price;
  // 上二行だけだとエラー
  Product({this.name,this.price});
  // このようにして初期化する
}

cascading notation

caascading notation = ドット二つ

List list = [];
list.add(color1);
list.add(color2);
list.add(color3);
list.add(color4);

// with cascade

List list = [];
list
  ..add(color1)
  ..add(color2)
  ..add(color3)
  ..add(color4);

listの展開

ドット三つ = リストの展開

final listA = [1, 2, 3, 4];
final listB = [...listA, 5, 6, 7, 8, 9];
// listB = [1,2,3,4,5,6,7,7,9]

python-likeなリストの生成

final indice = [0,1,2,3,4,5]
final list = [for(var i in indice) i*2,]
// [0,2,4,6,8,10]

initializer list

コンストラクタのすぐ後ろにあるコロンの用法

Named Constructorsで、コロンに続けてフィールドの初期化処理を記述できる。

class User {
  final String name; 
  final String email;
  User({this.name, this.email});
  User.doSomething()
  : this.name = "John Doe",
    this.email = "info@exaple.com";

}

https://makicamel.hatenablog.com/entry/2019/03/14/213933
https://stackoverflow.com/questions/50274605/colon-after-constructor-in-dart

ちょっとつまったこと

gradle ファイルを編集後、sync nowが表示されない(android studio)

Open for Editing in Android Studio からandorid 開発モードのandorid studio をひょうじすればいい.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Kotlin版] AppCompatActivityをシングルトンで保持してどこからでもアクセスできるようにする!(コピペOK)

ソースコード

Androidのアプリコンテキストをどこからでもアクセスしたいと思い、シングルトンなActivity拡張クラスを作成しました。

以下コピペOKなソースコードです!

import androidx.appcompat.app.AppCompatActivity

// シングルトンなContextカスタムクラス
class ContextStateful {
    // static領域
    companion object {
        // 遅延宣言
        private lateinit var instance: AppCompatActivity
        // Application#onCreateのタイミングでシングルトンが生成される
        fun onCreateApplication(applicationContext: AppCompatActivity) {
            instance = applicationContext
        }
        // シングルトンなインスタンス取得
        fun getInstance(): AppCompatActivity {
            return instance
        }
    }
}

使い方

(1) インスタンス化

■インスタンス生成

class MainActivity : AppCompatActivity() {
    // 初期表示
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // シングルトンなContextを生成
        ContextStateful.onCreateApplication(this)
    }
}

(2) 他クラスなどで使用したい場合

■インスタンス取得します

// インスタンス取得
ContextStateful.getInstance()

■インスタンス取得して、XMLから対象UIを取得します

// インスタンス取得して、XMLから対象UIを取得
ContextStateful.getInstance().findViewById(R.id.textView)

このような記載をすれば、どのクラスからでもアクセスできます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む