Pengenalan AsyncTask dan AsyncTaskLoader pada android studio


Ada dua cara untuk melakukan pemrosesan latar belakang di Android: menggunakan  kelas AsyncTask, atau menggunakan kerangka kerja Loader, yang menyertakan kelas  AsyncTaskLoader yang menggunakan AsyncTask. Di sebagian besar situasi, Anda akan  memilih kerangka kerja Loader, namun penting untuk mengetahui cara kerja AsyncTask,  sehingga Anda bisa membuat pilihan yang bagus.

 

Dalam artikel ini Anda akan mempelajari alasan pentingnya memproses beberapa tugas di  latar belakang, di luar thread UI. Anda akan mempelajari cara menggunakan AsyncTask,  bila tidak menggunakan AsyncTask, dan dasar-dasar penggunaan loader.

Thread UI

Bila aplikasi Android dimulai, aplikasi membuat thread utama, yang sering disebut  thread UI. Thread UI mengirimkan kejadian ke widget antarmuka pengguna (UI) yang  sesuai, dan ini merupakan tempat aplikasi Anda berinteraksi dengan komponen dari toolkit  UI Android (komponen dari paket android.widget dan android.view).
 Model thread Android memiliki dua aturan:

1 . Jangan memblokir thread UI.

Thread UI perlu memberikan perhatiannya untuk menggambar UI dan menjaga aplikasi  tetap responsif terhadap masukan pengguna. Jika semuanya terjadi di thread UI, operasi  panjang seperti akses jaringan atau kueri database bisa memblokir seluruh UI. 

Dari perspektif pengguna, aplikasi tersebut akan mogok. Lebih  buruk lagi, jika thread UI diblokir selama lebih dari beberapa detik (saat ini sekitar 5 detik)  pengguna akan ditampilkan dialog "application not responding" (ANR). Pengguna bisa  memutuskan untuk keluar dari aplikasi dan mencopot pemasangannya.

Untuk memastikan aplikasi Anda tidak memblokir thread UI:

  • Selesaikan semua pekerjaan dalam waktu kurang dari 16 md untuk setiap layar UI.

  • Jangan menjalankan tugas asinkron dan tugas lain yang berjalan lama pada thread  UI. Sebagai gantinya, implementasikan tugas pada thread latar belakang  menggunakan AsyncTask (untuk tugas singkat atau yang bisa disela) atau  AsyncTaskLoader (untuk tugas berprioritas tinggi, atau tugas yang perlu melaporkan  kembali ke pengguna atau UI). 

2. Lakukan pekerjaan UI hanya pada thread UI.

Jangan menggunakan thread latar belakang untuk memanipulasi UI Anda, karena toolkit  UI Android bukan thread-safe.
  

 

AsyncTask

 

Gunakan kelas AsyncTask untuk mengimplementasikan tugas asinkron yang berjalan  lama di thread pekerja. (Thread pekerja adalah thread yang bukan thread utama atau  thread UI.) AsyncTask memungkinkan Anda menjalankan operasi latar belakang dan  mempublikasikan hasil di thread UI tanpa memanipulasi thread atau penangan.
 Bila AsyncTask dieksekusi, maka akan melalui empat langkah:
  

  1. onPreExecute( ) dipanggil di thread UI sebelum tugas dieksekusi. Langkah ini  biasanya digunakan untuk mempersiapkan tugas, misalnya dengan menampilkan  bilah kemajuan di UI.

  2. doInBackground( Params. . . ) dipanggil pada thread latar belakang segera setelah  onPreExecute( ) selesai. Langkah ini menjalankan komputasi latar belakang,  mengembalikan hasil, dan meneruskan hasilnya ke onPostExecute( ) . Metode doInBackground( ) juga bisa memanggil publishProgress( Progress. . . ) untuk  mempublikasikan satu atau beberapa unit kemajuan.

  3. onProgressUpdate( Progress. . . ) berjalan di thread UI setelah publishProgress(  Progress. . . ) dipanggil. Gunakan onProgressUpdate( ) untuk melaporkan suatu  bentuk kemajuan ke thread UI sewaktu komputasi latar belakang dieksekusi.  Misalnya, Anda bisa menggunakannya untuk meneruskan data guna  menganimasikan bilah kemajuan atau menampilkan log di bidang teks.

  4. onPostExecute( Result) berjalan di thread UI setelah komputasi latar belakang  selesai.


 
 
