20210129のAndroidに関する記事は8件です。

Flutterのバージョンを切り替える

こちらの記事を参考にしました
https://qiita.com/sekitaka_1214/items/60c4c36585f2a216ffd0

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

休学中にアプリを作ったらappleにスパムアプリと言われた話

今年度大学を1年間休学しました。その間に作ったアプリをリリースしたのでやってきたことを振り返ろうかな〜と思いこの記事を書きました。

作ったトークアプリ

『ChillTalk』というトークアプリをつくりました。1つのルームにユーザーが集まり、移動をすることでいろんなグループの話が聞け、話相手を見つけられるのが特徴です。自分の付近にいるユーザーの声だけが聞こえます。
ezgif-4-49998c7a7c05.gif

3月

まず、わたしは機械工学部なのでプログラミングは少しいじっただけでまともに勉強したことがありませんでした。高校を選ぶ頃はものづくりが好きだったり、宇宙飛行士に憧れ機械系に進みました。しかし、もともとガジェットやアップルなどのテック企業が大好きだったこともありソフトウェアへの関心が強くなり仕事ではハードではなくソフトを作りたいと考えるようになりました。そんなとき、今やっている研究も楽しくなく来年度を続けるのかと考えるととても気が重くなり、休学を考えました。
一年後には学生に戻れて学生じゃ無くなるわけじゃないし、休学金もかかりません。ソフトウェアの勉強して、なにか作ってみたいと思い休学しました。

4 - 5 月

まだやることがあったので4月は学校に行っていました。
休学し始めた頃は、インスタのARフィルターを作っていました。
あとは、LINEスタンプとかも作りました。

6 - 7 月

ここで、真剣に1年なにやろうか考えました。そこで思いついたのがアプリ制作でした。
今までは自分で作って満足していたけどあまり人に使ってもらうことは考えていませんでした。今度はみんなに使ってもらえるアプリ作りたいと思いました。そこで考えたのがトークアプリです。
twitterのようなくだらない話をしたり、いきなり知らない人と絡められる、そんな気軽に人としゃべれる場所が欲しいなあと思いました。トークアプリすでに多くあります。しかし、ほとんどが1対1で会話するものです。いきなり2人きりで喋るのはきつい。話す内容を考えるのにハードルが高い。そんな感じで今まで1回も使ったことがありませんでした。
そこで考えたのが1つのルーム内にユーザーを集めてその中を移動して会話相手(グループ)を見つけるというものです。

↓友人に見みせるために書いたアイデア
1611715116656.jpg

映画の話をしたかったらマップ上の映画館に行けばいいし、誰かと話をしたかったらぶらぶらマップ内をあるいて話し相手を見つけれる、というものです。マンダロリアンの新作について誰かと話したいし、友達つくりたい。これならルームに入るだけで話し相手を見つけられるんじゃないか。
早速作り始めました。

8月

早速Xcodeで作りはじめました。

音声通話まわり

WebRTCという仕組みを使えば通話ができるらしい。そして、WebRTCを行う場合の通信方法がいくつかある。

P2P : ユーザー同士が直接通信する。ユーザー側の処理が増えるので接続数には制限がある。
MCU : サーバーを介して通信する。サーバー側の処理が増えるので接続数が増やせる。
SFU : サーバーを介して通信する。WebRTCに使われる。

2,3人の通信だとP2P品質がいいとのこと。今回つくりたいのは大人数の会話を行いたいのでその場合はSFUを使うといいらしい。
そして、NTT CommunicationsがSkyWayというWebRTCアプリのSDKを提供していた。これを使おう!!

移動まわり

ジョイスティックを使って移動したい。けど実装難しくない!?時間かかりそう。とりあえず十字キーにすることにしました。
ゲームみたいにスムーズに移動したいけどXcodeだとできない。毎フレームごとわずかな移動を連続させると処理が重くなりカクカクするし...とりあえず「x座標に1移動する」みたいな処理になりました。
そして、他のユーザーに近づくとその人のSkyWayのトークルームに入室に、会話でできるようにしました。本来実装したかったユーザー間の距離による音量減衰はできませんでした。

