連線到網路

如要在應用程式中執行網路作業,資訊清單必須包含下列權限:

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

安全網路通訊的最佳做法

將應用程式加入網路功能之前,您必須確保 將資料和資訊傳輸到應用程式時, 更是如此如要這麼做的話,請按照下列網路安全性最佳做法操作:

  • 請盡量減少透過網路傳輸機密或個人使用者資料
  • 應用程式透過 SSL,傳送到所有網絡。
  • 建議您建立網路安全性設定,讓應用程式信任自訂憑證授權單位 (CA),或限制可信任通訊的 CA 系統組合。

如要進一步瞭解如何套用安全網路的原則,請參閱 網路安全性提示

選擇 HTTP 用戶端

大多數具備網路連線的應用程式會使用 HTTP 傳送及接收資料。Android 平台包含 HttpsURLConnection 用戶端, ,支援 TLS、串流上傳和下載、可設定逾時 IPv6 及連線集區

第三方程式庫提供高階網路作業 API 也可選擇建立大型語言模型這些 API 可支援各種便利功能,例如將要求主體序列化,以及將回應主體反序列化。

  • Retrofit:類型安全的 HTTP 這個 JVM 用戶端以 OkHttp 為建構基礎。Retrofit 可讓您 以宣告方式建立用戶端介面,同時支援多個 序列化程式庫
  • Ktor:這個 JetBrains 的 HTTP 用戶端全為 Kotlin 建構而成,採用協同程式提供的技術。Ktor 支援多種引擎 序列化程式和平台

解析 DNS 查詢

搭載 Android 10 (API 級別 29) 以上版本的裝置內建支援功能,可同時透過明文查詢和「透過 TLS 執行 DNS」模式專門處理 DNS 查詢。DnsResolver API 提供一般的非同步解析,可讓您查詢 SRVNAPTR 和其他記錄類型。請注意,剖析回應會留在應用程式中執行。

在搭載 Android 9 (API 級別 28) 或以下版本的裝置上,平台 DNS 解析器僅支援 AAAAA 記錄。這可讓您查詢與名稱相關聯的 IP 位址,但不支援任何其他記錄類型。

如需以 NDK 為基礎的應用程式,請參閱 android_res_nsend 的說明。

使用存放區封裝網路作業

如要簡化執行網路作業的流程,並減少應用程式中各部分的程式碼重複,您可以使用存放區設計模板。存放區是一種資料處理作業的類別,也是針對某些特定資料或資源提供簡潔的 API 抽象層。

您可以使用 Retrofit 宣告介面,指定網路作業的 HTTP 方法、網址、引數和回應類型,如以下範例所示:

Kotlin

interface UserService {
    @GET("/users/{id}")
    suspend fun getUser(@Path("id") id: String): User
}

Java

public interface UserService {
    @GET("/user/{id}")
    Call<User> getUserById(@Path("id") String id);
}

在存放區類別中,函式可以封裝網路作業並公開結果。這個封裝可確保呼叫存放區的元件,並不需要知道資料的儲存方式。日後, 資料的儲存方式也與存放區類別區隔。適用對象 像是更新 API 端點等遠端變更 建議實作本機快取

Kotlin

class UserRepository constructor(
    private val userService: UserService
) {
    suspend fun getUserById(id: String): User {
        return userService.getUser(id)
    }
}

Java

class UserRepository {
    private UserService userService;

    public UserRepository(
            UserService userService
    ) {
        this.userService = userService;
    }

    public Call<User> getUserById(String id) {
        return userService.getUser(id);
    }
}

為了避免建立沒有回應的 UI,請勿在主執行緒中執行網路作業。根據預設,Android 會要求您在主 UI 執行緒以外的執行緒上執行網路作業。如果您嘗試在主執行緒上執行網路作業,系統會擲回 NetworkOnMainThreadException

在上一個程式碼範例中 實際上不會觸發網路作業UserRepository 的呼叫者 必須使用協同程式或 enqueue() 來實作執行緒 函式。詳情請參閱程式碼研究室的「從 網際網路 說明如何使用 Kotlin 協同程式實作執行緒。

在設定變更後仍然有效

發生設定變更 (例如畫面旋轉) 時,系統會刪除您的片段或活動,再重新建立工作。任何未儲存在執行個體中的資料 片段活動的狀態,只能儲存少量資料 就遺失了如果發生這種情況,您可能需要再次發出網路要求。

您可以使用 ViewModel 資料仍會留存在設定變更後仍然有效ViewModel 元件如下: 專為在註重生命週期的情境中儲存及管理 UI 相關資料而設計 。使用上述 UserRepositoryViewModel 即可讓 並將結果提供給片段或活動 使用 LiveData

Kotlin

class MainViewModel constructor(
    savedStateHandle: SavedStateHandle,
    userRepository: UserRepository
) : ViewModel() {
    private val userId: String = savedStateHandle["uid"] ?:
        throw IllegalArgumentException("Missing user ID")

    private val _user = MutableLiveData<User>()
    val user = _user as LiveData<User>

    init {
        viewModelScope.launch {
            try {
                // Calling the repository is safe as it moves execution off
                // the main thread
                val user = userRepository.getUserById(userId)
                _user.value = user
            } catch (error: Exception) {
                // Show error message to user
            }

        }
    }
}

Java

class MainViewModel extends ViewModel {

    private final MutableLiveData<User> _user = new MutableLiveData<>();
    LiveData<User> user = (LiveData<User>) _user;

    public MainViewModel(
            SavedStateHandle savedStateHandle,
            UserRepository userRepository
    ) {
        String userId = savedStateHandle.get("uid");
        Call<User> userCall = userRepository.getUserById(userId);
        userCall.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                if (response.isSuccessful()) {
                    _user.setValue(response.body());
                }
            }

            @Override
            public void onFailure(Call<User> call, Throwable t) {
                // Show error message to user
            }
        });
    }
}

如要進一步瞭解這個主題,請參閱下列相關指南: