How To Download File by Showing Progress Bar in Android


Bazı işlemler vardır çok kısa sürede gerçekleşebilir, bazıları ise fazladan zamana ihtiyaç duyarlar. Buna örnek olarak herhangi bir indirme (download) işlemini düşünebiliriz. Gösterilmek istenen dosya indirilene kadar biraz zaman geçmesi durumunda kullanıcıya bir uyarı veya bilgilendirme vermeliyiz eğer güzel bir arayüz tasarlıyorsak. Bu yazıda ProgressBar kullanacağız. Kısaca yazıdan bahsetmek gerekirse, butona tıkladığımızda önceden belirlediğimiz konumdaki dosyayı indirme işlemi başlayacak ve indirme işlemi bitene kadar ekranda bir ProgressBar görünüp, yüklemenin ilerleyişini bizlere gösterecek.

1. Yeni Proje Oluşturalım: File -> New -> Android Project

2. main.xml dosyasını düzenleyelim:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- Download Button -->
    <Button android:id="@+id/btnProgressBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Download File with Progress Bar"
        android:layout_marginTop="50dip"/>

    <!-- İndirme işleminden sonra görünecek olan ImageView -->
    <ImageView android:id="@+id/my_image"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

3. Şimdi main activity class’ ını yazmaya başlıyoruz:

public class AndroidDownloadFileByProgressBarActivity extends Activity {

    // progress dialog göstermek için button tanımlama.
    Button btnShowProgress;

    // Dialog & ImageView tanımlama.
    private ProgressDialog pDialog;
    private ImageView my_image;

    // Progress dialog tipi (0 - ilerleyen...)
    public static final int progress_bar_type = 0;

    // İndirmek için dosya url' si
    // Burada yaklaşık 4MB boyutunda bir dosya mevcut, dilediğiniz linki verebilirsiniz.
    private static String file_url = "http://upload.wikimedia.org/wikipedia/commons/8/88/Germany-Farchant-Landscape.JPG";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // main xml' deki button' u al.
        btnShowProgress = (Button) findViewById(R.id.btnProgressBar);
        // main.xml' deki imageView' i al, (indirme işleminden sonra görünecek)
        my_image = (ImageView) findViewById(R.id.my_image);

        /**
         * Button click olayı
         * */
        btnShowProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Yeni Async Task başlangıcı, çalıştırma şekli böyledir!
                new DownloadFileFromURL().execute(file_url);
            }
        });
    }

4. ProgressDialog gösterimi: ProgressDialog normal bildiğimiz AlertDialog class’ ının alt class’ ıdır. Şimdi kodların devamı olarak alert metodunu ekliyoruz.

/**
 * Dialog Gösterim Yeri.
 * */
@Override
protected Dialog onCreateDialog(int id) {
    switch (id) {
    case progress_bar_type:
        pDialog = new ProgressDialog(this);
        pDialog.setMessage("Downloading file. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setMax(100);
        pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pDialog.setCancelable(true);
        pDialog.show();
        return pDialog;
    default:
        return null;
    }
}

5. Şimdi ise arkaplanda yapılan indirme işi için asynctask class’ ını kullanacağız. Bunun için bir class tanımlayalım, adı da DownloadFileFromURL olsun. Buradaki olay şu: Resim indirme esnasında ProgressBar ekranda bilgi veriyor, bittiği zaman da ise ekrandan kayboluyor ve SD kartın içine indirilen resim ekranda ImageView yardımı ile gösteriliyor.

/**
* Dosyayı İndirmek için Arkaplan Async Task Class' ı.
* */
class DownloadFileFromURL extends AsyncTask<String, String, String> {

    /**
     * Arkaplan işlemi başlamadan önceki thread
     * Bu sırada bilgi olarak ProgressBar gösteriliyor...
     * */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showDialog(progress_bar_type);
    }

    /**
     * Arkaplanda dosya indirilme esnasındaki thread
     * */
    @Override
    protected String doInBackground(String... f_url) {
        int count;
        try {
            URL url = new URL(f_url[0]);
            URLConnection conection = url.openConnection();
            conection.connect();
            // dosya uzunluğunu almak.
            int lenghtOfFile = conection.getContentLength();

            // Dosya okumak için input stream oluşturmak - 8k buffer ile
            InputStream input = new BufferedInputStream(url.openStream(), 8192);

            // Dosya yazmak için Output stream oluşturmak
            OutputStream output = new FileOutputStream("/sdcard/downloadedfile.jpg");

            byte data[] = new byte[1024];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                // ProgressBar' ın ilerleyişini göstermek...
                // Bundan sonra onProgressUpdate() metodu çağırılacak
                publishProgress(""+(int)((total*100)/lenghtOfFile));

                // Veriyi dosyaya yazmak
                output.write(data, 0, count);
            }

            // Çıktıyı temizle.
            output.flush();

            // Açılan stream' ları kapat.
            output.close();
            input.close();

        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
        }

        return null;
    }

    /**
     * ProgressBar' ın güncellenmesi olayı.
     * */
    protected void onProgressUpdate(String... progress) {
         // Yüzdelik değerin belirlenmesi.
         pDialog.setProgress(Integer.parseInt(progress[0]));
    }

    /**
     * Arkaplan işlemi bittikten sonra çalışacak yer.
     * Progress dialog ekrandan kaldırılıyor.
     * **/
    @Override
    protected void onPostExecute(String file_url) {
        // Dosya yüklendikten sonra ProgressDialog' u ekrandan kaybet.
        dismissDialog(progress_bar_type);

        // İndirilen dosyayı ImageView' in içide göster.
        // SDCard' tan resmin yolunu oku.
        String imagePath = Environment.getExternalStorageDirectory().toString() + "/downloadedfile.jpg";
        // ImageView' de resmi göster.
        my_image.setImageDrawable(Drawable.createFromPath(imagePath));
    }

}