とりあえずテスト版が出来た

赤丸 : 自分、青丸 : 他ユーザー
ezgif-7-3721b88b0a89.gif

思ってたのと違う!! 移動方法も移動もスムーズじゃない。
よく考えれば、自分がやろうとしていることはシステム的にはゲームなんじゃないかと気づきました。
ゲーム開発ならUnityをつかうことになるけど、せっかくSwift勉強してXcode使えるようにそれを一切使わずに他の開発するのはもったいないと思いました。けれど、このアプリのアイデアはウケるし気がしたしみんなに使ってもらいたい。どうしてもこのアプリを作りたいと強く思いUnityを勉強しました。

9月

Unityの本を買ってきてサンプルのアプリを一通り作りました。思っていたより簡単である程度のことはすぐにできました。
スムーズに移動できる! ジョイスティックはアセットストアにあったものを使いました。(アセットストア便利すぎw)
リアルタイム同期にはPUNを使いました。簡単に説明すると、Photon(PUN)はユーザー間の通信をリレーするサーバーを提供してくれるサービスです。SDKを入れて設定するだけで簡単にリアルタイム通信を行うことができました。また、Photonが提供しているPUN VoiceをというボイステャットができるSDKを使用しました。そして、ユーザーのオブジェクトごとにスピーカーを設定することで音量減衰を実装できました。
今までXcodeでやっていたことはなんだったんだろう?と思うレベルで、すぐにアイデアを実装できました。

行き詰まったとき

ときどきアプリが思ったように動かなかったり、エラーが連続したりしてモチベーションがなくなるときが結構ありました。
そんなときはいろいろ作ったりして遊んでいました。

初めてOculuQuestを買ってボウリングしたり、
ezgif-5-dcb818ac7650.gif

VRで外国人とAppleのイベントみたり
Eh-QolUUcAIyGJo.jpeg

LEDテープをディスプレイ裏に貼ってArduinoとPCをつなげて画面の色と同期したり
PXL_20200927_081817028.PORTRAIT-01.COVER.jpg

ezgif-5-4bf81fda8432.gif

3Dプリンタでジョイスティックを作ったり
ezgif-5-0008d74a1c9d.gif

スマホを車のHUDにして速度を表示するアプリを作りました
ezgif-5-9089a5cb5b45.gif

これはAR,VR関係の人達に反響があって嬉しかったです。
Google PlayStoreでリリースしたのでダウンロードしてくださいーー!

冬あたり

SNSみたいにフォロー機能をつけて、フォローした人がアプリを立ち上げたらフォロワーに通知がいく機能や、フォローしているルーム内の座標を取得してそこにワープ出来たらいいなと思い実装を始めました。しかし、これが地獄の始まりでした。誰をフォローしたかなどを保存するのにはサーバーが必要です。そのあたりはFirebaseを使いました。swiftで使ったこともあってかサーバーへの保存・読み取りは簡単でした。しかし、フォローリストをサーバーとリアルタイムに同期させたり、フォロー一覧のスクロールビューを作るのにものすごい時間がかかり、それに伴いモチベーションも低下し気づいたら1ヶ月経っていました。
そして、ある程度出来たのがこちら

なんとか形になった!
数人の友人にTestFlightで使ってもらいました。
ezgif-1-c6118f956c62.gif

アイコンの移動や同期はうまくいきましたが、重大な問題が発覚しました。
スマホのスピーカーを使用して通話するとマイクがスピーカーの音を拾ってしましい、ハウリングが発生しました。
話すたびにハウリングし、まともに会話が出来ませんでした。
自分がイヤホンするとハウリングは発生しないのですが相手のマイクが自分の声を拾い、数秒後に声が返ってきます。非常に話しづらい...
(この原理を利用して、相手の話をやめさせる機械があるそうですw)