Untuk detail selengkapnya mengenai metode ini, lihat referensi AsyncTask . Di bawah  ini adalah diagram urutan pemanggilan.

Penggunaan AsyncTask


 
Untuk menggunakan kelas AsyncTask , definisikan subkelas AsyncTask yang  menggantikan metode doInBackground( Params. . . ) (dan biasanya juga metode  onPostExecute( Result) ). Bagian ini menjelaskan parameter dan penggunaan AsyncTask ,  kemudian menampilkan contoh lengkap.

 

A. Parameter AsyncTask


 
Di subkelas AsyncTask , sediakan tipe data untuk tiga jenis parameter.

  • "Params" menetapkan tipe parameter yang diteruskan ke doInBackground( )  sebagai larik.

  • "Progress" menetapkan tipe parameter yang diteruskan ke publishProgress( ) di  thread latar belakang. Parameter ini selanjutnya diteruskan ke metode  onProgressUpdate( ) di thread utama.

  • "Result" menetapkan tipe parameter yang dikembalikan doInBackground( ) .  Parameter ini secara otomatis diteruskan ke onPostExecute( ) di thread utama.


 
 
 Tetapkan tipe data untuk setiap tipe parameter ini, atau gunakan Void jika tipe  parameter tidak akan digunakan. Misalnya:
 
 public class MyAsyncTask extends AsyncTask <String, Void,  Bitmap>{}
 
 Dalam deklarasi kelas ini:

  • Tipe parameter "Params" adalah String , yang berarti bahwa MyAsyncTask  memerlukan satu atau beberapa string sebagai parameter di doInBackground( ),  misalnya untuk digunakan di kueri.

  • Tipe parameter "Progress" adalah Void, yang berarti bahwa MyAsyncTask tidak akan  menggunakan metode publishProgress( ) atau onProgressUpdate( ).

  • Tipe parameter "Result" adalah Bitmap. MyAsyncTask mengembalikan Bitmap di  doInbackground( ), yang diteruskan ke dalam onPostExecute( ) .

 

B. Contoh AsyncTask

 
 
 
Contoh di atas melewati tiga dari empat langkah-langkah AsyncTask dasar:

  • doInBackground( ) mengunduh materi, tugas yang berjalan lama. Langkah ini  menghitung persentase file yang diunduh dari indeks loop for dan meneruskannya  ke publishProgress(). Pemeriksaan untuk isCancelled( ) di dalam loop for  memastikan bahwa tugas telah dibatalkan, sistem tidak menunggu hingga loop selesai.

  • onProgressUpdate() memperbarui kemajuan persentase. Ini dipanggil setiap kali  metode publishProgress() dipanggil di dalam doInBackground( ) , yang memperbarui  kemajuan persentase.

  • doInBackground( ) menghitung jumlah total byte yang diunduh dan  mengembalikannya. onPostExecute( ) menerima hasil yang dikembalikan dan  meneruskannya ke dalam onPostExecute( ) , yang ditampilkan di dialog.


 
Tipe parameter yang digunakan dalam contoh ini adalah:

  • URL untuk tipe parameter "Params". Tipe URL berarti Anda bisa meneruskan  sejumlah URL ke dalam panggilan, dan URL secara otomatis diteruskan ke dalam  metode doInBackground( ) sebagai larik.

  • Integer untuk tipe parameter "Progress".

  • Long untuk tipe parameter "Result".

 

C. Mengeksekusi AsyncTask

 

Setelah Anda mendefinisikan subkelas AsyncTask , buat instance-nya di thread UI.  Kemudian panggil execute( ) di instance, dengan meneruskan sejumlah parameter.  (Parameter tersebut sesuai dengan tipe parameter "Params" yang dibahas di atas).

Misalnya, untuk mengeksekusi tugas DownloadFilesTask yang didefinisikan di atas,  gunakan baris kode berikut:

 new DownloadFilesTask( ) . execute( url1, url2, url3) ; Membatalkan AsyncTask
 
  
 Anda bisa membatalkan tugas kapan saja, dari thread apa pun, dengan memanggi
