51歳からのプログラミング　備忘　プロセス　スレッド　Handler -reference

<写経> 個人使用用
#プロセスとスレッド
>https://developer.android.com/guide/components/processes-and-threads?hl=JA
(2019/8/24)

[マルチスレッドまとめ的なのはここ](https://qiita.com/old_cat/items/a6d71f18a0789351c1a3)

##プロセス
- コンポーネント、プロセス、スレッドの関係
- マニフェスト設定（コンポーネントとプロセス）
- プロセスの重要度階層

---
###コンポーネント、プロセス、スレッドの関係
- アプリケーションで実行するコンポーネントが一つのとき、Androidシステムはシングルスレッド用のLinuxプロセスを開始します。
  - <font color="#888">コンポーネント<br>アクティビティ／サービス／コンテンツプロバイダ／ブロードキャストレシーバー<br>アクティビティ、サービス、ブロードキャストレシーバーはIntent（非同期メッセージ）でアクティベートします。
<br>
  - <font color="#888">process／Linuxプロセス<br>Linuxで実行中のプログラム。</font>

- デフォルトでは、同じアプリケーションのすべてのコンポーネントは同じプロセスとスレッド（メインスレッド）で実行されます。

- アプリのコンポーネントが開始したときに、他のプロセスが存在する場合、コンポーネントはそのプロセス内で開始し、同じ実行スレッドを使用します。

- ただし、アプリケーション内の別のコンポーネントを別のプロセスで実行するように調整でき、あらゆるプロセスに対して別スレッドを作成できます。

---
###マニフェスト設定
特定のコンポーネントが属するプロセスを管理する場合には、マニフェストファイルで指定します。

コンポーネント要素の各タイプのマニフェストエントリ<font color="#099"><strong>（\<activity>／\<service>／\<receiver>／\<provider>）</strong></font>は、コンポーネントを実行するプロセスを指定する<strong>android:process</strong>属性をサポートしてます。

**android:process**の設定によっては、各コンポーネントが独自のプロセスで実行っせたり、一部のコンポーネントで同じプロセスを共有したり、別のプロセスを使ったりできます。異なるアプリケーションのコンポーネントを同じプロセスで実行させたりもできます（アプリが同じLinux user idを共有してて、同じ証明書で署名されている必要があります）。

**\<application>**要素も`android:process`をサポートしており、全コンポーネントに適用されるデフォルト値を設定します。

Androidシステムは、プロセスをシャットダウンし、アプリケーションコンポーネントを破棄することがあります。破棄するプロセスを決定する際、システムは相対的な需要度によって候補を決めます。後ほど、破棄するプロセスを決定する規則を説明します。

---
###プロセスの重要度階層
Androidシステムは、プロセスで実行しているコンポーネントとコンポーネントの状態に基づいて、各プロセスを「重要度の階層」に位置付けし、重要度の低いプロセスから除去され、システムリソースを回復させようとします。

####プロセスの重要度階層　5レベル
1. フォアグラウンドプロセス
2. 可視プロセス
3. サービスプロセス
4. バックグラウンドプロセス
5. 空のプロセス

#####1.フォアグラウンドプロセス
- ユーザーが操作する<font color="#099">Activity</font>のホストになっている（<font color="#099">ActivityのonResume()メソッド</font>が呼び出された）
- ユーザーが操作するアクティビティにバインドされている（<font color="#099">Service</font>のホストになってる）
- フォアグランドで実行中の<font color="#099">Service</font>のホストになっている（サービスが<font color="#099">startForeground()</font>を呼び出した）
- <font color="#099">onCreate()、onStart()、onDestroy()</font>のいずれかのライフサイクルコールバックを実行してる<font color="#099">Service</font>のホストになっている
- <font color="#099">onReceive()</font>メソッドを実行している<font color="#099">BroadcastReceiver</font>のホストになっている

メモリやリソースが不足すると、フォアグラウンドプロセスを強制終了する必要が生じます。

#####2.可視プロセス
フォアグラウンドコンポーネントではないものの、ユーザーに対して通知領域の内容に影響を与える可能性のあるプロセス。以下の場合には可視プロセスとみなされます。

- フォアグランドにはないけれど、ユーザーに表示されている<font color="#099">Activity</font>のホストになっている（<font color="#099">onPause()</font>メソッドが呼びだされた）。

- 可視（またはフォアグラウンドの）アクティビティにバインドされている<font color="#099">Service</font>のホストになってる。

可視プロセスの重要性は高く、フォアグラウンドプロセスの実行を維持する必要がある場合にのみ、強制終了されます。

#####3.サービスプロセス
<font color="#099">startService()</font>メソッドで開始されたサービスを実行するプロセスで、上の2つのカテゴリに分類されないもの。フォアグラウンドプロセスと可視プロセスの全てと合わせて、それらを継続するのにメモリが不足した場合にのみ強制終了の候補となります。

#####4.バックグラウンドプロセス
ユーザーに表示されてないアクティビティを含むプロセス（<font color="#099">onStop()</font>メソッドが呼び出された）。
メモリ回復のためにいつでも強制終了される可能性があります。バックグラウンドサービスはLRU(Least Recently Used：最小使用頻度)リストで管理され、操作の古いものから終了されます。

アクティビティが正確にライフサイクルメソッドを実装し、現在の状態を保持した場合は、強制終了してもアクティビティを再開したときに、視覚的状態を復元します。

#####5.空のプロセス
アクティブなアプリケーションコンポーネントが一つもないプロセス。このプロセスはプロセスをキャッシュする目的で保持され、素早く次回のコンポーネントを起動させます。このプロセスは頻繁に強制終了します。

---
複数の重要度のあるコンポーネントでは、一番重要度の高いランクでプロセスを位置付けます。また他のプロセスのために動作しているプロセスは、依存／バインドしてるプロセスよりも下に位置付けれることはありません（下に位置付けられると、依存してるプロセスが破棄された場合に、実行できなくなる）。

サービスはバックグラウンドより重要度が高く、長時間操作するアクティビティ（特にプロセスがアクティビティよりも長く続く場合）では、プロセスはワーカースレッドを作成するよりサービスを使ったほうがいいでしょう。例えば、ウェブに画像をアップロードする場合、アクティビティでは、ユーザーがアクティビティから離れても、バックグラウンドで処理を続行できるよう、サービスを使うということです。ブロードキャストレシーバーでもスレッドに長時間処理させるのではなく、サービスを使いましょう。

##スレッド
アプリケーション起動時、システムはアプリケーション実行用のメインスレッドを作成します。メインスレッドは、イベント（描画イベントを含む）を適切なUIウィジットに送信する役割を担うために、非常に重要です。

また、メインスレッドは、アプリがAndroid UI ツールキットのコンポーネント（<font color="#099">android.widget／android.view</font>パッケージのコンポーネント）とやり取りもします。そのため、メインスレッドはUIスレッドとも呼ばれます（メインスレッドがUIスレッドでない特殊なケースもあり）。

コンポーネントのインスタンス毎に別スレッドが作成されることはありません。同じプロセスで実行される全てのコンポーネントは、UIスレッドでインスタンス化され、システムはUIスレッドから送信されたコンポーネントを呼び出します。システムのコールバックに応答するメソッドは、常にプロセスのUIスレッドで実行します。

（例：ユーザーが画面上のボタンをタッチすると、アプリのUIスレッドがタッチイベントをWidgetに送信し、Widgetがタッチ状態を設定して、イベントキューに無効化の要求を送信します。UIスレッドがキューから要求を受信し、Widgetに描画を通知する）

全てがUIスレッドで行われる場合、時間がかかる操作を実行すると、UI全体をブロックする可能性があります。またAndroid UIツールキットはスレッドセーフではないので、ワーカースレッドからUIを操作できません。全ての操作はUIスレッドから行う必要があります。そのため、Androidのシングルスレッドモデルには２つのルールを設けています。

#####シングルスレッドモデル・ルール
<strong>1. UIスレッドをブロックしない
2. UIスレッド以外からAndroid　UIツールキットにアクセスしない</strong>
　 UIスレッド以外からアクセスメソッドが用意されている。
（<strong><font color="#f55">Viewを作成したスレッドからしかViewを操作できない</font></strong>）

---
###ワーカースレッド
<font color="#888">ワーカースレッドは、UIを持たないスレッドで、受信した処理要求を実行します（backgroundThreadとも呼ばれる）。ワーカースレッドは、処理要求がなくても待機し、処理要求を受信したら実行する、という振る舞いをします。ワーカースレッドは処理内容によって複数存在することがあり、その存在場所をThreadPoolと呼ぶことがあります。</font>

シングルスレッドモデルによって、アプリケーションのUIの応答性のためにもUIスレッドをブロックしてはいけません。即座に実行する必要のない操作は、別のスレッド（ワーカースレッド(バックグラウンドスレッド））で実行します。

<参考:<font color="#f55">ルール違反のコード</font>>

```java:
public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
            mImageView.setImageBitmap(b);
        }
    }).start();
}
```
UIスレッドではなく、ワーカースレッドから、<font color="#099">ImageView</font>の変更を試みており、ルール２（Android UIツールキットはUIスレッドのみからアクセス）に違反しています。


#####UIスレッド以外からのアクセス方法
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable,long)

<参考:<font color="#f55">View.post(Runnable)による修正コード</font>>
View.post(Runnable)を実装してスレッドセーフにする

```java:
public void onClick(View v) {
    new Thread(new Runnable() {
        public void run() {
            final Bitmap bitmap =
                    loadImageFromNetwork("http://example.com/image.png");
            mImageView.post(new Runnable() {
                public void run() {
                    mImageView.setImageBitmap(bitmap);
                }
            });
        }
    }).start();
}
```
ネットワーク操作は別スレッドで実行(loadImageFromNetwork())。ImageViewはUIスレッドから操作（mImageView.post(new Runnable(){}))しています。

