Android中基於心知天氣API獲取天氣信息


爲什麼要寫這篇博客,主要是爲了鞏固一下JSON的知識,所以大家會看到很多偏文字的講解,當然最後的代碼我會貼出來,這點不必擔心,如果不想看講解可以直接跳到實現部分,也可以直接下載源碼,免費的.

JSON

JSON簡介

JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。易於人閱讀和編寫。同時也易於機器解析和生成。它基於JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一個子集。 說人話就是“JSON是一種是有一定順序的數組/對象”。

JSON對象

JSON對象特徵就是多個屬性是被 {} 括起來的,下面這就是一個JSON對象。
{
“area”: “北京海淀”,
“name”: “李大嘴”,
“age”: 25
}

JSON數組

JSON 數組其實就是包含了多個 JSON 對象的一個集合,數組是以數組括號 [ ] 括起來的,可以看到這個JSON數組是由相同的JSON對象組成。咱們可以把它稱爲典型的JSON數組
[{
“area”: “廣東”,
“name”: “山雞哥”,
“age”: 25
}, {
“area”: “廣西”,
“name”: “布布”,
“age”: 26
}]
有典型的JSON數組,肯定也有非典型的JSON數組
[{
“area”: “江蘇”,
“name”: “徐州”,
“age”: 25
}, {
“city”: “江蘇”,
“weather”: “晴”,
}]

JSON解析

JSON解析的方式有挺多的,官方提供的是JSONObect解析,谷歌的開源庫GSON,還有一些第三方的開源庫比如:Jackson,FastJSON。我這裏選擇的是官方提供的JSONObject進行解析。具體的實現在後面的實現部分會細講。

Android中獲取天氣

獲取天氣的流程

1:找到一個免費的天氣API(心知天氣)
2:訪問API(需要API Key),得到JSON數據
3:解析JSON數據得到天氣信息

獲取心知天氣的API key

登錄心知天氣官網,當然你需要先進行註冊,登錄之後如下圖所示在這裏插入圖片描述
登錄之後點擊右上角的控制檯,如下圖所示
在這裏插入圖片描述
選擇產品管理下的添加產品,選擇免費版,當然你如果有錢選擇開發版或者企業版也是可以的。然後回到產品界面,可以看到我們獲取的公鑰,私鑰非常重要但是我們用不上,一個公鑰就夠了,我是閒着沒事又添加了一個密鑰。在這裏插入圖片描述

獲取心知天氣的API

點擊API文檔,可以查看心知天氣的API示例和說明,我這裏直接截圖下來。第一行就是API的示例,下面的API示例中的參數說明,應該不需要我多解釋吧,注意KEY後面填寫的就是我們獲取的API公鑰
在這裏插入圖片描述
那我們先訪問下這個API示例,你可以在瀏覽器的搜索框中輸入上圖中的示例,看看能得到什麼東西呢
在這裏插入圖片描述
這是什麼?這不就是JSON數據嗎?我們大致可以看出裏面包含着城市,天氣,語言等等的信息,我們的任務要便是將這個JSON數據解析出來,變成到正常人能看懂的信息方式。

代碼部分

我們要使用OKhttp訪問該API,所以要添加OKhttp閉包,在build.Gradle的dependencies{}中添加如下代碼,添加後記得同步Gradle文件

 implementation 'com.squareup.okhttp3:okhttp:3.4.1'

AndroidMainfest.xml
添加一行權限(申請網絡權限)

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

activity_main.xml

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

<Button
    android:id="@+id/send_request"
    android:text="Send_request"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
    <TextView
        android:hint="原始JSON數據"
        android:id="@+id/response"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
  <EditText
      android:hint="city"
      android:id="@+id/City"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"/>
    <EditText
        android:hint="weather"
        android:id="@+id/Weather"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <EditText
        android:hint="temperature"
        android:id="@+id/Temperature"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

MainActivity.xml

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView responseText;
    private EditText weather;
    private EditText city;
    private EditText temperature;
    private String Weather;
    private String CityName;
    private String Tempeature;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button sendRequest = (Button) findViewById(R.id.send_request);
        responseText = (TextView) findViewById(R.id.response);
        weather = (EditText) findViewById(R.id.Weather);
        city = (EditText) findViewById(R.id.City);
        temperature = (EditText) findViewById(R.id.Temperature);
        sendRequest.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.send_request) {
            sendRequestWithOkHttp();
        }
    }

    private void sendRequestWithOkHttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();//創建一個OkHttp實例
                    Request request = new Request.Builder().url("https://api.seniverse.com/v3/weather/now.json?key=SrvH71t8JeTOXNLJP&location=beijing&language=zh-Hans&unit=c").build();//創建Request對象發起請求,記得替換成你自己的key
                    Response response = client.newCall(request).execute();//創建call對象並調用execute獲取返回的數據
                    String responseData = response.body().string();
                    showResPonse(responseData);//顯示原始數據和解析後的數據
                    parseJSONWithJSONObject(responseData);//解析SSON數據
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseJSONWithJSONObject(String jsonData) {//用JSONObect解析JSON數據
        try {
            JSONObject jsonObject = new JSONObject(jsonData);  
            JSONArray results = jsonObject.getJSONArray("results");   //得到鍵爲results的JSONArray
            JSONObject now = results.getJSONObject(0).getJSONObject("now");//得到鍵值爲"now"的JSONObject
            JSONObject location = results.getJSONObject(0).getJSONObject("location");   //得到鍵值爲location的JSONObject
            Weather = now.getString("text");//得到"now"鍵值的JSONObject下的"text"屬性,即天氣信息
            CityName = location.getString("name");  //獲得城市名
            Tempeature = now.getString("temperature"); //獲取溫度
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void showResPonse(final String response) {
        runOnUiThread(new Runnable() {//切換到主線程,ui界面的更改不能出現在子線程,否則app會崩潰
            @Override
            public void run() {
                responseText.setText(response);
                city.setText(CityName);
                weather.setText(Weather);
                temperature.setText(Tempeature);
            }
        });
    }
}

實現的效果如下

我只解析了其中的天氣,溫度和城市三個信息,其他的硬套應該不難,

進階-獲取任意城市的天氣信息

如果我想獲得任意一個城市的天氣,應該如何實現呢?其實很簡單,只要把API的地址中location的值改成可以輸入的值即可.重複代碼太多我就不想多寫了,我會把源碼一併上傳,可供大家參考.實現效果如下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章