实例源码下载
=========
下载地址:https://github.com/zhuanghongji/MultiThreadDownPlayerZhj
实例图片:
=====
实例源码:
=====
Manifest.xml 中添加权限:
<!-- 在SD卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 授权访问网络 -->
<uses-permission android:name="android.permission.INTERNET"/>
MainActivity.java :
public class MainActivity extends AppCompatActivity {
private ImageView mImageView;
private DownUtil mPictureDownUtil, mSongDownUtil;
private MediaPlayer mMediaPlayer;
private ProgressBar mPitureProBar, mSongProBar;
private int mPitureDownStatus, mSongDownStatus;
private Button mPictureDownBtn, mSongDownBtn;
private SeekBar mSongSeekBar;
private int mPlayStatus;
private ImageButton mPlayBtn;
private double mDuration;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1: // 改变图片的下载进度条
mPitureProBar.setProgress(mPitureDownStatus);
break;
case 2: // 图片下载完成后,设置歌手图片
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/李健.jpg");
mImageView.setImageBitmap(bitmap);
break;
case 3: // 改变歌曲文件的下载进度条
mSongProBar.setProgress(mSongDownStatus);
break;
case 4: // 改变播放的进度
mSongSeekBar.setProgress(mPlayStatus);
break;
case 5: // 播放完成后更改播放按钮图
mPlayBtn.setImageResource(R.drawable.start);
break;
}
}
};
public static final String URL_DOWNLOAD_JPG = "http://upload.timedg.com/2015/0228/1425097230412.jpg";
public static final String URL_DOWNLOAD_MP3 = "http://music.baidu.com/data/music/file?link=" +
"http://yinyueshiting.baidu.com/data2/music/" +
"245302327/2452981731439064061128.mp3?xcode=10c72737bdd9a2f07ed60eb536e08c87&song_id=245298173";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
intiEvents();
initMediaPlay();
}
/**
* 初始化播放器
*/
private void initMediaPlay() {
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource("/mnt/sdcard/假如爱有天意.mp3");
mMediaPlayer.prepare();
Log.i("Duration", String.valueOf(mMediaPlayer.getDuration()));
Log.i("CurrentPosition", String.valueOf(mMediaPlayer.getCurrentPosition()));
} catch (IOException e) {
e.printStackTrace();
}
new Thread() {
@Override
public void run() {
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
double completeRate = mMediaPlayer.getCurrentPosition();
double duration = mMediaPlayer.getDuration();
mPlayStatus = (int) (completeRate * 100 / duration);
mHandler.sendEmptyMessage(4);
Log.i("CurrentPosition", String.valueOf(mMediaPlayer.getCurrentPosition()));
if (mMediaPlayer.getDuration() - completeRate <= 1000) {
timer.cancel();
mHandler.sendEmptyMessage(5);
}
}
}, 0, 100);
}
}.start();
}
/**
* 初始化事件
*/
private void intiEvents() {
mPictureDownBtn.setOnClickListener(new MyOnClickListener());
mSongDownBtn.setOnClickListener(new MyOnClickListener());
mPlayBtn.setOnClickListener(new MyOnClickListener());
mSongSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mMediaPlayer.pause();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int progress = mSongSeekBar.getProgress();
mDuration = mMediaPlayer.getDuration();
mMediaPlayer.seekTo((int) (progress * mDuration / 100));
mMediaPlayer.start();
}
});
}
/**
* 初始化控件
*/
private void initViews() {
mImageView = (ImageView) findViewById(R.id.iv_singer_picture);
mPitureProBar = (ProgressBar) findViewById(R.id.bar_dowmload_picture);
mSongProBar = (ProgressBar) findViewById(R.id.bar_dowmload_song);
mPictureDownBtn = (Button) findViewById(R.id.btn_download_picture);
mSongDownBtn = (Button) findViewById(R.id.btn_download_song);
mSongSeekBar = (SeekBar) findViewById(R.id.seekbar_song_play);
mPlayBtn = (ImageButton) findViewById(R.id.btn_song_play);
}
public void makeToast(String s) {
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
private class MyOnClickListener implements OnClickListener {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_download_picture:
downloadPicture();
break;
case R.id.btn_download_song:
makeToast("歌曲下载");
downloadSong();
break;
case R.id.btn_song_play:
playSong();
break;
}
}
}
/**
* 下载歌手图片
*/
private void downloadPicture() {
// 初始化DownUtil对象(最后一个参数指定线程数)
mPictureDownUtil = new DownUtil(URL_DOWNLOAD_JPG,
"/mnt/sdcard/李健.jpg", 8);
new Thread() {
@Override
public void run() {
try {
// 开始下载
mPictureDownUtil.download();
} catch (Exception e) {
e.printStackTrace();
}
// 定义每0.1秒调度获取一次系统的完成进度
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 获取下载任务的完成比率
double completeRate = mPictureDownUtil.getCompleteRate();
mPitureDownStatus = (int) (completeRate * 100);
// 发送消息通知界面更新进度条
mHandler.sendEmptyMessage(1);
// 下载完全后取消任务调度
if (mPitureDownStatus >= 100) {
timer.cancel();
mHandler.sendEmptyMessage(2);
}
}
}, 0, 100);
}
}.start();
}
/**
* 下载歌曲文件
*/
private void downloadSong() {
// 初始化DownUtil对象(最后一个参数指定线程数)
mSongDownUtil = new DownUtil(URL_DOWNLOAD_MP3,
"/mnt/sdcard/假如爱有天意.mp3", 1);
new Thread() {
@Override
public void run() {
try {
// 开始下载
mSongDownUtil.download();
} catch (Exception e) {
e.printStackTrace();
}
// 定义每0.1秒调度获取一次系统的完成进度
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 获取下载任务的完成比率
double completeRate = mSongDownUtil.getCompleteRate();
mSongDownStatus = (int) (completeRate * 100);
// 发送消息通知界面更新进度条
mHandler.sendEmptyMessage(3);
// 下载完全后取消任务调度
if (mSongDownStatus >= 100) {
timer.cancel();
}
}
}, 0, 100);
}
}.start();
}
/**
* 播放歌曲
*/
private void playSong() {
boolean isPlaying = mMediaPlayer.isPlaying();
if (isPlaying == false) {
mMediaPlayer.start();
mPlayBtn.setImageResource(R.drawable.pause);
} else if ((isPlaying == true)) {
mMediaPlayer.pause();
mPlayBtn.setImageResource(R.drawable.start);
}
}
}
DownUtil.java :
public class DownUtil {
// 定义下载资源的路径
private String path;
// 指定所下载的文件的保存位置
private String targetFile;
// 定义需要使用多少线程下载资源
private int threadNum;
// 定义下载的线程对象
private DownThread[] threads;
// 定义下载的文件的总大小
private long fileSize;
public DownUtil(String path, String targetFile, int threadNum)
{
this.path = path;
this.threadNum = threadNum;
// 初始化threads数组
threads = new DownThread[threadNum];
this.targetFile = targetFile;
}
public void download() throws Exception
{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");
conn.setRequestProperty(
"Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
+ "application/x-shockwave-flash, application/xaml+xml, "
+ "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
+ "application/x-ms-application, application/vnd.ms-excel, "
+ "application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
// 得到文件大小
fileSize = conn.getContentLength();
Log.e("fileSize", fileSize + "");
conn.disconnect();
long currentPartSize = fileSize / threadNum;
Log.e("currentPartSize",currentPartSize+"");
RandomAccessFile file = new RandomAccessFile(targetFile, "rw");
// 设置本地文件的大小
file.setLength(fileSize);
file.close();
for (int i = 0; i < threadNum; i++)
{
// 计算每条线程的下载的开始位置
long startPos = i * currentPartSize;
Log.e("startPos",startPos+"");
// 每个线程使用一个RandomAccessFile进行下载
RandomAccessFile currentPart = new RandomAccessFile(targetFile,
"rw");
// 定位该线程的下载位置
currentPart.seek(startPos);
// 创建下载线程
threads[i] = new DownThread(startPos, currentPartSize,
currentPart);
// 启动下载线程
threads[i].start();
}
}
public class DownThread extends Thread {
// 当前线程的下载位置
private long startPos;
// 定义当前线程负责下载的文件大小
private long currentPartSize;
// 当前线程需要下载的文件块
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
private long currentPartSize;
// 当前线程需要下载的文件块
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-eLmySlMr-1714946522663)]
[外链图片转存中…(img-c7cBT11w-1714946522664)]
[外链图片转存中…(img-oiQFerAg-1714946522664)]
[外链图片转存中…(img-fr2foBsd-1714946522664)]
[外链图片转存中…(img-aiWMsGkj-1714946522665)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!