View.postを使ってViewをUIスレッドから操作できるようにする方法は、操作が複雑になるとメンテナンスも難しくなります。ワーカースレッドとの複雑なやりとりを処理するために、ワーカースレッドでHandlerを使うと、UIスレッドから配信されたメッセージを処理できます。でも推奨する方法は、AsyncTaskクラスの拡張です。UIを操作するワーカースレッドタスクの実行を簡略化します。


#####AsyncTaskの利用
<a name="async">AsyncTask</a>は非同期処理を実行します。スレッドやHandlerを自身で処理する必要はなく、ワーカースレッドの操作をブロックし、結果をUIスレッドに配信します。

AsyncTaskの利用は、<font color="#099">AsyncTask</font>をサブクラス化し、バックグラウンドスレッドのプール内で実行する<font color="#099">doInBackground()</font>コールバックメソッドを実装します。

結果をUIに反映させるために、<font color="#099">onPostExecute()</font>を実装します。<font color="#099">onPostExecute()</font>は、<font color="#099">doInBackground()</font>の結果をUIに配信し、UIスレッドを更新するので、UIを安全にアップデートできます。UIスレッドでは<font color="#099">execute()</font>を呼び出し、タスクを実行します。



<参考:前記のコードをAsycnTaskで書き換える>

```java
public void onClick(View v){
   new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask<String,Void,Bitmap>{
   //   システムはワーカースレッドで処理するために次のメソッドを呼び出し、
   //   AsyncTask.execue()メソッド渡すパラメータを配信します
   protected Bitmap doInBackground(String... urls){
      return loadImageFromNetwork(urls[0]);
   }

   //   システムはUIスレッドで処理するために次のメソッドを呼び出し
   //   doInBackground()メソッドに結果を配信します
   protected void onPostExecute(Bitmap result){
      mImageView.setImageBitmap(result);
   }
}
```
ワーカースレッドで処理する作業と、UIスレッドで処理する作業を分けたため、UIは安全になり、コードもシンプルになりました。