6. AndroidManifest.xml dosyasına izinlerin eklenmesi:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.arifsami.AndroidDownloadFileByProgressBar"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <!-- Permission: İnternet Erişim İzni -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Permission: SDCard Yazma İzni -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidDownloadFileByProgressBarActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

7. Son Olarak Tüm Kod:

package your-package;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class AndroidDownloadFileByProgressBarActivity extends Activity {

	// button tanımlamak.
    Button btnShowProgress;

    // Progress Dialog & ImageView tanımlamak.
    private ProgressDialog pDialog;
    private ImageView my_image;

    // Progress dialog tipi (0 - ilerleyiş...)
    public static final int progress_bar_type = 0;

    // İndirilecek olan dosyanın URL' si.
    //
    private static String file_url = "http://upload.wikimedia.org/wikipedia/commons/8/88/Germany-Farchant-Landscape.JPG";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

     // main.xml' den Button' u al.
        btnShowProgress = (Button) findViewById(R.id.btnProgressBar);
        // main.xml' den ImageView' i al.
        my_image = (ImageView) findViewById(R.id.my_image);

        /**
         * Button Click Olayı.
         * */
        btnShowProgress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Async Task olayına başlamak. Kullanımı bu şekilde!
                new DownloadFileFromURL().execute(file_url);
            }
        });
    }

    /**
     * Dialog gösterim şekli.
     * */
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case progress_bar_type:
            pDialog = new ProgressDialog(this);
            pDialog.setMessage("Downloading file. Please wait...");
            pDialog.setIndeterminate(false);
            pDialog.setMax(100);
            pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            pDialog.setCancelable(true);
            pDialog.show();
            return pDialog;
        default:
            return null;
        }
    }

    /**
     * İndirme işlemi için Arkaplan Async Task Class' ı.
     * */
    class DownloadFileFromURL extends AsyncTask<String, String, String> {

        /**
         * Arkaplandaki iş başlamadan önceki kısım!
         * ProgressBar gösterim yeri..
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showDialog(progress_bar_type);
        }

        /**
         * Arkaplanda indirilen dosya kısmı..
         * */
        @Override
        protected String doInBackground(String... f_url) {
            int count;
            try {
                URL url = new URL(f_url[0]);
                URLConnection conection = url.openConnection();
                conection.connect();
                // Dosya uzunluğunu al.
                int lenghtOfFile = conection.getContentLength();

                // Dosya okumak için input stream oluştur - 8k buffer ile.
                InputStream input = new BufferedInputStream(url.openStream(), 8192);

                // Dosyaya yazmak için output stream oluştur.
                OutputStream output = new FileOutputStream("/sdcard/downloadedfile.jpg");

                byte data[] = new byte[1024];

                long total = 0;

                while ((count = input.read(data)) != -1) {
                    total += count;
                    // İlerleyişi gösterme.
                    publishProgress(""+(int)((total*100)/lenghtOfFile));

                    // Dosyaya veri yazma.
                    output.write(data, 0, count);
                }

                // Output' u temizle.
                output.flush();

                // Açılan stream' ları kapat.
                output.close();
                input.close();

            } catch (Exception e) {
                Log.e("Error: ", e.getMessage());
            }

            return null;
        }

        /**
         * ProgressBar güncelleme kısmı..
         * */
        protected void onProgressUpdate(String... progress) {
            // Yüzdelik değerin ayarlanması.
            pDialog.setProgress(Integer.parseInt(progress[0]));
       }

        /**
         * Arkaplan işlemi bittikten sonrası..
         * Dialog penceresinin kaybolması..
         * **/
        @Override
        protected void onPostExecute(String file_url) {
            // Dosya yüklendikten sonra dialogu kaybet.
            dismissDialog(progress_bar_type);

            // Resmin yolunu sdcard içinden oku.
            String imagePath = Environment.getExternalStorageDirectory().toString() + "/downloadedfile.jpg";
            // Yüklenen resmi ImageView' de göster.
            my_image.setImageDrawable(Drawable.createFromPath(imagePath));
        }

    }

}

