Android ile dosya indirme ve bir ProgressDialog ilerleme gösteren
Güncellenir basit bir uygulama yazmaya çalışıyorum. Bunun için bir dosya indirebilen basit bir fonksiyon ihtiyacım vargeçerli ilerleme gösterirProgressDialog
. ProgressDialog
, nasıl yapılacağını biliyorum ama geçerli durumunu görüntülemek için nasıl ve en başta dosya indirmek için nasıl emin değilim.
CEVAP
Dosya indirmek için birçok yol vardır. Ben aşağıdaki en yaygın yolu yayınlayacağız; uygulamanız için daha iyi olduğuna karar.
1. AsyncTask
kullanın ve bir iletişim içinde indirme ilerlemesini gösterir
Bu yöntem, bazı arka plan işlemleri yürütmek ve aynı zamanda UI (bu durumda, bir ilerleme çubuğu güncelleme yapacağız) güncellemek için izin verir.
Bu örnek bir kod
// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;
// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);
// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");
mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
AsyncTask
Bu gibi görünecektir:
// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
private PowerManager.WakeLock mWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
@Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " connection.getResponseCode()
" " connection.getResponseMessage();
}
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/file_name.extension");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
return null;
}
total = count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
Yukarıdaki yöntem (doInBackground
) Her zaman bir arka plan iş parçacığı üzerinde çalışır. Herhangi bir UI görevleri var yapmamalısın. Diğer taraftan, onProgressUpdate
onPreExecute
UI iş parçacığı üzerinde ilerleme çubuğu değiştirebilirsiniz böylece orada çalıştırın:
@Override
protected void onPreExecute() {
super.onPreExecute();
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
mWakeLock.acquire();
mProgressDialog.show();
}
@Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress[0]);
}
@Override
protected void onPostExecute(String result) {
mWakeLock.release();
mProgressDialog.dismiss();
if (result != null)
Toast.makeText(context,"Download error: " result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
}
Bu çalıştırmak için WAKE_LOCK izni gerekir.
<uses-permission android:name="android.permission.WAKE_LOCK" />
2. Hizmetten indir
Büyük soru şudur:nasıl bir hizmet benim etkinlik güncellerim?. Farkında olmayabilirsin iki sınıf kullanacağız sonraki örnek: ResultReceiver
IntentService
. ResultReceiver
olanı bulmamızı sağlayacak güncelleme parçacığı bir hizmet; IntentService
sınıfı Service
yumurtlar yapmak için bir iş parçacığı arka plan iş var (bilmen gereken bir Service
çalışır aslında aynı iplik uygulaması; ne zaman uzatır Service
, sizin el ile spawn yeni bir iş parçacığı çalıştırmak için CPU engelleme işlemleri).
İndir hizmeti, bu gibi görünebilir:
public class DownloadService extends IntentService {
public static final int UPDATE_PROGRESS = 8344;
public DownloadService() {
super("DownloadService");
}
@Override
protected void onHandleIntent(Intent intent) {
String urlToDownload = intent.getStringExtra("url");
ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
try {
URL url = new URL(urlToDownload);
URLConnection connection = url.openConnection();
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(connection.getInputStream());
OutputStream output = new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total = count;
// publishing the progress....
Bundle resultData = new Bundle();
resultData.putInt("progress" ,(int) (total * 100 / fileLength));
receiver.send(UPDATE_PROGRESS, resultData);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
Bundle resultData = new Bundle();
resultData.putInt("progress" ,100);
receiver.send(UPDATE_PROGRESS, resultData);
}
}
Senin apaçık hizmeti ekleyin:
<service android:name=".DownloadService"/>
Ve etkinliğin bu gibi görünecektir:
// initialize the progress dialog like in the first example
// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);
Burada ResultReceiver
geliyor oynamak:
private class DownloadReceiver extends ResultReceiver{
public DownloadReceiver(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == DownloadService.UPDATE_PROGRESS) {
int progress = resultData.getInt("progress");
mProgressDialog.setProgress(progress);
if (progress == 100) {
mProgressDialog.dismiss();
}
}
}
}
2.1 Kullanım Groundy kütüphane
Groundy temelde bir arka plan hizmeti kod parçaları çalıştırmak yardımcı olan bir kütüphane ve ResultReceiver
kavramı yukarıda gösterilen dayanmaktadır. Bu kütüphanekaldırılmışşu anda. Bu nasıl olurtümkod gibi görünecektir:
İletişim gösteriyoruz nerede faaliyet...
public class MainActivity extends Activity {
private ProgressDialog mProgressDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
Groundy.create(DownloadExample.this, DownloadTask.class)
.receiver(mReceiver)
.params(extras)
.queue();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
}
});
}
private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
switch (resultCode) {
case Groundy.STATUS_PROGRESS:
mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
break;
case Groundy.STATUS_FINISHED:
Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
mProgressDialog.dismiss();
break;
case Groundy.STATUS_ERROR:
Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
mProgressDialog.dismiss();
break;
}
}
};
}
GroundyTask
bir uygulama tarafından kullanılıyorGroundydosyayı indirmek için ve ilerleme göster:
public class DownloadTask extends GroundyTask {
public static final String PARAM_URL = "com.groundy.sample.param.url";
@Override
protected boolean doInBackground() {
try {
String url = getParameters().getString(PARAM_URL);
File dest = new File(getContext().getFilesDir(), new File(url).getName());
DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
return true;
} catch (Exception pokemon) {
return false;
}
}
}
Ve sadece bildirim için bu ekleyin:
<service android:name="com.codeslap.groundy.GroundyService"/>
Bence daha kolay olamazdı. Sadece son kavanoz from Github kapmak ve gitmek için hazır. Bunu aklında tutGroundy'nin temel amacı, bir arka plan hizmeti dış REST API çağrıları yapmak ve kolayca UI sonrası sonuçları. Eğer uygulamanızda böyle bir şey yapıyorsanız, gerçekten yararlı olabilir.
2.2 Kullanma 53**
3. DownloadManager
sınıf (GingerBread
ve daha yeni sadece) kullanın
Bu yöntem müthiş, dosya indirme konusunda endişelenmenize gerek yok el ile, konuları, dereler, vb kolu. Zencefilli yeni bir özellik getirdi: dosyaları kolayca indirebilir ve sistem için sabit temsilci iş veren DownloadManager
.
İlk olarak, yardımcı bir yöntem bakalım:
/**
* @param context used to check the device version and DownloadManager information
* @return true if the download manager is available
*/
public static boolean isDownloadManagerAvailable(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
return true;
}
return false;
}
Yöntemin adı her şeyi açıklıyor. DownloadManager
kullanılabilir olmadığından emin olduktan sonra böyle bir şey yapabilirsiniz:
String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");
// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
Yükleme ilerleme bildirim çubuğunda gösteriyor olacak.
Son düşünceler
Birinci ve İkinci yöntem sadece buzdağının görünen kısmı. Eğer app güçlü olmak istiyorsanız, akılda tutulması gereken şeyler vardır. İşte kısa bir liste:
- Kullanıcı bir internet bağlantısı mevcut olup olmadığını kontrol etmelisiniz
- Eğer internet durumunu kontrol etmek istiyorsanız doğru izinleri (
INTERNET
WRITE_EXTERNAL_STORAGE
);ACCESS_NETWORK_STATE
da olduğundan emin olun. - Dizin dosya var indirmek için gidiyoruz olduğunu ve yazma izinleri olduğundan emin olun.
- Eğer indirme çok büyükse eğer önceki girişimleri başarısız olursa, yükleme devam etmek için bir yol uygulamak isteyebilirsiniz.
- Kullanıcılar eğer onları indirmek kesme izin verirseniz minnettar olacağım.
İndirme işlemi üzerinde tam kontrol sahibi olmak istemiyorsan, ben çok zaten yukarıda listelenen öğelerin çoğu işleyen DownloadManager
kullanmanızı öneririz.
Android dosya indirme sorunları ikili...
Nasıl Android emülatör MUAYENE bir dos...
Tarayıcı dosya indirme aldığında tespi...
Eksik Güncellemelerinden 4 uyarılar yü...
'varlık' sdcard klasörüne do...