AsyncTaskの仕組み。

- ジェネリクスを使ってパラメータのタイプ、進捗値、タスクの最終値を指定できる
- <font color="#099">doInBackground()</font>メソッドがワーカースレッド上で自動的に実行される
- <font color="#099">onPreExecute(),onPostExecute(),onProgressUpdate()</font>は、全てUIスレッドで呼び出される
- <font color="#099">doInBackground()</font>の返値は、<font color="#099">onPostExecute()</font>に送られる
- <font color="#099">publishProgress()</font>は、<font color="#099">doInBacktround()</font>で呼び出せ、UIスレッドで<font color="#099">onProgressUpdate()</font>を実行できる
- いつでも、どのスレッドからでもタスクをキャンセルできる
<table><td><font color="#f55">COUSION:ワーカースレッド使用時に発生する可能性のある問題<br>
画面の向きを変えた場合など、実行時の設定が変更されたことによって、アクティビティが予期せず再起動され、ワーカースレッドが破棄されることがあります。再起動の間、タスクを維持する方法、アクティビティが破棄された時の正しいタスクキャンセルの方法については、以下のサンプルアプリのソースコードを参照>https://code.google.com/archive/p/shelves/
</font></td></table>
AsyncTaskについてより詳しくは>https://developer.android.com/reference/android/os/AsyncTask.html?hl=JA

