Android开发--Lesson09--网络编程

Android网络编程的概念

HttpURLConnection 是 Java 提供的一个用于执行 HTTP 请求的类,它允许你通过 HTTP 或 HTTPS 协议与网络服务器进行通信。下面是 HttpURLConnection 的工作原理、执行原理以及执行流程的详细说明。

工作原理

HttpURLConnection 作为 Java 标准库的一部分,提供了一种简单的方式来发送和接收 HTTP 请求和响应。它封装了底层的网络通信细节,使开发者能够专注于构建请求和处理响应,而不需要深入了解 TCP/IP 或 HTTP 协议的具体实现。

主要功能

  • 发送 HTTP 请求(GET, POST, PUT, DELETE等)
  • 接收 HTTP 响应
  • 管理连接状态(如设置超时时间)
  • 处理输入输出流(读取响应数据、写入请求体)

执行原理

当你使用 HttpURLConnection 进行网络操作时,实际上是通过以下步骤来完成的:

  1. 建立连接:首先,你需要创建一个 URL 对象,并通过调用 openConnection() 方法获取一个 HttpURLConnection 实例。
  2. 配置请求:根据需要设置请求的方法(GET, POST 等)、请求头(如 Content-Type)、超时时间等属性。
  3. 发送请求:如果是 POST 或 PUT 请求,则需要向服务器发送数据;可以通过 OutputStream 写入数据到服务器。
  4. 接收响应:一旦请求被发送出去,就可以通过 InputStream 来读取服务器返回的数据。
  5. 关闭连接:无论请求是否成功,都应当关闭连接以释放资源。

 WebView

    <WebView
        android:id="@+id/wv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

 

在Android开发中,WebView 控件是一个非常强大的组件,它允许你在应用中嵌入网页内容。通过 WebView,你可以加载远程的网页、显示在线资源或渲染本地HTML内容。以下是 WebView 的一些主要作用和用途:

  • 使用 WebView 可以加载任何有效的URL,就像在浏览器中打开网页一样。这非常适合展示经常更新的内容或者需要频繁维护的信息,比如新闻文章、帮助文档等。
WebView webView = findViewById(R.id.webview);
webView.loadUrl("https://www.baidu.com");

 

  • 除了加载远程网页之外,WebView 还可以用来显示存储在设备上的HTML文件。这对于离线阅读或展示静态内容特别有用。
webView.loadUrl("file:///android_asset/filename.html");

 

需要注意的是 android_asset 指代的是assets包下面的静态资源文件,它只会扫描assets包下的文件,此包应该创建在app/src/main下

  • WebView 支持与JavaScript进行交互,使得开发者可以通过编写JavaScript代码来动态地控制网页内容,甚至可以从Java代码调用JavaScript函数,反之亦然。这为创建复杂的用户界面和功能提供了可能。
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);

 

只有配置上面的文件之后,才可以启动JS在andrid界面之上,对于一些大型网站,如百度这些网站必有JS文件,故而不开启上面的配置webView反而打开不了这个网站

  • WebViewloadDataWithBaseURL 方法用于加载包含基础 URL 和历史记录标题的数据。这个方法对于需要从字符串加载 HTML 内容到 WebView 中非常有用,并且允许你指定一个基础 URL 来解析相对 URL 链接。
public void loadDataWithBaseURL (String baseUrl, 
                String data, 
                String mimeType, 
                String encoding, 
                String historyUrl)
  1. baseUrl:用于解析页面中的相对 URL 链接的基础 URL。如果为 null 或者为空字符串,则认为所有链接都是绝对的。
  2. data:要加载的 HTML 数据内容。
  3. mimeType:数据的 MIME 类型。通常为 "text/html"
  4. encoding:字符编码格式,如 "utf-8" 或 "iso-8859-1"
  5. historyUrl:用于历史记录的 URL。可以是 null。这影响了当用户使用“后退”按钮时的行为,如果提供了这个参数,它将作为加载内容的虚拟URL存入浏览器的历史记录中。

测试

测试注意点,需要先完成网络的相关配置

 

 

测试如上的WebView提供的相关方法:

loadUrl加载assets文件夹的html:

 

        WebView wv = findViewById(R.id.wv);
        wv.loadUrl("file:///android_asset/qq_moment.html");

 

运行之后

 测试loadDataWithBaseURL

        WebView wv = findViewById(R.id.wv);
        String s = "<p><font color='red'>今天星期一</font></p>";
        wv.loadDataWithBaseURL(null, s,null,"utf-8",null);

 

运行之后:

 测试loadUrl并且开始JS

        // 获取WebView对象
        WebView wv = findViewById(R.id.wv);
        // 启用JavaScript
        wv.getSettings().setJavaScriptEnabled(true);
        // 设置WebChromeClient
        wv.setWebChromeClient(new WebChromeClient());
        // 加载网页
        wv.loadUrl("https://www.baidu.com");

 

运行测试

注意:loadDataWithBaseURL 和 loadUrl是对 WebView 同级加载,同时出现会发生覆盖的情况

 HttpURLConnection加载网络资源

在android API10之后从网络加载资源就不允许在主线程中了,故而我们需要为其单独创建一个新的线程来加载网络资源