PUN Voiceのマニュアルをみてみるとスマホとスピーカーを使用しての会話は非推奨とのこと。ハウリングを無くす機能もありませんでした。他の通話アプリはどうしているのかLINEを使ってテストしました。そしたら、相手が話している時は自分のマイクがミュートされていました。反対に自分が話しているときには相手の音声はオフになって聞こえなくなっていました。なるほど、意外とシンプル。これなら実装出来そう。
自分の音量が一定値を超えたら相手の音声をオフにし、音量が一定値以下になったら相手の音声をオンにする。というシンプルなものを作ってみました。
これでテストしてみたら、だいぶハウリングが無くなりました。しかし、遅延の存在を忘れていました。自分が話終えたあとすぐに相手の音声をオフにしていたので、相手のマイクから自分の声が聞こえてきます。自分が話し終えた後も遅延分音声をオフにしている必要があるのです。
遅延分も考慮して実装してみると、確かにハウリングは無くなりました。しかし、話し終えた後に相手の声が聞こえるまでの時間があり、素早い会話ができません。例えると、一球一球丁寧にキャッチボールをしているような感じでした。また、遅延も一定ではありません。相手の話ているのに音声がオンになっていなかったり使いづらかったです。遅延分の制御がとても大変でした。ここでまた2,3週間かかってしまいました。

そんな時、本来なくてもいい機能に時間を費やし過ぎていることに気がつきました。思いついた機能を付けたすことで、コードもエラーも多くなりました。確かにあったほうがいい機能かもしれないが、まだユーザーもいない状態で肝の機能以外で時間を費やすことは無駄だと思いました。とりあえず最低限の機能を持ったものをリリースしようと決めました。ここから一気に進捗が捗りました。

・アプリデザイン
・サインイン関係
・アイコン写真の設定
・バグの修正

そして、ハウリング問題を解決するためにもう一度PUN Voiceのマニュアルを読んでみると、ハウリングキャンセリング設定も見つけました!数ヶ月前には無かったはずなのに!!!設定のチェックマークをオンにすると、たしかに綺麗にハウリングが消えている!スピーカーつかっても普通に会話できる!時間かけて作ったアルゴリズムはなんだったんだ。と複雑な気分になりました。
その時に本当にこの機能が必要なのか考え結果、とりあえずアプリのコンセプト部分だけでいいからリリースすることを優先するようにしました。
こうして一通りアプリが完成しました。
ezgif-4-49998c7a7c05.gif

AppStoreとの戦い

いよいよストアの審査へ提出します。GooglePlayは問題ないと思っていたのですが、AppStoreがとても心配でした。

というのも上記にあった車のスピードをHUD表示するアプリをAppStoreに申請した際、何回か修正と提出を繰り返した後にこう言われました。


Guideline 4.2 - Design - Minimum Functionality

We understand that there are no hard and fast rules to define useful or entertaining, but Apple and Apple customers expect apps to provide a really great user experience.


要するに、シンプルすぎるからだめ。
ここまできていきなり殴られた気分になりました。(まあ、このアプリは3,4日で作ったのでそんなに傷は深くないですが)
こんなことが今回もある可能性があると思うととても心配でした。

いざトークアプリを提出しました。
何回かリジェクトされ、バグの修正やアプリ情報を追加している時、こんなメッセージが来ました。


Guideline 4.3 - Design


メッセージのやりとりはもう見れず細かい文章はもう覚えていないのですが、「マッチングアプリはもうたくさんあるからいらないよ。他と似たようなアプリならばスパムとみなして、アカウント消すよ。アプリのデザインを一からやり直して」というような事を言われました。
調べてみるとちらほら同じ4.3リジェクトをくらっている人がいましたが、このリジェクトされた場合はもう審査は通らないという感じでした。
落ち込みます。半年間作ってきたものをスパムと言われ、リリースできないなんて一体自分は何をしてきたのだろう。この日は一日中落ちこんでいました。

それでも、どうしてもリリースしたかったのでメールを書きました。