####スレッドセーフなメソッド
実装したメソッドが、複数のスレッドから呼び出される場合、メソッドがスレッドセーフになるように作成してください。

主にバインドされたサービスのメソッドなど、リモートで呼び出されるメソッドは、複数のスレッドから呼び出される可能性があります。複数のスレッドから呼び出された場合、リモートで呼び出されるメソッドを実行するスレッドは以下の通りになります。

- <font color="#099">IBinder</font>に実装されたメソッドの呼び出しが、<font color="#099">IBinder</font>を実行しているプロセスと同じプロセスで発生した場合、メソッドの実行スレッドは呼び出し側のスレッドです。
- 別のプロセスから呼び出された場合は、メソッドの実行スレッドは、システムが<font color="#099">IBinder</font>と同じプロセスに保持するスレッドプールから選びます。（UIスレッドでは実行されない）。

例えば、サービスの<font color="#099">onBind()</font>メソッドが、サービスのプロセスにあるUIスレッドから呼び出されるのに対して、<font color="#099">onBind()</font>が返すオブジェクトで実装されたメソッド（RPCメソッドを実装するサブクラスなど）は、スレッドプール内のスレッドから呼び出されます。サービスは複数のクライアントを持てるので、複数のスレッドプールが同じ<font color="#099">IBinderメソッド</font>を同時に動かせるため、IBinderメソッドはスレッドセーフになるよう実装しなければなりません。

<font color="#888">RPCメソッド:メソッドの呼び出しはローカルで、実行はリモート（別プロセス）で行い、結果を呼び出し側に返す。</font>

同様にコンテンツプロバイダは、他のプロセスから送られたデータリクエストを受け取れます。<font color="#099">ContentResolver</font>クラスと、<font color="#099">ContentProvider</font>クラスによって、プロセス間通信がどのように管理されているのかが見えなくなりますが、それらのリクエストに応答する<font color="#099">ContentProvider</font>メソッド（<font color="#099">query(),insert(),delete(),updata(),getType()</font>）は、プロセスのUIスレッドではなく、コンテンツプロバイダのプロセスにあるスレッドプールぁら呼び出されます。これらのメソッドは同時に複数のメソッドから呼ばれる可能性があるので、スレッドセーフになるように実装しなければなりません。