需要注意的是HttpURLConnection其实是Java的资源库实现的,故而Android的网络加载还是使用的Java的API

    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                // 创建 URL 对象
                URL url = new URL("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
                // 打开连接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                // 设置请求方法
                conn.setRequestMethod("GET");
                // 设置连接超时时间
                conn.setConnectTimeout(5000);
                // 获取输入流
                InputStream is = conn.getInputStream();

                // 解码成 Bitmap
                bitmap = BitmapFactory.decodeStream(is);
                // 关闭资源
                is.close();
                conn.disconnect();
            } catch (Exception e) {
                e.printStackTrace();
                // 打印错误信息
                Log.i("MyThread", "error:" + e.getMessage());
            }
        }
    }

 

然后如上实现之后了就可以在主线程中启动这个线程,并且将其加载的bitmap图像加载在ImageView中

    private Bitmap bitmap;
    private ImageView iv;
   //start()方法启动一个新的线程,run方法,在主线程普通运行方法
    new MyThread().start();
     iv = findViewById(R.id.iv);
     //设置bitmap到ImageView中
     iv.setImageBitmap(bitmap);

点击运行

 JSON数据解析

在 Android 开发中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它主要用于客户端与服务器之间的数据传输。Android 中的 JSON 数据解析指的是将从网络或其他来源获取的 JSON 格式字符串转换为 Java 对象或集合,以便于在应用中使用;反之亦然,即序列化 Java 对象为 JSON 字符串发送给服务器。

解析JSON数据需要使用到Goole的Gson开发工具包,可以在Gradle中导入

    // 确保版本号是最新的
    implementation 'com.google.code.gson:gson:2.8.9' 

 

完成导入之后就可以调用其方法解析数据:

我们的JSON数据是:

 解析JSON对象为Java对象需要为JSON格式对应一个实体类:

public class WeatherInfo {
    private String id;
    private String temp;
    private String weather;
    private String name;
    private String wind;

    @Override
    public String toString() {
        return "WeatherInfo{" +
                "id='" + id + '\'' +
                ", temp='" + temp + '\'' +
                ", weather='" + weather + '\'' +
                ", name='" + name + '\'' +
                ", wind='" + wind + '\'' +
                '}';
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    public String getName() {
        return name;
    }

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

    public String getWind() {
        return wind;
    }

    public void setWind(String wind) {
        this.wind = wind;
    }
}

 

然后这个json数据是放在assets包下的

 则可以使用getAssets()方法直接获得到这个包,然后打开包下对应的文件:

InputStream inputStream = getAssets().open("weather.json");

 

接下来可以使用一个创建一个WeatherService用来专门处理这里的json文件输入流:

public class WeatherService {
    // 从输入流中获取JSON数据,并解析为WeatherInfo对象列表
    public static List<WeatherInfo> getJSON(InputStream is) throws Exception{
        // 创建一个字节数组,用于存储从输入流中读取的数据
       //is.available() 可不阻塞地从此输入流读取(或跳过)的字节数
        byte[] buffer = new byte[is.available()];
        // 从输入流中读取数据,并存储到字节数组中
        is.read(buffer);
        // 关闭输入流
        is.close();
        // 将字节数组转换为字符串
        String json = new String(buffer,"utf-8");
        // 创建Gson对象
        Gson gson = new Gson();
        // 创建Type对象,用于指定解析后的数据类型
        Type listType = new TypeToken<List<WeatherInfo>>(){}.getType();
        // 使用Gson对象将JSON字符串解析为WeatherInfo对象列表
        List<WeatherInfo> weatherInfos = gson.fromJson(json,listType);
        // 返回解析后的WeatherInfo对象列表
        return weatherInfos;
    }
}

 

接着在调用此对象的getJSON方法,将刚刚读取到的流传入,让其转换为我们定义的WeatherInfo的Java对象处理:

            InputStream inputStream = getAssets().open("weather.json");
            List<WeatherInfo> weatherInfoList = WeatherService.getJSON(inputStream);

 

然后就可以循环的读取这个list中的对象信息,并且将其输出到页面上:

 TextView tv = findViewById(R.id.tv);
        try{
            InputStream inputStream = getAssets().open("weather.json");
            List<WeatherInfo> weatherInfoList = WeatherService.getJSON(inputStream);
            String s = "";
            for (int i=0;i<weatherInfoList.size();i++){
                s +="编号:"+weatherInfoList.get(i).getId()
+ ",城市:" + weatherInfoList.get(i).getName() 
+ ",温度:" + weatherInfoList.get(i).getTemp() 
+ ",天气:" + weatherInfoList.get(i).getWeather() 
+ ",风力:" + weatherInfoList.get(i).getWind() + "\n";
            }
            // 将拼接好的天气信息设置到 TextView 上显示
            tv.setText(s);
        }catch (Exception e){
            e.printStackTrace();
        }

 

测试结果:

多学一招:解析JSON的其它方式 

使用原生 org.json

Android SDK 自带了对 JSON 的支持,主要通过 JSONObjectJSONArray 类来实现。

  • JSONObject: 用于表示一个对象(键值对的无序集合)。
  • JSONArray: 用于表示一个数组(值的有序列表)。
String jsonData = "{\"name\":\"Tom\",\"age\":25}";
try {
    JSONObject jsonObject = new JSONObject(jsonData);
    String name = jsonObject.getString("name");
    int age = jsonObject.getInt("age");
} catch (JSONException e) {
    e.printStackTrace();
}

 

 

-----END-----

 

posted @ 2025-05-15 00:28  回忆也交给时间  阅读(44)  评论(0)    收藏  举报