在android中使用IntentService从服务器下载文件
Posted
技术标签:
【中文标题】在android中使用IntentService从服务器下载文件【英文标题】:downloading files from server using IntentService in android 【发布时间】:2013-12-27 14:41:52 【问题描述】:我正在尝试使用 IntentService 下载文件。我的下载队列被中断。
我正在使用下面的代码来启动一个服务
Intent intent = new Intent(ViewShowList.this, DownloadService.class);
// Create a new Messenger for the communication back
Messenger messenger = new Messenger(handler);
intent.putExtra("MESSENGER", messenger);
intent.putExtra("url", url);
intent.putExtra("share_id", showID);
intent.putExtra("showname", name);
intent.putExtra("showdatecreated", dateCreated);
intent.putExtra("noofFiles", noofFiles);
startService(intent);
返回通信处理程序
@SuppressLint("HandlerLeak")
private Handler handler = new Handler()
public void handleMessage(Message message)
Log.d(TAG, "handleMessage.....................");
//Object path = message.obj;
if (message.arg1 == DownloadService.COMPLETED)
Toast.makeText(mContext, getResources().getString(R.string.Text_MadeOffline), Toast.LENGTH_SHORT).show();
createOfflineShowsList();
syncShowAssets();
if (showListadapter != null)
showListadapter.notifyDataSetChanged();
else
Log.e(TAG, "Download Failed...");
;
下载服务.java
这是扩展 IntentService 的服务类
public class DownloadService
extends IntentService
private int OFFSET;
private int LIMIT;
String data;
private final String TAG = "DownloadService";
private int result = Activity.RESULT_CANCELED;
public static int COMPLETED = 100;
public static int FAILED = 101;
public static int LOW_SPACE = 102;
public static int NETWORK_PROBLEM = 103;
public static int ASSERT_EXISIT = 104;
public static int PARTIALLY_DOWNLOADED = 105;
public static int NO_FILE = 105;
private NotificationManager notificationManager;
private Notification notification;
ConnectivityManager connMgr;
ArrayList<HashMap<String, String>> showAssetList;
private SharedPreferences sotcPref;
PendingIntent contentIntent;
int i = 1;
String url;
String showname;
String showdatecreated;
String showId;
Messenger messenger;
int noofFiles;
public DownloadService()
super("DownloadService");
if (Constants.DEBUG)
Log.d(TAG, "Offline step 5 " + "DownloadService()constructor");
if (Constants.DEBUG)
Log.d(TAG, "DownloadService... Constructor");
OFFSET = 0;
LIMIT = 3;
@SuppressWarnings("deprecation")
@Override
protected void onHandleIntent(Intent intent)
// TODO Auto-generated method stub
if (Constants.DEBUG)
Log.d(TAG, "Offline step 6 " + "onHandleIntent");
connMgr = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
notificationManager = (NotificationManager) getApplicationContext().getSystemService(getApplicationContext().NOTIFICATION_SERVICE);
sotcPref = getApplicationContext().getSharedPreferences("SOTCPref", MODE_PRIVATE);
if (Constants.DEBUG)
Log.d(TAG, "onHandleIntent.........");
Bundle extras = intent.getExtras();
url = extras.getString("url");
showname = extras.getString("showname");
showdatecreated = extras.getString("showdatecreated");
//sara
if (showdatecreated.contains("/"))
data = showdatecreated.replaceAll("/", "#");
if (Constants.DEBUG)
System.out.println("date");
if (Constants.DEBUG)
System.out.println(data);
else
data = showdatecreated;
if (Constants.DEBUG)
System.out.println("date in else");
if (Constants.DEBUG)
System.out.println(showdatecreated);
if (Constants.DEBUG)
System.out.println(data);
showId = extras.getString("share_id");
noofFiles = extras.getInt("noofFiles");
messenger = (Messenger) extras.get("MESSENGER");
Intent notificationIntent = new Intent();
contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
notification = new Notification(R.drawable.sotc_notification_icon, "", System.currentTimeMillis());
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
notification.contentView = new RemoteViews(getApplicationContext()
.getPackageName(), R.layout.upload_progress_bar);
notification.icon = R.drawable.sotc_notification_icon;
notification.contentView.setTextViewText(R.id.textView1, showname);
notification.contentIntent = contentIntent;
notification.contentView.setProgressBar(R.id.progressBar1, 100, 0, false);
notificationManager.notify(1, notification);
if (Constants.DEBUG)
Log.i("FOO", "Notification started");
if (showname.length() > 18)
showname = showname.substring(0, 17);
if (DownloadAssets.TOTAL_ASSET_COUNT == 0)
downloadSetofAssets(OFFSET, LIMIT, url);
if (DownloadAssets.TOTAL_ASSET_COUNT > LIMIT)
if (Constants.DEBUG)
Log.d(TAG, "Offline step 8 " + "if(DownloadAssets.TOTAL_ASSET_COUNT > LIMIT)");
for (OFFSET = LIMIT; OFFSET < DownloadAssets.TOTAL_ASSET_COUNT; )
if (Constants.DEBUG)
Log.d(TAG, "Offline step 8.1 " + "if(DownloadAssets.TOTAL_ASSET_COUNT > LIMIT)");
downloadSetofAssets(OFFSET, LIMIT, url);
OFFSET = OFFSET + LIMIT;
if (i > 1)
result = DownloadService.COMPLETED;
notification.setLatestEventInfo(DownloadService.this, "Downloaded Successfully", "", contentIntent);
Message msg = Message.obtain();
msg.arg1 = result;
try
messenger.send(msg);
catch (android.os.RemoteException e1)
if (Constants.DEBUG)
Log.w(getClass().getName(), "Exception sending message", e1);
else
result = DownloadService.FAILED;
notification.setLatestEventInfo(DownloadService.this, "Downloaded Failed", "", contentIntent);
if (Constants.DEBUG)
Log.e(TAG, "Download Failed...");
notification.contentView.setImageViewResource(R.id.image, R.drawable.icon);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(1, notification);
private void downloadSetofAssets(int OFFSET, int LIMIT, String url)
// TODO Auto-generated method stub
if (Constants.DEBUG)
Log.d(TAG, "Offline step 7 " + "downloadSetofAssets");
try
url = url.replace("value1", URLEncoder.encode("" + OFFSET, "UTF-8"));
url = url.replace("value2", URLEncoder.encode("" + LIMIT, "UTF-8"));
catch (UnsupportedEncodingException e)
// TODO Auto-generated catch block
e.printStackTrace();
if (Constants.DEBUG)
Log.i(TAG, "Show offline -- Asset URL: " + url);
showAssetList = DownloadAssets.hit(getApplicationContext(), url);
for (HashMap<String, String> asset : showAssetList)
String thumbUrl = asset.get("thumb_url");
String normalUrl = asset.get("normal_url");
String mp4Url = asset.get("mp4_url");
String fileType = asset.get("filetype");
String assetID = asset.get("id");
String assetType = asset.get("asset_type");
if (Constants.DEBUG)
Log.d(TAG, "Thumb Url :" + thumbUrl);
if (Constants.DEBUG)
Log.d(TAG, "Normal Url :" + normalUrl);
if (Constants.DEBUG)
Log.d(TAG, "Asset ID : " + assetID);
if (Constants.DEBUG)
Log.d(TAG, "Asset Type : " + assetType);
if (Constants.DEBUG)
Log.d(TAG, "MP4 Url : " + mp4Url);
if (Constants.DEBUG)
Log.d(TAG, "FileType : " + fileType);
boolean isDownloaded = false;
if (assetType.equals("1")) // Image
File assetDirectory = createAssetDirectory(showId, showname, data, assetID, assetType);
if (assetDirectory != null)
File thumb = new File(assetDirectory.getAbsolutePath(), "/Thumb");
thumb.mkdirs();
// Thumbnail
File thumbFile = new File(thumb.getAbsolutePath(), "/Thumb." + getExtention(thumbUrl));
if (Constants.DEBUG)
Log.d(TAG, "Thumb File ath : " + thumbFile.getAbsolutePath());
isDownloaded = doInBackground(this, thumbUrl, thumbFile.getAbsolutePath(), messenger);
File normal = new File(assetDirectory.getAbsolutePath(), "/Normal");
normal.mkdirs();
// Normal
File normalFile = new File(normal.getAbsolutePath(), "/Normal." + getExtention(normalUrl));
if (Constants.DEBUG)
Log.d(TAG, "Normal File path: " + normalFile.getAbsolutePath());
isDownloaded = doInBackground(this, normalUrl, normalFile.getAbsolutePath(), messenger);
else if (assetType.equals("2")) // Video
File assetDirectory = createAssetDirectory(showId, showname, data, assetID, assetType);
if (assetDirectory != null)
if (!fileType.equals("Youtube")) // via AddLink
File thumb = new File(assetDirectory.getAbsolutePath(), "/Thumb");
thumb.mkdirs();
// Thumbnail
File thumbFile = new File(thumb.getAbsolutePath(), "/Thumb." + getExtention(thumbUrl));
if (Constants.DEBUG)
Log.d(TAG, "Thumb File ath : " + thumbFile.getAbsolutePath());
isDownloaded = doInBackground(this, thumbUrl, thumbFile.getAbsolutePath(), messenger);
File mp4url = new File(assetDirectory.getAbsolutePath(), "/Normal");
mp4url.mkdirs();
// mp4_Url
File mp4File = new File(mp4url.getAbsolutePath(), "/Normal." + getExtention(mp4Url));
if (Constants.DEBUG)
Log.d(TAG, "Normal File path: " + mp4File.getAbsolutePath());
isDownloaded = doInBackground(this, mp4Url, mp4File.getAbsolutePath(), messenger);
else if (Constants.DEBUG)
Log.d(TAG, "Asset type is video but is Youtube link. So not proceeding for offline");
else if (assetType.equals("3")) // Audio
File assetDirectory = createAssetDirectory(showId, showname, data, assetID, assetType);
if (assetDirectory != null)
File thumb = new File(assetDirectory.getAbsolutePath(), "/Thumb");
thumb.mkdirs();
// Thumbnail
File thumbFile = new File(thumb.getAbsolutePath(), "/Thumb." + getExtention(thumbUrl));
if (Constants.DEBUG)
Log.d(TAG, "Thumb File ath : " + thumbFile.getAbsolutePath());
isDownloaded = doInBackground(this, thumbUrl, thumbFile.getAbsolutePath(), messenger);
File normal = new File(assetDirectory.getAbsolutePath(), "/Normal");
normal.mkdirs();
// Normal
File normalFile = new File(normal.getAbsolutePath(), "/Normal." + getExtention(normalUrl));
if (Constants.DEBUG)
Log.d(TAG, "Normal File path: " + normalFile.getAbsolutePath());
isDownloaded = doInBackground(this, normalUrl, normalFile.getAbsolutePath(), messenger);
else
if (!assetType.equals("5"))
File assetDirectory = createAssetDirectory(showId, showname, data, assetID, assetType);
if (assetDirectory != null)
File thumb = new File(assetDirectory.getAbsolutePath(), "/Thumb");
thumb.mkdirs();
// Thumbnail
File thumbFile = new File(thumb.getAbsolutePath(), "/Thumb." + getExtention(thumbUrl));
if (Constants.DEBUG)
Log.d(TAG, "Thumb File ath : " + thumbFile.getAbsolutePath());
isDownloaded = doInBackground(this, thumbUrl, thumbFile.getAbsolutePath(), messenger);
File normal = new File(assetDirectory.getAbsolutePath(), "/Normal");
normal.mkdirs();
// Normal
File normalFile = new File(normal.getAbsolutePath(), "/Normal." + getExtention(normalUrl));
if (Constants.DEBUG)
Log.d(TAG, "Normal File path: " + normalFile.getAbsolutePath());
isDownloaded = doInBackground(this, normalUrl, normalFile.getAbsolutePath(), messenger);
else //"5" Link
if (Constants.DEBUG)
Log.d(TAG, "This is Web Link");
isDownloaded = true;
private String getLoginFolders()
// TODO Auto-generated method stub
File file = null;
int status = Constants.getSDCardStatus();
if (status == Constants.MOUNTED)
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"/SOTC_OFF/.nomedia");
f.mkdirs();
file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"/SOTC_OFF/" + sotcPref.getString("domain", "") + "/" + sotcPref.getString("user_id", ""));
file.mkdirs();
return file.getAbsolutePath();
private File createAssetDirectory(String showid, String showname,
String data, String assetID, String assetType)
// TODO Auto-generated method stub
if (Constants.DEBUG)
Log.d(TAG, "Offline step 10 " + "createAssetDirectory");
File file = null;
int status = Constants.getSDCardStatus();
if (status == Constants.MOUNTED)
if (DownloadAssets.TOTAL_ASSET_COUNT != 0)
/**
* From to concept here is to avoid duplication of new
* offline shows when show is updated. So, we are here
* renaming previous offline show's folder name with
* updated asset count.
*/
boolean isRenameSuccess = false;
File f = new File(getLoginFolders());
if (!f.exists())
f.mkdirs();
File[] fileArray = f.listFiles();
File f2 = new File(getLoginFolders(), "/"
+ showid.trim() + ","
+ showname.trim() + ","
+ data);
for (File from : fileArray)
String s1 = from.getName().substring(0, from.getName().lastIndexOf(","));
if (Constants.DEBUG)
Log.i(TAG, "s1: " + s1);
if (f2.getName().equalsIgnoreCase(s1))
//Rename
File to = new File(getLoginFolders(), "/"
+ showid.trim() + ","
+ showname.trim() + ","
+ data + ","
+ noofFiles);
if (Constants.DEBUG)
Log.i(TAG, "from existence: " + from.exists());
try
isRenameSuccess = from.renameTo(to);
catch (Exception e)
// TODO Auto-generated catch block
e.printStackTrace();
if (Constants.DEBUG)
Log.i(TAG, "isRenameSuccess: " + isRenameSuccess);
break;
file = new File(getLoginFolders(), "/"
+ showid.trim() + ","
+ showname.trim() + ","
+ data + ","
+ noofFiles +
"/File_"
+ assetID + ","
+ assetType.trim());
if (file != null)
if (!file.exists())
file.mkdirs();
return file;
public static String getExtention(String url)
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
return extension;
@SuppressWarnings("deprecation", "deprecation")
boolean doInBackground(Context context, String urlPath, String destinationPath, Messenger messenger)
boolean isDownloaded = false;
int lastPercent = 0;
File destination = new File(destinationPath);
if (!destination.exists())
if (chkConnectionStatus())
InputStream stream = null;
FileOutputStream fos = null;
try
URL imageUrl = new URL(urlPath);
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
stream = conn.getInputStream();
int contentLength = conn.getContentLength();
if (Constants.DEBUG)
Log.i(TAG, "contentLength : " + contentLength);
if (contentLength == 0)
result = DownloadService.NO_FILE;
destination.delete();
isDownloaded = false;
Toast.makeText(getApplicationContext(), getResources().getString(R.string.Text_NoFile), 1000).show();
else if (contentLength > availablestorageOnExternalDir())
//No Space Available
result = DownloadService.LOW_SPACE;
destination.delete();
isDownloaded = false;
Toast.makeText(getApplicationContext(), getResources().getString(R.string.Text_NoSpaceShow), 1000).show();
else
fos = new FileOutputStream(destination.getPath());
long total = 0l;
final int buffer_size = 4 * 1024;
try
byte[] bytes = new byte[buffer_size];
for (; ; )
int count = stream.read(bytes, 0, buffer_size);
if (count == -1)
break;
fos.write(bytes, 0, count);
total += count;
int percent = (int) ((total * 100) / contentLength);
if (percent > lastPercent)
notification.contentView.setProgressBar(R.id.progressBar1, 100, percent, false);
lastPercent = percent;
if (destination.length() < contentLength)
result = DownloadService.PARTIALLY_DOWNLOADED;
destination.delete();
isDownloaded = false;
else
if (Constants.DEBUG)
Log.e(TAG, "Sucessful downloaded-------------------------------------------------" + i++);
// Sucessful finished
//i++;
result = Activity.RESULT_OK;
isDownloaded = true;
catch (Exception ex)
conn.disconnect();
Message msg = Message.obtain();
msg.arg1 = result;
msg.obj = destination.getAbsolutePath();
try
messenger.send(msg);
catch (android.os.RemoteException e1)
if (Constants.DEBUG)
Log.w(getClass().getName(), "Exception sending message", e1);
if (Constants.DEBUG)
Log.v(TAG, "Completed.............. ");
catch (Exception e)
e.printStackTrace();
finally
if (stream != null)
try
stream.close();
catch (IOException e)
e.printStackTrace();
if (fos != null)
try
fos.close();
catch (IOException e)
e.printStackTrace();
else
/// no network connection
result = DownloadService.NETWORK_PROBLEM;
notification.setLatestEventInfo(context, "Please check your network connection", "", contentIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(1, notification);
isDownloaded = true;
Message msg = Message.obtain();
msg.arg1 = result;
msg.obj = destination.getAbsolutePath();
try
messenger.send(msg);
catch (android.os.RemoteException e1)
if (Constants.DEBUG)
Log.w(getClass().getName(), "Exception sending message", e1);
else
result = DownloadService.ASSERT_EXISIT;
Message msg = Message.obtain();
msg.arg1 = result;
msg.obj = destination.getAbsolutePath();
try
messenger.send(msg);
catch (android.os.RemoteException e1)
if (Constants.DEBUG)
Log.w(getClass().getName(), "Exception sending message", e1);
isDownloaded = true;
return isDownloaded;
public long availablestorageOnExternalDir() //Get Available space(in Bytes)
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable = (long) stat.getBlockSize() * (long) stat.getAvailableBlocks();
long megAvailable = bytesAvailable / (1024 * 1024);
if (Constants.DEBUG)
Log.e("", "Available MB : " + megAvailable);
if (Constants.DEBUG)
Log.e("", "Available Bytes : " + bytesAvailable);
return bytesAvailable;
public boolean chkConnectionStatus()
final android.net.NetworkInfo wifi =
connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
final android.net.NetworkInfo mobile =
connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (wifi.isAvailable())
if (wifi.isConnected())
return true;
return false;
else if (mobile.isAvailable())
if (mobile.isConnected())
return true;
return false;
else
return false;
下载Assets.java
//To download
//files into
//created folders
public class DownloadAssets
private static final String TAG = "DownloadAssets";
public static int TOTAL_ASSET_COUNT;
static synchronized ArrayList<HashMap<String, String>> hit(Context context, String url)
if (Constants.DEBUG)
Log.d(TAG, "Offline step 9 " + "hit url" + url);
ArrayList<HashMap<String, String>> mList = new ArrayList<HashMap<String, String>>();
String message = null;
String result = null;
try
result = Constants.queryRESTurl(url);
if (result != null)
if (result.equals("timeout"))
message = context.getResources().getString(R.string.Text_TimeOut);
else
JSONObject json = Constants.convertStringtoJsonObject(result);
try
JSONObject results = json.getJSONObject(ThumbnailFragment.JSON_RESPONSE_ATTR_RESULTSET);
String totalAssetCount = results.getString(ThumbnailFragment.JSON_RESPONSE_ATTR_ASSET_COUNT);
TOTAL_ASSET_COUNT = Integer.parseInt(totalAssetCount);
if (Constants.DEBUG)
Log.i("5" + TAG, "totalAssetCount : " + totalAssetCount);
if (TOTAL_ASSET_COUNT != 0)
JSONArray assetData = results.getJSONArray(ThumbnailFragment.JSON_RESPONSE_ATTR_ASSET_ARRAY);
if (Constants.DEBUG)
Log.i(TAG, "6Madhu " + assetData.toString());
int nObjects = assetData.length();
if (Constants.DEBUG)
Log.i(TAG, "7Madhu " + nObjects);
if (nObjects != 0)
for (int i = 0; i < nObjects; i++)
HashMap<String, String> map = new HashMap<String, String>();
JSONObject e = assetData.getJSONObject(i);
map.put("id", "" + e.getString("assets_id"));
map.put("asset_name", "" + e.getString("asset_name"));
map.put("thumb_url", "" + e.getString("thumb_url"));
map.put("asset_type", "" + e.getString("asset_type"));
map.put("large_url", "" + e.getString("large_url"));
map.put("mp4_url", "" + e.getString("mp4_url"));
map.put("normal_url", "" + e.getString("normal_url"));
map.put("description", "" + e.getString("description"));
map.put("filetype", "" + e.getString("filetype"));
map.put("filename", "" + e.getString("original_filename"));
map.put("filesize", "" + e.getString("filesize"));
mList.add(map);
if (Constants.DEBUG)
Log.i(TAG, "Size in Loop " + mList.size());
else if (Constants.DEBUG)
Log.i(TAG, "EXECUTING ELSE nObjects");
else if (Constants.DEBUG)
Log.i(TAG, "EXECUTING ELSE count");
catch (JSONException e)
if (Constants.DEBUG)
Log.e("8log_tag", "Error parsing data " + e.toString());
message = context.getResources().getString(R.string.Text_InvalidResponse);
catch (Exception e)
if (Constants.DEBUG)
Log.e("8log_tag", "Error parsing data " + e.toString());
message = context.getResources().getString(R.string.Text_InvalidResponse);
e.printStackTrace();
else
if (Constants.DEBUG)
Log.i(TAG, "EXECUTING ELSE result");
message = context.getResources().getString(R.string.Text_InvalidResponse);
catch (Exception e)
// TODO Auto-generated catch block
message = context.getResources().getString(R.string.Text_ServerProblem);
e.printStackTrace();
if (Constants.DEBUG)
Log.e(TAG, "Message : " + message);
if (Constants.DEBUG)
Log.d(TAG, "Offline step 9 End " + "hit return " + mList);
return mList;
我的查询是 文件正在下载,但不是第一次从服务器下载所有文件。如果我下载更多文件夹,例如 Folder1、Folder2 然后 Folder3、Folder1 和 Folder2 中断(即下载了 1 个文件)但 Folder3 已完全下载... 如何保持要下载的文件/文件夹的队列? !
【问题讨论】:
您需要更具体地说明下载失败的原因。 您好 HDave,我发现下载失败的情况。但是在下载多个文件夹时仍然出现中断。 “中断”是什么意思?究竟是什么异常? @HDave Folder1 包含 file11,file12....file1n 和 Folder2 包含 file21,file22,....file2n 。如果我请求在未完全下载的Folder1文件和Folder2已完全下载的文件中逐一下载。因此请求“下载文件夹1”被请求“下载文件夹2”中断。 我正在使用 google nexus 设备。如果我单击下载按钮,则最后一个已完全下载。但在最后一个没有完全下载之前。 【参考方案1】:为了加快和维护意图队列,请遵循以下方法
protected void onHandleIntent(Intent intent)
synchronized (intent)
final Intent intentCpy=intent;
new Thread(new Runnable()
@Override
public void run()
//onHandleIntent code which is in question post
在以下方法中使用 ConcurrentHashMap 实现线程安全
private synchronized void downloadSetofAssets(int OFFSET , int LIMIT , String url)
有关 ConcurrentHashMap 的更多详细信息,请访问 http://www.cs.umd.edu/class/spring2013/cmsc433/Notes/14-CMSC433-ConcurrentCollections.pdf
【讨论】:
以上是关于在android中使用IntentService从服务器下载文件的主要内容,如果未能解决你的问题,请参考以下文章
在Android O中运行后台运行Intentservice
从 IntentService 迁移到 Android O 的 JobIntentService
Android:intentservice,如何中止或跳过handleintent队列中的任务