Kodların ilerleyişini yorumlar ile açıklamaya çalıştım. Yine de anlaşılmayan yer olursa yorum yazın, en kısa zamanda cevap vermeye çalışacağım.

Reklamlar

28 Eyl 2012 tarihinde Android içinde yayınlandı ve , , , , , , , , olarak etiketlendi. Kalıcı bağlantıyı yer imlerinize ekleyin. 3 Yorum.

  1. anladigim kadariyla proje sadece bir buttonla indirme yapip hemen resmi gosteriyor.eger 2 button olusturmak istesek ve biri sadece indiricek ve indirme surecini gosterecek ,digeri ise yeni activity icinde ve tikladiginda resmi gosterecek.bu durumda nasil bir yol izlemek gerekir?

    • Şöyle düşünelim, zaten 1 tane button burada var, ona tıklayınca indirme işlemini de yapıyor zaten. Mesele sizin de dediğiniz gibi indirdikten sonra başka bir butona basıp yeni bir activity içerisinde göstermek..

      Şimdi DownloadFileFromURL() metodumuzu biliyoruz, bu asynctask class’ ından extends edildi, yani arkaplanda işlemler sırasıyla ilerliyor.
      Açıklamalarda belirttiğim gibi;
      1- İndirme işleminin öncesi, yani onPreExecute()
      2- İndirme işleminin gerçekleştiği yer, yani, doInBackground()
      3- İndirme işleminin bitip, sıradaki işlemin geldiği yer, yani onPostExecute()

      Sizin istediğiniz doğrultusunda zaten 2. aşamaya kadar tamam, mesele 3. aşamanın içerisinde.
      Dikkat edersek, 3. aşamada, yani onPostExecute() metodunun içerisinde indirilen dosyanın yolu mevcut, yani bunu saklayabiliriz, ayrıca kullanabiliriz de. Şöyle ki:
      // SDCard’ tan resmin yolunu oku.
      String imagePath = Environment.getExternalStorageDirectory().toString() + “/downloadedfile.jpg”;

      Buradaki imagePath değişkenini global olarak da tanımlayabilirsiniz, xml e koyduğunuz diğer bir button click olayı içerisinde bu yolu işleyebilir, resmi başka bir activity nin içerisinde açabilirsiniz. Nasıl olacak bu olay derseniz eğer, Activity ler arası geçişleri inceleyebilirsiniz.

      Bulunduğun sayfada
      Intent i = new Intent(BulunduğunActivity.this, GidilecekActivity.class);
      i.putExtra("Key", "Value");

      Key: Anahtarın, yani GidilecekActivity içerisinde bu değerle istek yapacaksın.
      Value: imagePath’ i buraya koyabilirsin mesela, istediğin değer.

      GidilecekSayfa için:
      getIntent().getStringExtra("Key");
      önceki sayfada attığın değeri bu şekilde alıyorsun..

      Özet olarak: imagePath değerini diğer bir activity ‘e aktaracaksınız, oradaki imageView’ in setDrawable metodunu işleyeceksiniz, bu kadar.

  2. merhaba
    protected void onPostExecute(String file_url) {
    üstteki kod satırında file_url nin değeri nedir veya nasıl değiştirebiliriz

Bir Yanıt Bırakın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Log Out / Değiştir )

Connecting to %s

%d blogcu bunu beğendi: