آموزش ساخت دانلودر (به روش دانلود از طریق دانلود منیجر اندروید)
قابلیت ها:
-فعال یا غیر فعال کردن نوتیفیکیشن.
-ست کردن Title برای نوتیفیکیشن (اگر ست نکنید زمان باقی مانده از دانلود رو میزنه).
-ست کردن Description برای نوتیفیکیشن.
-ست کردن نام فایل خروجی(باید با پسوند باشد).
-ست کردن نوع فایل خروجی.
-OnDownloadCompleteListener
-OnDownloadProgressListener
توضیحات: چند پارامتر ورودی در کانستراکتور وجود دارد، دلیل وجود این پارامترها، الزام وجود آنهاست. (مثلا url حتما باید پرشده باشه و امکان خالی گذاشتنش نباید وجود داشته باشه)
سورس:
package helper; import android.app.Activity; import android.app.DownloadManager; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; /** * Created by Hajhosseini on 10/31/2015. */ public class DownloadManagerHelper extends AsyncTask { private Activity activity; private String url; private String downloadPath; private String fileName; private String requestType; public DownloadManagerHelper(Activity _activity,String _url,String _downloadPath){ activity = _activity; downloadPath = _downloadPath; url = _url; } @Override protected void onPreExecute() { super.onPreExecute(); if(fileName == null) fileName = getFileName(url); } @Override protected Object doInBackground(Object[] params) { downloadFile(); return null; } @Override protected void onPostExecute(Object object) { super.onPostExecute(object); if (downloadCompleteListener != null) downloadCompleteListener.onDownloadComplete(); } private void downloadFile() { DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); request.setDescription(notificationTitle); request.setTitle(notificationDescription); if(requestType != null && !requestType.equals("")) request.setMimeType(requestType); request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { request.allowScanningByMediaScanner(); if (SHOW_NOTIFICATION_PROGRESS) request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE); else request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION); } request.setDestinationInExternalPublicDir(downloadPath, fileName); final DownloadManager manager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE); final long downloadId = manager.enqueue(request); DownloadManager.Query q = new DownloadManager.Query(); q.setFilterById(downloadId); boolean downloading = true; while (downloading) { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); Cursor cursor = manager.query(query); cursor.moveToFirst(); int downloadedSize = cursor.getInt(cursor .getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); int totalSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) { downloading = false; } final int percent = (int) (100.0f * (float) downloadedSize / totalSize); activity.runOnUiThread(new Runnable() { @Override public void run() { if (downloadProgressListener != null) downloadProgressListener.onDownloadProgressListener(percent); } }); cursor.close(); } } private DownloadProgressListener downloadProgressListener; private DownloadCompleteListener downloadCompleteListener; private boolean SHOW_NOTIFICATION_PROGRESS = false; private String notificationTitle = ""; private String notificationDescription = ""; public DownloadManagerHelper showNotificationProgress(){ SHOW_NOTIFICATION_PROGRESS = true; return this; } public DownloadManagerHelper setDownloadFileName(String _fileName){ fileName = _fileName; return this; } public DownloadManagerHelper setNotificationTitle(String _notificationTitle){ notificationTitle = _notificationTitle; return this; } public DownloadManagerHelper setNotificationDescription(String _notificationDescription){ notificationDescription = _notificationDescription; return this; } public interface DownloadCompleteListener{ void onDownloadComplete(); } public interface DownloadProgressListener{ void onDownloadProgressListener(int percent); } public DownloadManagerHelper setDownloadProgressListener(DownloadProgressListener progressListener){ downloadProgressListener = progressListener; return this; } public DownloadManagerHelper setDownloadCompleteListener(DownloadCompleteListener completeListener){ downloadCompleteListener = completeListener; return this; } public DownloadManagerHelper setRequestType(String _requestType){ requestType = _requestType; return this; } public void startDownload(){ this.execute(); } private String getFileName(String url){ return (url.substring( url.lastIndexOf('/')+1, url.length())); } }
طریقه استفاده:
new DownloadManagerHelper(getActivity(),"http://orig15.deviantart.net/4eb3/f/2014/004/8/0/__i_m_so_pathetic____no_background__by_liamwhite1-d70v94v.png",Environment.DIRECTORY_DOWNLOADS) .showNotificationProgress() .setDownloadFileName("pony.jpg") .setRequestType("image/JPG") .setNotificationTitle("some title") .setNotificationDescription("some desc") .setDownloadCompleteListener(new DownloadManagerHelper.DownloadCompleteListener() { @Override public void onDownloadComplete() { Toast.makeText(getActivity(),"DONE",Toast.LENGTH_LONG).show(); } }) .setDownloadProgressListener(new DownloadManagerHelper.DownloadProgressListener() { @Override public void onDownloadProgressListener(int percent) { Log.i("LOG","Percent is : "+percent); } }) .startDownload();
به نکته خوبی اشاره کردید حامد جان. این قابلیت وجود داره و استفاده ازش بسیار راحته:
زمان ساخت دانلودر باید یک آیدی به اینستنس اون اختصاص بدیم:
long id = downloadManager.enqueue(request);
زمانی که میخواید دانلود متوقف بشه، فقط کافیه از کد زیر استفاده کنید:
downloadManager.remove(id);
downloadManager همون اینستنسی هست که دانلود رو استارت کرده. پس شما باید اون دانلود منیجر رو نگه داری یا فقط یک دانلود منیجر توی برنامه داشته باشی که بتونی با آیدی های مختلف، دانلود ها رو مدیریت کنی.
سلام من دو تا سوال دارم :
1- من وقتی روی Environment.DIRECTORY_DOWNLOADS ذخیره میکنم همه چی درست کار میکنه ولی نمیدونم چرا فایل ها رو توی دایرکتوری های sd card نمیریزه!!!
این مسیر دایرکتوری منه که ساخته شده از قبل :
Environment.getExternalStorageDirectory().getAbsolutePath()+"/folder"
permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2- اگه یه آدرس url اشتباه بهش بدیم تا ابد میره تلاش میکنه و بی نتیجه می مونه!!!
چجوری میشه متد timeOut براش پیاده سازی کرد؟
سلام ممنونم از کدهاتون خیلی مفید بود . چندتا سوال داشتم :
1 - دانلود ها فقط باید در پوشه download قرار بگیرند ؟ منظورم همون Environment.DIRECTORY_DOWNLOADS هست چون فقط تو این مسیر درست کار میکنه و وقتی مسیر خودم رو میدم خطا میده . همچنین وقتی میخوام از پوشه download فایل رو به مسیر خودم کپی کنم هم این کار انجام نمی شه .
2 - قابلیت resume در این دانلود منیجر وجود نداره ؟چون با دستور downloadmanager.remove(id)d که دانلود رو متوقف میکنم بعد دوباره دانلود رو شروع میکنم ، فایل از اول شروع به دانلود می شه .
طریقه استفاده از Handler:
کد زیر رو میتونید توی کلاس App - Application یا G تعریف کنید.
public static final Handler HANDLER = new Handler();
اگر فقط یک جا استفاده میکنید، نیازی نیست static final رو بنویسید، ولی اگر چند جا استفاده میکنید میتونه استاتیک باشه.
و همچنین اگر static final نمیذارید میتونید توی کلاس دانلودر تعریفش کنید.
حالا کد زیر رو
activity.runOnUiThread(new Runnable() { @Override public void run() { if (downloadProgressListener != null) downloadProgressListener.onDownloadProgressListener(percent); } });
به کد زیر تغییر بدید
HANDLER.post(new Runnable() { @Override public void run() { if (downloadProgressListener != null) downloadProgressListener.onDownloadProgressListener(percent); } });
با توجه به اینکه AsyncTask خودش یک متد refresh داره که روی Main Thread اجرا میشه، بهتر بود که من از اون متد استفاده میکردم، ولی چون این کد خیلی قدیمیه و هیچ تفاوتی میان این 2 کد نیست، شما همینو تغییر بدید.
توضیحات: توی با توجه به اینکه ما میخوایم در هنگام دانلود فایل، اپلیکیشن Freez نشه و کاربر بتونه کارهای دیگه هم انجام بده، باید از Worker Thread ها استفاده کنیم، مشکل زمانی به وجود میاد که شما میخواید درصد دانلود رو روی صفحه نمایش بدید، در این قسمت نیازه که این عملیات بر روی Main Thread انجام بشه(کد بالا)، به همین منظور از Handler یا UiThread که همون Main Thread هست استفاده میکنیم.
ببخشید اقای حاج حسینی من از یه customCircle استفاده می کنم که میزان درصد دانلود رو نمایش میده میشه این کلاس دانلود رو کاری کرد که از 0 تا 100 رو بشماره نه یهو یه حجمی رو دانلود کنه چون اینجوری این ویوو سفارشی یهو پر میشه و زیاد جالب نیست
با سلام خدمت همه دوستان گرامی
و تشکر از آقای حاج حسینی عزیز
آقای حاج حسینی من سوالی در این لینک کردم که البته خواستم که با کتابخانه Volley بشه ولی یه چیزی اضافه بر کدی هست که باید بذارم ولی نمیدونم چطور!
حالا میخوام از دانلودر شما استفاده کنم و اینکه چطور Authorization Basic رو به Header بفرستم تا بتونم دانلودم رو انجام بدم. و اینکه فایلهایی که میخوام از سرور بگیرم از همه نوع هست ینی همون File Mime Type. با این دانلودر میشه همه نوع فایل رو دان کرد؟
مهمترین مسئله من همون فرستادن Authorization Basic به Header هست که باید انجام بشه. آیا میشه با این کد این کارو کرد؟ اگر میشه به چه شکل؟!
ممنون میشم راهنمایی کنید و یه سری به لینکی که گفتم بزنید.
با تشکر فراوان
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .