3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Android Studioで非同期処理とWeb API連携

Last updated at Posted at 2019-06-24

技術書を見ながら、APIを使って天気情報を取得するアプリを作成。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--都市リストを表示する-->
    <ListView
        android:id="@+id/lvCityList"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.5" />

    <!--お天気情報を表示する画面下半分のレイアウト-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:layout_weight="0.5"
        android:orientation="vertical">

        <!--「お天気詳細」と表示する-->
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:gravity="center"
            android:text="@string/tv_winfo_title"
            android:textSize="25dp"
            />

        <!--都市名と天気を横並びにするためのレイアウト-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="10dp"
            android:orientation="horizontal">

            <!--都市名の表示-->
            <TextView
                android:id="@+id/tvCityName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="20sp"/>

            <!--天気を表示する-->
            <TextView
                android:id="@+id/tvWeatherTelop"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:textSize="20sp"/>
        </LinearLayout>

        <!--天気の詳細情報部分がスクロールできるようにする画面部品-->
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <!--天気の詳細情報を表示する-->
            <TextView
                android:id="@+id/tvWeatherDesc"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:textSize="15dp"/>
        </ScrollView>
    </LinearLayout>
</LinearLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.asyncsample">

    <uses-permission
        android:name="android.permission.INTERNET"/>
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
strings.xml
<resources>
    <string name="app_name">お天気情報</string>
    <string name="tv_winfo_title">お天気詳細</string>

</resources>
MainActivity.java
package com.example.asyncsample;

import androidx.appcompat.app.AppCompatActivity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

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

//        画面部品ListViewを取得
        ListView lvCityList = findViewById(R.id.lvCityList);
//        SimpleAdapterで使用するListオブジェクトを用意
        List<Map<String, String>> cityList = new ArrayList<>();
//        都市データを格納するMapオブジェクトの用意とcityListへのデータ登録
        Map<String, String> city = new HashMap<>();
        city.put("name", "大阪");
        city.put("id", "270000");
        cityList.add(city);
        city = new HashMap<>();
        city.put("name", "神戸");
        city.put("id", "280010");
        cityList.add(city);

//        SimpleAdapterで使用するfrom-to用変数の用意
        String[] from = {"name"};
        int[] to = {android.R.id.text1};
//        SimpleAdapterを設定
        SimpleAdapter adapter = new SimpleAdapter(MainActivity.this, cityList, android.R.layout.simple_expandable_list_item_1, from, to);
//        ListViewにSimpleAdapterを設定
        lvCityList.setAdapter(adapter);
//        ListViewにリスナを設定
        lvCityList.setOnItemClickListener(new ListItemClickListener());
    }

//    リストが選択された時の処理が記述されたメンバクラス
    private class ListItemClickListener implements AdapterView.OnItemClickListener{
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id){
//            ListViewでタップされた行の都市名と都市IDを取得
            Map<String, String> item = (Map<String, String>) parent.getItemAtPosition(position);
            String cityName = item.get("name");
            String cityId = item.get("id");
//            取得した都市名をtvCityNameに設定
            TextView tvCityName = findViewById(R.id.tvCityName);
            tvCityName.setText(cityName + "の天気:");
//            天気情報を表示するTextViewを取得
            TextView tvWeatherTelop = findViewById(R.id.tvWeatherTelop);
//            天気詳細情報を表示するTextViewを取得
            TextView tvWeatherDesc = findViewById(R.id.tvWeatherDesc);
//            WeatherInfoReceiverをnew。引数として上で取得したTextViewを渡す。
            WeatherInfoReceiver receiver = new WeatherInfoReceiver(tvWeatherTelop, tvWeatherDesc);
//            WeatherInfoReceiverを実行
            receiver.execute(cityId);
        }
    }

    private class WeatherInfoReceiver extends AsyncTask<String, String, String> {
//        現在の天気を表示する画面部品フィールド
        private TextView _tvWeatherTelop;

//        天気の詳細を表示する画面部品フィールド
        private TextView _tvWeatherDesc;

//        コンストラクタ
//        お天気情報を表示する画面部品をあらかじめ取得してフィールドに格納している
        public WeatherInfoReceiver(TextView tvWeatherTelop, TextView tvWeatherDesc){
            _tvWeatherTelop = tvWeatherTelop;
            _tvWeatherDesc = tvWeatherDesc;
        }
        @Override
        public String doInBackground(String... params){
//            可変長引数の1個目(インデックス0)を取得。これが都市ID。
            String id = params[0];
//            都市IDを使って接続URL文字列を作成
            String urlStr = "http://weather.livedoor.com/forecast/webservice/json/v1?city=" + id;
//            天気情報サービスから取得したJSON文字列。天気情報が格納されている。
            String result = "";
//            ここに上記URLに接続してJSON文字列を取得する処理を記述
//            JSON文字列を返す
            HttpURLConnection con = null;

            InputStream is = null;
            try{
                URL url = new URL(urlStr);
                con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
                con.connect();
                is = con.getInputStream();
                result = is2String(is);
            }
            catch(MalformedURLException ex){

            }
            catch(IOException ex){

            }
            finally{
                if(con != null){
                    con.disconnect();
                }
                if(is != null){
                    try{
                        is.close();
                    }
                    catch(IOException ex){

                    }
                }
            }
            return result;
        }
        @Override
        public void onPostExecute(String result){
//            天気情報用文字列変数を用意
            String telop = "";
            String desc = "";
            try{
                JSONObject rootJSON = new JSONObject(result);
                JSONObject descriptionJSON = rootJSON.getJSONObject("description");
                desc = descriptionJSON.getString("text");
                JSONArray forecasts = rootJSON.getJSONArray("forecasts");
                JSONObject forecastNow = ((JSONArray) forecasts).getJSONObject(0);
                telop = forecastNow.getString("telop");
            }
            catch(JSONException ex){

            }
//            ここに天気情報JSON文字列を解析する処理を記述。
//            天気情報用文字列をTextViewにセット
            _tvWeatherTelop.setText(telop);
            _tvWeatherDesc.setText(desc);
        }

    }
    private String is2String(InputStream is) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        StringBuffer sb = new StringBuffer();
        char[] b = new char[1024];
        int line;
        while(0 <= (line = reader.read(b))){
            sb.append(b, 0, line);
        }
        return sb.toString();
    }
}
3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?