####スレッドセーフ
スレッド競合（複数のスレッドが同時の同じクラスやメソッド、変数にアクセスしてデータを破壊する関係）を避けるために、あるスレッドの実行中は、他のスレッドをコントロール（同期(Synchronization)、調停または排他制御）し、複数のスレッドから同時アクセスが生じても、安全なクラスやメソッドにすること。

##プロセス間通信（IPC)
Androidでは、リモートプロシージャコール（RPC）を使った、プロセス間通信のメカニズムを備えており、メソッドはアクティビティや他のアプリケーションコンポーネントから呼び出された後、リモート（別プロセス）で実行され、結果を呼び出し側に返します。プロセス間通信の処理はシステムが担っているため、開発者はRPCプログラミングインターフェイスの定義と実装をするだけでOKです。IPCの実行は、アプリが<font color="#099">bindService()</font>を使ってサービスにバインドされている必要があります。詳細は>https://developer.android.com/guide/components/services.html?hl=JA

#Handle
Handlerを使うと、スレッドの<font color="#099">MessageQueue</font>に関連付けられた<font color="#099">Message</font>や実行可能なオブジェクト（Runnableとかも）を送信したり、処理できます。

Handlerのインスタンスは、シングルスレッドと、そのスレッドのメッセージキューに関連づけられてます。

新しいHandlerを生成すると、Handlerは生成したスレッドと、そのメッセージキューに割り当てされます。その後、Handlerはメッセージと実行可能なメッセージキューを配信できるようになり、またキューから取り出してメッセージを実行できるようになります。

###主なHandlerの用法
- メッセージをスケジュールし、スケジュールした時点で実行可能にする
- メッセージを別のスレッドで実行するようにして、キューに入れる

####メッセージをスケジュールする
#####使うメソッド
■ **Post Version**
<strong><font color="#099">post(Runnable)／postAtTime(java.lang.Runnable,long)／postDelayed(Runnable,Object,long)</font></strong>

■ **Send Message Version**<strong><font color="#099">
sendEmptyMessege(int)／sendMessage(Message)／sendMessageAtTime(Message,long)／sendmessageDelayed(Message,long)
</font></strong>

Postバージョンは、実行可能なオブジェクトを受け取ると、オブジェクトをキュー入れる働きをします。

SendMassegeバージョンはメッセージオブジェクトをキューに入れます。メッセージオブジェクトは、HandlerのHandleMessage(Message)メソッドで使われる予定のデータの集まりを保持してます。（HandleMessage(Massage)は、Handlerのサブクラスを実装します）

Handlerをpostしたりsendすると、メッセージキューの準備ができ次第、処理できるようになります。処理の先延ばしを指定したり、実行時間を指定したりもできます。

後ほど、タイムアウト処理や、ticks（タイマー的な）など、タイミング動作の実装について説明します。

アプリケーションが実行されたとき、メインスレッドはメッセージキュー実行のための専用スレッドになります。メッセージキューは、アクティビティ、ブロードキャスト、レシーバーなどのトップレベルのアプリケーションオブジェクトや、それらが作るウィンドウを管理します。

Handlerを使えば別のスレッドを作成して、メインアプリケーションと通信できるようになります。そのためには前もってpostやsendMessageメソッドを使います。

RunnableやメッセージはHandler'sメッセージキューでスケジュールされ、適切な時に実行されます。

---
###Handlerまとめ的な
<マルチスレッドとスレッド間通信>
■　**Thread**クラスの拡張　|　**Runnable**インターフェイスの継承
　　**UIスレッドとの通信**
　　view#post(Runnable)
　　View#postDelayed(Runnable.long)
　　runOnUiThread(Runnable)
■　**AsyncTask**クラス
　　**処理と通信**
　　execute(),doInBackground(),postExecute()などで
■　**Handler**クラス
　　**マルチスレッド間の通信手段**
　　別途作ってあるスレッド間の通信を担います
　　Message
　　Runnable