l  metode cancel( ) .
  

  • Metode cancel( ) akan mengembalikan false jika tugas tidak bisa dibatalkan,  biasanya karena sudah diselesaikan secara normal. Jika tidak, cancel( ) akan  mengembalikan true.

  • Untuk mengetahui apakah tugas sudah dibatalkan, periksa nilai yang dikembalikan  isCancelled( ) secara berkala dari doInBackground( Obj ect[] ) , misalnya dari dalam  loop seperti yang ditampilkan dalam contoh di atas. Metode isCancelled( ) akan  mengembalikan true jika tugas dibatalkan sebelum diselesaikan secara normal.

  • Setelah tugas AsyncTask dibatalkan, onPostExecute( ) tidak akan digunakan setelah  doInBackground( ) dikembalikan. Sebagai gantinya, onCancelled( Obj ect) akan dipanggil. Implementasi default onCancelled( Obj ect) cukup memanggil  onCancelled( ) dan mengabaikan hasil.

  • Secara default, tugas yang sedang diproses boleh diselesaikan. Untuk  memperbolehkan cancel( ) menyela thread yang sedang mengeksekusi tugas,  teruskan true untuk nilai mayInterruptIfRunning .

 

 D. Keterbatasan AsyncTask

AsyncTask tidak praktis untuk beberapa kasus penggunaan:

  • Perubahan pada konfigurasi perangkat menyebabkan masalah. Bila konfigurasi  perangkat berubah sewaktu AsyncTask berjalan, misalnya jika pengguna mengubah  orientasi layar, aktivitas yang membuat AsyncTask akan dimusnahkan dan dibuat  ulang. Metode AsyncTask tidak dapat mengakses aktivitas yang baru saja dibuat dan  hasil AsyncTask tidak akan dipublikasikan.

  • Objek AsyncTask lama tetap ada, dan aplikasi Anda bisa kehabisan memori atau  mogok. Jika aktivitas yang membuat AsyncTask dimusnahkan, AsyncTask tidak akan  dimusnahkan bersamanya. Misalnya, jika pengguna keluar dari aplikasi setelah  AsyncTask dimulai, AsyncTask akan terus menggunakan sumber daya kecuali jika  Anda memanggil cancel( ) .


 
Bila menggunakan AsyncTask :

  • Tugas singkat atau yang bisa disela.

  • Tugas yang tidak perlu untuk melaporkan kembali ke UI atau pengguna.  

  • Tugas dengan prioritas rendah yang bisa ditinggalkan sebelum selesai.


 
Untuk semua situasi lainnya, gunakan AsyncTaskLoader , adalah bagian dari kerangka  kerja Loader yang akan dijelaskan berikutnya.
  

 

Loader

 

Tugas latar belakang biasanya digunakan untuk memuat data seperti laporan prakiraan  cuaca atau ulasan film. Pemuatan data bisa jadi banyak menggunakan memori, dan Anda  ingin data tersedia sekalipun jika konfigurasi perangkat berubah. Untuk situasi ini, gunakan  loader, yang berupa rangkaian kelas yang memfasilitasi pemuatan data ke dalam aktivitas.


 
 
Loader menggunakan kelas LoaderManager untuk mengelola satu atau beberapa  loader. LoaderManager menyertakan serangkaian callback bila loader telah dibuat, bila  pemuatan datanya selesai, dan bila disetel ulang. Memulai loader
 Gunakan kelas LoaderManager u
ntuk mengelola satu atau beberapa instance Loader  dalam aktivitas atau fragmen.
 Gunakan initLoader( ) untuk melakukan inisialisasi dan mengaktifkannya. Biasanya,  Anda melakukan ini dalam metode onCreate( ) aktivitas. 

Misalnya:
 
 
 // Prepare the loader. Either reconnect with an existing one,
 // or start a new one.getLoaderManager( ) . initLoader( 0, null,  this) ;
 
  
 Jika Anda menggunakan Pustaka Dukungan, buat panggilan ini menggunakan  getSupportLoaderManager( ) sebaga
i ganti getLoaderManager( ) . 

