Firebaseに新機能が追加されたらしい

グーグル、「Firebase」に新機能を追加--アプリ内メッセージングツールなど - ZDNet Japan https://japan.zdnet.com/article/35124174/

この記事が社内でシェアされてたので、本家記事を眺めながらまとめた。

まとめ

  • アプリを活発に利用しているユーザーとその開発者がコミュニケーションを図れるようになるアプリ内メッセージングツールができた=> Firebase In-App Messaging
  • 「Firebase Crashlytics」における「BigQuery」と「Jira Software」との統合
  • CrashlyticsはBigQueryとの統合によってクラッシュ時のデータをより詳細に分析できるようになる
  • Jira Softwareとの統合により、クラッシュの通知を「Slack」のようなサードパーティーのツールを介して行える
  • 「Firebase Hosting」の機能向上、開発者は単一プロジェクト内で複数のウェブサイトをホストできる
  • Firebaseコンソールがライブデータを取り扱い、パフォーマンス上の問題のほか、通知やA/Bテストの状況を表示できる
  • Functions」や「Hosting」「Storage」といった、他のFirebaseサービスの利用状況や稼働状況を確認できる
  • Remote Configのhistory機能を追加

これらの改善はすべて今日から始まり、数週間以内に誰もが利用できるようになる

感想

「Firebase Hosting」の機能向上、開発者は単一プロジェクト内で複数のウェブサイトをホストできる

個人的にはこれが一番面白そう

Firebase Hostingを利用してVuejs + Materializecss のサイトをいくつか運営しているので、自サイトで使えないか調べてみよう。

BotkitでSlackのアプリメッセージをキャッチしたい

概要

SlackでBotkitを使用してbotを作るとき、ユーザーのメッセージに反応するにはambientだったりmention,direct_messageなど使うが、これらはアプリ経由やwebhook経由からのメッセージには反応しない。
つまり人間が発言したメッセージ以外はbotがキャッチしてくれない。

図で説明するとこんな感じ

スクリーンショット 2018-08-07 0.21.40.png

このAPPが付いたメッセージをBotkitでキャッチしたい、とする。

方法

controller.hearsで2番めのイベント引数にbot_messageを渡すだけで反応してくれる

const Botkit = require('botkit');
const controller = Botkit.slackbot();
controller.hears([''], 'ambient, bot_message', (bot, message) => {
    //botがあれこれする箇所
});

ちなみに、Botkit自身が投稿したSlackメッセージには反応しない。

備考

ちなみに、このbot_messageはBotkitドキュメントに見当たらず、下記Issueを見た時に偶然知った。

Any reason why bots don't hear other bots in slack? · Issue #284 · howdyai/botkit https://github.com/howdyai/botkit/issues/284

参考リンク

Botkit公式ドキュメント https://botkit.ai/docs/readme-slack.html

Lottie-Androidで素晴らしいアニメーション試す

Lottie-Androidとは

Airbnbが開発したアニメーションを簡単に表示できるライブラリ

詳しくは公式ページを参照
https://airbnb.design/lottie/

AndroidGithubはここ
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ディレクトリを作ってそこに置いた

スクリーンショット 2018-08-03 13.16.34.png

実装

自動再生させたければレイアウト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のというサイトから好きなアニメーションを選んで、簡単にアプリに導入できるのは素晴らしい

そしてアニメーションのクオリティが高い!

作ろうと思えばアニメーションは自分で作れるらしい

気になった事

いくつかアニメーションjsonAndroid Studioにコピーするとビルドが失敗した

Android Studiojsonを読み込めなかったのか、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

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

メモ githubのコミットログ

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も使ったけど長くなるので別記事にする。

参考リンク

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-AndroidAndroidアプリをデバッグしよう - 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メニューが表示された

Hyperion-Androidを使用する動画も撮ってみた

備考

今回使用したコードのリポジトリは以下

https://github.com/banbara23/Android-Kotlin-Lab/tree/Hyperion-Android

ffmpegで4:3のアスペクト比を16:9に変換する in Mac

昔に撮影した映像を再生すると、4:3のアスペクト比なのに16:9に引き伸ばされて再生された。

どうにか4:3にしたい。

VLCで16:9で再生するのではなく、どこでも4:3で表示できるようにした。

環境

ffmpeg version 4.0.1

Mac OS X 10.13.6

方法

ffmpegコマンドでできるらしい

ffpmegはbrew install ffmpeg でインストール済み

ffmpeg -i my_video.mp4  -c copy -aspect 4:3 new_my_video.mp4

一瞬で出来た!

ffmpegがあればコンバーターソフトなんていらんなー

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がいくつか用意されています。これらのAPIJavaが提供する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を使用し、上のようにバックグラウンドスレッドでハンドラを実行できます。また、このAPIAndroidのライフサイクルを認識していないため、アクティビティ、フラグメント、またはビューへのハードリファレンスは、メモリリークの可能性があります。

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スレッドをブロックするから使わない方が良い