####Handlerまとめ概要
**class android.os.Handler**

HandlerはUIスレッドやワーカースレッド間の通信を実現します！

Handlerインスタンスを作成したスレッド内に、<strong><font color="#05f">MessageQueue</font></strong>（メッセージやRunnableを積み上げて保管）と、MessageQueueからメッセージやRunnableを取り出す<strong><font color="#05f">Looper</font></strong>を生成するね。<font color="#05f">Handlerはスレッド間通信を実現するので、他のスレッドから参照できる</font>ようデザインされてるらしい。

Handlerのインスタンスは生成したスレッドとメッセージキューに関連付けられてて、メッセージなどがキューに追加されるとtrueを返します。指定時間経過前にLooperが終了するとRunnableは放棄されてFalseになるので、Falseが出たらメッセージキューが終了してる可能性がありますとのこと！

####Handlerの通信

- Messageを使う方法
- Runnableを使う方法

Handlerは、すでに作成されているスレッド間の情報交信手段を提供します。UIスレッドだけでなくワーカースレッド間の通信を実現します。

Messageを使うと、LooperがhandleMessageを処理し、Runnableを使うと、UI側でRunnableを実行するのですね。

<Messageを使った通信例>
######HandlerとMessageの事例１
```java:Message
public class MainActivity extends AppCompatActivity {

    TextView textView;

    // UIスレッド(MainActivity)でHandlerインスタンスを生成します
    // これでMessageQueueもLooperもUIスレッドの物だね
    // インスタンス handler は別スレッドから参照可能なので
    // 別スレッドで handler を参照して、messageを載せれば
    // UIスレッド（MainActivity)でLooperが処理してくれるんだぜ！
    // カッコいいじゃん！！
    // では、handler さんに登場願います！
    Handler handler = new MyHandler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyMessage();
    }

    private void MyLovelyMessage() {
        // UIスレッド（MainActivity)で生成した handler にアクセスし
        // handler に Messageを載せて sendMessage!
        // これでUIスレッドのLooperが上手くやってくれるはず！
        Message message = handler.obtainMessage(1);
        handler.sendMessage(message);
    }

    class MyHandler extends Handler{
        @Override
        public void handleMessage(Message message){
            // handle が UIスレッドで何をするかを定義する
            // Looperによって自動的に実行されるよ！
            String msg = String.valueOf(message.what);
            textView.setText(msg);
        }
    }
}

```
上のコードを内部関数的にシンプルに

```java:Message
public class MainActivity extends AppCompatActivity {

    TextView textView;

    Handler handler = new Handler(){
      @Override
      public void handleMessage(Message message){
          String msg = String.valueOf(message.what);
          textView.setText(msg);
      }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyRunnable();
    }

    private void MyLovelyRunnable() {
        Message message = handler.obtainMessage(1);
        handler.sendMessage(message);
    }
}
```
######HandlerとRunnableを使った事例

```java
public class MainActivity extends AppCompatActivity {

    TextView textView;

    // HandlerをUIスレッド(MainAvtivity.class)で生成します
    // これで、MessageQueue も Looper も、このスレッド(UIスレッド)に関連付けれます
    //
    // Handlerインスタンスは、他のスレッドからも参照できるので
    // 他のスレッドで、インスタンス handler を使って
    // Runnableをこのスレッド(UIスレッド)に渡せば
    // このスレッド(UIスレッド側)でRunnableを実行できるようになります
    // 素敵ですね！
    // ではHandlerのインスタンスを生成しましょう！！
    Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textView1);

        MyLovelyHandler();

    }

    private void MyLovelyHandler(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                // UIスレッド(MainActivity)で生成したHandlerのインスタンスは
                // 他のスレッドからでも参照可能です
                // インスタンスhandlerにRunnableを載せて
                // UIスレッド（MainActivity)に渡して処理してもらいましょう！
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("I Love Handler");
                    }
                });
            }
        }).start();
    }
}
```