The matching feature is just a part of the app.
It was created to be used with people you know, such as classmates, workmates, and friends.

The best feature of this app is that it allows you to move around the room, listen to different conversations, and participate in the ones that interest you. This feature has been well received by many people and we believe it is much desired.

There is no other app in the App Store that has this feature. This is a unique feature that only this app has. For these reasons, I don't think it's the same as other matching apps or talk apps.

I am responsible for being the developer of this app. While the app is being used by users, I will always check and strictly respond to reports from users to maintain the quality of the app.


・自分が作りたかったのは、このアプリにくれば誰とでも何人とでも話ができるというものです。それはどのアプリにもない独自性のある機能である事。
・個人開発者ではあるがユーザーの秩序を保ち利用規約を守らせる事。
を書きました。少しオーバーに書き過ぎたかもw
この熱量が少しでも伝われ!!と思いかきました。なんとかなるかもしれないと。

翌朝アプリのステータスを確認してみると...
Es3Ne4IUYAYYau3.jpeg

やったぁーー!!!!!!

あっさりと審査通りました。この時は本当に嬉しかったです。
地獄から一気に元気になりました。
GooglePlayでも審査が通り、こうして無事リリースできました。

この一年で学んだこと

・アプリ開発初心者がいきなりリアルタイム同期(SNS)のアプリを作るのはハードルが高い
・やらない事を決める
・100%の完成はしない
・ある程度完成したらみんなに使ってもらい、ユーザーの声を聞いて機能の追加を考えていく
・困ったらエラーログをしっかり読む
・アプリ制作たのしい
・ものづくりたのしい

これからもアプリを作ってくうえで一番気を付けたいことは、100%を目指したらいつまでも終わらないことです。そんあんことは前から分かったつもりでいたけれど、なんだかんだこり始めてしまうものです。twitterにもアプリ起動後のロード時間はあるし、iPhoneにもいろいろバグがあります。世の中を見てみるとみんな完璧ではないことに気づきました。
決して動作が速く、バグもない完璧な物が評価いいわけではありません。みんなが気に入るのは根幹にあるアイデアなのかなと思いました。

これからはもっとアイデアに重点を置いて短い期間でアプリを作っていきたいと思います!
最後まで読んでいただきありがとうございました。

ぜひ「ChillTalk」を使ってみてください!
GooglePlayはこちら
AppStoreはこちら

twitterもフォローお願いします!
https://twitter.com/Brian3546

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

アプリの一部をWebViewにするメリット・デメリット

前提条件

  • iOSとAndroidの両方で同じアプリを開発する
  • Webでも同じようなアプリを提供する

メリット

  • iOSとAndroidで共通のWebページが使える
    →アプリ側の工数と、アプリ側とWeb側を合計した全体の工数が減る
  • Webページのコーディングを並行して別の人に振れる
    →スケジュールを短縮できる
  • アプリよりWebエンジニアのほうが人を集めやすい

デメリット

  • Webページを実装する必要がある
    アプリ独自のWebページを作るのでなく、レスポンシブデザインにできるといい
  • WebViewが多いとリジェクトされる(iOS)
    →プッシュ通知を付けるだけで通ることもあるよう
  • スマホ固有の機能(カメラやNFC読み取りなど)はWebViewにしにくい
  • 機能にもよるが、ネイティブのほうが使い勝手がいい
  • 通信する分だけネイティブよりパフォーマンスが落ちる
  • オフラインで使えない
  • 認証周りを工夫する必要がある
    →ログインが必要なアプリの場合、Webページを開いたときにログイン状態になっていないといけない

まとめ

WebView化は工数削減の手段になり、すでにWebアプリがあると特に有効です。

参考リンク

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

windowsでsoファイルの中のシンボルを見る

androidのapkに含まれているsoファイルの中のシンボルの確認方法。
忘れて3か月のうちに2回も悩んだので備忘録。

