PDA

View Full Version : قابلیت resume برای دانلود فایل از طریق اینترنت



moralschool
سه شنبه 30 اردیبهشت 1393, 22:18 عصر
من برای دانلود مثلا یه فایل صوتی از اینترنت از این مشکلات رو دارم :


1- اگه کاربر روی دکمه back کلیک کرد ، دانلود فایل لغو میشه و اگه دوباره بخواد اونو دانلود کنه باید از اول این کار رو انجام بده !


2- و یه مشکل بزرگتر اینه که اگه در حین دانلود صفحه نمایش رو لمس کنه ، بازم دانلود لغو میشه !!!!!!!


دوستان برای حل این مشکل چه راهی رو پیشنهاد میکنند ؟
ممنون


اینم کدی هست که در یه دکمه برای دانلود فایل صوتی استفاده میکنم :



imgdownload.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub



File file = new File(root.getAbsolutePath() + "/my_folder/" + "music.mp3");
if (file.exists() ){
//imgdownload1.setEnabled(false);
imgplay1.setEnabled(true);
Toast.makeText(getApplicationContext(), "فایل قبلا دانلود شده است", Toast.LENGTH_LONG).show();
return;
}







if(isNetworkConnected()){ // check internet connection
// your codes


// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(Main.this); // MainActivity = activity name
mProgressDialog.setMessage("فایل در حال دانلود می باشد");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.ST YLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(Main.this); // MainActivity = activity name
downloadTask.execute("http://آدرس فایل.mp3"); // the url to the file you want to download

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
File file = new File(root.getAbsolutePath() + "/my_folder/" + "music.mp3");
if (file.exists() ){
file.delete();
return;
}
}
});

}


}


// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
class DownloadTask extends AsyncTask<String, Integer, String> {

private Context context;

public DownloadTask(Context context) {
this.context = context;
}

@Override
protected String doInBackground(String... sUrl) {
// 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);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
wl.acquire();

try {
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/my_folder/music.mp3"); // /sdcard/file_name.extension
File outputFile = new File("/sdcard/my_folder/music.mp3" + ".tmp");
output = new FileOutputStream(outputFile);


byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled())
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);
}
outputFile.renameTo(new File("/sdcard/my_folder/music.mp3"));
} 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();
}
} finally {
wl.release();
}
return null;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
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) {
mProgressDialog.dismiss();
if (result != null)
Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"فایل با موفقیت دانلود شد", Toast.LENGTH_SHORT).show();




}



}
});

c0mmander
پنج شنبه 01 خرداد 1393, 02:42 صبح
برای مشکل بزرگتون پروسه دانلود رو داخل یک نخ قرار بدید و انجام عملیات رو به اون بدید.

اما برای مشکل عدم resume شدن : والا منم این مشکل رو با مونو داشتم که با استفاده از HttpWebRequest مشکل رو حل کردم. اما طریقه اجراییشو در جاوا نمیدم.

moralschool
پنج شنبه 01 خرداد 1393, 06:52 صبح
ممنون یعنی از thread ؟؟
میشه بیشتر توضیح بدید که به چه شکل ؟

c0mmander
پنج شنبه 01 خرداد 1393, 12:18 عصر
به طور کلی باید به این صورت عمل بشه .

1- تعریف کلاس
2- تعریف نخ
3- تعریف متد نخ
4- انتصاب متد به نخ
4- Run کردن نخ

اما شما باید ابتدا کد های دانلود خودتون رو داخل یک متد بنویسید و بعد از تعریف theard و قرار دادن اون متد در theard دستور رو اجرا کنید. این کار باعث میشه که یک مسیر اجرایی داشته باشید که دیگه تحت تاثیر رویداد های دیگری نیست. هم چینن در مواردی هم که برنامه در حال انجام پردازشی میباشد میتوانید به نخ بدهید تا برنامه در زمان محاسبه هنگ نکنند و کاربر بتوانید از دیگر جاهای برنامه شما استفاده کند
-------------------------------------------------------------------------------
اما برای Resume کردن, قبل از هر چیزی یک پیشنهادی میکنم : اول به دنبال راهی برای Resume کردن دانلود ها در یک برنامه ویندوزی یا سیستمی باشید و بعد به سراغ اندروید بروید!

این روش شاید بهترین روش نباشه اما بخوبی برای من عمل میکنه:

1- تعریف HttpWebRequest
2- تعریف HttpWebResponse
3- محاسبه طول فایل دانلود شده (همان startpoint برای دانلود جدید)
4- قرار دادن startpoint محاسبه شده به add range در httpwebrequst
5- پاسخ گرفتن از سرور با استفاده از httpwebresponse که حجم کلی فایل رو می توان گرفت
6- و ذخیره کردن پاسخ های داده ای در فایلی که با append باز شده

__________________________________________________ ___

درسته کاری من با زبان کاری شما با شما متفاوت است اما در کل میشه روش ها رو با یک سری تغییرات میتونید استفاده کنید.

moralschool
پنج شنبه 01 خرداد 1393, 23:17 عصر
ممنون از توضیحاتتون مطمئنا توضیحات کاملی هست اما متاسفانه ما هنوز اول راهیم و خوب متوجه نمیشیم

لطفا اگه میشه یه نمونه یا یه مثال ساده برای این کار معرفی کنید
اگه با توجه به کدی که بنده در بالا ذکر کردم باشه که خیلی بیشتر کمک میکنه
در هر صورت ممنونم

c0mmander
جمعه 02 خرداد 1393, 00:08 صبح
خیلی دوست داشتم که کدی رو برات قرار میدادم اما زبان برنامه نویسی من C# هست و به درد کار شما نمی خوره.

اما به هر حال روش یکی هست . لینک های زیر رو بررسی کن :

http://stackoverflow.com/questions/3411480/how-to-resume-an-interrupted-download

http://stackoverflow.com/questions/4593275/resume-download-not-working-in-android

این هم یک تکه کد کاملی از قابلیت resume با جاوا:

http://stackoverflow.com/questions/14423108/pause-resume-http-connection-download

برای قابلیت نخ هم من آموزشش رو داخل همین جا دیدم. میتونید از اون استفاده کنید.