zoukankan      html  css  js  c++  java
  • android音乐播放器——通过webview下载歌曲

      最近在自己的音乐播放器中添加了一个下载网络歌曲的功能,虽然还没有做到边下边播放的功能,不过总算是开了一个头了,下载功搞定了,离目标也就不远了。

      android自带播放器支持“边下载边播放”的功能,当你使用系统浏览器点击一个“MP3的下载链接”时,它就会自动播放这首歌曲并保存到本地(不知道用第三方浏览器是否也如此,笔者认为应该是系统浏览器会自动识别MP3下载链接,并调用系统播放器来播放)。

      与这个过程类似,在笔者做的音乐播放器中,当用户选择“歌曲下载”时,会转到一个webview中,这里我将webview的初始url定向到"htpp://www.top100.cn"(巨鲸音乐),当点击MP3的下载链接时,就会将音乐下载到sdcard的根目录。webview所在activity的代码如下:

    setContentView(R.layout.web);
    web = (WebView)findViewById(R.id.web);
    web.setWebViewClient(new DownLoadWebViewClient(this));
    WebSettings s = web.getSettings();
    s.setSaveFormData(false);
    s.setSavePassword(false);
    s.setUseWideViewPort(true);
    s.setJavaScriptEnabled(true);
    s.setLightTouchEnabled(true);
    web.setWebChromeClient(new WebChromeClient() {
    	public void onProgressChanged(WebView view, int progress) {
               //Activity和Webview根据加载程度决定进度条的进度大小
               //当加载到100%的时候 进度条自动消失
                context.setProgress(progress * 100);
    	}
    });
    web.loadUrl("http://www.top100.cn/");
    
    

      web.setWebViewClient(new DownLoadWebViewClient(this));其中DownLoadWebViewClient就使我们下载MP3文件的关键,它继承自WebViewClient,这里我们Override它的public boolean shouldOverrideUrlLoading(WebView view, String url)方法,在方法中我们判断点击的链接时否为“下载MP3文件”,如果成立,则启动一个service来下载mp3文件,代码如下:

    public class DownLoadWebViewClient extends WebViewClient {
    	private Context context;
    	public DownLoadWebViewClient(Context context){
    		this.context = context;
    	}
    	@Override
    	public boolean shouldOverrideUrlLoading(WebView view, String url) {
    		Log.i("info", "open an url");
    		String urlStr = "";									//存放解码后的url
    		//如果是utf8编码
    		if (isUtf8Url(url)){
    			urlStr = Utf8URLdecode(url);
    		//如果不是utf8编码
    		} else {
    			urlStr = URLDecoder.decode(url);
    		}
    		//如果链接是下载top100.cn中的mp3文件
    		if (url.substring(url.length()-4).equals(".mp3")&&url.substring(7,10).equals("221")){
    			Log.i("info", "mp3 file");
    			String ss[] = urlStr.split("/");
    			String musicName = ss[ss.length-1];				//得到音乐文件的全名(包括后缀)
    			Log.i("info", "musicfile: " + musicName);
    			
    			//将下载链接和文件名传递给下载模块
    			Intent intent = new Intent(context,DownLoadService.class);
    			intent.putExtra("url", url);
    			intent.putExtra("musicName", musicName);
    			context.startService(intent);
    		}
    		return super.shouldOverrideUrlLoading(view, url);
    	}
    

      这里略去了url解码的相关方法。其中DownLoadService用于下载MP3文件并在,它接收DownLoadWebViewClient传递来的url和音乐文件名,代码如下:

    public class DownLoadService extends Service implements Runnable{	//实现Runable接口
    	
    	private String URL_str;						//网络歌曲的路径
    	private File download_file;					//下载的文件
    	private int total_read = 0;					//已经下载文件的长度(以字节为单位)
    	private int readLength = 0;					//一次性下载的长度(以字节为单位)
    	private int music_length = 0;					//音乐文件的长度(以字节为单位)
    	private boolean flag = false;					//是否停止下载,停止下载为true
    	private Thread downThread;					//下载线程
    	private String musicName;					//下载的文件名
    	@Override
    	public IBinder onBind(Intent intent) {
    		return null;
    	}
    
    	@Override
    	public void onCreate() {
    		downThread = new Thread(this);			//初始化下载线程
    		downThread.start();
    	}
    
    	@Override
    	public void onStart(Intent intent, int startId) {
    	     URL_str = intent.getExtras().getString("url");		//获取下载链接的url
    	     musicName = intent.getExtras().getString("musicName");//获取下载的文件名
    	}
    	
    	@Override
    	public void onDestroy() {
    		flag = true;								//停止下载
    	}
    	
    	//实现Run方法,进行歌曲的下载
    	@Override
    	public void run() {															
    		FileOutputStream fos = null;				//文件输出流
    		FileInputStream fis = null;				//文件输出流
    		InputStream is = null;					//网络文件输入流
    		URL url = null;
    		try {
    			url = new URL(URL_str);				//网络歌曲的url
    			HttpURLConnection httpConnection = null;
    			httpConnection = (HttpURLConnection)
    			url.openConnection();				//打开网络连接
    			download_file = new File(Environment.	//在sdcard根目录建立一个与要下载的文件的名字相同的文件
    					getExternalStorageDirectory()
    					+ "/" + musicName);
    			fos = new FileOutputStream(download_file, true);		//初始化文件输出流
    			fis = new FileInputStream(download_file);				//初始化文件输入流
    			total_read = fis.available();						//初始化“已下载部分”的长度,此处应为0
    			music_length = httpConnection.getContentLength();		//要下载的文件的总长度
    			
    			if (is == null) {								//如果下载失败则打印日志,并返回
    				Log.i("info", "donload failed...");
    				return;
    			}
    			
    			byte buf[] = new byte[1024];					  //定义下载缓冲区
    			readLength = 0;							  //一次性下载的长度
    			Log.i("info", "download start...");						
    			
    			//向前台发送开始下载广播
    			Intent startIntent = new Intent();
    			startIntent.setAction("com.alex.downloadstart");
    			sendBroadcast(startIntent);
    			
    			//如果读取网络文件的数据流成功,且用户没有选择停止下载,则开始下载文件
    			while (readLength != -1  && !flag) {					
    				if((readLength = is.read(buf))>0){
    					fos.write(buf, 0, readLength);
    					total_read += readLength;			//已下载文件的长度增加
    				}	
    				if (total_read == music_length) {			//当已下载的长度等于网络文件的长度,则下载完成
    					flag = false;
    					Log.i("info", "download complete...");
    					
    					//向前台发送下载完成广播
    					Intent completeIntent = new Intent();
    					completeIntent.setAction("com.alex.downloadcompleted");
    					sendBroadcast(completeIntent);
    					
    					//关闭输入输出流
    					fos.close();
    					is.close();
    					fis.close();
    				}
    				Thread.sleep(50);							//当前现在休眠50毫秒
    				Log.i("info", "download process : " 				//打印下载进度
    						+ ((total_read+0.0)/music_length*100+"").substring(0, 4)+"%");
    			}
    		} catch (Exception e) {
    			Intent errorIntent = new Intent();
    			errorIntent.setAction("com.alex.downloaderror");
    			sendBroadcast(errorIntent);
    			e.printStackTrace();
    		}
    	}
    
    	
    
    }
    

      这里有个小bug,如果下载同一首歌曲多次,程序不会多次新建文件,而将数据写入与之同名的文件中。

  • 相关阅读:
    科研道路上培养的7种能力
    (OK) network diagnose tools
    linux-bridge-ping-high-latency-ebtables.txt
    houshoul
    Android x86 Virtual box with Internet and connection to adb?
    linux內核調試kmsg,dmesg
    Android Logging System
    Linux 日志级别(loglevel)详解
    Linux之绝处逢生------SysRq
    /proc/sysrq-trigger详解
  • 原文地址:https://www.cnblogs.com/zchajax/p/2047129.html
Copyright © 2011-2022 走看看