Android网络编程,HTTP请求和Json解析

一. 基本网络请求类HttpURLConnection

以下代码模拟了点击按钮请求百度的网页源码:其中需要注意的是Android在API27之后不再支持明文访问HTTP,需要在manifest文件中配置属性允许使用明文访问,并且Url需要使用https

layout.xml


<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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Button
        android:id="@+id/web_btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击获取百度页面"
        android:textSize="20sp"
        android:layout_marginBottom="5dp"
        android:onClick="getHttpText"/>





    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/web_tv1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />


    ScrollView>

LinearLayout>

字节流转换字符串工具类:

public class HttpInputStreamParse {

    public static String parseInput(InputStream in) throws IOException {

        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        String temp;
        while((temp = br.readLine())!= null){
            sb.append(temp);
        }
        return sb.toString();
    }
}

主类.java:

public class MainActivity extends AppCompatActivity {

    private static final String HTTP_ADDRESS = "https://www.baidu.com";
    private TextView tv1;
    private WebView wb1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1 = findViewById(R.id.web_tv1);
        //wb1 = findViewById(R.id.webview1);
    }

    public void getHttpText(View view) {
//        wb1.loadUrl(HTTP_ADDRESS);
//        wb1.setWebViewClient(new WebViewClient(){
//            @Override
//            public boolean shouldOverrideUrlLoading(WebView view, String url) {
//                view.loadUrl(url);
//                return true;
//            }
//        });
new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(HTTP_ADDRESS);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(5000);
                    connection.connect();
                    int code = connection.getResponseCode();
                    if (code != HttpURLConnection.HTTP_OK) {
                        Log.d("NETWORK",code+"");
                    }// 200;

                    InputStream inputStream = connection.getInputStream();
                    final String rec = HttpInputStreamParse.parseInput(inputStream);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv1.setText(rec);
                        }
                    });//这里使用handler也可以与主线程通信
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

}

配置manifest.xml文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.hait.cs.networkdemo">

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

    <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/Theme.NetworkDemo"
        android:usesCleartextTraffic="true"
        >
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>
    application>

manifest>

二. 使用webveiw控件

将上述代码中的webview相关内容解除注释即可得到一个显示的网页,webview的内容显示会将下方源码挤出布局空间。

同时可以使用webview处理添加html和JavaScript文件,这里不再赘述。

三. Json解析

可以在AS中的main文件夹下生成assets文件夹注意不要写错,将Json数据添加至此(在assets文件夹下新建文件后缀xxx.json即可),调用this.getResources().getAssets().open("json路径名")获得一个InputStream对象,转成字符串后可以调用JSONObject对象的optXXX()方法解析Json中的key值从而得到value的值,需要注意数据类型。

json对象:

{
  "name": "张三",
  "age" : 24,
  "married":false
}

json对象数组

[
  {"name": "张三",
    "age" : 24,
    "married":false
  },
  {"name": "阿珍",
    "age" : 25,
    "married":true
  },
  {"name": "阿强",
    "age" : 26,
    "married":true
  }
]

其中json对象中的属性可以是一个json对象,例如添加属性”address“,其可以是一个json对象包含省,市,区等多个属性

除此之外,json对象的属性也可以是一个数组,例如属性"hobby"可以是[ 唱、跳、rap、篮球 ]

可以使用一些软件模拟在线的json请求,例如postman和apipost等。

以下代码演示了如何解析一个json对象,布局文件省略,大致是点击按钮,解析asset文件夹下的一个json对象文件,将解析结果用textview展示出来。

主类.java

public class JsonParseActivity extends AppCompatActivity {

    private TextView tv1;
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_json_parse);
        tv1 = findViewById(R.id.json_tv1);
    }

    public void parseJson(View view) {
        try {
            InputStream open = this.getResources().getAssets().open("weather.json");
            String json = HttpInputStreamParse.parseInput(open);

            JSONObject jsonObject = new JSONObject(json);

            String name = jsonObject.optString("name");
            int age = jsonObject.optInt("age");
            String married = jsonObject.optString("married");

            tv1.setText(name+":"+age+":"+married);
        } catch (IOException | JSONException e) {
            e.printStackTrace();
        }


    }
}

解析Json数组:使用JsonArray获取输入流,之后遍历数组即可