方法

  1. cygwinをインストール。起動。
  2. apkを.zipに拡張子を変えて解凍→lib/armeabi-v7a/の下などに.soファイルがある
  3. それに対してcygwinのターミナル上でreadelf -s を実行。

参考

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13143958248
https://pyopyopyo.hatenablog.com/entry/20070315/p1

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

Kotlin Json文字列のserialization 正しい対処できなかったので逃げ対応で対処しました

 金田著「はじめてのandroidプログラミング 第5版」を使って、勉強しています。

 「第10章アニメーションする ツーリスト情報アプリを作ろう」の第一段階p393まで、写経が進みました。コンパイルしたところ、次のようなエラーが発生しましたので報告します。
 以下、本書を持っている前提で説明します。本書を使って勉強中の方、一緒に勉強しましょう。

1.エラーの発生状況

e: E:\Engineering\AndroidStudioProjects\hajimeteno5\TouristSights\app\src\main\java\com\example\touristsights\Sight.kt: (12, 1): 
Your current kotlinx.serialization core version is too low, 
while current Kotlin compiler plugin 1.4.21 requires at least 1.0-M1-SNAPSHOT. 
Please update your kotlinx.serialization runtime dependency.
(現在のkotlinx.serializationコアのバージョンが低すぎます。
現在のKotlinコンパイラプラグイン1.4.21では1.0-M1-SNAPSHOT以上が必要です。
kotlinx.serialization のランタイム依存関係を更新してください。)

 これは、次のコードで発生していました。

Sight.kt
package com.example.touristsights

import kotlinx.serialization.Serializable
// 省略
@Serializable    // ここで発生
class Sight ( )

2.調査

 付属のソースコードと比較してみると、build.gradle(Project)ファイルの次の部分で差異がありました。(コメントアウト削除の方が、エラーが発生した時。)

build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
//    ext.kotlin_version = "1.4.21"     // 削除
    ext.kotlin_version = "1.3.72"       // 修正
    repositories {
        google()
        jcenter()
    }

3.一時対策

 修正の通り、変更しSyncNowを実行し、再コンパイルしたところ、成功しました。(とりあえず、現状、写経を目的としているため、とりあえずこれで良しとします。)

4.原因として考えられること

AndroidStudioのバージョンの違い、或いはKotlinのバージョンの違い
私   :ver.4.1.2
本の推奨:ver4.1

5.本当の対策方法

 ググったところ、「【2020年秋版】kotlinx.serializationで配列のJson文字列をパース」という資料を見つけた。試してみようと思いましたが、

plugins {
    id 'org.jetbrains.kotlin.jvm' version "$kotlin_version"
    id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version"
}

を入れる部分が分からなかったので、今日は諦めました。今後、写経が終わったら、gradleを勉強しつつ、またkotlinx.serialization 1.0 releasedといった資料を物色して、再挑戦したいと思います。
 どなたか、対策を見つけられたら教えてください。

6.その他追記:表示の回転について

 本アプリは、表示を回転させ、横画面でも表示できるように作られているが、エミュレータの端末(Nexus5x API30)で回転すると、なぜか縦表示のままです。本書指定のpixel2 api30や実機huawei nova lite(CAZ-TL10)、そしてhuaweiP10lite(was-lx2j)では正常動作を確認しました。

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

【備忘録】Jenkins使ってAndroidのGradleビルドするとAapt2InternalException出たときの対処方法

▼はじめに

AndroidStduioで作成したプロジェクトをJenkinsを使ってビルドを行ったところエラーが出ました。
解消方法を調べてみましたが、かなり苦労したので備忘録として残しておくことにします。

▼開発環境

  • Windows 10 Home 20H2
  • Android Studio 3.5.3
  • Android SDK Platform 29
  • Android SDK Build-Tools 28.0.3
  • Gradle 5.1.1
  • Jenkins 2.263.3 LTS(Windows)

▼問題の現象

ローカル環境でビルドしAPKが生成できるところまで確認しました。
同じことをJenkins側でもやってみます。

Jenkins上でフリースタイルジョブを作成。
そこから「Windowsバッチコマンドの実行」を使って該当のプロジェクトをビルドしたところビルドエラーが発生しました。

以下、ログの一部です。

> Task :app:mergeDebugResources FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDebugResources'.
> 8 exceptions were raised by workers:
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #3: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #0: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #5: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #6: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #4: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #2: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #1: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.
  com.android.builder.internal.aapt.v2.Aapt2InternalException: AAPT2 aapt2-3.4.2-5326820-windows Daemon #7: Daemon startup failed
  This should not happen under normal circumstances, please file an issue if it does.


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 34s

▼問題が解消されなかった方法

▼問題が解消された方法

Unityのフォーラムで同じように悩んでいる方を発見。

■参考サイト:Batchmode build always fail with (Aapt2 Daemon startup failed)Gradle Error. - Unity

内容を読むとJenkinsを実行しているユーザーを変えてたところ解消されたという記事のようです。
こちらを参考に変えてみたところ私も問題を解消することができました。

▼実行ユーザーを変更する前に注意事項

実行ユーザーを切り替えることでJenkinsの設定が初期状態に戻ります。
作業を行う前に予め設定やプラグインは退避するかメモしておき、復元作業を行ってください。

▼実行ユーザーを変更するまでの手順

  1. タスクマネージャー > 詳細タブ にてJenkinsを実行しているユーザーを確認します。
    下記の場合はSYSTEMユーザーで実行していることが分かります。
    SYSTEMユーザーを今ログインしているユーザーに切り替えます。
    タスクマネージャー

  2. コントロールパネル > システムとセキュリティ > 管理ツール > サービス 内に Jenkins があると思います。
    サービス

  3. Jenkins 項目をダブルクリックしログオンタブにてアカウントを選択し自分のユーザー情報を入力しOKを押します。
    ユーザー

  4. パソコンを再起動します。

  5. 再度タスクマネージャーを確認するとユーザーが切り替わっていると思います。
    タスクマネージャー2

▼結果

この状態でJenkinsに再度アクセスし、
初期設定や前環境の移行作業を行い同様にビルドを行ったところ正常にビルドすることができました。

▼最後に

今回の対応の副産物で、システムの環境変数だけでなくユーザーごとに設定している環境変数も使えるようになったり、作業ユーザーのみインストールしていたツール等も使えるようになりました。

そもそも何故使えないのかと思っていたら実行ユーザーが原因だったようです。

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

Android TWRP(Team Win Recovery Project)を起動しようとするとエラーが発生する

目的

  • Android TWRP(Team Win Recovery Project)を起動しようとするとエラーが発生する問題を解決したときのメモをまとめる

情報

  • 筆者のAndroidタブレットはNexus7である。

問題発生までの経緯

問題

  • 下記のような文字列が出力されてリブートを繰り返す
Could not mount /data and unable to find crypto footer. Failed to mount '/data' (Invalid argument) Unable to recreate /data/media folder. Updating partition details... Failed to mount '/data' (İnvalid argument) ...done Unable to mount storage Failed to mount '/data' (Invalid argument) Full SELinux support is present. Unable to mount /data/media/TWRP/.twrps Running Recovery Commands Failed to mount '/data' (Invalid argument) Formatting Cache using make_ext4fs... Done processing script file Renamed stock recovery file in /system to prevent the stock ROM from replacing TWRP.

問題解決までの経緯

  1. PCとAndroidタブレットをUSBケーブルで接続した。
  2. 下記コマンドをコマンドプロンプトで実行する。

    adb reboot bootloader
    
  3. 下記コマンドをコマンドプロンプトで実行する。

    fastboot oem lock
    
  4. 充電が切れるまで本体を放置する。(再起動を繰り返しAndroidタブレットの充電が切れるのを待つ)

  5. 本体を充電し電源を入れる。

  6. 下記コマンドをコマンドプロンプトで実行する。

    adb reboot bootloader
    
  7. タブレットの画面上で「Recovery mode」を音量ボタンで選択して画面ロックボタンで決定する。

  8. 正常にTWRPが起動した。

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

【kotlin】flowで非同期処理やローディングをいい感じにやりたい

はじめに

本記事は主に初心者向けの記事になります。

-> Androidで非同期処理するにはコルーチンを使えばいいみたい。
-> 最近はflow, channelが熱いとか。
-> 基本的な使い方はわかったけど実際どんな感じで使えばいい?

って感じの方向けです。(自分の備忘録も兼ねてます)

今回やること

以下の動作をする機能を実装します。

  • APIリクエストを投げる
  • レスポンスが返ってくるまでローディングを表示
  • APIリクエストエラーハンドリング

実装

成功、失敗、ローディングなどの状態を管理するために、リクエストのresultなどをラッピングするクラスを作って定義します。

sealed class State<T> {
    class Loading<T> : State<T>() // ローディング中
    data class Success<T>(val data: T) : State<T>() // 成功時
    data class Failure<T>(val e: Throwable) : State<T>() // 失敗時
}

このStateクラスを使ってflowで流れてくるデータを判別して各々に処理を書きます。
今回はダミーのweather flowデータを取得するweatherAPIをコールします。

val repository = WeatherRepository()
repository.getCurrentWeather()
    .flowOn(Dispatchers.Default) // これより上のflowの実行コンテキストの指定
    .onEach { result ->
        when (result) {
            is State.Loading -> {
                showLoadingProgress() // loadingDialogとかの表示
            }
            is State.Success -> {
                // do something
                Log.d("### flow result ###", result.data.toString())
                hideLoadingProgress() // loadingDialogとかを消す
            }
            is State.Failure -> {
                // do something
                Log.e("### flow result ###", result.e.stackTraceToString())
                hideLoadingProgress() // loadingDialogとかを消す
            }
        }
    }
    .launchIn(lifecycleScope) // 動作するコルーチンスコープの指定

resultからAPIのレスポンスを取得できます。

onEachlaunchInは書き方が少し違うだけで以下と同じです。こっちの方がネストがちょっと浅くなって個人的に好き。

CoroutineScope.launch{
    flow.collect { result ->
        ...
    }
}

内容的にはflowで流れてきたデータをラッピングクラスのインスタンスで分けて処理をしていくだけです。

repositoryに関してはこんな感じになってます。
なお、requestWeatherApisuspend関数です。

WeatherRepository.kt
class WeatherRepository(
    val weatherDataSource: WeatherDataSource = WeatherDataSource()
) {
    fun getCurrentWeather(): Flow<State<Weather>> = flow {
        val result = try {
            val weather = weatherDataSource.requestWeatherApi()
            State.Success(weather)
        } catch (e: Throwable) {
            State.Failure(e)
        }
        emit(result)
    }.onStart {
        // collectされた時にローディング状態を最初に流す
        emit(State.Loading())
    }
}

try-catchでエラーをキャッチし、flowのオペレータの一つであるonStartでローディング状態を流します。

onStartを使えばflowに最初に流すデータを指定することができます。

flowに流れるデータは
1. State.Loading() (collectされると同時にemit)
2. State.Success(weather) (リクエストが完了したらemit)
になります。

WeatherDataSourceはこんな感じの3秒待ってデータを吐き出すようなものです。今回はこれをAPIに見立てて実装しています。

WeatherDataSource.kt
class WeatherDataSource {
    suspend fun requestWeatherApi(): Weather {
        delay(3000)
        return Weather("sunny", Date())
    }
}

data class Weather(
    val weather: String,
    val date: Date
)

おわり

短いですがこれにて終わりになります。
Utillクラスとかを作るともっとボイラープレート減ってよくなりそう。。。

rx java使いにとってはflowはとってもなじみやすくなりそうですね。自分はまだまだですが。
オペレータとかも一部previewとかexperimentalとかありますがstableになってきたりしているので今年から本格的に導入されていく気がする。

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