- 投稿日:2019-08-28T22:39:40+09:00
【ドメイン取得不要】無料でAdMobのapp-ads.txtに対応してみた
はじめに
ちゃんとしたドメインのアプリのLPやウェブサイトを持ってる人には縁のない記事です?♂️
そんなものを持っていない私が、この度Firebase Hostingを利用してお金をかけずにapp-ads.txtの設置に成功したので備忘録として残しておきます?「そもそもapp-ads.txtってなんやねん」という人はこの記事がわかりやすかったです。
AdMobから「AdMob使ってるならapp-ads.txt置いてね」というメールが届きました。
ファイルは、掲載している Google Play ストア(Android)または App Store(iOS)のウェブサイトのルートディレクトリに公開する必要があります。 詳細については、IAB による app-ads.txt の仕様を参照してください。メールをよく読んでみると、どうやらアプリストアに登録しているウェブサイトのルートディレクトリに設置する必要があるようです。
また、よくハマりがちですがヘルプを読むとサブドメインに置くのはNGのようです⚠️本記事が想定している読者は下記に当てはまるような方々です。
△ そもそもストアにウェブサイトを登録していなかった(今回外部サイトでもいいので準備する必要があります?)
○ アプリのLPが無いため、ストアに登録していたウェブサイトが外部サービスだった?
○ やるべきことは分かったが、app-ads.txtのためだけにドメインにお金を払いたくない?私自身も個人でいくつかアプリを提供していますが
- ストアに登録しているウェブサイトはTwitterだった
- ドメインを持っているがブログで利用中(ルートディレクトリにファイルを置けない)
というような状態でした。
手順
Firebaseコンソール上での作業
Hostingの利用開始
Firebaseプロジェクト未作成の場合は最初にプロジェクトを作成する必要があります。
プロジェクトの[Hosting]を開いて[始める]を押すと、このようにドメインが2つ発行されます。
ランダムな文字列でかっこ悪いのが玉に瑕ですが無料なので目を瞑ってどちらかを使っていきましょう。ローカルでの作業
Firebase Hostingの初期化とセットアップ
Firebaseを初めて利用する場合にはFirebase CLIのインストールが必要です。
詳細な方法としては公式ドキュメントを見てください。# 初回のみ必要(ログイン済みの状態でログインしても問題ないです!) $ firebase login # 適当なディレクトリを作る $ mkdir hoge && cd hoge # プロジェクトの初期化をする $ firebase init # このときHostingだけ選択する ? Which Firebase CLI features do you want to set up for this folder? Press Space to select features, then Enter to confirm your choices. ◯ Database: Deploy Firebase Realtime Database Rules ◯ Firestore: Deploy rules and create indexes for Firestore ◯ Functions: Configure and deploy Cloud Functions ❯◉ Hosting: Configure and deploy Firebase Hosting sites ◯ Storage: Deploy Cloud Storage security rules # 準備したプロジェクトを選択する ? Select a default Firebase project for this directory: [don\'t setup a default project] # 何も入力せずにEnterを押せばOK ? What do you want to use as your public directory? (public) # 何も入力せずEnterを押す(No扱いっぽい) ? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) : (中略) : ✔ Firebase initialization complete!app-ads.txtの設置
AdMobコンソールの[すべてのアプリ]→[APP-ADS.TXT]タブを開き、右端にある[APP-ADS.TXTの設定方法]を押すとこのような画面が表示されます。
2のコードスニペットをコピーしてそのまま利用します。# コードスニペットを書き込んだapp-ads.txtを生成する $ echo "コピーしたコードスニペット" > public/app-ads.txt登録するウェブサイトの設置
このタイミングでLPを作りたい人はそれをそのままpublic/index.htmlとして置き換えましょう。
これが今回の肝なのですが、私のようにapp-ads.txt設置前と変わらず外部サイトを掲載したい場合は、下記のようなindex.htmlを用いてリダイレクトさせます?
index.html<!DOCTYPE html> <html> <head> <meta http-equiv="refresh" content="1;URL=登録したいウェブサイトのURL(外部サイト可)"> </head> </html>deployする
# public配下がこのようになっていることを確認する $ ls public/ 404.html app-ads.txt index.html # deployする $ firebase deployDeployに成功したら
Firebase Hostingに発行されたドメイン/index.htmlにアクセスし、自分の設定したindex.htmlが置かれていることを確認します。
(外部サイトへリダイレクト設定した場合には1秒程度でリダイレクトがかかるはずです。)
また、Firebase Hostingに発行されたドメイン/app-ads.txtにアクセスできることも確認しておきます。各種アプリストアのコンソール上での作業
ウェブサイトURLの登録
各OSのアプリストアのコンソールからアプリのウェブサイトが登録できるのでそこに一つ前の手順で確認した
Firebase Hostingに発行されたドメイン/index.htmlを入力します。
このときアプリのウェブサイトでなくデベロッパーのウェブサイトと間違えやすいですが、そうするとAdMobのクローラーに見つけてもらえなくなるので注意が必要です⚠️反映を待つ
これで必要な作業はすべて終了です、あとは待つだけです!
正常に設置できるとこのような表示になりますが、緑のランプが点灯するまで予想以上に時間がかかりますので気長に待ちましょう?
私の場合はちゃんと設置できているのに1日経過後にグレーのランプになり、最終的に3~4日くらい経ってから緑になりました。おわりに
最初は「app-ads.txtのためにドメイン取るんか…正直面倒だし勿体ないな」と思っていましたが、このようにすれば無料でも対応可能でした、Firebase万歳ですね?
リダイレクトのさせ方は諸説あると思いますがウェブは全然分からないのでとりあえず目についた方法で対応しています、詳しい方は是非コメント欄にて優しくご指摘いただけますと幸いです?♂️
- 投稿日:2019-08-28T20:45:16+09:00
[Maps SDK] 地図にMarkerを置く(その2・Utility Library編)
前に書いた記事で、Maps SDK for Android で表示した地図に配置する Marker について書きました。基本機能だけでも色々できますが、Google Maps Android API Utility Library を導入すると更にできることが広がります。
ここでは Utility Library の導入と使用法についてまとめてみました。
- 基本機能だけでできること(前の記事)
- Utility Library を使ってできること(この記事)
この記事でやること
- Utility Library の導入
- Marker をクラスタにまとめる
- クラスタ化した Marker をカスタマイズする
- Icon Generator を使って地図に地名を表示する
注意事項
Android Studio で Maps SDK for Android が使えることを前提にしています。そのための手順は以前まとめましたので、そちらご確認下さい。
環境
このページに書かれているコード等は以下の環境下で動作・検証しています。
macOS Mojave バージョン10.14.6
Android Studio 3.5
Pixel3a + Android 9また、ここに書いた内容をもとにしたサンプルコードを GitHub で公開しています。
Utility Library の導入
モジュールの build.gradle に以下の dependencies を追加します。
dependencies { compile 'com.google.maps.android:android-maps-utils:0.5+' }Marker をクラスタにまとめる
地図のズームレベルが下がって複数の Marker が一箇所に集まったとき、「クラスタ」にまとまるようにすることができます。
下の図だと、左が全ての Marker がバラバラに表示されている状態、右がクラスタになって表示されている状態です。以下の手順で実装することができます。
- ClusterItem を実装したクラスを作成
- ClusterManager オブジェクトを生成
- ClusterItem を ClusterManager に追加
ClusterItem を実装したクラスを作成
Marker ひとつひとつに相当するクラスです。 com.google.maps.android.clustering.ClusterItem を実装して、必要なメソッドを定義すればOKです。
getSnippet / getTitle / getPosition では、それぞれ Marker の snippet / titie / position に相当するものを返すようにします。以下は実装例です。class SegmentClusterItem(val segment: Segment) : ClusterItem { override fun getSnippet(): String = segment.flowerName override fun getTitle(): String = segment.title override fun getPosition(): LatLng = segment.coordinate }ClusterManager オブジェクトを生成
com.google.maps.android.clustering.ClusterManager クラスをインスタンス化します。
このとき GoogleMap の以下のメソッドに ClusterManager インスタンスを設定するようにします。
- setOnCameraIdleListener
- setOnMarkerClickListener
以下は ClusterManager をインスタンス化しているところです。
val manager = ClusterManager<SegmentClusterItem>(this@ClusteringActivity, this).apply { setOnCameraIdleListener(this) setOnMarkerClickListener(this) }ClusterItem を ClusterManager に追加
あとは ClusterManager#addItem で ClusterManager に ClusterItem を追加していくだけです。これで Marker がある程度まで接近するとクラスタにまとまるようになります。
Segment.values().forEach { manager.addItem(SegmentClusterItem(it)) }クラスタにならない場合
上記の実装をしても Marker がクラスタにまとまらない場合は、Marker の数が少ないことが考えられます。
Marker がクラスタにまとまるかどうかは、一定の領域内に含まれる Marker(=ClusterItem)の数で判定されます。デフォルトでは、5個以上の Marker が領域内に含まれないとクラスタになってくれません。これを変更するには、クラスタにする Marker の数を定義した ClusterRenderer オブジェクトを ClusterManager#setRenderer にセットする必要があります。以下は、DefaultClusterRenderer を継承した ClusterRenderer クラスの実装例です。shouldRenderAsCluster で「何個以上の Marker が集まったらクラスタにするか」を判定します。この例では、2つ以上でクラスタになるようにしています。
class SegmentClusterRenderer(context: Context, map: GoogleMap, manager: ClusterManager<SegmentClusterItem>) : DefaultClusterRenderer<SegmentClusterItem>(context, map, manager) { override fun shouldRenderAsCluster(cluster: Cluster<SegmentClusterItem>?): Boolean { // ClusterItemが一定距離内にいくつ集まったらクラスタ化するかをBooleanで返す return cluster?.size ?: 0 >= 2 } }以下でこの Renderer を Manager にセットしています。
manager.renderer = SegmentClusterRenderer(this@ClusteringActivity, map, manager)クラスタ化した Marker をカスタマイズする
ClusterRenderer と IconGenerator を併用することで、Marker のアイコンやクラスタのアイコンを変更することができます。
下の図は、大阪市の各区役所に Marker を立てて、区の花をアイコンで表示しています。クラスタになると、そこに含まれる Marker の数が女性のイラストに表示されるようにしています。
![]()
ClusterRenderer で継承すべきメソッドは以下の通りです。
両方とも実装すべき処理は同じで、Marker やクラスタが描画されるときの MarkerOptions を変更することになります。
メソッド 実装内容 onBeforeClusterItemRendered Marker(=ClusterItem) のカスタマイズ onBeforeClusterRendered クラスタのカスタマイズ また com.google.maps.android.ui.IconGenerator を使えば任意のレイアウトで Bitmap を生成することが可能です。生成した Bitmap を、BitmapDescriptorFactory#fromBitmap を使って MarkerOptions#icon にセットすることで、Marker やクラスタのアイコンを任意に変更しています。
以下は DefaultClusterRenderer を継承した ClusterRenderer の例で、 res/layout/icon_segment.xml のレイアウトを使って Marker にアイコンを設定しています。icon_segment.xml には imageIcon というIDが付与された ImageView だけが配置されています。private val itemImageView: ImageView private val itemIconGenerator: IconGenerator = IconGenerator(context).apply { val iconView = LayoutInflater.from(context).inflate(R.layout.icon_segment, null, false).apply { itemImageView = findViewById(R.id.imageIcon) } setContentView(iconView) } override fun onBeforeClusterItemRendered(item: SegmentClusterItem, markerOptions: MarkerOptions) { itemImageView.setImageResource(item.segment.imageResId) val icon = itemIconGenerator.makeIcon() markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)) }ざっくり以下のような手順です。
- レイアウトから View をインフレート
- インフレートした View から、操作したい View を findViewById で取得
- IconGenerator#setContentView で、1の View をセット
- 2に任意の文字や画像をセット
- IconGenerator#makeIcon で Bitmap を生成
- MarkerOptions#icon に生成した Bitmap をセット
Icon Generator を使って地図に地名を表示する
地図上に地名などを表示したいという要件もあると思いますが、Marker に title や snippet をセットするだけでは Info Window のコンテンツとしてしか表示できません。
なのでここでは IconGenerator を使って、マーカーとして地名を強引に表示してみました。
IconGenerator で文字画像を作成するのは、前項と同じやり方で可能です。TextView を含んだレイアウト(もしくは TextView そのもの)を IconGenerator のコンテンツとして設定し、任意の文字列を TextView にセットしてから IconGenerator#makeIcon するという手順になります。
これで Bitmap ができますので、あとは Marker を生成して icon にセットするということになります。val textView: TextView val iconGenerator = IconGenerator(this@CustomIconActivity).apply { setBackground(null) // nullにしないとデフォルトの背景が表示されてしまう(文字だけにならない) textView = layoutInflater.inflate(R.layout.icon_station_name, null, false) as TextView setContentView(textView) } textView.text = station.title addMarker(MarkerOptions() .icon(BitmapDescriptorFactory.fromBitmap(iconGenerator.makeIcon())) .position(station.position) .anchor(0.5f, 0.0f) .zIndex(2.1f))まとめ
以上、Utility Library を使った Marker のカスタマイズについてまとめてみました。
Utility Library には KML を扱ったりヒートマップを追加したりと、他にも多彩な機能が用意されています。
「参考」に公式ドキュメントへのリンクを貼っておきましたので、実際に読んで色々触ってみるのをお勧めします。この記事がそのきっかけになれば、大変嬉しく思います。参考
Google Maps Android API Utility Library
googlemaps/android-maps-utils (GitHub)
- 投稿日:2019-08-28T19:53:57+09:00
Github Actions (v2) でDanger + ktlintを実行させる
はじめに
自分の環境でもようやくGithub ActionsのBetaが来たのでさっそく触ってみました。
Dangerを利用してプルリクエスト時に自動コードチェック出来るようにしていきます。Github Actionsの設定ファイル
いきなり本題ですがGithub Actionsのymlファイルです。
Danger自体の設定とktlint自体の設定は今回省略するので、知りたい方はそれぞれ左記のリンクを参照してください。.github/workflows/ktlint.ymlname: CI on: pull_request: branches: - master jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Setup ruby uses: actions/setup-ruby@v1 with: ruby-version: '2.6' architecture: 'x64' - name: install danger run: | gem install bundler bundle install - name: run ktlintCheck run: ./gradlew ktlintCheck - name: run danger env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: dangerそれでは設定ファイルの内容を順番に説明していきます。
まず、onにpull_requestを指定することでターゲットブランチがmasterのプルリクエストを作成することでCIが走るようになっています。on: pull_request: # ここをpushにするとpush時にCIが走る branches: - master続いて
runs-onでコンテナのイメージを選択できます。現時点では下記の表のVirtual environmentにあるようにWindows、Ubuntu、macOSと選択できます。jobs: build: runs-on: ubuntu-latest最後に
stepsです。処理の塊をActionと呼び、Actionはusesに設定することが出来ます。既に用意されているActionの一覧はこちらを参照してください。steps: - uses: actions/checkout@v1 # git checkoutしてくれるAction。 - name: Setup ruby uses: actions/setup-ruby@v1 # ruby設定用のAction with: ruby-version: '2.6' architecture: 'x64' - name: install danger # dangerはrunでスクリプトを記述する run: | gem install bundler bundle install - name: run ktlintCheck # ktlintCheckを実行させる run: ./gradlew ktlintCheck - name: run danger env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # GITHUB_TOKENがデフォで発行されるのでそれをdangerで利用する。 # 環境変数についての詳しい話は↓参照 # https://help.github.com/en/articles/virtual-environments-for-github-actions run: danger # dangerはgithub actionsに対応しているため実行するだけでOK!なんと、、たったこれだけでプルリクで自動コードチェックが走りました。
自前でのGithubトークンの発行やbotアカウントの用意も不要です!非常に便利!
コードはこちらに置いてあるので参考にどうぞ。
- 投稿日:2019-08-28T16:05:24+09:00
Activityのライフサイクルについて確認、ついでにアプリ作った
Activityのライフサイクルとは
Androidでなんか作ろうとするときにぶつかる1stステージの反り立つ壁(大げさ)
ここで時間をかけたり、開発をリタイアしないように頑張る。ライフサイクルって?
詳しいことは下記の公式リファレンスや先人が書いた有用な記事を読んでみよう。
Activity Lifecycle
アクティビティ
Activity のライフサイクル再確認実際に確認してみる
これがやりたかった。
アプリを作り、アプリを動かして確認してみた。
onCreate()、onResume()などが呼び出されるタイミングで音を鳴らして確認してみる。アプリ起動
にぎやか pic.twitter.com/U38NHcN86d
— PP!! (@PP_punp) August 28, 2019聞き取れなくもないが、やっぱ聞き取れない
方針変更
音を鳴らすのではなく、画面にテキストを表示する方針に変更した
できたものがこれ
できたもの pic.twitter.com/hPG2u2s50m
— PP!! (@PP_punp) August 28, 2019せっかく作ったからアプリを公開
Activityろがー
画面回転させたり、マルチウィンドウ機能使ったりして遊んでみてください。
やってることは該当するメソッドが呼び出されたときテキスト表示、onDestroy()のときは音声出力。おわり\(^o^)/
蛇足
ライフサイクルという言葉の意味について調べてると
”誕生から死にいたる人の一生。人生の周期”
とあった。こう書かれるとユーザーの操作によって簡単に破棄されたりするアクチビチーに変に感情移入してしまった。。がその5秒後には擬人化して、かわいいボイスで「私はたぶん3人目だと思うから...」とか「メモリから圧迫されます!!」とか言わせたら面白そうとか全く別のことを考えてた。
- 投稿日:2019-08-28T16:05:24+09:00
Activityのライフサイクルについて確認。ついでにアプリ作った
ライフサイクルとは
誕生から死にいたる人の一生。人生の周期。
Activityのライフサイクルって?
詳しいことは下記の公式ドキュメントや先人が書いた有用な記事を読んでみよう。
Activity Lifecycle
アクティビティ
Activity のライフサイクル再確認実際に確認してみる
これがやりたかった。
アプリを作り、アプリを動かして確認してみた。
onCreate()、onResume()などが呼び出されるタイミングで音を鳴らして確認してみる。アプリ起動
にぎやか pic.twitter.com/U38NHcN86d
— PP!! (@PP_punp) August 28, 2019聞き取れなくもないが、やっぱ聞き取れない
方針変更
音を鳴らすのではなく、画面にテキストを表示する方針に変更した
できたものがこれ
できたもの pic.twitter.com/hPG2u2s50m
— PP!! (@PP_punp) August 28, 2019せっかく作ったからアプリを公開
Activityろがー
画面回転させたり、マルチウィンドウ機能使ったりして遊んでみてください。
これするとおわり\(^o^)/
- 投稿日:2019-08-28T16:05:24+09:00
Activityのライフサイクルについて確認するアプリ作った
ライフサイクルとは
誕生から死にいたる人の一生。人生の周期。
Activityのライフサイクルって?
詳しいことは下記の公式ドキュメントや先人が書いた有用な記事を読んでみよう。
Activity Lifecycle
アクティビティ
Activity のライフサイクル再確認実際に確認してみる
これがやりたかった。
アプリを作り、それを動かしてonCreate()、onResume()などが呼び出されるタイミングで音を鳴らして
アプリを起動してから、ユーザーの操作に応じて呼び出されるメソッドを確認してみる。アプリ起動
にぎやか pic.twitter.com/U38NHcN86d
— PP!! (@PP_punp) August 28, 2019聞き取れなくもないが、やっぱ聞き取れない
方針変更
音を鳴らすのではなく、画面にテキストを表示する方針に変更した
できたものがこれ
できたもの pic.twitter.com/hPG2u2s50m
— PP!! (@PP_punp) August 28, 2019せっかく作ったからアプリを公開
Activityろがー
画面回転させたり、マルチウィンドウ機能使ったりして遊んでみてください。おわり\(^o^)/
- 投稿日:2019-08-28T10:30:51+09:00
【ReactNative】native_modules.gradle line 191でハマった話
概要
新任者の端末内に研修用の簡単なReactNativeのプロジェクトを作った時にハマった話。
発生経緯
デスクトップに「新任研修」というフォルダを作り、既に他端末で動作確認済みのReactNativeプロジェクトをまるっとコピー。
念のため動作確認のためrun-androidさせてみるreact-native run-androidすると下記のエラーが発生
/Users/lukaskurucz/Git/app-name/node_modules/@react-native-community/cli-platform-android/native_modules.gradle' line: 191なんじゃこりゃ。native_modules.gradleなんて見たこともないモジュールがエラーを吐いている。
ゴミが残ってるのかもと、一度クリーンしてみる。
cd android && gradlew cleanが、そもそもcleanが同じエラーで通らない。
原因
仕方がないのでnative_modules.gradleとやらを見てみることにする。
どうやら下記の行あたりでエラーが出ているようだ。native_modules.gradledef json = new JsonSlurper().parseText(reactNativeConfigOutput) this.packageName = json["project"]["android"]["packageName"]これだけ見ていても訳が分からないので、とりあえずJSONにパースする前のreactNativeConfigOutputをログに吐かせてみる。
native_modules.gradle// reactNativeConfigOutputをログに書き出し this.logger.info(reactNativeConfigOutput) def json = new JsonSlurper().parseText(reactNativeConfigOutput) this.packageName = json["project"]["android"]["packageName"]するとreactNativeConfigOutputが見事に文字化けしているではないか!!
しかも化けているのはプロジェクトのパス部分。あ、そういえばさっき・・・
デスクトップに「新任研修」というフォルダを作り...
絶対それが原因だ!!
と思い、試しに「新任研修」を「work」にリネームしてみると問題なく動作するようになった。パスに日本語を含めるという初歩的なミスでしたとさ。
- 投稿日:2019-08-28T10:02:04+09:00
THETA で OpenCV を使って色検知してみた
Maker Faire Tokyo 2019 に THETA プラグインのネタで参加
こんにちは。リコーの@ueue です。
8 月 3(土)4(日)に東京ビッグサイトで行われた Maker Faire Tokyo(MFT)に THETA プラグインネタで参加しました。
僕は、「だるまさんがころんだ」というネタを持ち込みました。
この記事では「だるまさんがころんだ」の中身について説明します。
メインは OpenCV による特定の色の動き検知になります。ちなみに他に MFT に持ち込んだネタは以下に詳細な記事があります。
THETA V、THETA Z1 は OS に Android を採用していて、本体内部で Android アプリを動かすことができます。
THETA 本体にインストールできる Android アプリのことを THETA プラグインと呼んでいて、開発したプラグインは公式プラグインストアにて配布することができます。インスタントカメラもライントレーサーも、そしてこのだるまさんがころんだもすべて THETA プラグインでつくられています。
これらのコードはGithub で公開されており、
今回の「だるまさんがころんだ」プラグインもこちらで公開しています。THETA で「だるまさんがころんだ」とは?
普通のだるまさんがころんだは鬼が「だるまさんがころんだ」といい終わったタイミングでふりかえり、
鬼が見ている間は参加者は動いてはいけません。参加者は「だるまさんがころんだ」と言っている間に
ちょっとずつ鬼に近づいて鬼にタッチできたら勝ちというゲームです。ただ、人通りが多い MFT の会場内で特定の人の動きを検知するのは至難の業です。
なので、今回は「赤、青、緑の大きなかたまり」が動いたことを検知することにしました。
MFT 当日はブースの位置や大きさなどを加味し、青と緑 2 色の大きな風船(直径 90㎝)を参加者に持ってもらい、風船が動いたことを検知するデモンストレーションにしました。また、「近づいてタッチ」を THETA で検知するのはむずかしいので
かわりに「だるまさんがころんだ → 一定時間動き検知」を 3 回繰り返して、どの色もうごかなかったら
鬼の負け(参加者の勝ち)というルールにしました。もう一つ普通のだるまさんがころんだと違う点は、鬼が 360 度カメラである点です。
すなわち、THETA を中心にして 360 度のどこにいても検知することができます。
僕はプラグインを利用することで、THETA を 360 度カメラから 360 度画像認識装置に進化させられると
思っていて、このだるまさんがころんだプラグインはその第一弾です。話を戻して、だるまさんがころんだプラグインの動作を整理すると以下のような流れとなります。
- だるまさんがころんだプラグインを起動
- シャッターボタンを押下
- 「だるまさんがころんだ」という音声ファイルがながれる(音声ファイルは 4 種類の中からランダムに起動)
- 一定期間、赤、青、緑のかたまりの動きを検知
- 動きを検知したら「**色が動いた」という音声ファイルを流して終了 動きがない場合は 3 に戻る。
- 3 から 5 を 3 回繰り返し、どの色も動かない場合は「みんなのかち」という音声ファイルを流して終了。
上記に加えて、THETA が見ている特定色のフィルター結果画像を Vysor を通して見る仕組みも実装しています。
Wi-Fi ボタンをおすことで、
順に緑フィルター結果、青フィルター結果、赤フィルター結果、フィルターなしの画像をみることができます。
これは色抽出のしきい値をきめるところで利用します。詳細は後述します。全体構成
処理は大きく 2 つの部分にわかれており、それぞれ別スレッドで動作します。
一つは OpenCV を使った画像処理部分です。
カメラが撮影したフレームごとに色抽出し、重心位置の計算を行います。もう一つは鬼の処理です。
鬼は上記の重心位置を必要なタイミングで取り出して、動き(位置の変化量)を計算します。この 2 つのスレッドで各色の重心位置の情報を共有します。
画像処理
まずは OpenCV による画像処理部分を説明します。
ここは以下の記事をベースに作っています。
THETA の中で OpenCV を動かす【プレビューフレーム応用編】コードはGithubから
もってきました。これをベースにすれば OpenCV がすぐ動きます。ここの処理は MainActivity の onCameraFrame 内で処理しています。
コードはこちらになります。大まかな流れは以下になります。
- 画像処理 1. RGB 情報のフレームを取得
- 画像処理 2. フレームをリサイズ
- 画像処理 3. RGB から HSV に変換
- 画像処理 4. 各色を抽出
- 画像処理 5. 抽出した対象物の中から最大のものの重心のポジションを計算
画像処理のために OpenCV のImgproc クラスのメソッドを使います。
Imagproc クラスのメソッドでフレームに相当する Mat オブジェクトを順に変換していく、という流れになります。画像処理 1. RGB 情報のフレームを取得
対応するのは以下の部分です。
この Mat オブジェクト frameOrg が一つのフレームの情報に対応しています。
この時点では色情報は RGB で持っています。// RGBのフレーム Mat frameOrg = inputFrame.rgba();以下で、この frameOrg に対して処理を施して
新しい Mat オブジェクトを取得する、という流れになっています。画像処理 2. フレームをリサイズ
それなりの大きさの色の塊を抽出するのに大きな画像である必要はないので
リサイズして小さくします。
これで必要なメモリ量や CPU パワーを軽減させることが狙いです。対応するコードは以下の部分です。
//リサイズ Mat frameMini = frameOrg.clone(); Imgproc.resize(frameOrg, frameMini, new Size(160, 80), 0, 0, Imgproc.INTER_LINEAR);Imgproc.resize メソッドを使います。
リサイズされた結果として frameMini オブジェクトができます。画像処理 3. RGB から HSV に変換
色情報を RGB から HSV に変換します。
HSV は色を色相(Hue)、彩度(Saturation)、明度(Value)の 3 値で表現するカラーモデルです。
Imgproc.cvtColor メソッドを使います。
第三引数の指定で変換方法をコントロールできます。frameMini オブジェクトが HSV 情報を持ったオブジェクトとして上書きされます。// HSVに変換 Imgproc.cvtColor(frameMini.clone(), frameMini, Imgproc.COLOR_RGB2HSV);画像処理 4. 色を抽出
OnCameraFrame メソッドでは以下に対応します。
// 色を抽出 final Scalar GreenMin = new Scalar(50,50,10); final Scalar GreenMax = new Scalar(90,255,255); final Scalar BlueMin = new Scalar(100, 100, 10); final Scalar BlueMax = new Scalar(130, 255, 255); final Scalar RedMin = new Scalar(0, 100, 30); final Scalar RedMax = new Scalar(5, 255, 255); final Mat frameGreen = getColorFrame(frameMini, GreenMin, GreenMax); final Mat frameBlue = getColorFrame(frameMini, BlueMin, BlueMax); final Mat frameRed = getColorFrame(frameMini, RedMin,RedMax);Scalar オブジェクトが色の範囲を決めています。
例えば緑の範囲を以下のように決めています。final Scalar GreenMin = new Scalar(50,50,10); final Scalar GreenMax = new Scalar(90,255,255);Scalar の引数が順に HSV の値です。
すなわち色相、彩度、明度が 50、50、10 から 90、255、255 の間に含まれるものを緑と定義しています。
この値が色抽出のインプットになります。
この数値の決め方は後述します。getColorFrame メソッドで色の抽出とノイズ除去を行っています。
private Mat getColorFrame(Mat frame, Scalar min, Scalar max) { Mat frameColor = frame.clone(); // color抽出 Core.inRange(frameColor.clone(), min, max, frameColor); Imgproc.threshold(frameColor.clone(), frameColor, 100, 255, THRESH_BINARY); //noize除去 Imgproc.morphologyEx(frameColor.clone(), frameColor, Imgproc.MORPH_OPEN, mStructuringElement); return frameColor; }Core.inRange で色の抽出をおこなっています。第 4 引数が変換後の画像です。
このあとはImgproc.thresholdで 2 値化したのち、Imgproc.morphologyでモルフォロジー変換によりノイズを除去します。
モルフォロジー変換についてはこちらのサイトを参照ください。画像処理 5. 抽出した対象物の中から最大のものの重心のポジションを計算
この処理は getMaxContourPosition メソッドで行っています。
// 最大の輪郭の中心位置を取得 int[] positionGreen = getMaxContourPosition(frameGreen);getMaxContourPosition は以下のとおりです。
Imgproc.findContoursメソッドで
画像の輪郭を抽出します。今回、一番困ったのはここです。
さきほど、ノイズ除去をおこないましたが、例えば、赤い服を着た人が近くを通ったら、それは
物体として検出してしまいます。findContors の結果にはすべての物体の輪郭が含まれるため、
結果に複数の輪郭が含まれる場合、どうやって風船のものだけを抽出するのかというところが問題です。結論としては「輪郭の面積が最大値のものを抽出する」という方法を採用しました。
- THETA は超広角レンズのため、距離が離れると急激に被写体の画像が小さくなる。
- MFT の会場では風船を持った人が THETA から、それほど離れることはできない。
- 今回の風船はかなり大きい(直径 90cm くらい)
- 風船より前方に、同じ色の物体が入る可能性は低い
- 風船より後方で、直径 90cm よりも更に大きい物体が入る可能性は低い
つまり、かなり状況依存な抽出法になっています。
private int[] getMaxContourPosition(Mat frame) { List<MatOfPoint> contours = new ArrayList<>(); Imgproc.findContours(frame, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE); double maxArea = 0; MatOfPoint maxContour = new MatOfPoint(); for (MatOfPoint contour : contours) { double area = Imgproc.contourArea(contour); if (maxArea < area) { maxArea = area; maxContour = contour; } } Moments p = Imgproc.moments(maxContour); int[] position = new int[2]; position[0] = (int) (p.get_m10() / p.get_m00()); position[1] = (int) (p.get_m01() / p.get_m00()); return position; }こうやって計算した値をメンバ変数である positionNowGreen、positionNowBlue、positionNowRed にいれます。
synchronized (lockGreen) { positionNowGreen = positionGreen; }positonNow は別スレッドの Oni クラスで読み込むために syncronized を使っています。
色範囲の決め方
色抽出処理のところで決めた色範囲の決め方について説明します。
final Scalar GreenMin = new Scalar(50,50,10); final Scalar GreenMax = new Scalar(90,255,255);この値の決め方について。今回は以下のようにしました。
こういうサイトなどで
まずは RGB と HSV 変換サイトで、HSV の値の当たりをつけます。
あとは、対象の風船を THETA の近くにおいて、
その領域をうまく区切れているか、他の物体ははいっていないかというのを
画像を見ながら、ひたすら試行錯誤します。画面を見るためには Vysor を使います。
下の画面は緑を抽出した画面です。THETA の前においている緑のボールを検知していることが
わかります。あと、ディスプレイの下にちょこっと写っている緑の風船も検知しています。この画面をみながら、Scalar の引数の HSV 値を最適化していきます。
ちなみに、Wi-Fi ボタンを押すことで、緑、青、赤、フィルターなしの画像が表示されます。
そのように切り替える仕組みは OnCameraFrame メソッドの最後にあります// Vysorを使って、色抽出した画面をチェックする // Wi-Fiボタンで表示切り替え switch (showFrameNumber % 4) { case 0: Imgproc.resize(frameGreen.clone(), frameOrg, new Size(640, 320), 0, 0, Imgproc.INTER_LINEAR); break; case 1: Imgproc.resize(frameBlue.clone(), frameOrg, new Size(640, 320), 0, 0, Imgproc.INTER_LINEAR); break; case 2: Imgproc.resize(frameRed.clone(), frameOrg, new Size(640, 320), 0, 0, Imgproc.INTER_LINEAR); break; case 3: //do nothing. return original frame } return frameOrg;Wi-Fi ボタンを押すと showFrameNumber の値がインクリメントされます。
その数に対応した色の Frame サイズをもとに戻して return しています。なお、Wi-Fi ボタンの押下の処理は OnCreate の OnKeyDown の中で行っています。
setKeyCallback(new KeyCallback() { @Override public void onKeyDown(int keyCode, KeyEvent keyEvent) { if (keyCode == KeyReceiver.KEYCODE_CAMERA) { if (!oniAlive) { Oni oni = new Oni(); oni.start(); } } if (keyCode == KeyReceiver.KEYCODE_WLAN_ON_OFF) { showFrameNumber += 1; } }ちなみに、同じ onKeyDown の中でシャッターボタンを押すと Oni クラスの処理が走るように設定されています。
鬼クラス
Oni クラスがだるまさんがころんだの処理のメインです。
ここは以下の処理をしているだけなのでソースを見てもらえればわかると思います。
- シャッターボタンが押されたら処理をスタート
- 4 種類の「だるまさんがころんだ」音声ファイルからランダムに一つを選択して、流す。
- 音声ファイル終了直後の各色の位置を記録
- 動きを検知するフレームの枚数を 6 から 16 の幅でランダムに決定
- 500msec まって、そのタイミングの位置を検知
- 4 と 5 の距離を算出して、しきい値と比較 7-1. しきい値を超えていれば「**色がうごいた」音声ファイルを流して終了 7-2. しきい値を超えていなければ 2-6 を 3 回繰り返す
- 3 回繰り返して、どの色の動きも検知しなかった場合、「みんなの勝ち」音声ファイルをながして終了
Oni クラスの全体はこちらです
2 つだけポイントを説明します。
まず、1 つ目のポイント。
シャッターが連続で押された場合、2 回目以降を無視するための仕組みとして
run メソッドの最初に oniAlive というフラグを設定しています。
これは run メソッドが起動中であることを別のスレッドに伝えるためです。oniAlive = true;oniAlive をチェックしているのはシャッターボタンがおされたタイミングです。
oniAlive が false のときのみ run メソッドが起動されます。public void onKeyDown(int keyCode, KeyEvent keyEvent) { if (keyCode == KeyReceiver.KEYCODE_CAMERA) { if (!oniAlive) { Oni oni = new Oni(); oni.start(); } }もう一つのポイントは positionNowGreen、positionNowBlue、positionNowRed の読み込みです。
OpenCV のスレッドで値が入力されているため、その値を読み込むときには syncronized を使っています。synchronized (lockGreen) { positionInitGreen = positionNowGreen; }まとめ
OpenCV の色検知を利用した「だるまさんがころんだ」プラグインの中身を説明しました。
RICOH THETA プラグインパートナープログラムについて
THETA プラグインに興味を持たれた方がいれば、以下の記事もぜひご覧ください。
RICOH THETA プラグイン開発者コミュニティでは、他にも記事を書いています。
RICOH THETA プラグインについてはこちらに情報がまとまっています。興味を持たれた方はtwitterのフォローとTHETA プラグイン開発コミュニティ(slack)への参加もぜひどうぞ。
- 投稿日:2019-08-28T08:46:58+09:00
Flutterウィークリー #72
Flutterウィークリーとは?
FlutterファンによるFlutterファンのためのニュースレター
https://flutterweekly.net/この記事は#72の日本語訳です
https://mailchi.mp/flutterweekly/flutter-weekly-72※Google翻訳を使って自動翻訳を行っています。翻訳に問題がある箇所を発見しましたら編集リクエストを送っていただければ幸いです。
読み物&チュートリアル
Flutterオンライン調査ソフトウェア
https://google.qualtrics.com/jfe/form/SV_3kiGXYfYOfXUjB3?Source=Twitter&linkId=71914718
Flutterチームが簡単なアンケートに回答して製品を改善できるように支援する
60 Days Of Flutter : Flutterからのメッセンジャーの構築
https://medium.com/@adityadroid/60-days-of-flutter-building-a-messenger-from-scratch-ab2c89e1fd0f
Aditya Gurjarは60日間、完全なFlutterアプリを開発し、プロセスを文書化します。最初の記事はすでに作成されています。FlutterとCloudinaryを使用して写真日記アプリを作成する9つの最も簡単な手順
Promise Nzubechi Amadiによるこの記事に従って、写真ダイアリーアプリを段階的に作成してください。Flutter CLI:52の非表示サンプル
https://medium.com/flutter-community/flutter-cli-52-hidden-samples-fc90f218a9d0
Nitish Kumar Singhは、 Flutter CLIツールで52の非表示のサンプルプロジェクトを示しています。Flutterウィジェットのbuild()メソッドが「すべてがウィジェット」であることを証明する方法
Bui Minh Trietは、Containerウィジェットの構築方法の分析を使用して、テーブルの下でウィジェットがどのように機能するかを学習します。Flutter依存性注入
https://medium.com/flutter-community/dependency-injection-in-flutter-f19fb66a0740
Flutterアプリに依存性注入を実装する方法に関するZubair Rehmanによる優れた記事思考のFlutter
https://medium.com/flutter-community/thinking-flutter-22f38961f9ba
Pratik Jainは、いくつかの例を使用して新しいウィジェットの設計に取り組む前に、どのように考えるかを分析します。ビデオ&メディア
カスタムドロワー、ファイリングバグ、データベースの操作(The Boring Flutter Development Show、Ep。27)
https://www.youtube.com/watch?v=SJKrtx759Xk&feature=youtu.be
ボーリングショーのこのエピソードでは、エミリーとエミリーが協力してデータベースをFlutterアプリに追加し、ユーザーがお気に入りの記事を保存したり、パッケージにバグを登録したり、カスタムドロワーメニューの作成を開始できるようにします。フレアベクトルアニメーション:Zero to Hero
https://www.youtube.com/playlist?list=PLjr4ufdmNA4Jt19RyRQPD7cMF0r0juDs8
Flareを使用してアニメーションを作成する方法を学ぶためのビデオチュートリアルの全リストFlutterアニメーション-AnimatedSwitcherを使用した放射状メニュー
https://www.youtube.com/watch?v=1Bz06bLeWHY&feature=youtu.be
Flutterカスタムアイコン-自動および手動の方法(アイコンフォントまたはSVG)
https://www.youtube.com/watch?v=qZYqmM3daO0&feature=youtu.be
カスタムアイコンを使用してFlutterにベクターフォントベースのアイコンの新しいセットを追加する方法に関するビデオチュートリアル。今週のパッケージ
https://www.youtube.com/playlist?list=PL163X1AUpNTGyw4eNVnvIfPl3chAXsReW
「週のパッケージ」を示す毎週成長するプレイリスト、またはさまざまな利用可能なFlutterパッケージの使用方法。抽象化により開発時間を節約| Flutter抽象化
https://www.youtube.com/watch?v=n2yGl7vJJGM&feature=youtu.be
この抽象化に関するFlutterチュートリアルでは、抽象化が必要な理由、抽象化がどのように役立つか、偽の実装を使用して実際に何時間もの開発時間を節約できるかがわかります。ライブラリ&コード
aliyigitbireroglu / flutter-peek-and-pop
https://github.com/aliyigitbireroglu/flutter-peek-and-pop
同じ名前のiOS機能に基づくFlutter Peek&Pop実装。
Almoullim / background_location
https://github.com/Almoullim/background_location
AndroidおよびiOS用のFlutterバックグラウンドロケーションプラグイン
form_bloc / packages / flutter_form_bloc
https://github.com/GiancarloCode/form_bloc/tree/master/packages/flutter_form_bloc
Flutter form_blocパッケージでフォームを作成するのに役立ちますフラッターウィジェットを持つパッケージ。
mannprerak2 / nearby_connections
https://github.com/mannprerak2/nearby_connections
近くの接続API用のFlutterプラグイン(Android)
schibsted / tweet_ui
https://github.com/schibsted/tweet_ui
Tweet UIのFlutterパッケージ
fluttercommunity / get_it
https://github.com/fluttercommunity/get_it
インターフェースを具体的な実装から切り離すことができる単純な直接サービスロケーター。
- 投稿日:2019-08-28T08:46:22+09:00
Flutterウィークリー #71
Flutterウィークリーとは?
FlutterファンによるFlutterファンのためのニュースレター
https://flutterweekly.net/この記事は#71の日本語訳です
https://mailchi.mp/flutterweekly/flutter-weekly-71※Google翻訳を使って自動翻訳を行っています。翻訳に問題がある箇所を発見しましたら編集リクエストを送っていただければ幸いです。
読み物&チュートリアル
Flutter and Graphql-ファイルをアップロードする方法
https://codinglatte.com/posts/flutter/flutter-and-graphql-how-to-upload-files/
GraphQLとFlutterを使用してファイルをアップロードする方法に関するチュートリアル。Flutterチュートリアル:習慣トラッカーUI
https://cybdom.tech/flutter-tutorial-habit-tracker-ui/
カスタムペインタとベジェカーブを含むUIの作成に関するチュートリアル。Flutterサノススナップ効果
https://fidev.io/thanos-snap-effect-in-flutter/
MarcinSzałekが説明した画像に適用する楽しい効果。効果の最高の名前:)Flutter非同期プログラミングのガイド
Gaspard MertenによるFlutter先物、ストリーム、コンプリーターの紹介。Flutter Androidの文字Flutter
https://medium.com/flutter-community/android-strings-to-flutter-12a5c307147c
ŁukaszWiśniewskiは、作成する理由と、ライブラリを使用してAndroid xml文字列ファイルをi18n Flutterクラスに変換する方法について説明します。FlutterとGraphQLを使用したシンプルなアプリケーションの構築
DanielBerríoBarreraがFlutterでのGraphQLの使用について紹介します。Flutter —プロバイダーを使用したFirebase Realtime Database CRUD操作
Mohamed Hassan Kadriによるプロバイダーライブラリを使用して、Firebaseでcrud操作を処理する方法。BLoCパターン付きのFlutter BottomNavigationBar
https://medium.com/@lovnicki.sandro/flutter-bottomnavigationbar-with-bloc-pattern-bba6f13d49f3
SandroLovničkiは、BLoCデザインパターンでBottomNavigationBarウィジェットを使用する方法を示します。バックグラウンドでFlutterを実行するには?
https://medium.com/vrt-digital-studio/flutter-workmanager-81e0cfbd6f6e
Tim Rijckaertは、 Flutterバックグラウンドジョブを定期的にトリガーする必要性をどのように解決したかについて説明します。Flutterための必須のVSコード拡張機能
Daniele CambiによるFlutter動作するために推奨されるVSコード拡張のキュレーションリスト。FlutterアプリでColorTweenを使用する
https://medium.com/flutterpub/using-colortween-in-flutter-app-d05a3ebe83f5
Tyagi Priyankaによるこの記事で、ColorTweenを使用してアニメーションを実装する方法を学びます。Flutter PCゲームをモバイルに
https://rainway.com/blog/2019/08/06/flutter/
Rainwayチームは、 Flutterを使用してモバイルにゲームをストリーミングする方法を説明し、驚くべき結果を出しました。ビデオ&メディア
CustomPaintを使用したFlutterアニメーションノイズ
https://www.youtube.com/watch?v=-3bRoZ2kbW8&feature=youtu.be
CustomPaintウィジェットを使用してFlutterノイズアニメーションを作成する方法を学びます。AnimatedPadding(今週のFlutterウィジェット)
https://www.youtube.com/watch?v=PY2m0fhGNz4&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=46
AnimatedPaddingを使用すると、ウィジェットのパディングを動的に変更し、2つの値の間でアニメーション化できます。より良いコードのためのDart機能:スプレッド、Collection-If、Collection-For
https://www.youtube.com/watch?v=mnaN_6465Gk&feature=youtu.be
このチュートリアルでは、Spreads、Collection-If、およびCollection-Forを実際に使用する方法を示します。Flutter Animation Tutorial – AnimatedWidgetとAnimatedBuilderによるリファクタリング
https://www.youtube.com/watch?v=o-h_e4b71o8&feature=youtu.be&app=desktop
AnimatedWidgetとAnimatedBuilderを手動アニメーションに適用して、コードをよりクリーンで再利用しやすくします。ライブラリ&コード
アリアミン/ shopx
https://github.com/Ali-Amin/shopx
MobX状態管理を使用したEコマースFlutterアプリ
asjqkkkk / flutter-todos
https://github.com/asjqkkkk/flutter-todos
包括的で美しいFlutter Todo-Listアプリは、ベストプラクティスプロジェクトでもあります。印象的なドキュメントの栄誉。
dmh2000 / Flutter -GraphqlX
https://github.com/dmh2000/Flutter-GraphqlX
DartとFlutter GraphQLを使用する例
fayeed / flutter_parsed_text:
https://github.com/fayeed/flutter_parsed_text
テキストを解析し、リンクされたテキストウィジェットにするFlutterパッケージ
flutter-ui-challenges / flutter_web_challenge_googlemaps
https://github.com/flutter-ui-challenges/flutter_web_challenge_googlemaps
Google Maps UIの再設計のFlutterチャレンジ。
fluttervn / super_widgets
https://github.com/fluttervn/super_widgets
一般的に一緒に使用される複数のウィジェットを単一のウィジェットに結合する一連のウィジェット。
JideGuru / Flutter FurnitureAppUI:
https://github.com/JideGuru/FlutterFurnitureAppUI
khalidfsh / flutter_localizations_tale
https://github.com/khalidfsh/flutter_localizations_tale
sarbagyastha / flutter_rating_bar
https://github.com/sarbagyastha/flutter_rating_bar
フラッター用のシンプルなレーティングバー。レーティングバーインジケーターも含まれ、レーティングの一部をサポートします。
- 投稿日:2019-08-28T08:44:55+09:00
Flutterウィークリー #70
Flutterウィークリーとは?
FlutterファンによるFlutterファンのためのニュースレター
https://flutterweekly.net/この記事は#70の日本語訳です
https://mailchi.mp/flutterweekly/flutter-weekly-70※Google翻訳を使って自動翻訳を行っています。翻訳に問題がある箇所を発見しましたら編集リクエストを送っていただければ幸いです。
読み物&チュートリアル
Flutter –ポートレートとランドスケープのレイアウト
https://codingwithjoe.com/flutter-portrait-and-landscape-layouts/
縦向きでも横向きでも、美しく表示できるFlutterフォームの作成方法を調べてください。「刷新」 Flutterボトムシート
https://medium.com/flutter-community/revamped-flutter-bottom-sheet-61662dc2983
Sumeet Rukejaは、独自のボトムシートをゼロから作成して、さらにカスタマイズできるようにする方法を説明します。Flutterはよさそうですが、痛いです。ここに私の不満があります。
ベルナルド・フェラーリはFlutterを試し、その過程で発見したいくつかの問題を共有しています。プロバイダーパッケージの詳細
https://medium.com/flutter-nyc/a-closer-look-at-the-provider-package-993922d3a5a5
プロバイダーパッケージをよりよく理解するためのMartin Rybakの記事Flare& Flutterした水追跡アプリの構築
https://medium.com/2dimensions/building-a-water-tracking-app-with-flare-flutter-f03de436dba3
FlutterアプリからFlareアニメーションを処理する方法を理解するための優れたチュートリアル。Flutter —デバッグUIチートシート
https://medium.com/@louagejulien/flutter-debugging-ui-cheat-sheet-18a7b09dd468
Julien LouageによってキュレーションされたUIのデバッグフラグのリストFlutterとムーア
https://medium.com/flutterpub/flutter-and-moor-c2b2e03b1fbe
Aseem Wangooによるこの記事では、Moorを使用してFlutterデータベースの操作を簡素化する方法を学びます。Flutterとコマンドライン—ラブストーリー
https://medium.com/flutter-community/flutter-and-the-command-line-a-love-story-a3648ef2411
GonçaloPalmaは、コマンドラインオプションをレビューしてFlutterます。Flutter Rx Dartを使用したインスタント画像検索
https://medium.com/@sagarsuri56/instant-image-search-using-rxdart-in-flutter-9eedd4b53364
Rx Dartを使用して画像検索アプリを作成する方法を説明するSagar Suri。Dialog ManagerでFlutterダイアログを管理する
https://medium.com/flutter-community/manager-your-flutter-dialogs-with-a-dialog-manager-1e862529523a
Dane Mackierは、中央のダイアログマネージャーを使用してアプリでダイアログを処理する方法を示します。プロバイダー—およびそのタイプ
https://medium.com/flutterpub/provider-and-its-types-dda8463586e7
Flutterを使用したテキスト読み上げ
https://medium.com/@arend.kuehle/text-to-speech-with-flutter-8d959dad40a8
FlutterでTTSを使用する際のArendKühleによるヒント。レンタル代理店向けのFlutterデータ入力フォームアプリの作成
Steve Zwartによるこの記事でFlutterフォームの取り扱いを学ぶカールとDart楽しみ-マーキーデセルス:クリスの洞察力
http://sellsbrothers.com/fun-with-curl-and-dart
Chris Sellは、Curlでリクエストを生成し、それらをDartコードに変換する方法を説明します。Flutter次のアプリを作成する理由
https://skillsmatter.com/skillscasts/13223-why-i-m-building-my-next-app-in-flutter
ビデオ&メディア
Flutterフォーム検証を追加し、Firebase Authエラーメッセージのユーザーに警告する方法
https://www.youtube.com/watch?v=bSUdYUw4Jjs
サインアップとサインインフォームにカスタムフォーム検証を追加し、エラーメッセージを処理する方法AnimatedPositioned( Flutter Widget of the Week)
https://www.youtube.com/watch?v=hC3s2YdtWt8&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=45
AnimatedPositionedは、指定された位置が変更されるたびに、指定された期間にわたって子の位置を自動的に移行しますFlutterグリッターアニメーションを作成する(The Boring Flutter Development Show、Ep。27)
この退屈なショーのエピソードでは、アンドリューはゲストメアリーと一緒に、 Flutterキラキラと輝くアニメーションを作成するというアイデアを探求します。Flutterアニメーションチュートリアル-基本を理解し、簡単にアニメーション化する
https://www.youtube.com/watch?v=txLvvlooT20&feature=youtu.be
Flutter Bloc-自動ルックアップ-v0.20(以降)、更新されたチュートリアル
https://www.youtube.com/watch?v=_vOpPuVfmiU&feature=youtu.be
このチュートリアルでは、BLoCライブラリを使用して状態を管理する最新のベストプラクティスと方法を学習します。Flutter File Upload-画像を選択、切り取り、クラウドに保存
https://www.youtube.com/watch?v=HCmAwk2fnZc&feature=youtu.be
FlutterとFirebase Cloud Storageでファイルをアップロードしてください。画像を選択、切り取り、クラウドストレージバケットにアップロードする方法を学ぶFlutter Live: Flutter Blocパッケージの学習|私と一緒に学びましょう!
https://www.youtube.com/watch?v=eAiCPl3yk9A&feature=youtu.be
Flutterミニマルデザイン-栄養アプリ
https://www.youtube.com/watch?v=K1uH_SN4X0w
エリック・ザイデル( Flutter共同設立者)へのインタビュー
https://www.youtube.com/watch?time_continue=287&v=AMOs1cuNhDY
フルテランドのメンバーがエリック・ザイデルにインタビューします(ポルトガル語での紹介ですが、インタビューは英語です)Material Themer- Flutter開発ツールの情報ビデオ
https://www.youtube.com/watch?v=o_xs5sXEaqg&feature=youtu.be
Material Themerアプリを使用すると、ThemeDataを視覚的に作成し、ワンクリックでコードを生成できますライブラリ&コード
Flutter Enhancement Suite
https://plugins.jetbrains.com/plugin/12693-flutter-enhancement-suite
Flutter作業をこれまで以上に簡単にするための重要なプラグイン!AubergineDevelopers / flutter_scale
https://github.com/AubergineDevelopers/flutter_scale
Flutterパッケージを使用すると、Scaleウィジェットを簡単に統合できます。
csells / flutter_mazegen
https://github.com/csells/flutter_mazegen
Flutter迷路を生成するために古いC ++を移動する
florent37 / Flutter -ShapeOfView
https://github.com/florent37/Flutter-ShapeOfView
フラッターウィジェットにカスタムシェイプを追加し、Material Design 2を準備
mjohnsullivan / ffi
https://github.com/mjohnsullivan/ffi
DartからCライブラリを呼び出す方法を示す一連の簡単な例。
- 投稿日:2019-08-28T07:14:46+09:00
Androidアプリ配信に関してまとめ(TWAアプリ)
Androidアプリリリースに必要な作業
署名済APKファイルの作成
1. リリース用の設定を行う
こちらを参考にリリースに必要な準備を行う
- ログ記録とデバッグをオフにする
- プロジェクト ディレクトリをクリーンアップする
- マニフェストおよび Gradle ビルド設定を確認およびアップデート
など2. アプリの署名鍵とアップロード鍵の生成を行う
AndroidStudioで鍵とキーストアの生成を行う
鍵の管理に関してはApp Signingがよい
3. サーバーに配置する関連付け用jsonを生成する
以下のコマンドでSHA-256フィンガープリントを抽出
keytool -list -v -keystore エイリアス -storepass キーストアのパス実効例サンプル
$keytool -list -v -keystore ./mykeystore.ks -alias test -storepass password -keypass password Alias name: key0 Creation date: 28 Jan 2019 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Test Test, OU=Test, O=Test, L=London, ST=London, C=GB Issuer: CN=Test Test, OU=Test, O=Test, L=London, ST=London, C=GB Serial number: ea67d3d Valid from: Mon Jan 28 14:58:00 GMT 2019 until: Fri Jan 22 14:58:00 GMT 2044 Certificate fingerprints: SHA1: 38:03:D6:95:91:7C:9C:EE:4A:A0:58:43:A7:43:A5:D2:76:52:EF:9B SHA256: F5:08:9F:8A:D4:C8:4A:15:6D:0A:B1:3F:61:96:BE:C7:87:8C:DE:05:59:92:B2:A3:2D:05:05:A5:62:A5:2F:34 Signature algorithm name: SHA256withRSA Subject Public Key Algorithm: 2048-bit RSA key Version: 3表示された情報をもとにこちらでステートメントを生成する
実効例サンプル
[{ "relation": ["delegate_permission/common.handle_all_urls"], "target" : { "namespace": "android_app", "package_name": "com.example", "sha256_cert_fingerprints": ["aaaa"] } }]作成されたステートメントをwebアプリケーション側の
/.well-known/assetlinks.jsonに配置する4. アプリの署名を行う
App Signing方式でアップロード鍵を使用してリリース用としてアプリに署名をする
Google Playで配信
最初にGoogle Play Consoleでデベロッパーズアカウントを作成する必要があります
※ アカウント作成には$25必要です
※ ストアに掲載するにあたってスクショやヘッダー画像が必要になるため準備が必要です
ストア配信にあたって必要素材や情報登録後の手順についてはこちらの記事がわかりやすい
Google Play での Android アプリの配信方法(インストールとアップデート)を試してみる - Qiita

































































