処理そのものは簡単ですが、Android Studio ならではの、操作が満載です。
MainActivity.java
1) ボタンクリック
2) AsyncTask のインスタンスから、execute
3) doInBackground で非同期処理
4) onPostExecute で UI スレッド処理
package app.lightbox.winofsql.jp.httpget;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new AsyncTask<String, Void, String>() {
@Override
protected String doInBackground(String... params) {
HttpGet hg = new HttpGet();
String result = hg.execute(params[0],params[1]);
return result;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
TextView tv = (TextView) MainActivity.this.findViewById(R.id.textView);
tv.setText(s);
}
}.execute("http://weather.livedoor.com/forecast/webservice/json/v1?city=270000", "utf-8");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
AsyncTask の概要
( AsyncTaskは、UIスレッドの適切かつ容易な使用を可能にします )
AsyncTask<String, Void, String> の一つ目の String は、doInBackground の引数の型です。実際には、文字列の配列で、doInBackground へ引き渡されます。最後の String は、onPostExecute の引数の型で、doInBackground の戻り値でもあります。つまり、非同期スレッドから、UI スレッドへの引渡しが String だと言う事です。
仕様として、インターネットへのアクセスは非同期処理で実行する必要があるので、doInBackground で行いますが、そこから直接画面の操作ができないので、onPostExecute で処理する事になります。onPostExecute で必要な情報は、基本的には doInBackground の戻り値でまかなうようになっています。
さらに、真ん中の Void は、onProgressUpdate と言う実行中の進行状況の処理に使われますが、ほぼ使わないので Void にしています。面倒ならば、AsyncTask<String, String, String> でもいいです。
関連情報
▼ HttpGet クラスについてはこちら
Eclipse + JFace : HttpURLConnection で GET
▼ 呼び出している API についてはこちら
お天気Webサービス仕様 - Weather Hacks - livedoor 天気情報
▼ API をもっとテストしやすくする情報はこちら
Livedoor の お天気Webサービス API は、JSON のテストするのに重宝しています。
インターネットにアクセスするので、AndroidManifest を変更
<u と入力すると候補が表示されます( CTRL + SPACE でも表示されます )
uses-permission を選択すると、次は属性値の候補
終了タグ無しで閉じたい( つまり入力の完了 )は、CTRL + SHIFT + ENTER です。
入力が完了しました
styles.xml (v21) の変更
最小バージョンを Android 5.1.1 にしていると、画面のタイトル部分が白くなってコンテンツとの境界がわかり難いので変更します。最小バージョンを Android 4 にしていると、そうはならないと思います。( 古いほうに合わされるようです )
▼ AndroidManifest の要領で以下のように変更します。
ボタンイベントの作成
基本的に問題は『ALT + Enter』で解決して行きます。ほぼ勝手に import とかしてくれますが、候補が出る事もあります。
上では、まだ Button をタイプしたけれど、import はされていません。しかし、ALT + Enter で import されます。
上の状態では、import は終わっていますが、お約束のキャストがされていません。左に表示されているアイコンを開くと、キャストの選択肢が現れます。
▼ イベント作成
イベントの setOnClickListener を候補から選択します。
引数の中で new と入力すると、候補が現れて、選択すると自動的に処理用のブロックが作成されます
記述完了です
AsyncTask の入力も基本的には同じようなものです。ただ、@Override の選択は、ブロック内の挿入可能箇所で、CTRL + O で表示されるダイアログで選択します。
さて、画面作成
ボタンの下に ScrollView を配置して、その中に TextView を使って長い JSON の文字列をスクロールして表示できるようにしています
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/scrollView"
android:layout_alignParentStart="false"
android:layout_below="@+id/button"
android:fillViewport="false">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:textSize="16sp"/>
</ScrollView>
</RelativeLayout>
ボタン
ボタンは、デザイナで適当に配置して、wrap_content( 表示内容に合わせる ) です。
ScrollView
その下にデザイナから ScrollView を配置すると、android:layout_below が設定されますが、これはプロパティからは layout:alignComponent の中で設定されています。実際の内容と、Android Studio のプロパティ表現が違う場合があるので注意です。さらに、プロパティからは、fill_parent( 親に対して最も大きく ) を設定して、ボタンの下いっぱいのスクロールビューを完成させます。
TextView
デサイナからはうまく入らないかもしれないですが、エディタで ScrollView 内に配置すればいいと思います。横幅のみ、fill_parent にして、高さは、wrap_content です。
テキストサイズは数字を入力すると、Android Studio の仕様だと思いますが、単位が dp になります。しかし、結局左側に問題解決用のアイコンが出て、sp に変更するようになります。