Lottie-Androidで素晴らしいアニメーション試す
Lottie-Androidとは
Airbnbが開発したアニメーションを簡単に表示できるライブラリ
詳しくは公式ページを参照
https://airbnb.design/lottie/
AndroidのGithubはここ
https://github.com/airbnb/lottie-android
導入
app/gradleに以下を追加
implementation 'com.airbnb.android:lottie:2.5.5'
アニメーションファイルは以下サイトに山ほどあるんで、好きなアニメーションのjsonをダウンロードする
LottieFiles - https://www.lottiefiles.com/
jsonをresに配置する
自分はrawディレクトリを作ってそこに置いた
実装
自動再生させたければレイアウトxmlに追加するだけで済む
<com.airbnb.lottie.LottieAnimationView android:layout_width="100dp" android:layout_height="100dp" app:lottie_autoPlay="true" app:lottie_loop="true" app:lottie_rawRes="@raw/giftbox" />
たったこれだけ、素晴らしい
もちろんコードで実装することも可能、今回はやらないけどね
完成物
いろいろアニメーションを載っけてみた
感想
LottieFilesのというサイトから好きなアニメーションを選んで、簡単にアプリに導入できるのは素晴らしい
そしてアニメーションのクオリティが高い!
作ろうと思えばアニメーションは自分で作れるらしい
気になった事
いくつかアニメーションjsonがAndroid Studioにコピーするとビルドが失敗した
Android Studioがjsonを読み込めなかったのか、jsonが正しく書かれてないのか不明...
また、Android Studioのレイアウトxmlを修正する際にエディタがすっごく重たくなる気がする。
これはAndroid Studio 3.2 Beta 5だからなんだろうか...
使用コード
banbara23/Android-Kotlin-Lab at Lotties https://github.com/banbara23/Android-Kotlin-Lab/tree/Lotties
Navigation Architecture Componentを試した
Google I/O 2018でNavigation Architecture Componentが追加されてからずっと気になっており、そろそろ試さねばと思って実装してみた。
シングルActivity+多Fragmentの遷移を作っていく。
環境
Android Studio 3.2 Beta 5 Build #AI-181.5281.24.32.4913314, built on July 26, 2018 JRE: 1.8.0_152-release-1136-b04 x86_64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o macOS 10.12.6
compileSdkVersion 28
kotlin_version = '1.2.51'
Navigation導入
お手本にしたのはAndroid Developers
- Implement navigation with the Navigation Architecture Component | Android Developers https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing#kotlin
safeArgsの導入
classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha04"
Navigationの導入
apply plugin: "androidx.navigation.safeargs" def nav_version = "1.0.0-alpha04" implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin
AndroidXだとビルドエラーになるのでgradle.protertiesに以下を追加
android.enableJetifier=true android.useAndroidX=true
resにNavigationファイルを作成
ここから本番
Android Developersによると以下の方法で説明されていた。
- プロジェクトウィンドウで、resディレクトリを右クリックし、New > Android Resource File を選択します。
- File nameに「nav_graph」などの名前を入力します。(名前は何でもいい)
- Resource typeドロップダウンリストからNavigationを選択します。
- OKをクリックします
スクショ撮ってきた
プロジェクトウィンドウのresディレクトリを右クリックし、New > Android Resource File を選択
File nameにnav_graphを入力、Resource typeにNavigationを選択
nav_graph.xmlが作成された
Fragmentを作成
Fragmentは自分で作る必要がある
今回はプロジェクトウィンドウからNew > Fragment > Fragment(Brank)
で2〜3個ほどFragmentを作った
- FirstFragment
- SecondFragment
- ItemFragment(リスト)
Navigationエディタで遷移を操作
さきほど作成したnav_graph.xmlを選択して下部のDesignタブを選択すると、Graphエディタなるものが使える
スクショ(遷移作成済み)
あとはここにFragmentを追加し、遷移先のFragmentを選ぶだけ。
xmlは一切書かずにエディタをポチポチすると、nav_graf.xmlには自動でタグが作成されていた
<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/nav_graph" app:startDestination="@id/firstFragment"> <fragment android:id="@+id/firstFragment" android:name="com.ikemura.android_kotlin_lab.FirstFragment" android:label="fragment_first" tools:layout="@layout/fragment_first"> <action android:id="@+id/action_firstFragment_to_secondFragment" app:destination="@id/secondFragment" /> </fragment> <fragment android:id="@+id/secondFragment" android:name="com.ikemura.android_kotlin_lab.SecondFragment" android:label="fragment_second" tools:layout="@layout/fragment_second"> <action android:id="@+id/action_secondFragment_to_itemFragment" app:destination="@id/itemFragment" /> </fragment> <fragment android:id="@+id/itemFragment" android:name="com.ikemura.android_kotlin_lab.ItemFragment" android:label="fragment_item_list" tools:layout="@layout/fragment_item_list" /> </navigation>
注意点
Navigation Editorを使うには設定が必要らしい
公式から引用
Note: The Navigation Editor is enabled by default only on Canary builds of Android Studio. To enable the Navigation Editor on Beta, Release Candidate, or Stable builds, click File > Settings (Android Studio > Preferences on Mac), select the Experimental category in the left pane, check Enable Navigation Editor, and then restart Android Studio.
- Navigation EditerはCanary buildsでのみ有効(ベータ版も含まれる)
- File > Settings (Android Studio > Preferences on Mac) > Experimental > Navigation Editorのチェックを有効にする
- Android Studioを再起動
遷移コードをFragmentに実装
まずはボタン押下で FirstFragment => SecondFragment の遷移
公式で一番最初に紹介されてたパターン
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_first, container, false) //ボタンクリック view.findViewById<Button>(R.id.fist_navigate_button).setOnClickListener { //SecondFragmentへの遷移開始 Navigation.findNavController(it).navigate(R.id.secondFragment) } return view
これでSecondFragmentに遷移できるようになった
次に SecondFragment => ItemFragment の遷移
ここでは上と違う書き方で遷移コードを書いてみる
Navigationクラスの便利メソッドがあるらしいので、そちらを使ったパターン
second_navigate_button.setOnClickListener( //遷移開始 Navigation.createNavigateOnClickListener(R.id.itemFragment, null) )
nullとなってる箇所にはBundleをセットできるらしい
バックキーで戻る遷移
Activityにこのコードを追加するだけで、端末バックキーで簡単に前にFragmentに戻れる
override fun onSupportNavigateUp() = findNavController(this, R.id.my_nav_host_fragment).navigateUp()
これだけでシングルActivity+多Fragmentの遷移ができた
感想
ほとんどコードを書かずにFragment間を簡単に遷移できるのは素直にすごいと思った。
遷移する際にパラメータやアニメーションも指定できそうなので、シングルActivity+多Fragmentの作成が捗りそう。
Activity間の遷移にはあまり使い物にならない、とよく見るので、主にFragment間だけで使えそう。
DialogFragmentにも使えるんだろうか?Dialogは普通にコードで表示するんだろうか? あとで調べてみよう。
今回使ったコードはこちら banbara23/Android-Kotlin-Lab at Navigation https://github.com/banbara23/Android-Kotlin-Lab/tree/Navigation
SafeArgsも使ったけど長くなるので別記事にする。
参考リンク
- android-architecture-components/NavigationBasicSample at master · googlesamples/android-architecture-components https://github.com/googlesamples/android-architecture-components/tree/master/NavigationBasicSample
- 【Android】Google IO 2018で新発表された navigation についての詳細レポート - DMM inside https://inside.dmm.com/entry/2018/05/25/android-navigation
- Navigation Architecture Component メモ – Kenji Abe – Medium https://medium.com/@star_zero/navigation-architecture-component-%E3%83%A1%E3%83%A2-10f0acc3d4d9
- Implement navigation with the Navigation Architecture Component | Android Developers https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing#kotlin
Hyperion-Androidを使ってみた
社内でHyperion-Androidがデバッグに便利、という情報を得たので試しに使ってみた。
環境
Android Studio 3.2 Beta 5 Build #AI-181.5281.24.32.4913314, built on July 26, 2018 JRE: 1.8.0_152-release-1136-b04 x86_64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o macOS 10.12.6
Hyperion-Androidとは
説明は書くのが面倒なので省く、以下記事をみると分かりやすい - Hyperion-AndroidでAndroidアプリをデバッグしよう - Qiita https://qiita.com/takahirom/items/2f6557f945ddd7c5e074
インストール
リポジトリを探してREADMEを眺める
willowtreeapps/Hyperion-Android: App Debugging & Inspection Tool for Android https://github.com/willowtreeapps/Hyperion-Android
usageに載ってるが、コア機能とプラグインをapp/build.gradleに突っ込めば使えるそうだ
implementation 'androidx.appcompat:appcompat:1.0.0-beta01' implementation 'androidx.constraintlayout:constraintlayout:1.1.2' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-core:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-attr:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-measurement:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-disk:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-recorder:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-phoenix:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-crash:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-shared-preferences:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-geiger-counter:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-timber:0.9.24' + debugImplementation 'com.willowtreeapps.hyperion:hyperion-build-config:0.9.24' + testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.0-alpha4' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
ビルド=>エラー
Sync => OK
Run Buld => エラーになった!!!??
エラーメッセージは
Program type already present: android.support.v4.os.ResultReceiver
既にResultReceiver
が存在? 何を言っとるんだねキミは...
ググるとAndroidX関連のエラーらしい
そういえば試しにAndroidX導入したんだった。
解決方法
gradle.propertiesに以下を追加するだけ
# This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true +android.enableJetifier=true +android.useAndroidX=true
ビルド再チャレンジ
Sync => OK
Run Buld => OK
よーし、できた
本体を振るとHyperion-Androidメニューが表示された
Hello Hyperion-Android pic.twitter.com/2lPF4lzI6X
— イケムラ (@ikemura_jp) 2018年8月1日
備考
今回使用したコードのリポジトリは以下
https://github.com/banbara23/Android-Kotlin-Lab/tree/Hyperion-Android
Androidでの非同期処理の8つの方法
Androidでの非同期処理の8つの方法
この記事は自分の勉強のため以下リンクの日本語訳しました。
8 ways to do asynchronous processing in Android and counting https://android.jlelse.eu/8-ways-to-do-asynchronous-processing-in-android-and-counting-f634dc6fae4e
Androidには、非同期処理を行うためのAPIがいくつか用意されています。これらのAPIにJavaが提供するAPIを組み合わせて、非同期タスクを実行する方法は数多くあります。
JavaスレッドやAndroid AsyncTasksは、よく知られていて、あなたが望むことができるため、すべてのものに使用する傾向があります。ただし、すべてのAPIが同じではないため、要件に適したメソッドを選択すると、コードが安定して、よりクリーンで、読みやすく、直感的になります。
それで、Androidで非同期ジョブを実行する7つの方法に飛びついてみましょう。オプションは、最初にAndroid APIまたはJavaの一部としてソートされ、次にそれらが遭遇したり使用された頻度によってソートされます。
8つの方法
- AsyncTask
- IntentService
- Loader
- JobScheduler and GcmNetworkManager
- CountDownTimer
- Java Threads or Android HandlerThread
- FutureTask
- Java Timer / ScheduledThreadPoolExecutor
AsyncTask
おそらく最もよく知られている非同期APIのAsyncTaskは実装が簡単で、メインスレッドで結果を返します。 AsyncTaskにはいくつかの問題があります。たとえば、アクティビティやフラグメントのライフサイクルを認識していないため、アクティビティが破棄されたときにAsyncTasksの動作を処理するのはプログラマの責任です。つまり、長時間実行する操作に最適なオプションではなく、アプリがバックグラウンドにあり、アプリがAndroidによって終了された場合、バックグラウンド処理も終了します。
new AsyncTask<URL, Integer, Long>() { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }.execute(url1, url2, url3); // Modified Code from google Android API
IntentService
これは、Androidで長時間実行される処理のためのデファクトの選択です。 大きなファイルをアップロードまたはダウンロードするのがよい例です。ユーザーがアプリを終了してもアップロードとダウンロードが続行され、これらのタスクが実行されている間にユーザーがアプリを使用できないようにすることはできません。
public class RSSPullService extends IntentService { @Override protected void onHandleIntent(Intent workIntent) { // Gets data from the incoming Intent String dataString = workIntent.getDataString(); ... // Do work here, based on the contents of dataString ... } }
// AndroidManifest.xml <application android:icon="@drawable/icon" android:label="@string/app_name"> ... <!-- Because android:exported is set to "false", the service is only available to this app. --> <service android:name=".RSSPullService" android:exported="false"/> ... <application/>
Loader
ローダーは複雑なトピックですが、ローダーの単一の実装であれば、おそらくそれ自身のためにすべての投稿に値するでしょう。今のところ、ローダーがAndroid Honeycombに導入され、互換性ライブラリの一部であることを指摘する価値はあります。彼らは、フラグメントとアクティビティのライフサイクルを認識しており、ロードされたデータをキャッシュすることさえできます。
私は、AsyncTaskLoadersがAsyncTaskに内在する多くの問題を解決するので、AsyncTaskLoadersに注意を向けたいと思います。Android Design Patternsにはローダーに関するすばらしい記事があります。ローダーの詳細を理解するために読むことをお勧めします。 https://www.androiddesignpatterns.com/2012/08/implementing-loaders.html
JobScheduler と GcmNetworkManager
私がこれら2つを一緒に束ねている理由は、効果的に似ているからです。JobSchedulerはAPI 21でリリースされましたが、まだGoogleから公式の互換性のバージョンはありません(Evan TatarkaはJobSchedulerCompatを無効にしています)。しかし、Google Play 7.5の一部としてバンドルされているGcmNetworkManagerは、似たようなものですが、特にネットワーク操作用です。
JobSchedulerの使用は少し複雑です。幸いなことに、GoogleのJobSchedulerの使い方のサンプルがあります。効果的には、サービスを作成し、JobInfo.Builderを使用してジョブを作成する必要があります。これは、サービスの実行基準を指定します。計測されていないネットワーク上にある場合や、アプリが充電中の場合などです。これらの条件が満たされるとすぐにコードが実行されるという保証や実行の順序は保証されません。以下は、Googleのコードからジョブをスケジュールする方法の抜粋です。
JobInfo.Builder builder = new JobInfo.Builder(kJobId++, mServiceComponent); String delay = mDelayEditText.getText().toString(); if (delay != null && !TextUtils.isEmpty(delay)) { builder.setMinimumLatency(Long.valueOf(delay) * 1000); } String deadline = mDeadlineEditText.getText().toString(); if (deadline != null && !TextUtils.isEmpty(deadline)) { builder.setOverrideDeadline(Long.valueOf(deadline) * 1000); } boolean requiresUnmetered = mWiFiConnectivityRadioButton.isChecked(); boolean requiresAnyConnectivity = mAnyConnectivityRadioButton.isChecked(); if (requiresUnmetered) { builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); } else if (requiresAnyConnectivity) { builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); } builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked()); mTestService.scheduleJob(builder.build()); // CANCEL JOBS JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); tm.cancelAll();
GcmNetworkManagerページで、その使用方法のコード例を見ていきます。
https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmNetworkManager
一般的な概念は、特定の基準が満たされたときにサービスを実行するようスケジュールする必要がある場合に似ています。
スケジュールされたタスクはワンオフまたは定期的にすることができます。
https://developers.google.com/cloud-messaging/network-manager#schedule_tasks
カウントダウンタイマー
これが何のために使われているかを推測する賞はありません。これは非常に使いやすいですが、コンテキストに依存しますので、アクティビティやフラグメントを終了する場合は、キャンセルすることでこれをクリーンアップする必要があります。明確にするために、CountDownTimerについては非同期的なものはありません。あなたがそれを見たらそれはHandlerに遅延メッセージを投稿するだけです。つまり、起動したスレッドでonTick()とonFinish()が実行され、CountDownTimerを実行しているスレッドで実行され、UIの更新を実行できます。このため、ToTick()やonFinish()で重い操作をしないことも重要です。CountDownTimerがリストに含まれている理由は、このクラスを使用しても、CountDownTimerがメインスレッドから初期化されても、ユーザーがアプリを使用できないようにすることができず、効果的に非同期効果が得られるからです。また、更新間隔が小さく、処理に時間がかかる場合は、バックプレッシャーの問題が発生し、実行スレッドがブロックされる可能性があります。
new CountDownTimer() { @Override public void onFinish() { } @Override public void onTick(long millisUntilFinished) { } }.start();
JavaスレッドまたはAndroid HandlerThread
Javaスレッドは実装するのがかなり簡単です。ただし、Androidではこれを避けるのが最善です。私はそれらがすべての種類のインスタンスで使用されているのを見てきましたが、Androidは実際にはバックグラウンドスレッドでUIアップデートを許可していないため、制限しています。より良いオプションは、AsyncTaskを使用することです。
new Thread(new Runnable(){ public void run() { // do something here } }).start();
Android HandlerThreadは、バックグラウンドスレッドのメッセージを処理するために使用できます。メッセージ処理は処理ではなくリダイレクトを行う傾向があるため、これはかなり制限されていますが、バックグラウンドスレッドでいくつかのタスクを実行する方法を提供しています。使用可能なのは、バックグラウンドスレッドでサービスを実行することです。
public class TickTockService extends Service { public void onCreate() { // Start up the thread running the service. Note that we create a // separate thread because the service normally runs in the process's // main thread, which we don't want to block. We also make it // background priority so CPU-intensive work will not disrupt our UI. mThread = new HandlerThread("ServiceArguments", Process.THREAD_PRIORITY_BACKGROUND); mThread.start(); // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = mThread.getLooper(); mServiceHandler = new Handler(mServiceLooper); } }
FutureTask
FutureTaskは非同期処理を実行しますが、結果がまだ準備できていないか処理が完了していない場合は、get()を呼び出すとスレッドがブロックされます。
驚いたことに私はこれを数回使用しました。場合によっては、Google Volleyでリクエストをブロックする方法があります。以下は、これを行う方法の例です。これを行う場合は、UIスレッドをブロックしていないことを確認してください。
RequestFuture<JSONObject> future = RequestFuture.newFuture(); JsonObjectRequest request = new JsonObjectRequest(URL, null, future, future); requestQueue.add(request);
それは常にあなたがを使用することをブロックします。 future.get(30、TimeUnit.SECONDS)
その時間が過ぎると、無期限に待つのではなくタイムアウト例外がスローされます
try { JSONObject response = future.get(); // this will block (forever) } catch (InterruptedException e) { // exception handling } catch (ExecutionException e) { // exception handling }
Java Timer / ScheduledThreadPoolExecutor
Java Timerを使って5秒後に何かをする例 これらは、バックグラウンドスレッドでいくつかの処理をスケジュールするために使用できます。Androidで同じことを処理する他の方法がありますが、postDelayedまたはHandler with HandMessageDelayed()を使用してHandlerを使用し、上のようにバックグラウンドスレッドでハンドラを実行できます。また、このAPIはAndroidのライフサイクルを認識していないため、アクティビティ、フラグメント、またはビューへのハードリファレンスは、メモリリークの可能性があります。
Timer timer = new Timer(); timer.schedule(new TimerTask(){ public void run() { // time ran out. timer.cancel(); } }, 5000);
From Java API
特定の遅延の後に実行するコマンド、または定期的に実行するコマンドをさらにスケジュールできるThreadPoolExecutor。このクラスは、複数のワーカースレッドが必要な場合、または(このクラスが拡張する)ThreadPoolExecutorの追加の柔軟性や機能が必要な場合に、Timerよりも優れています。遅延されたタスクは、有効にされるよりも早く実行されますが、有効にされた後に開始されるリアルタイムの保証はありません。まったく同じ実行時間にスケジューリングされたタスクは、先入れ先出し(FIFO)の提出順で有効になります。
public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor { static class CustomTask<V> implements RunnableScheduledFuture<V> { ... } protected <V> RunnableScheduledFuture<V> decorateTask( Runnable r, RunnableScheduledFuture<V> task) { return new CustomTask<V>(r, task); } protected <V> RunnableScheduledFuture<V> decorateTask( Callable<V> c, RunnableScheduledFuture<V> task) { return new CustomTask<V>(c, task); } // ... add constructors, etc. } // Code from Java API
ScheduledThreadPoolExecutorは、TimerやJava Threadsと同じようにAndroidで多くの問題を抱えています。UIを更新する必要がある場合は、メッセージをUIスレッドに投稿するか、リスナーを渡すためにハンドラを使用する必要があります。ScheduledThreadPoolExecutorはJavaの一部であり、ActivityまたはFragmentのライフサイクルを認識していないため、メモリリークを防ぐためにListenerを手動でクリーンアップまたは置き換える必要があります。
まとめ
Androidで非同期処理するとき
- UIを反映するなら AsyncTask
- 長時間通信してアプリ終了しても実行させたいなら IntentService
- 処理データをキャッシュしたいなら Loader
- API21以降でで条件付きで実行するなら JobScheduler
- 遅延付きでUIを更新したいなら CountDownTimer
JavaのThreadは使うな、UIが更新できない、ASyncTaskを使え
FutureTaskはUIスレッドをブロックするから使わない方が良い
Android Studioで ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded
環境
Android Studio 3.0.1 Build #AI-171.4443003, built on November 10, 2017 JRE: 1.8.0_152-release-915-b08 x86_64 JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Mac OS X 10.12.6
Java 8
現象
とあるプロジェクトにライブラリ追加したりコード書いたりしてビルドしたら以下のエラーが出てビルドできなくなった。
Information:Gradle tasks [clean, :app:assembleStaging] Error:Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded Error:Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded Error:Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded Error:Uncaught translation error: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: GC overhead limit exceeded Error:4 errors; aborting Error:Execution failed for task ':app:transformClassesWithDexForStaging'. > com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.ide.common.process.ProcessException: Error while executing java process with main class com.android.dx.command.Main with arguments {--dex --num-threads=4 --multi-dex --main-dex-list /Users/xxxxxx/dev/xxxxxxx/app/build/intermediates/multi-dex/staging/maindexlist.txt --output /Users/xxxxxxxxxxxxx/app/build/intermediates/transforms/dex/staging/folders/1000/1f/main /Users/xxxxx/dev/xxxxxxxx/app/build/intermediates/transforms/jarMerging/staging/jars/1/1f/combined.jar} Information:BUILD FAILED in 2m 25s Information:6 errors Information:0 warnings Information:See complete output in console
ビルドで OutOfMemoryError
だと...?
そんな重いことしてないはず。
RxJava, RxAndroid, Retrofitライブラリを追加しただけなのに!
ググる
情報でた
解決方法
app/build.gradleに以下を追加してメモリを抑える
android { dexOptions { javaMaxHeapSize "4g" } }
ビルドしてみると、、、ビルド通った!
ビルド完了!!
めでたしめでたし
PM2でnodejsアプリを動かす
foreverは使ったことあるが、pm2の方が高機能という話を聞いたので使ってみる。
PM2のインストール
グローバルインストールする
npm i -g pm2
pm2コマンドが認識されていればインストールOK
PM2を使う
開始するだけなら
pm2 start jsファイル
--name
で名前つきでスクリプトを起動すると便利
というか、名前がないと操作が不便すぎるので必須だと思う
slack-botという名前で起動する
$ pm2 start main.js --name slack-bot [PM2] Starting /home/pi/dev/slack-bot/main.js in fork_mode (1 instance) [PM2] Done. ┌───────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├───────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ │ slack-bot │ 0 │ fork │ 1432 │ online │ 0 │ 0s │ 12% │ 20.0 MB │ pi │ disabled │ └───────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
再起動
pm2 restart アプリ名
$ pm2 restart slack-bot Use --update-env to update environment variables [PM2] Applying action restartProcessId on app [slack-bot](ids: 0) [PM2] [slack-bot](0) ✓ ┌───────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├───────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ │ slack-bot │ 0 │ fork │ 1480 │ online │ 1 │ 0s │ 66% │ 15.1 MB │ pi │ disabled │ └───────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ Use `pm2 show <id|name>` to get more details about an app
いけたっぽい
停止する
pm2 stop アプリ名
$ pm2 stop slack-bot [PM2] Applying action stopProcessId on app [slack-bot](ids: 0) [PM2] [slack-bot](0) ✓ ┌───────────┬────┬──────┬─────┬─────────┬─────────┬────────┬─────┬────────┬──────┬──────────┐ │ App name │ id │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ ├───────────┼────┼──────┼─────┼─────────┼─────────┼────────┼─────┼────────┼──────┼──────────┤ │ slack-bot │ 0 │ fork │ 0 │ stopped │ 1 │ 0 │ 0% │ 0 B │ pi │ disabled │ └───────────┴────┴──────┴─────┴─────────┴─────────┴────────┴─────┴────────┴──────┴──────────┘ Use `pm2 show <id|name>` to get more details about an app
stoppedになってる
ログを見る
pm2 logs アプリ名
$ pm2 logs slack-bot [TAILING] Tailing last 15 lines for [slack-bot] process (change the value with --lines option) /home/pi/.pm2/logs/slack-bot-error-0.log last 15 lines: ...
モニタリング
起動しているアプリのログやプロセスの確認ができる。
pm2 monit
見やすくて少しカッコいい
設定ファイルを用いた起動指定
YamlとJsonで起動オプションを設定ファイルに定義できる。
今回はYamlで作成してみる。
# ファイル名:pm2config.yml(ファイル名は自由です) name: slack-bot # アプリ名 script: main.js # スクリプトファイルパス watch: true # フォルダやサブフォルダ内のファイルが変更された場合、アプリは再読み込みされます log-date-format: "YYYY-MM-DD HH:mm Z" # ログに日付を追加
設定ファイルで使える項目は以下リンク http://pm2.keymetrics.io/docs/usage/application-declaration/#attributes-available
設定ファイルで起動する
pm2 start pm2.yml pm2 stop pm2.yml pm2 restart pm2.yml