其实,没想过下载是个这么easy的事情,不过,这种下载方法很有问题。肯定是不能真的应用的。
实现下载歌词,并直接在system.out.println中打印出来。下载mp3实现本地存储。
画界面神马的,两个按钮,一个下歌词,一个下mp3.
必须要有面向对象思想啊。
src中两个包,download包主要是与activity相关的代码。utils包中是具体的下载操作实现。
download包中,只有一个文件,download18.
download18中,依旧声明对象,根据ID获取对象,绑定监听器。
下载歌词按钮的监听器,复写onClick,声明新的httpDownload对象,声明String类的lrc对象,直接根据下载地址,调用httpDownload.download方法实现下载操作,并打印出来。
下载mp3按钮的监听器,复写onClick,声明新的httpDownload对象,调用httpDownloader.downFile方法,实现下载操作,并根据结果返回一个int型的result。
utils包中,两个文件,HttpDownloader.java和FileUtils.java。
HttpDownloader中,HttpDownloader类,分成三块。
第一块:下载文本文件。创建一个URL对象,通过它,创建一个HttpURLConnection对象,得到InputStram,从中读取数据。
StringBuffer sb = new StringBuffer();
//最后实际返回的是sb
String line = null;
//就是个中间转接的东西,用来判断buffer空了没,还有就是一行一行传递给sb
BufferedReader buffer = null;
//urlConn.getInputStream得到的放在这里面,不过是经过了两次改装
try{
//创建一个URL对象
url = new URL(urlStr);
//创建一个http连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//使用IO流读取数据,使用装饰者进行两次改装
buffer = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
while((line = buffer.readLine()) != null){
sb.append(line);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
buffer.close();
}catch(Exception e){
e.printStackTrace();
}
}
return sb.toString();
第二块:mp3文件下载。这里并没有进行真正具体的下载操作,而是调用了第三块(InputStream)来完成根据URL得到输入流,调用了FileUtils类的write2SDFromInput方法来完成将下载的数据写入sdcard。这一块只负责判断文件是否已存在,或者文件是否下载成功了。
InputStream inputStream = null;
try {
FileUtils fileUtils = new FileUtils();
//如果文件已经存在,返回1
if (fileUtils.isFileExist(path + fileName)) {
return 1;
} else {
System.out.println("else");
//调用第三块(InputStream)来完成根据URL得到输入流
inputStream = getInputStreamFromUrl(urlStr);
System.out.println("input");
//调用了FileUtils类的write2SDFromInput方法来完成将下载的数据写入sdcard
File resultFile = fileUtils.write2SDFromInput(path, fileName, inputStream);
//如果下载失败,返回-1
if(resultFile == null){
System.out.println("write false");
return -1;
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println("eee");
return -1;
}finally{
try {
inputStream.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
//如果没有出现异常,则代表下载成功,返回0
return 0;
}
第三块:InputStream getInputStreamFromUrl,根据URL得到输入流。其实这功能在第一块当中已经实现,这里只是把它们封装一下,给第二块调用而已。其实第一块也可以调用它。
public InputStream getInputStreamFromUrl(String urlStr)
throws MalformedURLException, IOException {
url = new URL(urlStr);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
InputStream inputStream = urlConn.getInputStream();
return inputStream;
}
FileUtils,实现具体的下载mp3操作。分为五部分。
一。获取当前外部存储设备的目录,即,SDcard的路径
SDPATH = Environment.getExternalStorageDirectory() + "/";
二。在SD卡上创建文件,它返回一个文件类型的对象
File file = new File(SDPATH + fileName);
Boolean a = file.createNewFile();
System.out.println(a);
return file;
三。在DS卡上创建目录
File dir = new File(SDPATH + dirName);
dir.mkdir();
return dir;
四。判断SD卡上的文件是否存在
File file = new File(SDPATH + fileName);
return file.exists();
五。将一个InputStream里面的数据写入到SD卡中
参数包括路径,文件名,输入流(InputStream)
public File write2SDFromInput(String path,String fileName,InputStream input){
File file = null;
OutputStream output = null;
try {
creatSDDir(path); //创建文件夹
System.out.println("dir");
file = creatSDFile(path+fileName); //创建文件
System.out.println("file");
output = new FileOutputStream(file); //输出流
System.out.println("output");
byte buffer [] = new byte[1*1024]; //缓冲区
//从输入流中读入数据,放入buffer,如果buffer不为空(即输入流中还有数据),就把buffer中的数
据通过输出流写到文件中
while((input.read(buffer))!= -1){
output.write(buffer);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
finally{
try {
output.close();
} catch (Exception e2) {
// TODO: handle exception
e2.printStackTrace();
}
}
return file;
}
}

问题是:
1.byte buffer [] = new byte[1*1024]; //缓冲区
因为buffer是一次性分配固定大小,造成下载的mp3总是大于实际大小,不知是不是这个原因,mp3听起来也是一卡一卡的。
2.有些下载地址无法成功,错误提示,链接无效。
3.一些可以下载成功的地址,如果多次下载,就会报错。
java.io.IOException: Received authentication challenge is null
在网上找到的可能原因:
1.没设Token
2.请求的链接包含的中文需要编码,URLEncoder.encode(query, "UTF-8").
3.是因为那些报这个错误的用户的TOKEN已经失效了,可能用户取消授权又重新授权过,那就会报这个错。
到底为什么,我也没有搞明白。
|
代码备份