1. 程式人生 > >使用Retrofit和淘寶IP地址庫查詢IP

使用Retrofit和淘寶IP地址庫查詢IP

概述

Retrofit官方主頁
Retrofit是為Java和Android打造的一個型別安全的HTTP客戶端API。使得對Web方面知之甚少的開發者也可以方便地使用網路請求,省略了TCP複雜的過程,可以實現快速開發,高效使用。這篇部落格記錄了使用Retrofit從淘寶IP地址庫查詢IP地址資訊的經過。免費的API,不需要註冊,安利一波。

開發環境

Android Studio 1.5.1
Windows 10 64 bit
和github的正常穩定連線

開動

1.新建一個AS專案

2.修改xml檔案

不需要什麼UI,一個EditText,一個Button,一個TextView就好。可以把TextView弄得大一點,不然下面空一塊好醜。

3.修改gradle依賴檔案

要開啟那個app目錄下(Module:app字尾)
在裡面新增以下幾行:[新增前最好去檢查一下更新,把版本號換成最新的]

    compile 'com.squareup.retrofit2:converter-gson:2.0.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.0'

解釋一下這兩行程式碼吧,第一行的資訊在converter-gson ,從字面意思是“一個叫gson的轉換器”,其實它的意思就是字面意思。gson是google的一個解析json的工具,可以把json的鍵值對對映到一個類裡的物件。看過ip.taobao.com 就知道,伺服器傳回的是json資料,我們就是使用gson解析json。當然你也可以根據喜好選擇其他的工具。第二行,很顯然,自然就是建立和Retrofit框架的親密關係了。

然後sync一下,依賴就新增好了。Retrofit相關檔案會從網址上自己下好,用這段時間去在Activity裡關聯處理xml裡的基本元件是個不錯的選擇。

程式碼時間

1.在manifest檔案中宣告網路許可權。

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

2.根據API資訊適配框架

請求介面(GET):

/service/getIpInfo.php?ip=[ip地址字串]

返回資訊大概就是這樣子的:
已使用線上格式化工具格式化

{
    "code": 0
, "data": { "ip": "210.75.225.254", "country": "中國", "area": "華北", "region": "北京市", "city": "北京市", "county": "", "isp": "電信", "country_id": "86", "area_id": "100000", "region_id": "110000", "city_id": "110000", "county_id": "-1", "isp_id": "100017" } }

首先處理請求介面

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface RetrofitService {

    @FormUrlEncoded
    @POST("service/getIpInfo.php")
    Call<IPItem> queryIP(@Field("ip") String ip);

}

建立返回資料物件

然後根據返回資訊造個類,內容是code和data。然後再為data造個類。類裡面大概city, region, isp之類的,後面是字串就把型別改成字串。不用全部都弄上,我們並不是需要所有的資訊。最後alt+insert為它們新增get方法。
IPItem.java

public class IPItem {
    private int code;//status code
    private IPData data;

    public IPData getData() {
        return data;
    }

    public int getCode() {
        return code;
    }
}

IPData.java

public class IPData {
    private String region;//province
    private String city;
    private String country;
    private String isp;//Internet Service Provider
    private String country_id;

    public String getCountry() {
        return country;
    }

    public String getCountry_id() {
        return country_id;
    }

    public String getRegion() {
        return region;
    }

    public String getCity() {
        return city;
    }

    public String getIsp() {
        return isp;
    }

    public String toString() {
        return isp;
    }
}

在OnClickListener裡,首先

Retrofit retrofitIP = new Retrofit.Builder()
.baseUrl("http://ip.taobao.com/")                       .addConverterFactory(GsonConverterFactory.create())
.build();

然後繫結Service

 RetrofitService queryService = retrofitIP.create(RetrofitService.class);
 //RetrofitService.class是適配介面的類名。

然後通過Call發起請求:

Call<IPItem> call = queryService.queryIP(ip);
call.enqueue(new Callback<IPItem>() {……}

然後直接自動補全出 onResponse && onFailure 方法
在Response裡直接呼叫body()方法就可以將內容填充到類裡了。

IPItem ipItem = response.body();

下面是草民實現的一個版本:

btnQuery.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                final String ip = editIP.getText().toString();
                Retrofit retrofitIP = new Retrofit.Builder().baseUrl("http://ip.taobao.com/")
                        .addConverterFactory(GsonConverterFactory.create()).build();

                if (ip.isEmpty())
                    Log.e(TAG, "IP is Empty");
                else Log.i(TAG, ip);

                RetrofitService queryService = retrofitIP.create(RetrofitService.class);
                Call<IPItem> call = queryService.queryIP(ip);
                call.enqueue(new Callback<IPItem>() {
                    @Override
                    public void onResponse(Call<IPItem> call, Response<IPItem> response) {
                        IPItem ipItem = response.body();
                        StringBuilder result = new StringBuilder();
                        if (0 == ipItem.getCode()) {
                            IPData data = ipItem.getData();
                            if (!data.getCountry_id().equals("IANA")) {
                                result.append("IP:");
                                result.append(ip);
                                result.append("\n");
                                result.append("Location:");
                                result.append(data.getCountry());
                                result.append(data.getRegion());
                                result.append(data.getCity());
                                result.append(" ");
                                result.append(data.getIsp());
                                tvInfo.setText(result);
                            } else tvInfo.setText("未分配或者內網IP");
                        }
                    }

                    @Override
                    public void onFailure(Call<IPItem> call, Throwable t) {
                        Log.e(TAG, "QUERY FAILURE");
                    }
                });
            }
        });

寫在後面

實現效果
到此,基本的使用就這樣結束了。希望大家同時去閱讀一下官方的API文件,獲取更廣泛的使用。