parseJsons方法

public void parseJsons(View view) {
       try {
           InputStream open = this.getResources().getAssets().open("persons.json");
           String jsons = HttpInputStreamParse.parseInput(open);
           JSONArray jsonArray = new JSONArray(jsons);
           StringBuilder sb = new StringBuilder();
           for (int i = 0; i< jsonArray.length();i++){
               JSONObject jsonObject = jsonArray.getJSONObject(i);
               String name = jsonObject.optString("name");
               int age = jsonObject.optInt("age");
               String married = jsonObject.optString("married");
               sb.append(name+":"+age+":"+married);
               sb.append("\n");
           }
           tv2.setText(sb.toString());


       } catch (IOException | JSONException e) {
           e.printStackTrace();
       }
   }

四. 使用 Gson解析

使用google开发的第三方库Gson来解析json文件。

添加Gson依赖:选择module,open module settings,dependencies,添加依赖,输入关键字gson*添加对应版本的依赖库。

Gson解析时可以直接将json字符串转换为一个实体类对象,因此可以创建一个pojo包,将待解析的json文件按照对应属性来创建java bean类。

这里可以选择添加插件 gsonformat 或 gsonformat plus,在file选项卡下的settings内选择plugin选项卡搜索对应插件安装即可(mac os选择 Android Studio选项卡下的preference选项,选择plugin并搜索)。

pojo java bean: PersonBean.java

public class PersonBean {

    private String name;
    private int age;
    private boolean married;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }
public void setAge(int age) {
        this.age = age;
    }

    public boolean isMarried() {
        return married;
    }

    public void setMarried(boolean married) {
        this.married = married;
    }
}

使用gson解析json对象:直接给按钮写响应,在布局中构建onClick响应函数parseGson,在主类中创造此方法。

 public void parseGson(View view) {

        try {
            Gson gson = new Gson();
            InputStream open = this.getResources().getAssets().open("weather.json");
            String json = HttpInputStreamParse.parseInput(open);
            PersonBean personBean = gson.fromJson(json, PersonBean.class);
            String name = personBean.getName();
            String age = String.valueOf(personBean.getAge());
            String married = String.valueOf(personBean.isMarried());
            tv1.setText(name+":"+age+":"+married);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

上述做法直接转换为类对象

使用gson解析json数组:直接给按钮写响应,在布局中构建onClick响应函数parseGsons,在主类中创造此方法

public void parseGsons(View view) {
        try {
            InputStream open = this.getResources().getAssets().open("persons.json");
            String json = HttpInputStreamParse.parseInput(open);
            Gson gson = new Gson();
            Type type = new TypeToken<List<PersonBean>>(){}.getType();
            List<PersonBean> personList = gson.fromJson(json, type);
            StringBuilder sb = new StringBuilder();
            for (PersonBean pb:personList){
                String name = pb.getName();
                String age = String.valueOf(pb.getAge());
                String married = String.valueOf(pb.isMarried());
                sb.append(name+":"+age+":"+married);
                sb.append("\n");
            }
            tv2.setText(sb.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

上述代码关键语句在构建type对象,new出TypeToken的实例获取type对象,将json数组转成javabean泛型的集合。最后遍历集合进行操作即可。
附加问题:更加复杂的json文件进行解析,例如json文件:

[
  {
    "name": "zhangsan",
    "age": 18,
    "married": false,
    "zhifubao": {
      "account": "zhangsan",
      "balance": 10000
    },
    "hobby": ["sing","dance","basketball"]
  },
  {
    "name": "lisi",
    "age": 19,
    "married": false,
    "zhifubao": {
      "account": "lisi",
      "balance": 20000
    },
    "hobby": ["idol","rap","walking-dead"]
  }
]

上述文件是一个json数组,数组内两个json对象,其中json对象中属性“zhifubao”又是一个json对象,且属性“hobby”是一个json数组。

解析上述文件时,可参考插件自动构建javabean,外围的json数组一定是一个集合,集合内对象类型为javabean,每一个javabean类中有各种属性,对于复杂属性“zhifubao”,可将其再次构建javabean,内有属性“account”,“balance”。相当于构建支付宝实体类。对于复杂属性“hobby”,其数据类型为一个字符串集合。

你可能感兴趣的:(Android开发,android,http,json)