package com.cinderella.musicsearch; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.libhy.RingSelect; import android.R.integer; import android.app.Activity; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.media.MediaPlayer; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CompoundButton; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.SimpleAdapter.ViewBinder; public class MusicPageActivity extends ListActivity { private static MusicPageActivity sMusicPageActivity; private static SogouMusicSearcher sFetcher; private static FetchDownloadLinkTask sFetchDownloadLinkTask; private static PreviewTask sPreviewTask; private static int sIndex; private static TextView sArtistTextView; private static TextView sAlbumTextView; private static TextView sSizeTextView; private static TextView sSongTextView; private MusicInfo mMusicInfo; private String mDownloadedMusicPath; private DownloadMusicTask mDownloadMusicTask; private int mCurLinkIndex = 0; private ProgressBar mProgressBar; private TextView mMessage; private Button mRetryButton; private Button mPreviewButton; private Button mDownloadButton; private Button mEditButton; private DownloadLinkListAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Utils.D("onCreate()"); setContentView(R.layout.music_page); // AdListener.createAds(this); mProgressBar = (ProgressBar) findViewById(R.id.search_progress); mMessage = (TextView) findViewById(R.id.search_message); mRetryButton = (Button) findViewById(R.id.retry_button); mPreviewButton = (Button) findViewById(R.id.preview_button); mPreviewButton.setOnClickListener(new PreviewClickListener()); mDownloadButton = (Button) findViewById(R.id.download_button); mDownloadButton.setOnClickListener(new DownloadClickListener()); mEditButton = (Button) findViewById(R.id.edit_button); mEditButton.setOnClickListener(new EditClickListener()); mRetryButton.setOnClickListener(new RetryClickLister()); sAlbumTextView = (TextView) findViewById(R.id.album); sArtistTextView = (TextView) findViewById(R.id.artist); sSizeTextView = (TextView) findViewById(R.id.size); sSongTextView = (TextView) findViewById(R.id.song); initData(getIntent()); initView(); fetchDownloadLink(); } @Override protected void onDestroy() { super.onDestroy(); if (mDownloadMusicTask != null) { mDownloadMusicTask.setBackground(true); } if (sFetchDownloadLinkTask != null) { sFetchDownloadLinkTask.cancel(true); } } @Override protected void onNewIntent(Intent intent) { Utils.D("onNewIntent()"); initData(intent); initView(); fetchDownloadLink(); } private void initData(Intent intent) { sIndex = intent.getIntExtra(Const.INDEX, 0); Utils.D("sIndex: "+sIndex); mDownloadedMusicPath = null; mMusicInfo = SearchActivity.sData.get(sIndex); mAdapter = null; mCurLinkIndex = 0; mDownloadMusicTask = null; setListAdapter(mAdapter); setLoadingStatus(); } private void initView() { sAlbumTextView.setText(mMusicInfo.getAlbum()); sArtistTextView.setText(mMusicInfo.getArtist()); sSizeTextView.setText("Size: "+mMusicInfo.getDisplayFileSize()); sSongTextView.setText(mMusicInfo.getTitle()); mDownloadButton.setText(R.string.download); } private void fetchDownloadLink() { if (sFetchDownloadLinkTask != null) { sFetchDownloadLinkTask.cancel(true); } sFetchDownloadLinkTask = new FetchDownloadLinkTask(); sFetchDownloadLinkTask.execute(); setLoadingStatus(); } private class FetchDownloadLinkTask extends AsyncTask<Void, Void, Void> { @Override protected Void doInBackground(Void... params) { if (sFetcher == null) { sFetcher = new SogouMusicSearcher(); } sFetcher.setMusicDownloadUrl(mMusicInfo); return null; } @Override protected void onPostExecute(Void parm) { sFetchDownloadLinkTask = null; if (mAdapter == null) { mAdapter = new DownloadLinkListAdapter(MusicPageActivity.this, R.layout.link_item); setListAdapter(mAdapter); } mAdapter.notifyDataSetChanged(); if (mAdapter.getCount() == 0) { setErrorStatus(); } else { mDownloadButton.setEnabled(true); mPreviewButton.setEnabled(true); } } } private void downloadMusic() { mDownloadMusicTask = new DownloadMusicTask(this, mMusicInfo, mMusicInfo.getDownloadUrl().get(mCurLinkIndex)); mDownloadMusicTask.execute(); } private class DownloadMusicTask extends AsyncTask<Void, Integer, File> { private Context mContext; private MusicInfo mDownloadMusicInfo; private boolean mIsDownloadBackGround = false; private DownloadProgressDialogListerner mDownloadProgressDialogListerner; private String mMusicPath; private String mUrl; public DownloadMusicTask(Context context, MusicInfo musicInfo, String url) { mContext = context; mDownloadMusicInfo = musicInfo; mUrl = url; } @Override protected void onPreExecute() { mDownloadProgressDialogListerner = new DownloadProgressDialogListerner(mContext); mDownloadProgressDialogListerner.onDownloadStart(); mDownloadButton.setText(R.string.show_progress); } @Override protected File doInBackground(Void... params) { Utils.D("background start:"); int count = 0; URL url = null; HttpURLConnection urlConn = null; InputStream stream = null; DataInputStream is = null; try { Utils.D("Download url: "+mUrl); url = new URL(mUrl); urlConn = (HttpURLConnection)url.openConnection(); urlConn.setRequestProperty("User-Agent", "Mozilla/5.0 (Linux; U; Android 0.5; en-us) AppleWebKit/522+ (KHTML, like Gecko) Safari/419.3 -Java"); urlConn.setConnectTimeout(4000); urlConn.connect(); stream = urlConn.getInputStream(); byte[] buff = new byte[4096]; is = new DataInputStream(stream); int len; File f = new File(Const.sMusicDir+mDownloadMusicInfo.getTitle()+".mp3"); mMusicPath = f.getAbsolutePath(); FileOutputStream file = new FileOutputStream(f); int percent = 0; int last_percent = 0; while ((len = is.read(buff)) > 0) { file.write(buff, 0, len); count = count + len; if (mDownloadMusicInfo.getFilesize() != 0) { percent = (int) ((count*100)/mDownloadMusicInfo.getFilesize()); if (percent != last_percent) { Utils.D("percent: "+percent); publishProgress(percent); last_percent = percent; } } } urlConn.disconnect(); return f; } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(File result) { mDownloadMusicTask = null; if (result == null) { mDownloadProgressDialogListerner.onDownloadFinish(); mDownloadButton.setText(R.string.download); Toast.makeText(MusicPageActivity.this, MusicPageActivity.this.getString(R.string.toast_download_failed)+mMusicInfo.getTitle(), Toast.LENGTH_LONG).show(); } if (result.length() < Const.MIN_MP3_LENGTH) { Utils.D("file size too small."); mDownloadProgressDialogListerner.onDownloadFinish(); mDownloadButton.setText(R.string.download); Toast.makeText(MusicPageActivity.this, R.string.link_broken, Toast.LENGTH_LONG).show(); result.delete(); } else { Utils.D("result!=null"); Toast.makeText(MusicPageActivity.this, MusicPageActivity.this.getString(R.string.toast_download_finish)+mMusicInfo.getTitle(), Toast.LENGTH_LONG).show(); mDownloadButton.setText(R.string.play); mEditButton.setVisibility(View.VISIBLE); mDownloadedMusicPath = result.getAbsolutePath(); if (!mIsDownloadBackGround) { mDownloadProgressDialogListerner.onDownloadFinish(); } else if (mIsDownloadBackGround) { Intent intent = new Intent(MusicPageActivity.this, DownloadedActivity.class); String title = getString(R.string.app_name); String resTitle = mMusicInfo.getTitle(); String resText = getString(R.string.toast_download_finish)+mMusicInfo.getTitle(); String resExpandedTitle = resText; String resExpandedText = getString(R.string.click_to_view_music); Utils.addNotification(MusicPageActivity.this, intent, title, resTitle, resText, resExpandedTitle, resExpandedText); } } } @Override protected void onProgressUpdate(Integer... values) { if (!mIsDownloadBackGround) { mDownloadProgressDialogListerner.onProgressUpdate(values[0]); } } @Override protected void onCancelled() { Utils.D("onCancel of DownloadTask called......."); mDownloadMusicTask = null; mDownloadButton.setText(R.string.download); if (mDownloadedMusicPath != null) { Utils.deleteFile(mMusicPath); } if (!mIsDownloadBackGround) { mDownloadProgressDialogListerner.cancelDownload(); } } public void showProgressDialog() { mDownloadProgressDialogListerner.showProgressDialog(); } public void hideProgressDialog() { mDownloadProgressDialogListerner.hideProgressDialog(); } public boolean isProgressDialogShowing() { return mDownloadProgressDialogListerner.isShowing(); } public void setBackground(boolean isBackground) { mIsDownloadBackGround = isBackground; } } private class DownloadProgressDialogListerner { private Context mContext; private ProgressDialog mDownloadProgressDialog; public DownloadProgressDialogListerner(Context context) { mContext = context; } public void onDownloadStart() { mDownloadProgressDialog = new ProgressDialog(mContext); mDownloadProgressDialog.setTitle(R.string.download); mDownloadProgressDialog.setIndeterminate(false); mDownloadProgressDialog.setMax(100); mDownloadProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDownloadProgressDialog.setProgress(0); mDownloadProgressDialog.setButton(DialogInterface.BUTTON1, MusicPageActivity.this.getString(R.string.hide), new HideProgressDialogClickListener()); mDownloadProgressDialog.setButton(DialogInterface.BUTTON2, MusicPageActivity.this.getString(R.string.cancel), new cancelProgressDialogClickListener()); mDownloadProgressDialog.setCancelable(true); showProgressDialog(); } public void onProgressUpdate(int progress) { mDownloadProgressDialog.setProgress(progress); } public void onDownloadFinish() { mDownloadProgressDialog.cancel(); } public void hideProgressDialog() { mDownloadProgressDialog.dismiss(); } public void showProgressDialog() { mDownloadProgressDialog.show(); } public void cancelDownload() { mDownloadProgressDialog.cancel(); } public boolean isShowing() { Utils.D("mDownloadProgressDialog.isShowing: "+mDownloadProgressDialog.isShowing()); return mDownloadProgressDialog.isShowing(); } } private class PreviewTask extends AsyncTask<Void, Void, Integer> { private ProgressDialog mStreamProgressDialog; private MediaPlayer sPreviewMediaPlayer; @Override protected void onPreExecute() { mStreamProgressDialog = new ProgressDialog(MusicPageActivity.this); mStreamProgressDialog.setTitle(R.string.streaming); mStreamProgressDialog.setMessage(MusicPageActivity.this.getText(R.string.preview_wait)); mStreamProgressDialog.setIndeterminate(true); mStreamProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); mStreamProgressDialog.setCancelable(true); mStreamProgressDialog.setOnDismissListener(new dismissPreviewDialogClickListener()); mStreamProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, MusicPageActivity.this.getString(R.string.cancel), new cancelPreviewDialogClickListener()); mStreamProgressDialog.show(); } @Override protected Integer doInBackground(Void... params) { sPreviewMediaPlayer = new MediaPlayer(); try { if (mDownloadedMusicPath == null) { sPreviewMediaPlayer.setDataSource(mMusicInfo.getDownloadUrl().get(mCurLinkIndex)); } else { sPreviewMediaPlayer.setDataSource(mDownloadedMusicPath); } sPreviewMediaPlayer.prepare(); sPreviewMediaPlayer.start(); } catch (Exception e) { return null; } return 1; } @Override protected void onPostExecute(Integer result) { Utils.D("in postExecute of PreviewTask."); if (result == null) { mStreamProgressDialog.cancel(); Toast.makeText(MusicPageActivity.this, R.string.preview_failed, Toast.LENGTH_LONG).show(); } } @Override protected void onCancelled() { Utils.D("in onCancel of PreviewTask"); mStreamProgressDialog.cancel(); stopPreviewPlayer(); sPreviewTask = null; } public void stopPreviewPlayer() { sPreviewMediaPlayer.stop(); sPreviewMediaPlayer.release(); sPreviewMediaPlayer = null; } } private void previewTask() { if (sPreviewTask != null) { sPreviewTask.cancel(true); } sPreviewTask = new PreviewTask(); sPreviewTask.execute(); } private class DownloadLinkListAdapter extends BaseAdapter { private int mResource; private LayoutInflater mInflater; public DownloadLinkListAdapter(Context context, int resource) { mResource = resource; mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public int getCount() { if (mMusicInfo==null || !mMusicInfo.isRealDownloadLink()) { return 0; } else { return mMusicInfo.getDownloadUrl().size(); } } @Override public Object getItem(int position) { if (mMusicInfo!=null && mMusicInfo.isRealDownloadLink()) { return mMusicInfo.getDownloadUrl().get(position); } else { return null; } } @Override public long getItemId(int position) { if (mMusicInfo==null || !mMusicInfo.isRealDownloadLink()) { return -1; } return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v; ArrayList<String> linkList = mMusicInfo.getDownloadUrl(); if (convertView == null) { v = mInflater.inflate(mResource, parent, false); } else { v = convertView; } String link = linkList.get(position); RadioButton rb = (RadioButton) v.findViewById(R.id.is_checked); rb.setText(link); rb.setOnClickListener(new LinkItemClickListener(position)); if (position == mCurLinkIndex) { rb.setChecked(true); } else { rb.setChecked(false); } return v; } } private class LinkItemClickListener implements View.OnClickListener{ private int mPosition; public LinkItemClickListener(int position) { mPosition = position; } @Override public void onClick(View v) { mCurLinkIndex = mPosition; mAdapter.notifyDataSetChanged(); } } private class DownloadClickListener implements View.OnClickListener { @Override public void onClick(View v) { Utils.D("mDownloadMusicTask == "+mDownloadMusicTask); Utils.D("mDownloadedMusicPath == "+mDownloadedMusicPath); if (mDownloadMusicTask == null && mDownloadedMusicPath == null) { downloadMusic(); } else if (mDownloadMusicTask!=null && mDownloadedMusicPath==null && mDownloadMusicTask.isProgressDialogShowing()){ mDownloadMusicTask.hideProgressDialog(); } else if (mDownloadMusicTask!=null && mDownloadedMusicPath==null && !mDownloadMusicTask.isProgressDialogShowing()) { mDownloadMusicTask.showProgressDialog(); } else if (mDownloadedMusicPath!=null) { Utils.startMusicPlayer(MusicPageActivity.this, mDownloadedMusicPath); } } } private class PreviewClickListener implements View.OnClickListener { @Override public void onClick(View v) { previewTask(); } } private class EditClickListener implements View.OnClickListener { @Override public void onClick(View v) { RingSelect.startPureEditor(MusicPageActivity.this, mDownloadedMusicPath); } } private class RetryClickLister implements View.OnClickListener { @Override public void onClick(View v) { fetchDownloadLink(); } } private class HideProgressDialogClickListener implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { if (mDownloadMusicTask != null) { mDownloadMusicTask.hideProgressDialog(); } } } private class cancelProgressDialogClickListener implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { if (mDownloadMusicTask != null) { boolean isCanceled = mDownloadMusicTask.cancel(true); Utils.D("isCanceled?:"+isCanceled); } } } private class cancelPreviewDialogClickListener implements DialogInterface.OnClickListener { @Override public void onClick(DialogInterface dialog, int which) { cancelPreviewDialog(); } } private class dismissPreviewDialogClickListener implements DialogInterface.OnDismissListener { @Override public void onDismiss(DialogInterface dialog) { cancelPreviewDialog(); } } private void cancelPreviewDialog() { if (sPreviewTask != null) { sPreviewTask.stopPreviewPlayer(); sPreviewTask.cancel(true); Utils.D("previewTask.isCanceled?="+sPreviewTask.isCancelled()); } sPreviewTask = null; } private void setLoadingStatus() { mProgressBar.setVisibility(View.VISIBLE); mMessage.setVisibility(View.VISIBLE); mRetryButton.setVisibility(View.GONE); mMessage.setText(R.string.loading_downloaded_music); } private void setErrorStatus() { mProgressBar.setVisibility(View.GONE); mMessage.setVisibility(View.VISIBLE); mRetryButton.setVisibility(View.VISIBLE); mMessage.setText(R.string.load_download_link_failed); } }