20210815のAndroidに関する記事は5件です。

UnityのAndroid開発でエラーもなく突然激重になる現象とそれを対処した方法

こんにちは、ハニカムラボのおのです. 現象や状況 Unity2020系、Unity2019系で発生 Unity上のエディタでは発生しない 実機(Android6系と7系)で発生確認 3種類ほどのタブレット端末で発生 Android5系のスマートフォンでは発生せず 10分から40分画面スリープもなく放置していると発生 操作していても発生することも 見た目はほぼフリーズしている状態だが、画面遷移など時間が立つと起こるためたぶんすごいFPSが下がっているという状況 Android Logcatなどでもエラーが発見できない ただ、警告がずっと出続けていた(EGL_BAD_PARAMETER) 結果 Optimized Frame Pacing の項目のチェックをはずすと警告が消え、フリーズ現象がなくなった Optimized Frame Pacingとは 2019.2から追加されたっぽい > 低変動でのフレームの分散を可能にすることで、安定したフレームレートとよりスムーズなゲームプレイ体験を実現します だそうだ この記事とは別の現象だったが、不具合があるらしい 2020.3.8fではまだまだ不具合があるっぽい この機能に全く対応できない古すぎる端末だと動くのかなと予想 Android5系のスマートフォンで動いた理由 対処した方法など 今回単純なエラーが出たわけでもなく、そのエラーを見つけるのも大変だったため、色々試してみたのでその共有です。 Firebaseなど外部ライブラリとUnityのバージョンの相性確認 https://firebase.googleblog.com/2020/08/firebase-compatibility-with-unity-20201.html http://halcyonsystemblog.jp/blog-entry-732.html 警告を消す DOTweenの警告を消した https://qiita.com/neusstudio/items/f4429024ea0f54d727fc Android Logcatを利用 Unity内でも見れるのもある:https://baba-s.hatenablog.com/entry/2018/12/25/090000 Unity内にLogViewerを入れた https://assetstore.unity.com/packages/tools/integration/log-viewer-12047?locale=ja-JP Android StudioのProfilerでCPUやメモリ確認 https://developer.android.com/studio/profile/cpu-profiler?hl=ja シーン内のオブジェクト全部削除 新規プロジェクトの作成 端末で他のサードパーティ製アプリで同じく放置してみる Unityのダウングレード 色々な端末向けにビルド iPhone向けにしてみたり、PC向けにしてみたり 色々なビルド設定で虱潰しに
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

KMMを触ってみて思ったこと

はじめに KMM(Kotlin Multiplatform Mobile)とは、Kotlin/NativeというKotlinのコードをさまざまなOSのネイティブコード(マシン語)に変換する技術を使って、モバイル(iOSとAndroid)に特化したクロスプラットフォーム開発をできるようにするSDKです。 僕はKMMってなんか響きがかっこ良いんでKotlinでiOSアプリが作れるっていうところが凄いなと思って勉強を始めてみました。勉強を始めて一番最初に浮かんだ疑問として、Kotlinで開発するのであればただのAndroid開発と何が違うのかというのがありました。その疑問について色々調べてみました。 仕組みの違い そもそもAndroidのネイティブ開発ではKotlinやJavaを使うことができます。それぞれのコードがART(Android RunTime)という実行環境でAndroidOS上で動くようなネイティブコードにコンパイルされることで動いています。 対してKMMはKotlin/NativeがKotlinを各OSのネイティブコードに変換するための諸々をやってくれているので動くそうです。Kotlin/Nativeの公式ドキュメントの文章を見てみると、 Kotlin/Native is a technology for compiling Kotlin code to native binaries, which can run without a virtual machine. It is an LLVM based backend for the Kotlin compiler and native implementation of the Kotlin standard library. ということらしいです。全然わけがわからないです。色々調べてみたところ、この部分の詳しい説明として↓の記事がありました。 https://developers.cyberagent.co.jp/blog/archives/23149/ 要約すると、Kotlin/Nativeは ・ 標準ライブラリ ・ メモリ管理 ・ プログラムランチャー の3つの機能を提供してくれていることで動くそうです。 なので普通のAndroid開発とKMMでは、最終的にAndroidOS上で動くネイティブコードに変換している点は共通していてそのプロセスが違うということらしいです。 開発する上での具体的な違い まずKMMはマルチモジュール構成となっていて、共有モジュールと各OSのモジュールの三つの構成になっています。各OSのモジュールではそれぞれのOSでしか使えないライブラリ等が使えます。僕はとりあえずサンプルアプリはMVVMで、ViewModelとViewをそれぞれのOS毎に分岐して書くというやり方で作りました。普通のAndroid開発とKMMで開発するときの具体的な実装時の違いとして使えるライブラリの違いがありました。ここがかなり重要な違いかなと思いました。例えば、 HTTPクライアント ・Android -> Retrofit(+ OkHttp) ・KMM -> Ktor client Coroutines ・Android -> coroutines-android ・KMM -> native-mt AAC(Android Architecture Components) ・Android -> 使える ・KMM -> 共有部分のコードでは使えない 他にもあると思いますがこの辺りが違いを実感しました。特にiOSにも対応しないといけないので当たり前ではあるんですが、共有部分のコードでAACが使えないのが辛かったです。ViewModelScope等のAndroidのライフサイクル対応のCoroutineが使えなかったので結局ViewModelを分ける以外にやり方がわかりませんでした。それに関係する話ですが、アーキテクチャに関しても、 ・Android -> MVVMが推奨 ・KMM -> 何が正解か全くわからない といった感じでKMMは何が正解なのかよくわかりませんでした。KMMはそれぞれのOSの違いに対応する時に、どうしてもコードを共通化できない部分が出てきてしまってそれぞれ分岐させなければいけないところがあると思うんですが、その分け方のベストプラクティスみたいなものがわからないです。 感想 とりあえずKotlinでiOSのアプリが作れたのはめちゃくちゃ感動しました。ただ結局ViewModel以降はそれぞれのOS毎に書いているのであんまりクロスプラットフォームで開発している!みたいな実感は湧きませんでした。アーキテクチャ等のベストプラクティスみたいなものがわかればもう少し共通化できる部分が増やせるのかなと思いました。またKMMでの開発を通してAndroid自体の開発に関して少し理解が深まる部分があったのでそれもよかったなと思います。KMM開発においてiOS側からKotlinのflowをobserveする時などもっと具体的な壁もあったのでその辺りもいつか記事に書きたいです。 拙い理解と変な文章の記事をここまで読んでくださってありがとうございました。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android] HiltでApplicationComponentが見つからない

