凌峰创科服务平台

Android如何高效访问服务器HTML内容?

获取 HTML 字符串(最常见)

这是最基础的需求,比如你需要获取一个网页的 HTML 内容,然后从中解析出特定的信息(如标题、链接、价格等),这通常使用 HTTP 客户端 来完成。

Android如何高效访问服务器HTML内容?-图1
(图片来源网络,侵删)

在 Android 中,主要有两种主流的 HTTP 客户端库:

  1. OkHttp (强烈推荐): Android 开发的事实标准,由 Square 公司开发,性能优秀、API 简洁、功能强大。
  2. HttpURLConnection (原生 API): Java 标准库自带的,无需额外依赖,但 API 相对繁琐,功能也较少。

下面我们重点介绍 OkHttp 的使用方法。

步骤 1: 添加 OkHttp 依赖

在你的 app/build.gradle 文件中添加依赖:

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

步骤 2: 添加网络权限

app/src/main/AndroidManifest.xml 文件中添加网络访问权限:

Android如何高效访问服务器HTML内容?-图2
(图片来源网络,侵删)
<manifest ...>
    <!-- 必须添加的权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <application ...>
        ...
    </application>
</manifest>

步骤 3: 编写代码获取 HTML

由于网络请求不能在主线程(UI 线程)中执行,否则会抛出 NetworkOnMainThreadException 异常,我们有以下几种方式来处理异步请求:

方式 A: 使用 OkHttp 的 Callback (传统回调方式)

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
    private OkHttpClient client;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        client = new OkHttpClient();
        findViewById(R.id.button_fetch).setOnClickListener(v -> fetchHtml());
    }
    private void fetchHtml() {
        String url = "https://www.example.com"; // 替换成你的服务器地址
        Request request = new Request.Builder()
                .url(url)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 请求失败,在主线程更新UI
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "请求失败: " + e.getMessage(), Toast.LENGTH_SHORT).show());
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 请求成功
                if (response.isSuccessful()) {
                    final String htmlString = response.body().string();
                    // 注意:response.body().string() 只能被调用一次!
                    // 如果需要多次使用,请先将其保存起来。
                    // 在主线程更新UI
                    runOnUiThread(() -> {
                        // 将HTML显示在TextView中(对于长文本,建议使用ScrollView包裹的TextView)
                        TextView tvResult = findViewById(R.id.tv_result);
                        tvResult.setText(htmlString);
                        Toast.makeText(MainActivity.this, "获取成功!", Toast.LENGTH_SHORT).show();
                    });
                } else {
                    runOnUiThread(() -> Toast.makeText(MainActivity.this, "服务器返回错误: " + response.code(), Toast.LENGTH_SHORT).show());
                }
            }
        });
    }
}

方式 B: 使用 Kotlin Coroutines (更现代、推荐的方式)

如果你使用 Kotlin,结合协程可以让代码更简洁优雅。

Android如何高效访问服务器HTML内容?-图3
(图片来源网络,侵删)

build.gradle 中添加协程依赖:

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // 使用最新版本
}

