ネットワークに接続する
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
アプリでネットワーク オペレーションを行うには、マニフェストに次の権限を含める必要があります。
<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 を提供するサードパーティ ライブラリも利用できます。リクエスト本文のシリアル化やレスポンス本文のシリアル化解除など、さまざまな便利な機能がサポートされています。
- Retrofit: OkHttp の上に構築された、Square による JVM 用のタイプセーフな HTTP クライアント。Retrofit では、クライアント インターフェースの作成を宣言でき、複数のシリアル化ライブラリがサポートされています。
- Ktor: Kotlin 専用に構築された、JetBrains による HTTP クライアント。コルーチンを利用しています。Ktor は、さまざまなエンジン、シリアライザ、プラットフォームをサポートしています。
DNS クエリを解決する
Android 10(API レベル 29)以降を搭載したデバイスでは、クリアテキスト ルックアップと DNS over TLS モードの両方を使用する特殊な DNS ルックアップを組み込みでサポートしています。DnsResolver
API は汎用の非同期解決に使用でき、SRV
、NAPTR
などのレコードタイプを検索できます。応答の解析はアプリが行う必要があります。
Android 9(API レベル 28)以前を搭載したデバイスでは、プラットフォームの DNS リゾルバは A
レコードと AAAA
レコードのみをサポートします。これにより、名前に関連付けられた IP アドレスを検索できますが、他のレコードタイプはサポートされません。
NDK ベースのアプリについては、android_res_nsend
をご覧ください。
リポジトリでネットワーク オペレーションをカプセル化する
アプリのさまざまな部分でネットワーク オペレーションの実行プロセスを簡略化し、コードの重複を減らすために、リポジトリ設計パターンを使用できます。リポジトリは、データ オペレーションを処理し、特定のデータやリソースに対してクリーンな API 抽象化を行うクラスです。
次の例のように、Retrofit を使用して、ネットワーク オペレーションの HTTP メソッド、URL、引数、レスポンス タイプを指定するインターフェースを宣言できます。
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 を作成しないようにするため、メインスレッドでネットワーク オペレーションは行わないでください。デフォルトでは、メイン UI スレッド以外のスレッド上でネットワーク オペレーションを実行する必要があります。メインスレッドでネットワーク オペレーションを実行しようとすると、NetworkOnMainThreadException
がスローされます。
上のコード例では、ネットワーク オペレーションは実際にはトリガーされません。UserRepository
の呼び出し元は、コルーチンを使用するか、enqueue()
関数を使用してスレッド化を実装する必要があります。詳細については、Codelab のインターネットからデータを取得するをご覧ください。Kotlin コルーチンを使用してスレッド化を実装する方法について説明しています。
構成の変更に対処する
画面の回転などの構成の変更が発生すると、フラグメントまたはアクティビティが破棄され、再作成されます。フラグメント アクティビティのインスタンス状態に保存されていないデータ(保持できるのは少量のデータのみです)はすべて失われます。この場合、ネットワーク リクエストを再度行う必要が生じることがあります。
ViewModel
を使用すると、構成の変更後にもデータが引き継がれます。ViewModel
コンポーネントは、ライフサイクルを意識した方法で UI 関連のデータを保存し管理するためのものです。前述の UserRepository
を使用して、ViewModel
は必要なネットワーク リクエストを行い、その結果を 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
}
});
}
}
このトピックの詳細については、次の関連ガイドをご覧ください。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-08-27 UTC。
[[["わかりやすい","easyToUnderstand","thumb-up"],["問題の解決に役立った","solvedMyProblem","thumb-up"],["その他","otherUp","thumb-up"]],[["必要な情報がない","missingTheInformationINeed","thumb-down"],["複雑すぎる / 手順が多すぎる","tooComplicatedTooManySteps","thumb-down"],["最新ではない","outOfDate","thumb-down"],["翻訳に関する問題","translationIssue","thumb-down"],["サンプル / コードに問題がある","samplesCodeIssue","thumb-down"],["その他","otherDown","thumb-down"]],["最終更新日 2025-08-27 UTC。"],[],[],null,["To perform network operations in your application, your manifest must include\nthe following permissions: \n\n \u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\n \u003cuses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" /\u003e\n\n| **Note:** Both the [`INTERNET`](/reference/android/Manifest.permission#INTERNET) and [`ACCESS_NETWORK_STATE`](/reference/android/Manifest.permission#ACCESS_NETWORK_STATE) permissions are [normal\n| permissions](/develop/permissions/overview#normal-dangerous), which means they're granted at install time and don't need to be [requested at runtime](/training/permissions/requesting).\n\nBest practices for secure network communication\n\nBefore you add networking functionality to your app, you need to ensure that\ndata and information within your app stay safe when you are transmitting over a\nnetwork. To do so, follow these networking security best practices:\n\n- Minimize the amount of sensitive or personal [user\n data](/privacy-and-security/security-tips#user-data) that you transmit over the network.\n- Send all network traffic from your app over [SSL](/training/articles/security-ssl).\n- Consider creating a [network security\n configuration](/training/articles/security-config), which lets your app trust custom certificate authorities (CAs) or restrict the set of system CAs that it trusts for secure communication.\n\nFor more information on how to apply secure networking principles, see the\n[networking security tips](/privacy-and-security/security-tips#networking).\n\nChoose an HTTP client\n\nMost network-connected apps use HTTP to send and receive data. The Android\nplatform includes the\n[`HttpsURLConnection`](/reference/javax/net/ssl/HttpsURLConnection) client,\nwhich supports TLS, streaming uploads and downloads, configurable timeouts,\nIPv6, and connection pooling.\n\nThird-party libraries that offer higher-level APIs for networking operations are\nalso available. These support various convenience features, such as the\nserialization of request bodies and deserialization of response bodies.\n\n- [Retrofit](https://square.github.io/retrofit/): a type-safe HTTP client for the JVM from Square, built on top of OkHttp. Retrofit lets you create a client interface declaratively and has support for several serialization libraries.\n- [Ktor](https://ktor.io/): an HTTP client from JetBrains, built entirely for Kotlin and powered by coroutines. Ktor supports various engines, serializers, and platforms.\n\nResolve DNS queries\n\nDevices that run Android 10 (API level 29) and higher have built-in support for\nspecialized DNS lookups through both cleartext lookups and DNS-over-TLS mode.\nThe [`DnsResolver`](/reference/android/net/DnsResolver) API provides generic,\nasynchronous resolution, which lets you look up `SRV`, `NAPTR`, and other\nrecord types. Parsing the response is left to the app to perform.\n\nOn devices that run Android 9 (API level 28) and lower, the platform DNS\nresolver supports only `A` and `AAAA` records. This lets you look up the IP\naddresses associated with a name but doesn't support any other record types.\n\nFor NDK-based apps, see\n[`android_res_nsend`](/ndk/reference/group/networking#android_res_nsend).\n\nEncapsulate network operations with a repository\n\nTo simplify the process of performing network operations and reduce code\nduplication in various parts of your app, you can use the repository design\npattern. A repository is a class that handles data operations and provides a\nclean API abstraction over some specific data or resource.\n\nYou can use Retrofit to declare an interface that specifies the HTTP method,\nURL, arguments, and response type for network operations, as in the following\nexample: \n\nKotlin \n\n```kotlin\ninterface UserService {\n @GET(\"/users/{id}\")\n suspend fun getUser(@Path(\"id\") id: String): User\n}\n```\n\nJava \n\n```java\npublic interface UserService {\n @GET(\"/user/{id}\")\n Call\u003cUser\u003e getUserById(@Path(\"id\") String id);\n}\n```\n\nWithin a repository class, functions can encapsulate network operations and\nexpose their results. This encapsulation ensures that the components that call\nthe repository don't need to know how the data is stored. Any future changes to\nhow the data is stored are isolated to the repository class as well. For\nexample, you might have a remote change such as an update to API endpoints, or\nyou might want to implement local caching. \n\nKotlin \n\n```kotlin\nclass UserRepository constructor(\n private val userService: UserService\n) {\n suspend fun getUserById(id: String): User {\n return userService.getUser(id)\n }\n}\n```\n\nJava \n\n```java\nclass UserRepository {\n private UserService userService;\n\n public UserRepository(\n UserService userService\n ) {\n this.userService = userService;\n }\n\n public Call\u003cUser\u003e getUserById(String id) {\n return userService.getUser(id);\n }\n}\n```\n\nTo avoid creating an unresponsive UI, don't perform network operations on the\nmain thread. By default, Android requires you to perform network operations on a\nthread other than the main UI thread. If you try to perform network operations\non the main thread, a\n[`NetworkOnMainThreadException`](/reference/android/os/NetworkOnMainThreadException)\nis thrown.\n\nIn the previous code example, the\nnetwork operation isn't actually triggered. The caller of the `UserRepository`\nmust implement the threading either using coroutines or using the `enqueue()`\nfunction. For more information, see the codelab [Get data from the\ninternet](/codelabs/basic-android-kotlin-training-getting-data-internet),\nwhich demonstrates how to implement threading using Kotlin coroutines.\n\nSurvive configuration changes\n\nWhen a configuration change occurs, such as a screen rotation, your fragment or\nactivity is destroyed and recreated. Any data not saved in the instance\nstate for your fragment activity, which can only hold small amounts of data,\nis lost. If this occurs, you might need to make your network requests again.\n\nYou can use a [`ViewModel`](/topic/libraries/architecture/viewmodel) to let\nyour data survive configuration changes. The `ViewModel` component is\ndesigned to store and manage UI-related data in a lifecycle-conscious\nway. Using the preceding `UserRepository`, the `ViewModel` can make the\nnecessary network requests and provide the result to your fragment or activity\nusing [`LiveData`](/topic/libraries/architecture/livedata): \n\nKotlin \n\n```kotlin\nclass MainViewModel constructor(\n savedStateHandle: SavedStateHandle,\n userRepository: UserRepository\n) : ViewModel() {\n private val userId: String = savedStateHandle[\"uid\"] ?:\n throw IllegalArgumentException(\"Missing user ID\")\n\n private val _user = MutableLiveData\u003cUser\u003e()\n val user = _user as LiveData\u003cUser\u003e\n\n init {\n viewModelScope.launch {\n try {\n // Calling the repository is safe as it moves execution off\n // the main thread\n val user = userRepository.getUserById(userId)\n _user.value = user\n } catch (error: Exception) {\n // Show error message to user\n }\n\n }\n }\n}\n```\n\nJava \n\n```java\nclass MainViewModel extends ViewModel {\n\n private final MutableLiveData\u003cUser\u003e _user = new MutableLiveData\u003c\u003e();\n LiveData\u003cUser\u003e user = (LiveData\u003cUser\u003e) _user;\n\n public MainViewModel(\n SavedStateHandle savedStateHandle,\n UserRepository userRepository\n ) {\n String userId = savedStateHandle.get(\"uid\");\n Call\u003cUser\u003e userCall = userRepository.getUserById(userId);\n userCall.enqueue(new Callback\u003cUser\u003e() {\n @Override\n public void onResponse(Call\u003cUser\u003e call, Response\u003cUser\u003e response) {\n if (response.isSuccessful()) {\n _user.setValue(response.body());\n }\n }\n\n @Override\n public void onFailure(Call\u003cUser\u003e call, Throwable t) {\n // Show error message to user\n }\n });\n }\n}\n```\n\nRead related guides\n\nTo learn more about this topic, see the following related guides:\n\n- [Reduce network battery drain: Overview](/topic/performance/power)\n- [Minimize the effect of regular updates](/training/efficient-downloads)\n- [Web-based content](/guide/webapps)\n- [Application fundamentals](/guide/components/fundamentals)\n- [Guide to app architecture](/jetpack/guide)"]]