دانلود فایل در اندروید

منتشرشده توسط حامد قنبری در تاریخ

دانلود کردن بعنوان یکی از مهمترین امکانات موجود در اپلیکیشن های اندرویدی ، با توجه به نقشی که این امر در جهت کارکرد مطلوب برنامه ها دارد ، می تواند وسیله ای مهم و تاثیرگذار محسوب شود. استفاده از این امکان ، در آپدیت کردن ورژن ها ، بروزرسانی محتوانی درونی برنامه ، و حتی در توسعه هر چه بیشتر برنامه همواره مورد توجه برنامه نویسان خلاق و پیشرفته بوده است. علی رغم وجود منابع وافر در این زمینه (در اینترنت)، متاسفانه ناآگاهی کاربران و نومیدی آنان در جستجوی منابع بیشتر ، منجر به اتلاف هزینه های بسیاری برای کاربران شده است. از این رو برآن شدیم که در این پست به آموزش این امر بپردازیم.

لازم است که بدانیم نداشتن اطلاعت کافی در این زمینه بخصوص در زمینه برنامه نویسی سوکت ، قدری موجب کند شدن سرعت یادگیری ما خواهد شد اگر در این زمینه از اطلاعات کافی برخوردار نیستید اینجا کلیک کنید. یادتان باشد تا حد ممکن از کپی کردن کدها خودداری کنید و همزمان با یادگیری مفاهیم اساسی در این زمینه ، از حداکثر حافظه خود بهره ببرید.

در این مثال ما فرایند این کار را (یعنی دانلود کردن ) را با استفاده از progress bar برای شما آموزش خواهیم داد.

اگر در داخل برنامه اکلیپس یا اندروید استودیو قرار دارید پروژه جدیدی را  ایجاد کنید

   اکلیپس :File ⇒ New Android ⇒ Application Project

اندروید استودیو :File ⇒ New  ⇒ New Project

اما اگر هنوز برنامه خود را باز نکرده اید یکی از برنامه های فوق را باز نموده و بعد از تعیین مشخصات(نامگذاری) ، تعیین حداقل sdk  و نوع اکتیویتی (blank  یا Empty) ، نام اکتیویتی ابتدایی و اصلی خود  را همان MainActivity قرار دهید. بعد از لود کامل برنامه ، در مسیر res ⇒layout لایه متناظر اکتیوتی اصلی یعنی activity_main را پیدا نمود و کدهای مندرج و پیش فرض آن را پاک کرده و کدهای xml  زیر را به آن اضافه کنید:

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

    <!-- Download Button -->

   
    <ImageView android:id="@+id/Showimage"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>

    <Button android:id="@+id/btnDownload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Download "
        android:layout_gravity="center_horizontal"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="202dp" />

</RelativeLayout>

 

حال در کلاس MainActivity  ابتدا کلاس های مورد نیاز را import کرده و سپس با تعریف کلاس و Extend آن به نوع Activity ، ضمن تعریف لایوت متناظر درSetcontentView(R.layou.activity_main) ،کلاس Download را با OnClickListener کردن باتن تعبیه شده در لایوت و تعریف شده در کلاس فراخوانی می کنیم.

public class MainActivity extends Activity {


  
    private ProgressDialog pDialog;
    public static final int progress_bar_type = 0;
private String file_url = "http://psrd.ir/wp-content/uploads/2017/06/imagedownload.jpg";

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

        // show progress bar button
        Button btnDownload = (Button) findViewById(R.id.btnDownload);
        // Image view to show image after downloading

        btnDownload.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // starting new Async Task
                new Download().execute(file_url);
            }
        });
    }
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case progress_bar_type: // we set this to 0
                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;
        }
    }

 

به دنبال نوشتن کدهای فوق در کلاس MainActivity ، خواهیم دهید که کلاس نوشته شده در متد OnClick به شکل قرمز رنگ(نشانه خطا) درخواهد آمد. باhighlight کردن بر روی آن و فشردن همزمان دکمه های Alt و Enter ، خواهیم دید آپشن هایی بنام create class ‘Download و create inner class ‘Download ظاهر خواهد شد که با کلیک بر  روی دومین آن یعنی ایجاد کلاس درونی(در صورت کلیک بر روی اولین آیتم اشاره شده ، کلاسی خارج از کلاس MainActivity ایجاد خواهد شد ) ، کلاسی با نام Download  به شکل زیر در پایین صفحه ظاهر خواهد شد.

private class Download {
}

اما چون در کلاس مورد اشاره و فراخوانده شده در باتن ، که به شکل زیر می باشد

 new Download().execute(file_url);

کلاس فراخوانده شده را با asynctask تعریف کرده (execute از متدهای asynctask می باشد)از این رو لازم است متدهای آن نیز باید implement گردد . در این کلاس asynctask  دارای سه متد به شرح زیر می باشد که در

1- doInBackground

در این متد همانطور که از نامش پیداست عملیات اصلی یعنی فرایند خواندن آدرس(Url) ، کانکت شدن به آن ،   تعیین حجم بافر، inputStream کردن از سرور و  outputStream کردن در لوکیشن تعیین شده در دیوایس، تبدیل به رشته های بیتی و بستن دو نوع استریم در پشت زمینه انجام می شود.

2- onProgressUpdate

در این مرحله همانطور که از نامش پیداست در حین  انجام فرایند فوق ، عملیات مشخصی در برنامه بروز پیدا می کند که نشانگر تداوم وضعیت فوق است. در این مثال نیز progress bar به کاربر نشان داده می شود که در آن میزان پیشرفت دانلود را نشان می دهد  .

3-onPostExecute

این مرحله نیز از زمان اتمام عملیات اصلی شروع می شود . یعنی برنامه نویس در این متد تعیین می کند که بعد از عملیات اصلی که در این مثال دانلود عکس از سرور است  چه واکنشی از طرف برنامه صادر شود. که در این مثال نشان دادن عکس در imageView می باشد.

بنابراین کلاس درونی ما به شکل زیر خواهد بود.

    class Download extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread
         * Show Progress Bar Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showDialog(progress_bar_type);
        }

        /**
         * Downloading file in background thread
         * */
        @Override
        protected String doInBackground(String... f_url) {
            int count;
            try {
                URL url = new URL(f_url[0]);
                URLConnection conection = url.openConnection();
                conection.connect();
                // getting file length
                int lenghtOfFile = conection.getContentLength();

                // input stream to read file - with 8k buffer
            InputStream input = new BufferedInputStream(url.openStream(), 8192);

                // Output stream to write file
           OutputStream output = new FileOutputStream("/sdcard/imagedownload.jpg");

                byte data[] = new byte[1024];

                long total = 0;

                while ((count = input.read(data)) != -1) {
                    total += count;
                    // publishing the progress....
                    // After this onProgressUpdate will be called
                    publishProgress(""+(int)((total*100)/lenghtOfFile));

                    // writing data to file
                    output.write(data, 0, count);
                }

                // flushing output
                output.flush();

                // closing streams
                output.close();
                input.close();

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

            return null;
        }

        /**
         * Updating progress bar
         * */
        protected void onProgressUpdate(String... progress) {
            // setting progress percentage
            pDialog.setProgress(Integer.parseInt(progress[0]));
        }

        /**
         * After completing background task
         * Dismiss the progress dialog
         * **/
        @Override
        protected void onPostExecute(String file_url) {
            // dismiss the dialog after the file was downloaded
            dismissDialog(progress_bar_type);

            // Displaying downloaded image into image view
            // Reading image path from sdcard
String imagePath = Environment.getExternalStorageDirectory().toString()+"/imagedownload.jpg";
            // setting downloaded into image view
            displayimage.setImageDrawable(Drawable.createFromPath(imagePath));
        }

    }
}

کدهای ادغام شده و نهایی ما به شکل زیر خواهد بود.

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;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

public class MainActivity extends Activity {



    private ProgressDialog pDialog;
    public static final int progress_bar_type = 0;
private String file_url = "http://psrd.ir/wp-content/uploads/2017/12/imagedownload.jpg";

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

       
        Button btnDownload = (Button) findViewById(R.id.btnDownload);
        btnDownload.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
               
                new Download().execute(file_url);
            }
        });
    }
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case progress_bar_type: // we set this to 0
                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;
        }
    }


    class Download extends AsyncTask<String, String, String> {

       
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showDialog(progress_bar_type);
        }

      
        @Override
        protected String doInBackground(String... f_url) {
            int count;
            try {
                URL url = new URL(f_url[0]);
                URLConnection conection = url.openConnection();
                conection.connect();
                int lenghtOfFile = conection.getContentLength();

               
                InputStream input = new BufferedInputStream(url.openStream(), 8192);

                
      OutputStream output = new FileOutputStream("mnt/sdcard/imagedownload.jpg");

                byte data[] = new byte[1024];

                long total = 0;

                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) {
                Log.e("Error: ", e.getMessage());
            }

            return null;
        }

        
        protected void onProgressUpdate(String... progress) {
         
            pDialog.setProgress(Integer.parseInt(progress[0]));
        }

       
        @Override
        protected void onPostExecute(String file_url) {
        final ImageView displayimage = (ImageView) findViewById(R.id.Showimage);

           
            dismissDialog(progress_bar_type);

           
String imagePath = Environment.getExternalStorageDirectory().toString() + "/imagedownload.jpg";
        
            displayimage.setImageDrawable(Drawable.createFromPath(imagePath));
        }

    }
}

  ودر آخر  به سراغ فایل Androidmanifest.xml  می رویم و با افزودن مجوز دسترسی به اینترنت و رایت کردن به حافظه خارجی به  به شکل زیر :

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

مجوز دسترسی اپلیکیشن  به اینترنت و رایت فایل دانلود شده به حافظه خارجی را  تعریف می کنیم. در نهایت کدهای AndroidManifest.xml را به شکل زیر تنظیم می کنیم. توجه داشته باشد که در صورت کپی کردن کدها نام پکیج خودرا  با پکیج  ارائه شده در مثال مقایسه کنید و پکیج پروژه خود را در آن لحاظ کنید.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.site.psrd.downloadandroid">
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    </uses-permission>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

حال پروژه را اجرا کرده و از آن در آموزش هر چه بیشتر خود استفاده کنید. اگر مشکلی در اجرای کدها وجود دارد یا سوال مشخصی از نویسنده سایت دارید سوالات خود را در قسمت دیدگاه ها بیان کنید.

کپی برداری از محتوای سایت psrd، ممنوع بوده و پیگرد قانونی دارد. (تنها استفاده شخصی کاربران ، مجاز است) (کپی برداری توسط سایر وب سایت ها  غیرقانونی بوده و در صورت رویت به ستادسازماندهی اطلاع داده خواهد شد.

منبع اصلی این مقاله :

http://www.androidhive.info/2012/04/android-downloading-file-by-showing-progress-bar/