Misalnya:
 
 getSupportLoaderManager( ) . initLoader( 0, null, this) ; Metode initLoader( ) memerlukan tiga parameter:

  • ID unik yang mengidentifikasi loader. ID ini bisa berupa apa saja yang Anda inginkan.

  • Argumen opsional yang disediakan ke loader saat pembuatan, dalam bentuk  Bundle. Jika loader sudah ada, parameter ini akan diabaikan.

  • Implementasi LoaderCallbacks , yang dipanggil oleh LoaderManager untuk  melaporkan kejadian loader. Dalam contoh ini, kelas lokal mengimplementasikan  antarmuka LoaderManager. LoaderCallbacks , sehingga meneruskan referensi ke  dirinya sendiri, this .


 
Panggilan initLoader( ) memiliki dua kemungkinan hasil:

  • Jika loader yang ditetapkan melalui ID sudah ada, maka loader yang dibuat terakhir  menggunakan ID itu akan digunakan kembali.

  •  Jika loader yang ditetapkan melalui ID tidak ada, initLoader( ) akan memicu metode  onCreateLoader) . Di sinilah Anda mengimplementasikan kode untuk membuat  instance dan mengembalikan loader baru.

Catatan:Bila initLoader( ) membuat loader atau menggunakan kembali loader yang ada,  implementasi

LoaderCallbacks yang diberikan akan dikaitkan dengan loader dan dipanggil bila keadaan  loader berubah. Jika loader yang diminta sudah ada dan sudah menghasilkan data, maka  sistem segera memanggil onLoadFinished( ) (selama initLoader( ) ), jadi bersiaplah jika hal  ini terjadi.


 
 
Masukkan panggilan ke initLoader( ) di onCreate( ) sehingga aktivitas bisa dihubungkan  kembali ke loader yang sama bila konfigurasi berubah. Dengan cara itu, loader tidak  kehilangan data yang sudah dimuatnya.

A. Memulai ulang loader

Bila initLoader( ) menggunakan kembali loader yang ada, maka data yang telah dimuat  loader tidak akan diganti, namun kadang-kadang Anda perlu menggantinya. Misalnya, bila  Anda menggunakan kueri pengguna untuk melakukan penelusuran dan pengguna  memasukkan kueri baru, Anda perlu memuat ulang data dengan menggunakan istilah  penelusuran baru. Dalam situasi ini, gunakan metode restartLoader( ) dan teruskan ID  loader yang ingin dimulai ulang. Hal ini akan memaksa muatan data lain dengan data  masukan baru.

B. Tentang metode restartLoader( ) :

restartLoader( ) menggunakan argumen yang sama dengan initLoader( ) . restartLoader(  ) akan memicu metode onCreateLoader( ) , seperti yang dilakukan initLoader( ) saat  membuat loader baru. Jika sudah ada loader dengan ID yang diberikan, restartLoader( )  akan memulai ulang loader yang diidentifikasi dan mengganti datanya. Jika tidak ada loader  dengan ID yang diberikan, restartLoader( ) akan memulai loader baru.

C.Callback LoaderManager

Objek LoaderManager secara otomatis memanggil onStartLoading( ) saat membuat  loader. Setelah itu, LoaderManager akan mengelola keadaan loader berdasarkan pada  keadaan aktivitas dan data, misalnya dengan memanggil onLoadFinished( ) bila data telah  dimuat. Untuk berinteraksi dengan loader, gunakan salah satu callback LoaderManager di  aktivitas yang memerlukan data: Panggil onCreateLoader( ) agar bisa membuat instance  dan mengembalikan loader baru untuk ID yang diberikan.

  • Panggil onLoadFinished( ) bila loader yang dibuat sebelumnya selesai memuat. Di sinilah  Anda biasanya ingin memindahkan data ke dalam tampilan aktivitas.

  • Panggil onLoaderReset( ) bila loader yang dibuat sebelumnya sedang disetel ulang,  sehingga datanya tidak tersedia.

Di sinilah aplikasi harus membuang semua referensi apa pun yang dimilikinya ke data  loader. Subkelas Loader bertanggung jawab atas pemuatan data sebenarnya. Subkelas Loader yang Anda gunakan bergantung pada tipe data yang dimuat, namun salah satu yang  paling mudah adalah AsyncTaskLoader, yang akan dijelaskan berikutnya. AsyncTaskLoader  menggunakan AsyncTask untuk menjalankan tugas pada thread pekerja.
  

AsyncTaskLoader

AsyncTaskLoader adalah loader yang setara dengan AsyncTask. AsyncTaskLoader  menyediakan metode loadInBackground( ), yang dijalankan di thread terpisah. Hasil loadInBackground( )  secara otomatis dikirimkan ke thread UI, melalui onLoadFinished( ) LoaderManager  callback.

A. Penggunaan AsyncTaskLoader

Untuk mendefinisikan subkelas AsyncTaskLoader , buat kelas yang memperluas  AsyncTaskLoader<D> , dalam hal ini D adalah tipe data yang sedang Anda muat. Misalnya,  AsyncTaskLoader ini akan memuat daftar string: public static class StringListLoader extends  AsyncTaskLoader<List<String>> {}

 

Berikutnya, implementasikan konstruktor yang cocok dengan implementasi super kelas:  Konstruktor menggunakan konteks aplikasi sebagai argumen dan meneruskannya ke  panggilan untuk super() . Jika loader Anda memerlukan informasi tambahan untuk  melakukan pemuatan, konstruktor bisa mengambil argumen tambahan. Dalam contoh  yang ditampilkan di bawah ini, konstruktor menggunakan sebuah istilah kueri.


 
 
public StringListLoader(Context context, String queryString) { 

    super(context);
     mQueryString = queryString;
 }
 
 Untuk melakukan pemuatan, gunakan metode penggantian loadInBackground( ) , akibat  metode doInBackground( ) dari AsyncTask . Misalnya:
 
 
 @Override
 public List<String> loadInBackground() {

List<String> data = new ArrayList<String>;
 //TODO: Load the data from the network or from a database return data;
 }

 B.Mengimplementasikan callback

Gunakan konstruktor di callback onCreateLoader() LoaderManager , yang  merupakantempat membuat loader baru.
 Misalnya, callback onCreateLoader() ini menggunakan konstruktor StringListLoader  yang didefinisikan di atas:
 
 @Override
 public Loader<List<String>>
onCreateLoader(int id, Bundle args) { 

return new StringListLoader(this, args. getString("queryString")); 

}
 
 Hasil loadInBackground() secara otomatis diteruskan ke dalam callback onLoadFinished(  ) , di sinilah Anda bisa menampilkan hasil di UI. 

Misalnya:
 
 public void onLoadFinished(Loader<List<String>> loader,  List<String> data) {
 mAdapter. setData(data);
 }

Callback onLoaderReset( ) hanya dipanggil bila loader akan dimusnahkan, sehingga  seringkali Anda bisa mengosongkan onLoaderReset( ) , karena Anda tidak akan mencoba  mengakses data setelah loader ini dimusnahkan.
 
 Bila Anda menggunakan AsyncTaskLoader, da
ta Anda akan bertahan bila ada perubahan  konfigurasi perangkat. Jika aktivitas Anda dmusnahkan secara permanen, loader ini akan  dimusnahkan bersamanya, tanpa tugas yang menanti danmengonsumsi sumber daya  sistem.
 
 Loader juga memiliki manfaat lain, misal
nya loader bisa memantau perubahan sumber  data dan memuat ulang data jika terjadi perubahan. Anda akan mengetahui selengkapnya  tentang loader tertentu di pelajaran berikutnya.


 
 
 

Praktikum


 
 

1. Pertama jalankan aplikasi IDE Android Studio, caranya :

  • Pilih Start → Android Studio

  • Pilih → Start a new Android Studio Project

  • Pilih → Empty Activity → Next

  • name → AsyncTaskDownload

  • Package Name → ubah menjadi nama blog kalian masing-masing, di sini saya  menggunakan url blog saya naskahkode.com lalu di ikuti nama project AsyncTaskDownload

  • Save Location → home/zall/AndroidStudioProject/AsyncTaskDownload

  • Language → Java

  • Minimum API Level → API 14 → Klik Finish

 

2.Ubah script Activity_main.xml

Setelah tampil IDE ,  Buka dan ubah script activity_main.xml menjadi seperti gambar di code ini

   

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingTop="10dp"
android:paddingRight="10dp"
android:paddingBottom="10dp"
tools:context=".MainActivity">

<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Download" />

