Hubungkan ke Internet
Materi:
- Pengantar
- Keamanan jaringan
- Menyertakan izin dalam manifes
- Menjalankan operasi jaringan di thread pekerja
- Membuat koneksi HTTP
- Mem-parse hasil
- Mengelola keadaan jaringan
- Praktik terkait
Sebagian besar aplikasi Android memiliki beberapa data yang berinteraksi dengan pengguna; seperti artikel berita, informasi cuaca, kontak, data game, informasi pengguna, dan lainnya. Seringkali, data ini disediakan melalui jaringan oleh API web.
Dalam pelajaran ini, Anda akan mempelajari tentang keamanan jaringan dan cara membuat panggilan jaringan, yang melibatkan tugas-tugas ini:
- Sertakan izin dalam file AndroidManifest.xml.
- Pada thread pekerja, buat koneksi klien HTTP yang menghubungkan ke jaringan dan mengunduh (atau mengunggah) data.
- Parse hasil, yang biasanya dalam format JSON.
- Periksa keadaan jaringan dan tanggapi sebagaimana semestinya.
Keamanan jaringan
Transaksi jaringan berisiko inheren, karena mereka melibatkan transmisi data yang boleh jadi bersifat privat untuk pengguna. Orang semakin sadar dengan risiko ini, terutama ketika perangkat mereka melakukan transaksi jaringan, jadi sangat penting jika aplikasi Anda mengimplementasikan praktik terbaik untuk menjaga data pengguna tetap aman setiap saat.
Praktik terbaik keamanan untuk operasi jaringan:
- Gunakan protokol yang sesuai untuk data sensitif. Misalnya untuk lalu lintas web aman, gunakan subkelas
HttpsURLConnection
dariHttpURLConnection
. - Gunakan HTTPS sebagai ganti HTTP di mana saja HTTPS didukung pada server, karena perangkat seluler sering menghubungkan pada jaringan tidak aman seperti hotspot Wi-Fi publik. Pertimbangkan penggunaan
SSLSocketClass
untuk mengimplementasikan komunikasi level soket yang diautentikasi dan dienkripsi. - Jangan gunakan porta jaringan host lokal untuk menangani komunikasi interproses sensitif (IPC), karena aplikasi lain di perangkat bisa mengakses porta lokal ini. Sebagai gantinya, gunakan mekanisme yang memungkinkan Anda menggunakan autentikasi, misalnya
Service
. - Jangan mempercayai data yang telah diunduh dari HTTP atau protokol tidak aman lainnya. Validasi masukan yang dimasukkan ke dalam
WebView
dan respons ke maksud yang Anda keluarkan terhadap HTTP.
Untuk praktik terbaik dan tips keamanan, lihat artikel Tips Keamanan.
Menyertakan izin dalam manifes
Sebelum aplikasi bisa melakukan panggilan jaringan, Anda perlu menyertakan izin dalam file AndroidManifest.xml. Tambahkan tag berikut di dalam tag
:
Saat menggunakan jaringan, praktik terbaiknya adalah memantau keadaan jaringan perangkat sehingga Anda tidak berupaya membuat panggilan jaringan ketika jaringan tidak tersedia. Untuk mengakses keadaan jaringan perangkat, aplikasi memerlukan izin tambahan:
Menjalankan operasi jaringan di thread pekerja
Selalu jalankan operasi jaringan di thread pekerja, terpisah dari UI. Misalnya, di kode Java, Anda bisa membuat implementasi
AsyncTask
(atau AsyncTaskLoader
) yang membuka koneksi jaringan dan mengkueri API. Kode utama Anda akan memeriksa apakah koneksi jaringan aktif. Jika aktif, maka akan menjalankan AsyncTask
di thread terpisah, kemudian menampilkan hasil di UI.
Catatan: Jika menjalankan operasi jaringan di thread utama sebagai ganti di thread pekerja, Anda akan menerima kesalahan.
Membuat koneksi HTTP
Sebagian besar aplikasi Android yang terhubung ke jaringan menggunakan HTTP dan HTTPS untuk mengirim dan menerima data melalui jaringan. Untuk penyegaran di HTTP, kunjungi Pelajari tutorial HTTP.
Catatan: Jika server web menawarkan HTTPS, Anda harus menggunakannya sebagai ganti HTTP untuk peningkatan keamanan.
Klien Android
HttpURLConnection
mendukung HTTPS, unggahan dan unduhan streaming, waktu tunggu yang dapat dikonfigurasi, IPv6, dan penjajakan koneksi. Untuk menggunakan klien HttpURLConnection
, bangun URI (tujuan permintaan). Selanjutnya dapatkan koneksi, kirim permintaan dan header permintaan apa pun, unduh dan baca respons dan header respons apa pun, dan putuskan koneksi.Membangun URI Anda
Untuk membuka koneksi HTTP, Anda perlu membangun URI permintaan. URI biasanya dibuat dari URL dasar dan sekumpulan parameter kueri yang menetapkan sumber daya yang dimaksud. Misalnya untuk menelusuri lima hasil buku pertama untuk "Pride and Prejudice" di Google Books API, gunakan URI berikut:
https://www.googleapis.com/books/v1/volumes?q=pride+prejudice&maxResults=5&printType=books
Untuk menyusun URI permintaan lewat program, gunakan metode
URI.parse()
dengan metode buildUpon()
dan appendQueryParameter()
. Kode berikut membangun URI lengkap yang ditampilkan di atas:// Base URL for the Books API.
final String BOOK_BASE_URL = "https://www.googleapis.com/books/v1/volumes?";final String QUERY_PARAM = "q"; // Parameter for the search stringfinal String MAX_RESULTS = "maxResults"; // Parameter to limit search results.final String PRINT_TYPE = "printType"; // Parameter to filter by print type.appendQueryParameter(QUERY_PARAM, "pride+prejudice")// Build up the query URI, limiting results to 5 items and printed books. Uri builtURI = Uri.parse(BOOK_BASE_URL).buildUpon().build();.appendQueryParameter(MAX_RESULTS, "5").appendQueryParameter(PRINT_TYPE, "books")
Untuk mengubah URI menjadi string, gunakan metode
toString()
:String myurl = builtURI.toString();
Hubungkan dan unduh data
Di thread pekerja yang menjalankan transaksi jaringan Anda, misalnya dalam penggantian metode
doInBackground()
di AsyncTask
, gunakan kelas HttpURLConnection
untuk menjalankan permintaan GET
HTTP dan mengunduh data yang diperlukan aplikasi. Begini caranya:- Untuk memperoleh
HttpURLConnection
baru, panggilURL.openConnection()
menggunakan URI yang Anda bangun. Transmisikan hasilnya keHttpURLConnection
.URI adalah properti utama permintaan, namun header permintaan juga bisa menyertakan metadata seperti kredensial, tipe materi pilihan, dan cookie sesi. - Setel parameter opsional:
- Untuk koneksi lambat, Anda mungkin menginginkan waktu tunggu koneksi yang lama (waktu untuk membuat koneksi awal ke sumber daya) atau waktu tunggu baca (waktu untuk benar-benar membaca data).
- Untuk mengubah metode permintaan ke selain
GET
, gunakansetRequestMethod()
. - Jika Anda tidak ingin menggunakan jaringan untuk masukan, setel
setDoInput
kefalse
. (Defaultnya adalahtrue
.) - Untuk metode lain yang bisa Anda setel, lihat dokumentasi referensi
HttpURLConnection
danURLConnection.
- Buka aliran masukan menggunakan
getInputStream()
, kemudian baca respons dan ubah menjadi string. Header respons biasanya menyertakan metadata seperti tipe materi dan panjang isi respons, tanggal modifikasi, dan cookie sesi. Jika respons tidak memiliki isi,getInputStream()
akan mengembalikan aliran kosong. - Panggil
disconnect()
untuk menutup koneksi. Memutus koneksi akan melepas sumber daya yang ditahan oleh koneksi sehingga sumber daya bisa ditutup atau digunakan kembali.
Langkah-langkah ini ditampilkan dalam Contoh permintaan, di bawah.
Jika mengeposkan data melalui jaringan dan tidak hanya menerima data, Anda perlu mengunggah isi permintaan, yang menampung data yang akan diposkan. Caranya:
- Konfigurasikan koneksi sehingga keluaran dimungkinkan dengan memanggil
setDoOutput(true)
. (Secara default,HttpURLConnection
menggunakan permintaanGET
HTTP. BilasetDoOutput
adalahtrue
,HttpURLConnection
menggunakan permintaanPOST
HTTP secara default.) - Buka aliran keluaran dengan memanggil
getOutputStream()
.
Untuk informasi selengkapnya tentang mengeposkan data ke jaringan, lihat "Mengeposkan Materi" dalam
dokumentasi HttpURLConnection
.
Catatan: Semua panggilan jaringan harus dijalankan di thread pekerja dan bukan di thread UI.
Contoh permintaan
Contoh berikut mengirimkan permintaan ke URL yang dibangun di bagian Membangun URI Anda, di atas. Permintaan memperoleh
HttpURLConnection
baru, membuka aliran masukan, membaca respons, mengubah respons menjadi string, dan menutup koneksi.private String downloadUrl(String myurl) throws IOException {InputStream inputStream = null;
// web page content.// Only display the first 500 characters of the retrieved int len = 500; try {HttpURLConnection conn = (HttpURLConnection) url.openConnection();URL url = new URL(myurl); conn.setReadTimeout(10000 /* milliseconds */);int response = conn.getResponseCode();conn.setConnectTimeout(15000 /* milliseconds */); // Start the query conn.connect();// Convert the InputStream into a stringLog.d(DEBUG_TAG, "The response is: " + response); inputStream = conn.getInputStream();conn.disconnect();String contentAsString = convertInputToString(inputStream, len); return contentAsString; // Close the InputStream and connection } finally {}if (inputStream != null) { inputStream.close(); }}
Mengubah InputStream menjadi string
InputStream
merupakan sumber byte yang dapat dibaca. Setelah Anda mendapatkan InputStream
, biasanya kemudian mendekode atau mengubahnya menjadi tipe data yang diperlukan. Dalam contoh di atas, InputStream
menyatakan teks biasa dari laman web yang berada di https://www.googleapis.com/books/v1/volumes?q=pride+prejudice&maxResults=5&printType=books.
Metode
convertInputToString
yang didefinisikan di bawah ini mengubah InputStream
menjadi string sehingga aktivitas bisa menampilkanya di UI. Metode ini menggunakan instance InputStreamReader
untuk membaca byte dan mendekode byte menjadi karakter:// Reads an InputStream and converts it to a String.
public String convertInputToString(InputStream stream, int len)throws IOException, UnsupportedEncodingException {reader = new InputStreamReader(stream, "UTF-8");Reader reader = null; char[] buffer = new char[len]; reader.read(buffer);}return new String(buffer);
Catatan: Jika Anda mengharapkan respons yang panjang, bungkus
InputStreamReader
di dalam BufferedReader
agar pembacaan karakter, larik, dan baris menjadi lebih efisien. Misalnya:
reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
Mem-parse hasil
Bila Anda membuat kueri API web, hasilnya seringkali dalam format JSON.
Di bawah ini adalah contoh respons JSON dari permintaan HTTP. Respons ini menampilkan nama tiga item menu di menu munculan dan metode yang dipicu bila item menu diklik:
{"menu": {
"id": "file","value": "File","popup": {{"value": "New", "onclick": "CreateNewDoc()"},"menuitem": [{"value": "Open", "onclick": "OpenDoc()"},{"value": "Close", "onclick": "CloseDoc()"} ] }}
Untuk menemukan nilai item dalam respons, gunakan metode dari kelas
JSONObject
dan JSONArray
. Misalnya, inilah cara untuk menemukan nilai "onclick"
dari item ketiga di larik "menuitem"
:JSONObject data = new JSONObject(responseString);
JSONArray menuItemArray = data.getJSONArray("menuitem");JSONObject thirdItem = menuItemArray.getJSONObject(2);String onClick = thirdItem.getString("onclick");
Mengelola keadaan jaringan
Membuat panggilan jaringan bisa mahal dan lambat, terutama jika perangkat memiliki konektivitas yang kecil. Mewaspadai keadaan koneksi jaringan bisa mencegah aplikasi Anda dari berupaya membuat panggilan jaringan saat jaringan tidak tersedia.
Kadang-kadang juga penting bagi aplikasi untuk mengetahui jenis konektivitas yang dimiliki perangkat: Jaringan Wi-Fi biasanya lebih cepat daripada jaringan data, dan jaringan data biasanya seringkali berkuota dan mahal. Untuk mengontrol kapan tugas tertentu dijalankan, pantau keadaan jaringan dan tanggapi sebagaimana mestinya. Misalnya, Anda mungkin ingin menunggu hingga perangkat terhubung ke Wi-Fi untuk melakukan pengunduhan file besar.
Untuk memeriksa koneksi jaringan, gunakan kelas berikut:
ConnectivityManager
akan menjawab kueri tentang keadaan konektivitas jaringan. Juga memberi tahu aplikasi bila konektivitas jaringan berubah.NetworkInfo
akan menjelaskan status antarmuka jaringan dari tipe yang diberikan (saat ini seluler atau Wi-Fi).
Cuplikan kode berikut menguji apakah Wi-Fi dan seluler terhubung. Dalam kode:
- Metode
getSystemService
mendapatkan instanceConnectivityManager
. - Metode
getNetworkInfo
mendapatkan status koneksi Wi-Fi perangkat, kemudian koneksi selulernya. MetodegetNetworkInfo
mengembalikan objekNetworkInfo
, yang berisi informasi tentang status koneksi jaringan yang diberikan (apakah menganggur, terhubung, dan seterusnya). - Metode
networkInfo.isConnected()
akan mengembalikantrue
jika jaringan yang diberikan terhubung. Jika jaringan terhubung, maka bisa digunakan untuk membangun soket dan meneruskan data.private static final String DEBUG_TAG = "NetworkStatusExample";ConnectivityManager connMgr = (ConnectivityManager)
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);getSystemService(Context.CONNECTIVITY_SERVICE); boolean isWifiConn = networkInfo.isConnected();boolean isMobileConn = networkInfo.isConnected();networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);