1. 使用 HttpURLConnection (Java 原生 API):这是最传统、最基础的方法,不需要引入任何第三方库,适合简单的下载任务。
  2. 使用 OkHttp (第三方库):这是目前 Android 开发中最流行、最推荐的 HTTP 客户端,它更高效、功能更强大(如异步请求、拦截器等),并且代码更简洁。

下面我将详细介绍这两种方法,并附上完整的代码示例和最佳实践。

android 下载网页代码怎么写
(图片来源网络,侵删)

使用 HttpURLConnection (原生 API)

这是 Java 标准库的一部分,在 Android 中可以直接使用。

核心步骤:

  1. 创建 URL 对象:将目标网址字符串转换为 java.net.URL 对象。
  2. 打开连接:调用 url.openConnection() 获取 HttpURLConnection 实例。
  3. 设置请求方法:通常设置为 GET
  4. 获取输入流:从连接中获取 InputStream,用于读取网页数据。
  5. 读取流数据:使用 BufferedReaderInputStream 中的数据一行行读出,并拼接成字符串。
  6. 关闭资源非常重要!finally 块中关闭 InputStreamBufferedReader,防止内存泄漏。

完整代码示例

添加网络权限

app/src/main/AndroidManifest.xml 文件中,必须在 <application> 标签之前添加网络权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.webdownload">
    <!-- 1. 添加网络访问权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        ...>
        ...
    </application>
</manifest>

在后台线程执行

android 下载网页代码怎么写
(图片来源网络,侵删)

网络操作不能在主线程(UI 线程)中进行,否则会抛出 NetworkOnMainThreadException 异常,我们使用 AsyncTask(简单场景)或 ExecutorService(更推荐)来处理。

这里使用 ExecutorService 作为示例:

import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static final String TARGET_URL = "https://www.example.com"; // 替换成你想下载的网址
    private TextView textViewResult;
    private Button buttonDownload;
    // 创建一个单线程的执行器
    private ExecutorService executor = Executors.newSingleThreadExecutor();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textViewResult = findViewById(R.id.text_view_result);
        buttonDownload = findViewById(R.id.button_download);
        buttonDownload.setOnClickListener(v -> {
            // 在后台线程中执行下载任务
            executor.execute(() -> {
                String htmlContent = downloadWebPage(TARGET_URL);
                // 切换回主线程更新UI
                runOnUiThread(() -> {
                    if (htmlContent != null) {
                        textViewResult.setText(htmlContent);
                        Toast.makeText(MainActivity.this, "下载成功!", Toast.LENGTH_SHORT).show();
                    } else {
                        textViewResult.setText("下载失败,请检查网络或网址。");
                        Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
                    }
                });
            });
        });
    }
    /**
     * 下载网页代码的核心方法
     * @param urlString 目标网址
     * @return 网页的HTML代码,失败则返回null
     */
    private String downloadWebPage(String urlString) {
        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;
        StringBuilder response = new StringBuilder();
        try {
            // 1. 创建URL对象
            URL url = new URL(urlString);
            // 2. 打开连接
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET"); // 设置请求方法
            urlConnection.setConnectTimeout(15000); // 连接超时时间 (毫秒)
            urlConnection.setReadTimeout(15000);  // 读取超时时间 (毫秒)
            urlConnection.connect(); // 实际建立连接
            // 3. 检查响应码是否为 200 (OK)
            int responseCode = urlConnection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                // 4. 获取输入流
                InputStream inputStream = urlConnection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream));
                // 5. 读取流数据
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                    response.append("\n"); // 保持换行
                }
            } else {
                Log.e(TAG, "Error: Server returned HTTP code: " + responseCode);
                return null;
            }
        } catch (IOException e) {
            Log.e(TAG, "Error downloading webpage", e);
            return null;
        } finally {
            // 6. 关闭资源
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(TAG, "Error closing reader", e);
                }
            }
        }
        return response.toString();
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 关闭线程池,防止内存泄漏
        executor.shutdown();
    }
}

布局文件 (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"
    android:padding="16dp">
    <Button
        android:id="@+id/button_download"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="下载网页代码" />
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="16dp">
        <TextView
            android:id="@+id/text_view_result"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="点击按钮开始下载..."
            android:textSize="12sp" />
    </ScrollView>
</LinearLayout>

使用 OkHttp (推荐)

OkHttp 是一个现代的、高效的 HTTP 客户端,它极大地简化了网络请求的代码。

android 下载网页代码怎么写
(图片来源网络,侵删)

核心步骤:

  1. 添加依赖:在 build.gradle 文件中添加 OkHttp 库。
  2. 创建 OkHttpClient 实例:这是一个客户端对象,可以被复用。
  3. 构建 Request 对象:定义请求的 URL、方法、头信息等。
  4. 发起异步请求:使用 client.newCall(request).enqueue() 发起请求,并在回调中处理结果。

完整代码示例

添加依赖和权限

app/build.gradle (Module: app)

dependencies {
    // ... 其他依赖
    implementation("com.squareup.okhttp3:okhttp:4.12.0") // 使用最新版本
}

AndroidManifest.xml:和方法一一样,需要添加 INTERNET 权限。

修改 MainActivity.java

import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity_OkHttp";
    private static final String TARGET_URL = "https://www.example.com";
    private TextView textViewResult;
    private Button buttonDownload;
    private OkHttpClient client;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textViewResult = findViewById(R.id.text_view_result);
        buttonDownload = findViewById(R.id.button_download);
        // 1. 创建 OkHttpClient 实例 (通常在 Application 或单例中创建)
        client = new OkHttpClient();
        buttonDownload.setOnClickListener(v -> {
            // 2. 构建 Request 对象
            Request request = new Request.Builder()
                    .url(TARGET_URL)
                    .build();
            // 3. 发起异步请求
            client.newCall(request).enqueue(new okhttp3.Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    // 请求失败
                    Log.e(TAG, "Request failed", e);
                    runOnUiThread(() -> {
                        textViewResult.setText("下载失败: " + e.getMessage());
                        Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
                    });
                }
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    // 请求成功
                    if (response.isSuccessful()) {
                        // 4. 从响应体中获取字符串
                        final String htmlContent = response.body().string();
                        runOnUiThread(() -> {
                            textViewResult.setText(htmlContent);
                            Toast.makeText(MainActivity.this, "下载成功!", Toast.LENGTH_SHORT).show();
                        });
                    } else {
                        // 服务器返回了错误状态码 (如 404, 500)
                        runOnUiThread(() -> {
                            textViewResult.setText("下载失败: Server error " + response.code());
                            Toast.makeText(MainActivity.this, "下载失败: Server Error", Toast.LENGTH_SHORT).show();
                        });
                    }
                }
            });
        });
    }
}

总结与对比

特性 HttpURLConnection OkHttp
易用性 代码较繁琐,需要手动处理流、连接关闭等 非常简洁,回调式设计,代码可读性高
功能 基础的 HTTP/HTTPS 功能 功能强大:支持 HTTP/2、连接池、拦截器、WebSocket 等
性能 性能一般,每个请求可能创建新连接 性能优异,内置连接池,可复用连接,减少延迟
依赖 无需额外依赖(Java 标准库) 需要添加第三方库依赖
推荐场景 简单的 demo、学习网络基础、无法添加第三方库的项目 所有生产环境项目,特别是需要高性能和复杂网络交互的场景

对于任何新的 Android 项目,强烈推荐使用 OkHttp,它已经成为 Android 开发的事实标准,能让你更专注于业务逻辑而不是网络实现的细节。HttpURLConnection 虽然原生,但在实际开发中已经很少被直接使用了。