Hiltのcodelab Android アプリでの Hilt の使用 で、以下のエラーが発生しました。 エラー: シンボルを見つけられません @dagger.hilt.InstallIn(value = {ApplicationComponent.class}) ^ シンボル: クラス ApplicationComponent 原因 Hiltのバージョンを最新の2.38.1にしていたことが原因で、エラーが発生していました。 修正 Hiltのバージョンをcodelabで指定されている2.28-alpha、または2.28.3-alphaにすることで解決しました。 build.gradle buildscript { ext.kotlin_version = '1.5.21' ext.hilt_version = '2.28-alpha' repositories { google() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:7.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FlutterのWorkManagerのcallbackDispatcherをstaticで宣言するとエラーになる

問題のライブラリはこちら https://pub.dev/packages/workmanager The callbackDispatcher needs to be either a static function or a top level function to be accessible as a Flutter entry point. この公式の指示に従ってstaticでcallbackDispatcherを宣言したらこんなエラーが・・・ E/flutter ( 2580): [ERROR:flutter/shell/common/shell.cc(103)] Dart Unhandled Exception: NoSuchMethodError: No top-level getter 'callbackDispatcher' declared. E/flutter ( 2580): Receiver: top-level E/flutter ( 2580): Tried calling: callbackDispatcher, stack trace: #0 NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:214:5) E/flutter ( 2580): E/flutter ( 2580): [ERROR:flutter/runtime/dart_isolate.cc(713)] Could not resolve main entrypoint function. E/flutter ( 2580): [ERROR:flutter/runtime/dart_isolate.cc(192)] Could not run the run main Dart entrypoint. E/flutter ( 2580): [ERROR:flutter/runtime/runtime_controller.cc(415)] Could not create root isolate. E/flutter ( 2580): [ERROR:flutter/shell/common/shell.cc(588)] Could not launch engine with configuration. 結論 トップレベルに宣言すれば治ります。 検証環境 Flutter 2.2.3 Dart 2.13.4 Workmanager 0.4.1 Kotlin 1.4.32
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android]思考停止で使っていたViewBindingを掘り下げる

ViewBindingとは? ビュー バインディングとは、ビューを操作するコードを簡単に記述できる機能です。 簡単に言語化すると「簡単操作」です。 ViewBindingはappモジュール内で設定すると、ファイルの数だけバインディングクラスという「仲介役」が静的に?生成されます。 そうすることで、xmlファイル内の(ID名のあるViewのみ)Viewを簡単にクラスから参照でき、簡単に「操作」出来るわけです。 ちなみに、生成されたバインディングクラスの名前は、xmlファイル名のキャメルケースになります。 設定 build.gradle(app) android { // (省略) viewBinding { enabled = true } } モジュール単位で設定すると前述したので、このように。 使い方 Activityで用いる場合 private lateinit var binding : MainActivityBinding // (省略) override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) binding = MainActivityBInding.inflate(layoutInflater) setContentView(binding.root) } inflateメソッドで、バインディングクラスのインスタンスを生成していることになります。 そして、getRootメソッドでルートビューの参照を取得します。 それをいつものようにsetContentViewにセットすれば、画面レイアウトの生成が完了です。 Fragmentで用いる場合 殆どActivityと同じなのですが、FragmentのライフサイクルはViewよりも長いので少し手を施す必要があります。 onDestroyViewで、Viewの参照を止める必要があります。 ドキュメントの書き方も、まぁ目的は達成しているのですが、手動でクラッシュ回避しているのと若干冗長できなので、自動で出来る方法を下記に記します。 var binding by autoCleared<HogeFragmentBinding>() こちらで、初期化すればViewが破棄されると同時にバインディングの参照もクリーンアップされます。 終わりに inflateとfragmentのライフサイクルについて深堀したいな。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む