Recently, I added a function for downloading online songs to my own music player. Although I haven't done the downloading function yet, I finally started it. The downloading is done, not far from the target.
The android player supports "download and play". When you click "MP3 download link" in the system browser, it will automatically play the song and save it to the local device (I don't know if this is the case with a third-party browser, I think the system browser will automatically recognize the MP3 download link, and call the system player to play the video ).
Similar to this process, in the author's music player, when the user selects "Download song", it will be transferred to a webview. Here I will direct the initial url of webview to "htpp: // www.top100.cn (whale music). When you click the MP3 download link, the music will be downloaded to the root directory of sdcard. The code of the activity where webview is located is as follows:
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 and Webview determine the progress of the progress bar according to the loading level
// When loading to 100%, the progress bar disappears automatically
context.setProgress (progress * 100);
}
});
web.loadUrl ("http://www.top100.cn/");
Web. setWebViewClient (new DownLoadWebViewClient (this); among them, DownLoadWebViewClient enables us to download the key MP3 file. It inherits from WebViewClient. Here we Override its public boolean shouldOverrideUrlLoading (WebView, String url) method: In the method, we determine whether the clicked link is "Download MP3 files". If it is true, start a service to download mp3 files. The Code is as follows:
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 = ""; // Store the decoded url
// If it is utf8 encoding
if (isUtf8Url (url)) {
urlStr = Utf8URLdecode (url);
// if not utf8 encoding
} else {
urlStr = URLDecoder.decode (url);
}
// If the link is to download the mp3 file in top100.cn
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]; // Get the full name of the music file (including the suffix)
Log.i ("info", "musicfile:" + musicName);
Ranch
// Pass the download link and file name to the download module
Intent intent = new Intent (context, DownLoadService.class);
intent.putExtra ("url", url);
intent.putExtra ("musicName", musicName);
context.startService (intent);
}
return super.shouldOverrideUrlLoading (view, url);
}
The url Decoding Method is omitted here. DownLoadService is used to download an MP3 file and receive the url and music file name transmitted by DownLoadWebViewClient. The Code is as follows:
public class DownLoadService extends Service implements Runnable {// Implement Runable interface
Hell
private String URL_str; // The path of the network song
private File download_file; // Downloaded file
private int total_read = 0; // The length of the downloaded file (in bytes)
private int readLength = 0; // length of one-time download (in bytes)
private int music_length = 0; // The length of the music file (in bytes)
private boolean flag = false; // whether to stop downloading, stop downloading as true
private Thread downThread; // Download thread
private String musicName; // Downloaded file name
@Override
public IBinder onBind (Intent intent) {
return null;
}
@Override
public void onCreate () {
downThread = new Thread (this); // Initialize the download thread
downThread.start ();
}
@Override
public void onStart (Intent intent, int startId) {
URL_str = intent.getExtras (). GetString ("url"); // Get the URL of the download link
musicName = intent.getExtras (). getString ("musicName"); // Get the downloaded file name
}
Hell
@Override
public void onDestroy () {
flag = true; // Stop download
}
Hell
// Implement Run method to download songs
@Override
public void run () {
FileOutputStream fos = null; // File output stream
FileInputStream fis = null; // File output stream
InputStream is = null; // Network file input stream
URL url = null;
try {
url = new URL (URL_str); // URL of network song
HttpURLConnection httpConnection = null;
httpConnection = (HttpURLConnection)
url.openConnection (); // Open the network connection
download_file = new File (Environment. // Create a file with the same name as the file to be downloaded in the sdcard root directory
getExternalStorageDirectory ()
+ "/" + musicName);
fos = new FileOutputStream (download_file, true); // Initialize file output stream
fis = new FileInputStream (download_file); // Initialize file input stream
total_read = fis.available (); // Initialize the length of the "downloaded part", which should be 0 here
music_length = httpConnection.getContentLength (); // Total length of the file to be downloaded
Ranch
if (is == null) {// If the download fails, print the log and return
Log.i ("info", "donload failed ...");
return;
}
Ranch
byte buf [] = new byte [1024]; // Define download buffer
readLength = 0; // One-time download length
Log.i ("info", "download start ...");
Ranch
// Send to the front to start downloading the broadcast
Intent startIntent = new Intent ();
startIntent.setAction ("com.alex.downloadstart");
sendBroadcast (startIntent);
Ranch
// If the data stream for reading the network file is successful, and the user has not chosen to stop the download, the file download will start
while (readLength! = -1 &&! flag) {
if ((readLength = is.read (buf))> 0) {
fos.write (buf, 0, readLength);
total_read + = readLength; // Increase the length of the downloaded file
}
if (total_read == music_length) {// When the downloaded length is equal to the length of the network file, the download is complete
flag = false;
Log.i ("info", "download complete ...");
Ranch
// Send the download completion broadcast to the front desk
Intent completeIntent = new Intent ();
completeIntent.setAction ("com.alex.downloadcompleted");
sendBroadcast (completeIntent);
Ranch
// Close the input and output stream
fos.close ();
is.close ();
fis.close ();
}
Thread.sleep (50); // Currently sleep for 50 milliseconds
Log.i ("info", "download process:" // Print download progress
+ ((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 ();
}
}
Hell
}
Here is a small bug. If you download the same song multiple times, the program will not create a new file multiple times, but write the data to the file with the same name.