本系列博文,详细讲述一个音乐播放器的实现,以及从网络解析数据获取最新推荐歌曲以及歌曲下载的功能。
功能介绍如下:
1、获取本地歌曲列表,实现歌曲播放功能。
2、利用硬件加速感应器,摇动手机实现切换歌曲的功能
3、利用jsoup解析网页数据,从网络获取歌曲列表,同时实现歌曲和歌词下载到手机本地的功能。
4、通知栏提醒,实现仿QQ音乐播放器的通知栏功能.
涉及的技术有:
1、jsoup解析网络网页,从而获取需要的数据
2、android中访问网络,获取文件到本地的网络请求技术,以及下载文件到本地实现断点下载
3、线程池
4、图片缓存
5、service一直在后台运行
6、手机硬件加速器
7、notification通知栏设计
8、自定义广播
9、android系统文件管理
上面两篇博文android-音乐播放器实现及源码下载(一)讲述了activity基类实现和application类的实现,以及最终设计界面展示。
android-音乐播放器实现及源码下载(二)讲述了主界面的设计和实现
本篇主要讲述两个service服务的设计和实现,一个是播放歌曲的service服务,一个是下载歌曲的service服务。
播放歌曲的service服务代码如下:
/**
* 2015年8月15日 16:34:37
* 博文地址:http://blog.csdn.net/u010156024
* 音乐播放服务 服务中启动了硬件加速器感应器
* 实现功能:摇动手机自动播放下一首歌曲
*/
public class PlayService extends Service implements
MediaPlayer.OnCompletionListener {
private static final String TAG =
PlayService.class.getSimpleName();
private SensorManager mSensorManager;
private MediaPlayer mPlayer;
private OnMusicEventListener mListener;
private int mPlayingPosition; // 当前正在播放
private WakeLock mWakeLock = null;//获取设备电源锁,防止锁屏后服务被停止
private boolean isShaking;
private Notification notification;//通知栏
private RemoteViews remoteViews;//通知栏布局
private NotificationManager notificationManager;
// 单线程池
private ExecutorService mProgressUpdatedListener = Executors
.newSingleThreadExecutor();
public class PlayBinder extends Binder {
public PlayService getService() {
return PlayService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
mSensorManager.registerListener(mSensorEventListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_GAME);
return new PlayBinder();
}
@SuppressWarnings("deprecation")
@Override
public void onCreate() {
super.onCreate();
acquireWakeLock();//获取设备电源锁
mSensorManager = (SensorManager)
getSystemService(Context.SENSOR_SERVICE);
MusicUtils.initMusicList();
mPlayingPosition = (Integer)
SpUtils.get(this, Constants.PLAY_POS, 0);
Uri uri = Uri.parse(MusicUtils.sMusicList.get(
getPlayingPosition()).getUri());
mPlayer = MediaPlayer.create(PlayService.this,uri);
mPlayer.setOnCompletionListener(this);
// 开始更新进度的线程
mProgressUpdatedListener.execute(mPublishProgressRunnable);
/**
* 该方法虽然被抛弃过时,但是通用!
*/
PendingIntent pendingIntent = PendingIntent
.getActivity(PlayService.this,
0, new Intent(PlayService.this, PlayActivity.class), 0);
remoteViews = new RemoteViews(getPackageName(),
R.layout.play_notification);
notification = new Notification(R.drawable.ic_launcher,
"歌曲正在播放", System.currentTimeMillis());
notification.contentIntent = pendingIntent;
notification.contentView = remoteViews;
//标记位,设置通知栏一直存在
notification.flags =Notification.FLAG_ONGOING_EVENT;
Intent intent = new Intent(PlayService.class.getSimpleName());
intent.putExtra("BUTTON_NOTI", 1);
PendingIntent preIntent = PendingIntent.getBroadcast(
PlayService.this,
1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(
R.id.music_play_pre, preIntent);
intent.putExtra("BUTTON_NOTI", 2);
PendingIntent pauseIntent = PendingIntent.getBroadcast(
PlayService.this,
2, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(
R.id.music_play_pause, pauseIntent);
intent.putExtra("BUTTON_NOTI", 3);
PendingIntent nextIntent = PendingIntent.getBroadcast
(PlayService.this,
3, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(
R.id.music_play_next, nextIntent);
intent.putExtra("BUTTON_NOTI", 4);
PendingIntent exit = PendingIntent.getBroadcast(PlayService.this,
4, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(
R.id.music_play_notifi_exit, exit);
notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
setRemoteViews();
/**
* 注册广播接收者
* 功能:
* 监听通知栏按钮点击事件
*/
IntentFilter filter = new IntentFilter(
PlayService.class.getSimpleName());
MyBroadCastReceiver receiver = new MyBroadCastReceiver();
registerReceiver(receiver, filter);
}
public void setRemoteViews(){
L.l(TAG, "进入——》setRemoteViews()");
remoteViews.setTextViewText(R.id.music_name,
MusicUtils.sMusicList.get(
getPlayingPosition()).getTitle());
remoteViews.setTextViewText(R.id.music_author,
MusicUtils.sMusicList.get(
getPlayingPosition()).getArtist());
Bitmap icon = MusicIconLoader.getInstance().load(
MusicUtils.sMusicList.get(
getPlayingPosition()).getImage());
remoteViews.setImageViewBitmap(R.id.music_icon,icon == null
? ImageTools.scaleBitmap(R.drawable.ic_launcher)
: ImageTools
.scaleBitmap(icon));
if (isPlaying()) {
remoteViews.setImageViewResource(R.id.music_play_pause,
R.drawable.btn_notification_player_stop_normal);
}else {
remoteViews.setImageViewResource(R.id.music_play_pause,
R.drawable.btn_notification_player_play_normal);
}
//通知栏更新
notificationManager.notify(5, notification);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(0, notification);//让服务前台运行
return Service.START_STICKY;
}
/**
* 感应器的时间监听器
*/
private SensorEventListener mSensorEventListener =
new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
if (isShaking)
return;
if (Sensor.TYPE_ACCELEROMETER == event.sensor.getType()) {
float[] values = event.values;
/**
* 监听三个方向上的变化,数据变化剧烈,next()方法播放下一首歌曲
*/
if (Math.abs(values[0]) > 8 && Math.abs(values[1]) > 8
&& Math.abs(values[2]) > 8) {
isShaking = true;
next();
// 延迟200毫秒 防止抖动
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isShaking = false;
}
}, 200);
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
/**
* 更新进度的线程
*/
private Runnable mPublishProgressRunnable = new Runnable() {
@Override
public void run() {
while (true) {
if (mPlayer != null && mPlayer.isPlaying()
&& mListener != null) {
mListener.onPublish(mPlayer.getCurrentPosition());
}
/*
* SystemClock.sleep(millis) is a utility function very similar
* to Thread.sleep(millis), but it ignores InterruptedException.
* Use this function for delays if you do not use
* Thread.interrupt(), as it will preserve the interrupted state
* of the thread. 这种sleep方式不会被Thread.interrupt()所打断
*/SystemClock.sleep(200);
}
}
};
/**
* 设置回调
*
* @param l
*/
public void setOnMusicEventListener(OnMusicEventListener l) {
mListener = l;
}
/**
* 播放
*
* @param position
* 音乐列表播放的位置
* @return 当前播放的位置
*/
public int play(int position) {
L.l(TAG, "play(int position)方法");
if (position < 0)
position = 0;
if (position >= MusicUtils.sMusicList.size())
position = MusicUtils.sMusicList.size() - 1;
try {
mPlayer.reset();
mPlayer.setDataSource(MusicUtils
.sMusicList.get(position).getUri());
mPlayer.prepare();
start();
if (mListener != null)
mListener.onChange(position);
} catch (Exception e) {
e.printStackTrace();
}
mPlayingPosition = position;
SpUtils.put(Constants.PLAY_POS, mPlayingPosition);
setRemoteViews();
return mPlayingPosition;
}
/**
* 继续播放
*
* @return 当前播放的位置 默认为0
*/
public int resume() {
if (isPlaying())
return -1;
mPlayer.start();
setRemoteViews();
return mPlayingPosition;
}
/**
* 暂停播放
*
* @return 当前播放的位置
*/
public int pause() {
if (!isPlaying())
return -1;
mPlayer.pause();
setRemoteViews();
return mPlayingPosition;
}
/**
* 下一曲
*
* @return 当前播放的位置
*/
public int next() {
if (mPlayingPosition >= MusicUtils.sMusicList.size() - 1) {
return play(0);
}
return play(mPlayingPosition + 1);
}
/**
* 上一曲
*
* @return 当前播放的位置
*/
public int pre() {
if (mPlayingPosition <= 0) {
return play(MusicUtils.sMusicList.size() - 1);
}
return play(mPlayingPosition - 1);
}
/**
* 是否正在播放
*
* @return
*/
public boolean isPlaying() {
return null != mPlayer && mPlayer.isPlaying();
}
/**
* 获取正在播放的歌曲在歌曲列表的位置
*
* @return
*/
public int getPlayingPosition() {
return mPlayingPosition;
}
/**
* 获取当前正在播放音乐的总时长
*
* @return
*/
public int getDuration() {
if (!isPlaying())
return 0;
return mPlayer.getDuration();
}
/**
* 拖放到指定位置进行播放
*
* @param msec
*/
public void seek(int msec) {
if (!isPlaying())
return;
mPlayer.seekTo(msec);
}
/**
* 开始播放
*/
private void start() {
mPlayer.start();
}
/**
* 音乐播放完毕 自动下一曲
*/
@Override
public void onCompletion(MediaPlayer mp) {
next();
}
@Override
public boolean onUnbind(Intent intent) {
L.l("play service", "unbind");
mSensorManager.unregisterListener(mSensorEventListener);
return true;
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
if (mListener != null)
mListener.onChange(mPlayingPosition);
}
@Override
public void onDestroy() {
L.l(TAG, "PlayService.java的onDestroy()方法调用");
release();
stopForeground(true);
mSensorManager.unregisterListener(mSensorEventListener);
super.onDestroy();
}
/**
* 服务销毁时,释放各种控件
*/
private void release() {
if (!mProgressUpdatedListener.isShutdown())
mProgressUpdatedListener.shutdownNow();
mProgressUpdatedListener = null;
//释放设备电源锁
releaseWakeLock();
if (mPlayer != null)
mPlayer.release();
mPlayer = null;
}
// 申请设备电源锁
private void acquireWakeLock() {
L.l(TAG, "正在申请电源锁");
if (null == mWakeLock) {
PowerManager pm = (PowerManager) this
.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
| PowerManager.ON_AFTER_RELEASE, "");
if (null != mWakeLock) {
mWakeLock.acquire();
L.l(TAG, "电源锁申请成功");
}
}
}
// 释放设备电源锁
private void releaseWakeLock() {
L.l(TAG, "正在释放电源锁");
if (null != mWakeLock) {
mWakeLock.release();
mWakeLock = null;
L.l(TAG, "电源锁释放成功");
}
}
private class MyBroadCastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
PlayService.class.getSimpleName())) {
L.l(TAG, "MyBroadCastReceiver类——》onReceive()");
L.l(TAG, "button_noti-->"
+intent.getIntExtra("BUTTON_NOTI", 0));
switch (intent.getIntExtra("BUTTON_NOTI", 0)) {
case 1:
pre();
break;
case 2:
if (isPlaying()) {
pause(); // 暂停
} else {
resume(); // 播放
}
break;
case 3:
next();
break;
case 4:
if (isPlaying()) {
pause();
}
//取消通知栏
notificationManager.cancel(5);
break;
default:
break;
}
}
if (mListener != null) {
mListener.onChange(getPlayingPosition());
}
}
}
/**
* 音乐播放回调接口
*/
public interface OnMusicEventListener {
public void onPublish(int percent);
public void onChange(int position);
}
}
播放歌曲的服务控制歌曲的播放,该服务功能如下:
1、通过回调接口OnMusicEventListener实现service服务与activity界面进行歌曲播放进度的更新和歌曲的切换。
2、启动了硬件加速器。通过硬件加速器控制手机摇一摇切换歌曲的功能。
3、通知栏启动提醒。
4、创建MediaPlayer进行歌曲的播放。
5、注册广播接受者,监听通知栏的点击时间。
6、获取设备电源锁。这一点请参考我的博文:实现音乐播放器后台Service服务一直存在的解决思路
另一个service服务是下载歌曲的DownloadService类,代码如下:
/**
* 2015年8月15日 16:34:37
* 博文地址:http://blog.csdn.net/u010156024
*/
public class DownloadService extends Service {
private SparseArray<Download> mDownloads = new SparseArray<Download>();
private RemoteViews mRemoteViews;
public class DownloadBinder extends Binder {
public DownloadService getService() {
return DownloadService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return new DownloadBinder();
}
@Override
public void onCreate() {
super.onCreate();
}
public void download(final int id, final String url, final String name) {
L.l("download", url);
Download d = new Download(id, url, MusicUtils.getMusicDir() + name);
d.setOnDownloadListener(mDownloadListener).start(false);
mDownloads.put(id, d);
}
private void refreshRemoteView() {
@SuppressWarnings("deprecation")
Notification notification = new Notification(
android.R.drawable.stat_sys_download, "",
System.currentTimeMillis());
mRemoteViews = new RemoteViews(getPackageName(),
R.layout.download_remote_layout);
notification.contentView = mRemoteViews;
StringBuilder builder = new StringBuilder();
for(int i=0,size=mDownloads.size();i<size;i++) {
builder.append(mDownloads.get(mDownloads.keyAt(i))
.getLocalFileName());
builder.append("、");
}
mRemoteViews.setTextViewText(R.id.tv_download_name,
builder.substring(0, builder.lastIndexOf("、")));
startForeground(R.drawable.ic_launcher, notification);
}
private void onDownloadComplete(int downloadId) {
mDownloads.remove(downloadId);
if(mDownloads.size() == 0) {
stopForeground(true);
return;
}
refreshRemoteView();
}
/**
* 发送广播,通知系统扫描指定的文件
* 请参考我的博文:
* http://blog.csdn.net/u010156024/article/details/47681851
*
*/
private void scanSDCard() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 判断SDK版本是不是4.4或者高于4.4
String[] paths = new String[]{
Environment.getExternalStorageDirectory().toString()};
MediaScannerConnection.scanFile(this, paths, null, null);
} else {
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED);
intent.setClassName("com.android.providers.media",
"com.android.providers.media.MediaScannerReceiver");
intent.setData(Uri.parse("file://"+ MusicUtils.getMusicDir()));
sendBroadcast(intent);
}
}
private Download.OnDownloadListener mDownloadListener =
new Download.OnDownloadListener() {
@Override
public void onSuccess(int downloadId) {
L.l("download", "success");
Toast.makeText(DownloadService.this,
mDownloads.get(downloadId).getLocalFileName() + "下载完成",
Toast.LENGTH_SHORT).show();
onDownloadComplete(downloadId);
scanSDCard();
}
@Override
public void onStart(int downloadId, long fileSize) {
L.l("download", "start");
refreshRemoteView();
Toast.makeText(DownloadService.this, "开始下载" +
mDownloads.get(downloadId).getLocalFileName(),
Toast.LENGTH_SHORT).show();
}
@Override
public void onPublish(int downloadId, long size) {
// L.l("download", "publish" + size);
}
@Override
public void onPause(int downloadId) {
L.l("download", "pause");
}
@Override
public void onGoon(int downloadId, long localSize) {
L.l("download", "goon");
}
@Override
public void onError(int downloadId) {
L.l("download", "error");
Toast.makeText(DownloadService.this,
mDownloads.get(downloadId).getLocalFileName() + "下载失败",
Toast.LENGTH_SHORT).show();
onDownloadComplete(downloadId);
}
@Override
public void onCancel(int downloadId) {
L.l("download", "cancel");
onDownloadComplete(downloadId);
}
};
}
该下载服务代码比较简单,主要结合Download类来实现真正的文件下载,同时实现Download类的回调接口Download.OnDownloadListener接口实现数据的传递和更新UI,Download类的代码如下:
/**
* 支持断点下载
* 支持回调进度、完成、手动关闭、下载失败、暂停/继续、取得文件大小, 获取文件名
* 支持设置同时下载线程个数
* 还需要优化
* 2015年8月15日 16:34:37
* 博文地址:http://blog.csdn.net/u010156024
*/
public class Download implements Serializable {
private static final long serialVersionUID = 0x00001000L;
private static final int START = 1; // 开始下载
private static final int PUBLISH = 2; // 更新进度
private static final int PAUSE = 3; // 暂停下载
private static final int CANCEL = 4; // 取消下载
private static final int ERROR = 5; // 下载错误
private static final int SUCCESS = 6; // 下载成功
private static final int GOON = 7; // 继续下载
private static final String UA = "Mozilla/5.0 (Windows NT 6.1; WOW64)" +
" AppleWebKit/537.36 (KHTML, like Gecko)" +
" Chrome/37.0.2041.4 Safari/537.36";
private static ExecutorService mThreadPool;// 线程池
static {
mThreadPool = Executors.newFixedThreadPool(5); // 默认5个
}
private int mDownloadId; // 下载id
private String mFileName; // 本地保存文件名
private String mUrl; // 下载地址
private String mLocalPath; // 本地存放目录
private boolean isPause = false; // 是否暂停
private boolean isCanceled = false; // 是否手动停止下载
private OnDownloadListener mListener; // 监听器
/**
* 配置下载线程池的大小
* @param maxSize 同时下载的最大线程数
*/
public static void configDownloadTheadPool(int maxSize) {
mThreadPool = Executors.newFixedThreadPool(maxSize);
}
/**
* 添加下载任务
* @param downloadId 下载任务的id
* @param url 下载地址
* @param localPath 本地存放地址
*/
public Download(int downloadId, String url, String localPath) {
if (!new File(localPath).getParentFile().exists()) {
new File(localPath).getParentFile().mkdirs();
}
L.l("下载地址", url);
mDownloadId = downloadId;
mUrl = url;
String[] tempArray = url.split("/");
mFileName = tempArray[tempArray.length-1];
mLocalPath = localPath.replaceAll("\"|\\(|\\)", "");
}
/**
* 设置监听器
* @param listener 设置下载监听器
* @return this
*/
public Download setOnDownloadListener(OnDownloadListener listener) {
mListener = listener;
return this;
}
/**
* 获取文件名
* @return 文件名
*/
public String getFileName() {
return mFileName;
}
public String getLocalFileName() {
String[] split = mLocalPath.split(File.separator);
return split[split.length-1];
}
/**
* 开始下载
* params isGoon是否为继续下载
*/
@SuppressLint("HandlerLeak")
public void start(final boolean isGoon) {
// 处理消息
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case ERROR:
mListener.onError(mDownloadId);
break;
case CANCEL:
mListener.onCancel(mDownloadId);
break;
case PAUSE:
mListener.onPause(mDownloadId);
break;
case PUBLISH:
mListener.onPublish(mDownloadId,
Long.parseLong(msg.obj.toString()));
break;
case SUCCESS:
mListener.onSuccess(mDownloadId);
break;
case START:
mListener.onStart(mDownloadId,
Long.parseLong(msg.obj.toString()));
break;
case GOON:
mListener.onGoon(mDownloadId,
Long.parseLong(msg.obj.toString()));
break;
}
}
};
// 真正开始下载
mThreadPool.execute(new Runnable() {
@Override
public void run() {
download(isGoon,handler);
}
});
}
/**
* 下载方法
* @param handler 消息处理器
*/
private void download(boolean isGoon, Handler handler) {
Message msg = null;
L.l("开始下载。。。");
try {
RandomAccessFile localFile =
new RandomAccessFile(new File(mLocalPath), "rwd");
DefaultHttpClient client = new DefaultHttpClient();
client.setParams(getHttpParams());
HttpGet get = new HttpGet(mUrl);
long localFileLength = getLocalFileLength();
final long remoteFileLength = getRemoteFileLength();
long downloadedLength = localFileLength;
// 远程文件不存在
if (remoteFileLength == -1l) {
L.l("下载文件不存在...");
localFile.close();
handler.sendEmptyMessage(ERROR);
return;
}
// 本地文件存在
if (localFileLength > -1l && localFileLength < remoteFileLength) {
L.l("本地文件存在...");
localFile.seek(localFileLength);
get.addHeader("Range", "bytes=" + localFileLength + "-"
+ remoteFileLength);
}
msg = Message.obtain();
// 如果不是继续下载
if(!isGoon) {
// 发送开始下载的消息并获取文件大小的消息
msg.what = START;
msg.obj = remoteFileLength;
}else {
msg.what = GOON;
msg.obj = localFileLength;
}
handler.sendMessage(msg);
HttpResponse response = client.execute(get);
int httpCode = response.getStatusLine().getStatusCode();
if (httpCode >= 200 && httpCode <= 300) {
InputStream in = response.getEntity().getContent();
byte[] bytes = new byte[1024];
int len = -1;
while (-1 != (len = in.read(bytes))) {
localFile.write(bytes, 0, len);
downloadedLength += len;
if ((int)(downloadedLength/
(float)remoteFileLength * 100) % 10 == 0) {
// 发送更新进度的消息
msg = Message.obtain();
msg.what = PUBLISH;
msg.obj = downloadedLength;
handler.sendMessage(msg);
}
// 暂停下载, 退出方法
if (isPause) {
// 发送暂停的消息
handler.sendEmptyMessage(PAUSE);
L.l("下载暂停...");
break;
}
// 取消下载, 删除文件并退出方法
if (isCanceled) {
L.l("手动关闭下载。。");
localFile.close();
client.getConnectionManager().shutdown();
new File(mLocalPath).delete();
// 发送取消下载的消息
handler.sendEmptyMessage(CANCEL);
return;
}
}
localFile.close();
client.getConnectionManager().shutdown();
// 发送下载完毕的消息
if(!isPause) handler.sendEmptyMessage(SUCCESS);
}
} catch (Exception e) {
e.printStackTrace();
// 发送下载错误的消息
handler.sendEmptyMessage(ERROR);
}
}
/**
* 暂停/继续下载
* param pause 是否暂停下载
* 暂停 return true
* 继续 return false
*/
public synchronized boolean pause(boolean pause) {
if(!pause) {
L.l("继续下载");
isPause = false;
start(true); // 开始下载
}else {
L.l("暂停下载");
isPause = true;
}
return isPause;
}
/**
* 关闭下载, 会删除文件
*/
public synchronized void cancel() {
isCanceled = true;
if(isPause) {
new File(mLocalPath).delete();
}
}
/**
* 获取本地文件大小
* @return 本地文件的大小 or 不存在返回-1
*/
public synchronized long getLocalFileLength() {
long size = -1l;
File localFile = new File(mLocalPath);
if (localFile.exists()) {
size = localFile.length();
}
L.l("本地文件大小" + size);
return size <= 0 ? -1l : size;
}
/**
* 获取远程文件大小 or 不存在返回-1
* @return
*/
public synchronized long getRemoteFileLength() {
long size = -1l;
try {
DefaultHttpClient client = new DefaultHttpClient();
client.setParams(getHttpParams());
HttpGet get = new HttpGet(mUrl);
HttpResponse response = client.execute(get);
int httpCode = response.getStatusLine().getStatusCode();
if (httpCode >= 200 && httpCode <= 300) {
size = response.getEntity().getContentLength();
}
client.getConnectionManager().shutdown();
} catch (Exception e) {
e.printStackTrace();
}
L.l("远程文件大小" + size);
return size;
}
/**
* 设置http参数 不能设置soTimeout
* @return HttpParams http参数
*/
private static HttpParams getHttpParams() {
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
HttpProtocolParams.setUseExpectContinue(params, true);
HttpProtocolParams.setUserAgent(params, UA);
// ConnManagerParams.setTimeout(params, 10000);
// HttpConnectionParams.setConnectionTimeout(params, 10000);
return params;
}
/**
* 关闭下载线程池
*/
public static void closeDownloadThread() {
if(null != mThreadPool) {
mThreadPool.shutdownNow();
}
}
/**
* 下载过程中的监听器
* 更新下载信息
*
*/
public interface OnDownloadListener {
public void onStart(int downloadId, long fileSize); // 回调开始下载
public void onPublish(int downloadId, long size); // 回调更新进度
public void onSuccess(int downloadId); // 回调下载成功
public void onPause(int downloadId); // 回调暂停
public void onError(int downloadId); // 回调下载出错
public void onCancel(int downloadId); // 回调取消下载
public void onGoon(int downloadId, long localSize); // 回调继续下载
}
}
Download类实现文件的下载,保存到本地,使用线程池来进行文件的下载,细看看不难明白,里面没有需要特别说明的,如果大家有不明白的地方,欢迎留言,我会尽快给答复的。^_^
下一篇博文收尾,讲述播放界面的实现和最后的总结。
版权声明:本文为博主原创文章,未经博主允许不得转载。