[Android] IntentServiceによる非同期処理


#*2020/1/16追記
Serviceと違い、IntentServiceではstopSelf()やstopServiceで明示的にサービスを終了しなくても自動で終了する。
https://akira-watson.com/android/intentservice.html

##記事の背景
前回BindServiceについて紹介した。https://qiita.com/QiitaD/items/5c313076b7b99823ce1a
次にBindServiceを使ってHTTP通信を行いたかったが、非同期処理できなかったので、今回はIntentServiceで実装してみたいと思う。

##作るもの
TomCatを使ってサーバから、ボタン押下により0～7の数をランダムに取得し、表示するプログラム。
以前AsyncTaskを用いて似たようなことをしたので参考にして頂きたい。

・AsyncTaskを継承したクラス内に書いたHTTP通信プログラム
https://qiita.com/QiitaD/items/79228417a68c51090a4e

・サーバ側のプログラム
https://qiita.com/QiitaD/items/b60a0baecbd1fa1d3ce8

##使い方
IntentServiceを呼び出すにはstartService()を使う。

~~~java
final Intent intent = new Intent(MainActivity.this, HttpConnectionIntentService.class);
startService(intent);
~~~

またIntentServiceを継承したクラスの実装は以下の通りである。

~~~java
public class HttpConnectionIntentService extends IntentService {

    public HttpConnectionIntentService(String name) {
        super(name);
    }

    //startServiceにより呼ばれるコンストラクタ
    public HttpConnectionIntentService() {
        super("HttpConnectionIntentService");
    }

    //重い処理を行うメソッド
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //通信処理を書く

        //IntentService内でServiceを終了したいときに呼ぶメソッド　呼び出し側で終了させたい場合はstopService(intent)を使う
        stopSelf();
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
    }
}
~~~

##結果
完成。
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506451/93b8d204-4470-6368-4960-1439d7699aea.png)

サンプルコードは一番下に乗せている。


##困ったところ
HTTP通信は非同期処理が必要であることを忘れ、BindServiceで実装しようとしていたので時間を取られた。IntentServiceを使うよう注意していただきたい。

##感想
BindServiceと比べると複雑ではないので使いやすいと感じた。ただし、明示的にServiceを終了しないと動作し続けることには注意したい。

##参考URL
・INTENTSERVICEを使って非同期処理を行う
https://techbooster.org/android/application/1570/

・Android非同期処理についてまとめる　メモ
https://qiita.com/tk_daze/items/bc83c69750e5f2e4015c

##サンプル
MainActivity.java

~~~java
public class MainActivity extends AppCompatActivity {

    Button buttonStartService_;
    public static Integer serverRandomnumber_ = -1;

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

        buttonStartService_ = (Button) findViewById(R.id.button_start_service);

        final Intent intent = new Intent(MainActivity.this, HttpConnectionIntentService.class);

        buttonStartService_.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startService(intent);
                TextView textView = findViewById(R.id.textview_get_server_random_number);
                textView.setText(String.valueOf(serverRandomnumber_));
            }
        });
    }
}
~~~

HttpConnectionIntentService.java

~~~java
public class HttpConnectionIntentService extends IntentService {

    public HttpConnectionIntentService(String name) {
        super(name);
    }

    public HttpConnectionIntentService() {
        super("HttpConnectionIntentService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        HttpConnection httpURLConnection = new HttpConnection() ;
        MainActivity.serverRandomnumber_ = httpURLConnection.fetchServerRandomNumber();
        stopSelf();
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
    }
}
~~~

HttpConnection.java

~~~java
public class HttpConnection {

    private final String URL_ = "任意のURL" ;
    private Integer serverRandomNumber_ = -1;
    private final String UTF_8_ = "utf-8";

    HttpURLConnection httpURLConnection_ = null;
    StringBuilder stringBuilder_ = new StringBuilder();
    BufferedReader bufferedReader_ = null;
    InputStream inputStream_ = null;
    InputStreamReader iuputStreamReader_ = null;

    public Integer fetchServerRandomNumber(){
        try {
            URL url = new URL(URL_);
            httpURLConnection_ = (HttpURLConnection) url.openConnection();
            httpURLConnection_.setRequestMethod("GET");
            httpURLConnection_.setConnectTimeout(15000);
            httpURLConnection_.setReadTimeout(15000);
            httpURLConnection_.connect();

            final int responseCode = httpURLConnection_.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_OK) {

                inputStream_ = httpURLConnection_.getInputStream();
                iuputStreamReader_ = new InputStreamReader(inputStream_, UTF_8_);
                bufferedReader_ = new BufferedReader(iuputStreamReader_);
                String line = null;
                while ((line = bufferedReader_.readLine()) != null) {
                    stringBuilder_.append(line);
                    serverRandomNumber_ = Integer.valueOf(new String(stringBuilder_));
                }
            } else {
                // If responseCode inputStream_ not HTTP_OK
            }
        } catch (java.io.IOException e) {
            e.printStackTrace();
        }finally {
            if (bufferedReader_ != null) {
                try {
                    bufferedReader_.close();
                } catch (IOException e) {
                }
            }
            if (iuputStreamReader_ != null) {
                try {
                    iuputStreamReader_.close();
                } catch (IOException e) {
                }
            }
            if (inputStream_ != null) {
                try {
                    inputStream_.close();
                } catch (IOException e) {
                }
            }
            if (httpURLConnection_ != null) {
                httpURLConnection_.disconnect();
            }
        }
        return serverRandomNumber_;
    }
}

~~~