<font color="#05f"></font>
<strong><font color="#05f"></font></strong>

---
######HandlerとService:ファイルを複数に分割した事例
Minターゲット:api28以上にしてあります。

作成ファイル

- MainActivity.java<br>
  Handlerインスタンスを生成<br>
  ForegroundServiceを実行
- MyService.java<br>
  Messageを作成してsendMessage
- MyHandler
  sendMessageされたメッセージを処理

<注意>
ServiceをForegroundで呼び出すと、5秒以内にService側でstartForeground(int,notification)しないとクラッシュするのですが、コードが長くなるので今回は記載せず、クラッシュするようになってます、すみません。

```MainActivity.java
public class MainActivity extends AppCompatActivity {
    public static TextView textView;

    // Handlerオブジェクト生成して、MessageQueueとLooperをUIスレッドに！
    // これでHandleオブジェクトに送られたメッセージをMessageQueueに格納し
    // Looperが勝手に取り出して処理するよ！（処理の内容は、MyHandler.classに定義しとくね！）
    static MyHandler myHandler = new MyHandler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);

        // Intentオブジェクトを生成してServiceを呼び出すよ！
        Intent intent = new Intent(this,MyService.class);
        startForegroundService(intent);

    }
}
```
```MyService.java
public class MyService extends Service {
    public MyService() {
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startid){
        // MainActivityのHandleオブジェクトにメッセージを載せてsendMessage!!
        // 送り先はUIスレッドのMessageQueue!
        // あとはLooperがMyHandler.classを実行して処理するんだね!!
        Message message = MainActivity.myHandler.obtainMessage(1);
        MainActivity.myHandler.sendMessage(message);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
```
```MyHandler.java
// UIスレッドのMessageQueueに格納されたメッセージを
// UIスレッドのLooperが、以下のhandleMessage()を実行処理するよ！

public class MyHandler extends Handler {
    @Override
    public void handleMessage(Message message){
        String msg = String.valueOf(message.what);
        MainActivity.textView.setText(msg);
    }
}
```
######Handler Runnable Service でのタイマー事例のサンプルコード
[参考にさせていただきました。ありがとうございます。こちら](https://dev.classmethod.jp/smartphone/android/android-tas/)
でもどうして、`myHandler.postDelayed(runnnable,milli)が2回呼ばれてるのか、ちょっとわからなかった。

<概要>
notification処理はしてないので、すぐにクラッシュします。
アプリ起動で自動的にForegroundServiceへ
ForegroundServiceで、handler.postDeployed(runnnable,mill)でタイマー処理
スタートボタンでカウント再開
ストップボタンでカウント停止

```MainActivity.java
public class MainActivity extends AppCompatActivity {
    public static TextView textView;
    static Handler myHandler = new Handler();
    boolean signal =false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnStart= findViewById(R.id.btnStart);
        Button btnStop = findViewById(R.id.btnStop);
        textView = findViewById(R.id.textView);

        final Intent intent = new Intent(this,MyService.class);
        startForegroundService(intent);
        
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(signal == false){
                    MyService.runnable.run();
                    signal = true;
                }
            }
        });

        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myHandler.removeCallbacks(MyService.runnable);
                signal = false;
            }
        });
    }
}

```
```MyService.java
public class MyService extends Service {
    static Runnable runnable;
    public MyService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startid) {

        runnable = new Runnable() {
            int i=0;
            @Override
            public void run() {
                i++;
                String st = String.valueOf(i);
                MainActivity.textView.setText(st);
                MainActivity.myHandler.postDelayed(this,1000);
            }
        };
        
//        MainActivity.myHandler.postDelayed(runnable,1000);
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
```