<TextView
android:id="@+id/attrs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="15dp"
android:layout_marginRight="15dp"
android:text="naskahkode.com"
android:textStyle="bold" />

</RelativeLayout>


3. Ubah script MainActivity.java

 Ubah menjadi seperti code di bawah  ini

   

package com.naskahkode.asynctaskdownload;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.util.Log;

public class MainActivity extends AppCompatActivity implements OnClickListener {
public static final int download_progress = 0;
private String file_url="https://dev.naskahkode.com/cv.pdf";
Button btn_download;
ProgressDialog prgDialog;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_download = (Button) findViewById(R.id.button1);
btn_download.setOnClickListener(this);
}
@Override

public void onClick(View v) {
if(ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
Log.i("Permission","Permission is Denied");
ActivityCompat.requestPermissions(MainActivity.this,new String[]
{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 101);
}else{
new DownloadFileAsync().execute(file_url);
}
}

@Override
protected Dialog onCreateDialog(int id){
switch(id){
case download_progress:
prgDialog = new ProgressDialog(this);
prgDialog.setMessage("Downloading file...");
prgDialog.setIndeterminate(false);
prgDialog.setMax(100);
prgDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
prgDialog.setCancelable(false);
prgDialog.show();
return prgDialog;
default:
return null;
}
}




class DownloadFileAsync extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute(){
super.onPreExecute();
showDialog(download_progress);
}
@Override
protected String doInBackground(String... aurl) {

int count;
try {
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
Log.i("koneksi","koneksi berhasil");
int lenghtOfFile = conexion.getContentLength();
Log.i("UkuranFile", "ukuran"+String.valueOf(lenghtOfFile));
InputStream input = new BufferedInputStream(url.openStream(),10*1024);
String fileName = conexion.getHeaderField("Content-Disposition");
if (fileName == null || fileName.length() < 1){
URL downloadUrl = conexion.getURL();
fileName = downloadUrl.getFile();
fileName = fileName.substring(fileName.lastIndexOf("/")+1);
} else {
fileName = URLDecoder.decode(fileName.substring(fileName.indexOf("filename=") + 9),
"UTF-8");
fileName = fileName.replaceAll("\"", "");
}
OutputStream output = new
FileOutputStream(Environment.getExternalStorageDirectory().getPath()+"/Download/"+fileName);
byte data[] = new byte[1024];
long total = 8;
while ((count = input.read(data))!= -1){
total += count;
publishProgress(((int) (total*100)/ lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
Log.d("koneksi","koneksi gagal");
}


return null;
}


protected void onProgressUpdate(Integer... progress) {
prgDialog.setProgress(progress[0]);

}

protected void onPostExecute(String result) {
dismissDialog(download_progress);
Toast.makeText(getApplicationContext(), "Download complete. File in /sdcard/Download",
Toast.LENGTH_SHORT).show();

}
}
}

 

4. Mengkonfigurasi Security Config

Buat sebuah file xml baru dengan Nama network_security_config.xml di dalam folder /res/xml dan ketikan kode program berikut seperti gambar di bawah ini

   

<?xml version="1.0" encoding="utf-8"?>

<network-security-config
xmlns:android="http://schemas.android.com/apk/res/android">
<base-config cleartextTrafficPermitted="true" />
</network-security-config>


 
File ini digunakan agar aplikasi bisa mengakses url yang tanpa SSL (url https), dan  struktur nya sendiri akan menjadi seperti gambar di bawah ini
 

   


5. Ubah  script AndroidManifest.xml 

Sesuaikan script AndroidManifest.xml seperti di bawah ini untuk mendaftarkan  komponen Intent Filter dan mendaftarkan permission akses internet & write external  storage yang kita butuhkan
 

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.naskahkode.asynctaskdownload">

<application
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AsyncTaskDownload">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE"/>

</manifest>

6. Run Project

Lalu coba jalankan menggunakan emulator yang tersedia di Android Studio Anda,  maka akan tampil seperti gabar dibawah  


 

 



 
  
 

Aplikasi akan meminta akses ke media penyimpanan anda, pilih izinkan selanjutnya  tekan tombol download Kembali maka progress download akan terlihat di layer.
 
 
 Selanjutnya coba cek di folder …/download/ menggunakan file manager. Dan coba buka  file hasil
download tersebut
 
 
  

7.Done