方法概览
-
使用
HttpURLConnection(标准 Java API)- 优点: 不需要第三方库,是 Android SDK 自带的,轻量级。
- 缺点: 代码相对繁琐,需要手动处理线程和流。
- 适用场景: 简单的网络请求,不想引入第三方库时。
-
使用
OkHttp(强烈推荐)- 优点: 现代、高效、易用,内置了线程池、缓存、连接池等,是 Android 开发的事实标准。
- 缺点: 需要添加第三方库依赖。
- 适用场景: 几乎所有网络请求场景,特别是新项目。
-
使用
WebView- 优点: 可以完整地渲染一个网页,获取渲染后的最终源码(可能包含 JavaScript 动态生成的内容)。
- 缺点: 相对重量级,主要用于展示网页,获取源码是其附加功能。
- 适用场景: 需要获取经过 JavaScript 执行和修改后的最终 HTML 源码时。
核心前提:网络权限
无论使用哪种方法,你都必须在 AndroidManifest.xml 文件中声明网络权限。
<!-- 允许应用访问网络 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 如果你的应用目标 API 级别是 28 或更高,还需要声明 cleartextTrafficAllowed -->
<!-- 因为从 Android 9 (API 28) 开始,默认禁止 HTTP 明文传输 -->
<application
android:usesCleartextTraffic="true"
...>
...
</application>
使用 HttpURLConnection (原生方式)
这是最基础的方法,理解它有助于你了解网络请求的本质。
步骤:
- 在后台线程中发起请求(Android 4.0+ 不允许在主线程进行网络操作)。
- 创建
URL对象。 - 打开
HttpURLConnection连接。 - 设置请求方法(如
GET)。 - 获取输入流并读取数据。
- 将数据流转换为字符串(源码)。
- 关闭连接。
示例代码:
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
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;
public class MainActivity extends AppCompatActivity {
private TextView textView;
private Button button;
// 切换到主线程的 Handler
private Handler mainHandler = new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
button = findViewById(R.id.button);
button.setOnClickListener(v -> {
// 在新线程中执行网络请求
new Thread(new Runnable() {
@Override
public void run() {
try {
String htmlSourceCode = getHtmlSourceCode("https://www.example.com");
// 将结果更新到 UI
updateUI(htmlSourceCode);
} catch (IOException e) {
e.printStackTrace();
updateUI("Error: " + e.getMessage());
}
}
}).start();
});
}
private String getHtmlSourceCode(String urlString) throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(15000); // 15秒连接超时
connection.setReadTimeout(15000); // 15秒读取超时
// 获取响应码
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { // 200 OK
// 获取输入流
InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
inputStream.close();
return response.toString();
} else {
throw new IOException("HTTP GET Request Failed with Response Code: " + responseCode);
}
}
private void updateUI(final String result) {
// 切换回主线程更新 UI
mainHandler.post(() -> {
textView.setText(result);
Toast.makeText(MainActivity.this, "Source code loaded!", Toast.LENGTH_SHORT).show();
});
}
}
使用 OkHttp (推荐方式)
OkHttp 大大简化了网络请求的代码,并且性能更好,是目前 Android 开发的主流选择。
步骤:
- 在
build.gradle(Module: app) 文件中添加OkHttp依赖。 - 创建
OkHttpClient和Request对象。 - 使用
client.newCall(request).execute()(同步) 或client.newCall(request).enqueue()(异步) 发起请求。 - 处理响应体
response.body().string()获取源码。
添加依赖
打开你的 app/build.gradle 文件,在 dependencies 代码块中添加:
dependencies {
// ... 其他依赖
implementation("com.squareup.okhttp3:okhttp:4.12.0") // 使用最新版本
}
然后点击 "Sync Now"。
示例代码
OkHttp 的异步回调方式非常适合 Android。
import android.os.Bundle;
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.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivityOkHttp extends AppCompatActivity {
private TextView textView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 假设布局文件和上面一样
textView = findViewById(R.id.textView);
button = findViewById(R.id.button);
// 创建 OkHttpClient 实例
OkHttpClient client = new OkHttpClient();
button.setOnClickListener(v -> {
// 1. 创建 Request 对象
Request request = new Request.Builder()
.url("https://www.example.com")
.build();
// 2. 创建 Call 对象并异步执行
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 请求失败
// 切换到主线程更新 UI
runOnUiThread(() -> {
textView.setText("Error: " + e.getMessage());
Toast.makeText(MainActivityOkHttp.this, "Request Failed", Toast.LENGTH_SHORT).show();
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 请求成功
if (response.isSuccessful()) {
// 获取响应体字符串 (网页源码)
final String htmlSourceCode = response.body().string();
// 切换到主线程更新 UI
runOnUiThread(() -> {
textView.setText(htmlSourceCode);
Toast.makeText(MainActivityOkHttp.this, "Source code loaded!", Toast.LENGTH_SHORT).show();
});
} else {
runOnUiThread(() -> {
textView.setText("Error: " + response.code());
Toast.makeText(MainActivityOkHttp.this, "Request Failed with Code: " + response.code(), Toast.LENGTH_SHORT).show();
});
}
}
});
});
}
}
使用 WebView
这种方法不直接请求网络,而是通过加载网页,然后获取其 DOM 内容,它能拿到 JavaScript 执行后的最终 HTML。
步骤:
- 在布局文件中添加
WebView组件。 - 在代码中获取
WebView实例。 - 设置
WebViewClient,并在onPageFinished回调中获取源码。 - 启用 JavaScript(如果网页需要)。
布局文件 (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"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Load via WebView" />
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
示例代码
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivityWebView extends AppCompatActivity {
private WebView webView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webView);
button = findViewById(R.id.button);
// 启用 JavaScript (非常重要!)
webView.getSettings().setJavaScriptEnabled(true);
button.setOnClickListener(v -> {
// 加载网页
webView.loadUrl("https://www.example.com");
});
// 设置 WebViewClient
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// 页面加载完成后调用
// 可以在这里执行 JavaScript 来获取最终的 HTML
view.evaluateJavascript("(function() { return document.documentElement.outerHTML; })();", value -> {
// value 是 JavaScript 返回的结果,带有前后的引号,需要处理
String htmlSourceCode = value.substring(1, value.length() - 1);
// 在这里你可以得到最终的 HTML 源码
// 注意:直接在 logcat 中打印很长的字符串可能会被截断
android.util.Log.d("WebViewSource", "HTML Source: " + htmlSourceCode.substring(0, Math.min(500, htmlSourceCode.length())) + "...");
// 你可以将它显示在另一个 TextView 中
// textView.setText(htmlSourceCode);
});
}
});
}
}
总结与对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| HttpURLConnection | 无需第三方库,轻量 | 代码繁琐,功能少 | 简单学习,无依赖需求 |
| OkHttp | 代码简洁,功能强大,性能好 | 需要添加依赖 | 绝大多数网络请求场景的首选 |
| WebView | 能获取 JS 渲染后的最终 HTML | 资源消耗大,主要用于展示页面 | 需要与网页深度交互或抓取动态内容的场景 |
对于绝大多数获取网页源码的需求,强烈推荐使用 OkHttp,因为它在开发效率和性能之间取得了最佳平衡,只有当你明确需要获取经过 JavaScript 动态修改的 HTML 时,才考虑使用 WebView。
