หากต้องการดำเนินการกับเครือข่ายในแอปพลิเคชัน คุณต้องใส่สิทธิ์ต่อไปนี้ในไฟล์ Manifest
<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: ไคลเอ็นต์ HTTP ที่ปลอดภัยตามประเภทสำหรับ JVM จาก Square ซึ่งสร้างขึ้นบน OkHttp Retrofit ช่วยให้คุณ สร้างอินเทอร์เฟซไคลเอ็นต์แบบประกาศและรองรับไลบรารี การซีเรียลไลซ์หลายรายการ
- Ktor: ไคลเอ็นต์ HTTP จาก JetBrains ซึ่งสร้างขึ้น สำหรับ Kotlin โดยเฉพาะและขับเคลื่อนด้วย Coroutines Ktor รองรับเครื่องมือ ตัวจัดรูปแบบ และแพลตฟอร์มต่างๆ
แปลงคำขอ DNS
อุปกรณ์ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไปรองรับการค้นหา DNS เฉพาะทางในตัวผ่านทั้งการค้นหาข้อความธรรมดาและโหมด DNS-over-TLS
API ของ DnsResolver
มีการแก้ปัญหาแบบอะซิงโครนัสทั่วไป ซึ่งช่วยให้คุณค้นหา 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 ที่ไม่ตอบสนอง โดยค่าเริ่มต้น Android กําหนดให้คุณดําเนินการเครือข่ายใน
เธรดอื่นที่ไม่ใช่เธรด UI หลัก หากคุณพยายามดำเนินการเครือข่าย
ในเทรดหลัก ระบบจะแสดง
NetworkOnMainThreadException
ในตัวอย่างโค้ดก่อนหน้า ระบบไม่ได้ทริกเกอร์การดำเนินการเครือข่ายจริงๆ ผู้เรียกใช้ UserRepository
ต้องใช้การสร้างเธรดโดยใช้โครูทีนหรือใช้ฟังก์ชัน enqueue()
ดูข้อมูลเพิ่มเติมได้ใน Codelab รับข้อมูลจากอินเทอร์เน็ต
ซึ่งแสดงวิธีใช้การทำงานแบบหลายเธรดโดยใช้โครูทีน Kotlin
รับมือกับการเปลี่ยนแปลงการกำหนดค่า
เมื่อมีการเปลี่ยนแปลงการกำหนดค่า เช่น การหมุนหน้าจอ ระบบจะทำลาย Fragment หรือ Activity แล้วสร้างขึ้นใหม่ ข้อมูลที่ไม่ได้บันทึกไว้ในสถานะอินสแตนซ์สำหรับกิจกรรมของ Fragment ซึ่งเก็บข้อมูลได้เพียงเล็กน้อยจะสูญหาย ในกรณีนี้ คุณอาจต้องส่งคำขอเครือข่ายอีกครั้ง
คุณใช้ ViewModel
เพื่อให้
ข้อมูลยังคงอยู่ได้แม้จะมีการเปลี่ยนแปลงการกำหนดค่า คอมโพเนนต์ ViewModel
ได้รับการออกแบบมาเพื่อจัดเก็บและจัดการข้อมูลที่เกี่ยวข้องกับ UI ในลักษณะที่คำนึงถึงวงจรของคอมโพเนนต์
เมื่อใช้ UserRepository
ก่อนหน้า ViewModel
จะส่งคำขอเครือข่ายที่จำเป็นและแสดงผลลัพธ์ไปยัง Fragment หรือ Activity โดยใช้ 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 } }); } }
อ่านคำแนะนำที่เกี่ยวข้อง
ดูข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อนี้ได้ในคำแนะนำที่เกี่ยวข้องต่อไปนี้
- ลดการใช้แบตเตอรี่ของเครือข่าย: ภาพรวม
- ลดผลกระทบของการอัปเดตเป็นประจำ
- เนื้อหาบนเว็บ
- พื้นฐานของแอปพลิเคชัน
- คู่มือสถาปัตยกรรมแอป