環境
- Android Studio 3.0
- Kotlin 1.2
やりたいこと
URL指定したらHTTPリクエストしてデータを取得、表示まで
基礎を学ぶ用なので必要最低限のコードのみ
ライブラリの追加
自分でゴリゴリHttpURLConnection書くのはツラみがあるのでokhttpというライブラリを使う。
元々JavaのライブラリだがKotlinにも対応しているので問題ない。古いQiitaの記事とかだと未対応だから~って書いてあるが。
build.gradleのdependencies項目に以下を追記 これだけ
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) (略) compile 'com.squareup.okhttp3:okhttp:3.10.0' }
コード
先にMainActivityにid=mytextのテキストビューを追加しておく
外部からデータを取得するメソッド ふつうはJSONとかだが、サンプルとしてここではGoogleのサイトを取得している
class MainActivity : AppCompatActivity() { (略) } fun getHtml(): String { val client = OkHttpClient() val req = Request.Builder().url("http://google.com").get().build() val resp = client.newCall(req).execute() return resp.body()!!.string() }
次にパーミッション。AndroidManifest.xmlに<uses-permission android:name="android.permission.INTERNET" />
を追加
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.user.fetchsample"> <application> (略) </application> <uses-permission android:name="android.permission.INTERNET" /> </manifest>
でメインの処理を書く。が、以下は動きそうで動かない ネットワーク通信はメインスレッドで行っていけなく、非同期通信しなければならない。(android.os.NetworkOnMainThreadExceptionが発生する)
// NOT WORK class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val tview = findViewById<TextView>(R.id.mytext) val result = getHtml() tview.setText(result)
仕方ないのでAsyncTaskを使う。AsyncTaskクラスを継承したMyAsyncTaskをMainActivityクラス内に記述。doInBackground()は非同期で行いたい処理の内容、onPostExecute()はdoInBackground()終了後にメインスレッドで実行される処理の内容である
inner class MyAsyncTask: AsyncTask<Void, Void, String>() { override fun doInBackground(vararg p0: Void?): String? { return getHtml() } override fun onPostExecute(result: String?) { super.onPostExecute(result) val tview = findViewById<TextView>(R.id.mytext) tview.setText(result) } }
で以下で非同期処理が実行される
MyAsyncTask().execute()
ソース全体は以下
package com.example.user.fetchsample import android.os.AsyncTask import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.widget.TextView import okhttp3.OkHttpClient import okhttp3.Request class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) MyAsyncTask().execute() } inner class MyAsyncTask: AsyncTask<Void, Void, String>() { override fun doInBackground(vararg p0: Void?): String? { return getHtml() } override fun onPostExecute(result: String?) { super.onPostExecute(result) val tview = findViewById<TextView>(R.id.mytext) tview.setText(result) } } } fun getHtml(): String { val client = OkHttpClient() val req = Request.Builder().url("http://google.com").get().build() val resp = client.newCall(req).execute() return resp.body()!!.string() }
サンプルとはいえgetHtml()がグローバルなところにいるのはいかがなものかと思いつつ、今日は眠いのでここまで