Итак, давайте переработаем наше приложения для загрузки файлов так, чтобы оно могло докачать файл при любых обстоятельствах. Научимся использовать BroadcastReceiver.
Создаём сервис и шлём сообщение
Код взаимодействия с сервером размещаем в классе, расширяющем WakefulIntentService:
import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.content.Intent; import com.commonsware.cwac.wakeful.WakefulIntentService; public class LoaderService extends WakefulIntentService { public static final String FURL = "FURL"; public LoaderService() { super("LoaderService"); } @Override protected void doWakefulWork(Intent intent) { String furl = intent.getStringExtra(FURL); FileOutputStream fos = null; InputStream inputStream = null; try { updateUI(0, 100); URL url = new URL(furl); HttpURLConnection urlConnection = (HttpURLConnection) url .openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.setDoOutput(true); urlConnection.connect(); fos = new FileOutputStream(File.createTempFile("Tmp", "download")); inputStream = urlConnection.getInputStream(); int totalSize = urlConnection.getContentLength(); int downloadedSize = 0; byte[] buffer = new byte[1024]; int bufferLength = 0; while ((bufferLength = inputStream.read(buffer)) > 0) { fos.write(buffer, 0, bufferLength); downloadedSize += bufferLength; updateUI(downloadedSize, totalSize); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (fos != null) fos.close(); if (inputStream != null) inputStream.close(); } catch (Exception e) { } } } private void updateUI(int downloadedSize, int totalSize) { Intent intt = new Intent(BackFLoaderActivity.ACTION_LOAD); intt.putExtra(BackFLoaderActivity.CURRVAL, downloadedSize); intt.putExtra(BackFLoaderActivity.MAXVAL, totalSize); sendBroadcast(intt); } }
Тут мы в методе doWakefulWork выполняем чтение файла по сети буфером по киллобайту, и на каждой итерации чтения вызываем метод updateUI. В этом методе мы создаём Intent указывая ему наш action, укладываем в него общий размер и суммарный скачанный размер файла. Intent отдаём в метод sendBroadcast, посылая тем самым сообщение.
Слушаем и реагируем на сообщение
Вот код главного Activity:
import com.commonsware.cwac.wakeful.WakefulIntentService; import android.app.Activity; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.Button; public class BackFLoaderActivity extends Activity { public static final String CURRVAL = "CURRVAL", MAXVAL = "MAXVAL"; public static final String ACTION_LOAD = "ACTION_LOAD"; private ProgressDialog progressDialog; private BroadcastReceiver rec; @Override public void onResume() { // creating and register receiver rec = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int curr = intent.getIntExtra(CURRVAL, 50); int max = intent.getIntExtra(MAXVAL, 100); if (!progressDialog.isShowing()) { progressDialog.setMessage("Downloading ..."); progressDialog.setCancelable(false); progressDialog.setMax(100); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.show(); } progressDialog.setProgress((int) ((curr / (float) max) * 100)); if (curr==max) { progressDialog.dismiss(); } } }; registerReceiver(rec, new IntentFilter(new IntentFilter(ACTION_LOAD))); super.onResume(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); progressDialog = new ProgressDialog(this); Button load = new Button(this); load.setText("Load file"); load.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { progressDialog.setMessage("Downloading ..."); progressDialog.setCancelable(false); progressDialog.setMax(100); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.show(); Intent intent = new Intent(BackFLoaderActivity.this, LoaderService.class); intent.putExtra(LoaderService.FURL, "http://anjedi.com/api_lib/2.2_level8.jar"); WakefulIntentService.sendWakefulWork(BackFLoaderActivity.this, intent); } }); setContentView(load, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } @Override protected void onPause() { unregisterReceiver(rec); super.onPause(); } }
Отсюда всё начинается, тут всё и заканчивается. По-порядку:
- В onCreate рисуем кнопку, определяя что нужно делать по клику. А по клику нужно запустить прогресс-бар, создать Intent, уложить в него url для загрузки файла и запустить с этим intent-ом серис.
- В onResume создаём экземпляр BroadcastReceiver и регистрируем его с указанием того же Action, с которым посылаем сообщение из сервиса. Зарегистрировать получателя сообщений можно и в манифесте, но в нашем случае так нагляднее.
- При создании BroadcastReceiver-а описываем, что он должен делать при получении сообщения в методе onRecrive. А должен он прочитать данные о общем размере и размере скачанной части файла и отобразить соответствующую долю на progress-баре.
- И не забудем удалить регистрацию BroadcastReceiver-а в методе onPause, чтобы не получить ошибку при уходе приложения в фон.
WakefulIntentService - это откуда ?
ОтветитьУдалитьгде взять этот класс
ОтветитьУдалитьimport com.commonsware.cwac.wakeful.WakefulIntentService; ?