在 Activity 中使用:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
class MainActivityKt : AppCompatActivity() {
    private val client = OkHttpClient()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<TextView>(R.id.button_fetch).setOnClickListener {
            fetchHtmlWithCoroutines()
        }
    }
    private fun fetchHtmlWithCoroutines() {
        val url = "https://www.example.com"
        // GlobalScope.launch 启动一个协程
        GlobalScope.launch(Dispatchers.Main) { // 在主线程执行UI更新
            try {
                // withContext(Dispatchers.IO) 将代码块切换到IO线程执行网络请求
                val htmlString = withContext(Dispatchers.IO) {
                    val request = Request.Builder()
                        .url(url)
                        .build()
                    client.newCall(request).execute().use { response ->
                        if (!response.isSuccessful) throw Exception("Unexpected code $response")
                        response.body!!.string()
                    }
                }
                // 回到主线程更新UI
                findViewById<TextView>(R.id.tv_result).text = htmlString
                Toast.makeText(this@MainActivityKt, "获取成功!", Toast.LENGTH_SHORT).show()
            } catch (e: Exception) {
                Toast.makeText(this@MainActivityKt, "请求失败: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

加载并显示完整的网页(WebView)

如果你的需求不是解析 HTML,而是想在 App 内直接显示一个完整的网页,那么使用 WebView 是最佳选择。

步骤 1: 添加 WebView 依赖和权限

确保 AndroidManifest.xml 中有网络权限。

步骤 2: 在布局文件中添加 WebView

<!-- res/layout/activity_main.xml -->
<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

步骤 3: 在 Activity 中加载网页

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class WebViewActivity extends AppCompatActivity {
    private WebView webView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = findViewById(R.id.webview);
        // 启用 JavaScript (如果网页需要)
        webView.getSettings().setJavaScriptEnabled(true);
        // 设置 WebViewClient,这样点击链接时会在当前 WebView 中打开,而不是跳转到浏览器
        webView.setWebViewClient(new WebViewClient());
        // 加载网页
        webView.loadUrl("https://www.google.com");
    }
    // 处理返回键,让 WebView 能够返回上一页
    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

解析 HTML (抓取数据)

获取到 HTML 字符串后,通常需要从中提取有用的信息,手动用字符串处理(如 indexOf, substring)非常脆弱,推荐使用 JSoup 这个专门为 HTML 设计的解析库。

步骤 1: 添加 JSoup 依赖

app/build.gradle 中添加:

dependencies {
    implementation("org.jsoup:jsoup:1.17.2") // 使用最新版本
}

步骤 2: 使用 JSoup 解析 HTML

结合上面的 OkHttp 示例,我们在获取到 HTML 字符串后进行解析。

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
// ... 在 OkHttp 的 onResponse 回调中 ...
if (response.isSuccessful()) {
    final String htmlString = response.body().string();
    runOnUiThread(() -> {
        // 使用 JSoup 解析
        Document doc = Jsoup.parse(htmlString);
        // 示例1: 获取<title>标签里的内容
        String title = doc.title();
        Log.d("JSoup", "网页标题: " + title);
        // 示例2: 获取所有<a>标签
        Elements links = doc.select("a[href]");
        Log.d("JSoup", "所有链接数量: " + links.size());
        for (Element link : links) {
            Log.d("JSoup", "链接: " + link.attr("href") + " - 文本: " + link.text());
        }
        // 示例3: 获取class为"my-class"的div
        Elements divs = doc.select("div.my-class");
        for (Element div : divs) {
            Log.d("JSoup", "找到的div内容: " + div.text());
        }
        // 示例4: 获取ID为"main-content"的元素
        Element mainContent = doc.getElementById("main-content");
        if (mainContent != null) {
            Log.d("JSoup", "主要内容: " + mainContent.text());
        }
    });
}

总结与对比

方式 适用场景 优点 缺点
OkHttp 获取 HTML 字符串 性能高,API 简洁。
支持异步请求,不阻塞 UI。
生态强大,可扩展性好。
本身不提供解析功能,需配合其他库。
WebView 完整显示网页 无需自己处理 HTML/CSS/JS。
用户体验与原生 App 内嵌网页一致。
占用内存较大。
安全性需注意(防止 XSS 攻击)。
与原生交互相对复杂。
JSoup 解析 HTML 专为 HTML 设计,非常强大和灵活。
支持类似 CSS 的选择器,方便定位元素。
容错性好,能处理不规范的 HTML。
只能解析静态 HTML,无法执行 JavaScript 来获取动态加载的内容。

重要注意事项

  1. 网络线程: 绝对不要在主线程中进行网络请求。
  2. HTTPS: 现代服务器普遍使用 HTTPS,如果你的服务器是自签名的证书,需要在 OkHttp 中配置信任所有证书(仅用于开发或测试环境,生产环境非常危险!)。
  3. 超时设置: 建议为 OkHttp 请求设置连接、读取和写入超时,防止应用因网络问题而卡死。
    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .build();
  4. : 很多现代网页使用 JavaScript 动态加载内容,使用 OkHttp + JSoup 只能获取到初始的 HTML,无法获取 JS 动态生成的内容,这种情况下,你可能需要使用 SeleniumPlaywright 等工具在服务器端模拟浏览器进行抓取,然后将结果通过 API 提供给 App。

希望这份详细的指南能帮助你解决 Android 访问服务器 HTML 的问题!

分享:
扫描分享到社交APP
上一篇
下一篇