SORU
12 HAZİRAN 2010, CUMARTESİ


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
12 HAZİRAN 2010, CUMARTESİ


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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • jkimisyellow

    jkimisyellow

    6 Mayıs 2009
  • Leigh Momii

    Leigh Momii

    10 Mayıs 2006
  • Tracy Hairston

    Tracy Hairst

    22 Mayıs 2009