android-音樂播放器實現及原始碼下載(一)
從本文開始,詳細講述一個音樂播放器的實現,以及從網路解析資料獲取最新推薦歌曲以及歌曲下載的功能。
功能介紹如下:
1、獲取本地歌曲列表,實現歌曲播放功能。
2、利用硬體加速感應器,搖動手機實現切換歌曲的功能
3、利用jsoup解析網頁資料,從網路獲取歌曲列表,同時實現歌曲和歌詞下載到手機本地的功能。
4、通知欄提醒,實現仿QQ音樂播放器的通知欄功能.
涉及的技術有:
1、jsoup解析網路網頁,從而獲取需要的資料
2、android中訪問網路,獲取檔案到本地的網路請求技術,以及下載檔案到本地實現斷點下載
3、執行緒池
4、圖片快取
5、service一直在後臺執行
6、手機硬體加速器
7、notification通知欄設計
8、自定義廣播
9、android系統檔案管理
主要技術是這些,其中,利用jsoup解析網路網頁,從而獲取需要的資料,請參考我的博文:
下面是最終結果展示:
圖一 本地歌曲列表
圖二 網路歌曲列表
圖三 播放歌曲介面
圖四 播放介面歌詞顯示部分
圖五 通知欄展示 播放和下載時的展示
在本地歌曲列表介面長按選單鍵可以顯示選單:
在網路歌曲列表中,點選歌曲,可以顯示下載和取消選單項:
基本的介面就是上面的圖所展示的。大家覺得還可以的話,就給留個言~~^_^【握手】
下面就開始詳細講述實現細節。首先提一點,播放器中獲取的網路歌曲部分,請參看我的博文:android中使用JSOUP如何解析網頁資料詳述
網路歌曲列表的獲取就是利用jsoup從網頁抓取資料進行展示的。關於這部分的東西,在本系列博文中不再詳細說明了。
關於音樂播放器部分,需要使用到service服務,總共需要兩個,一個是音樂播放的service,一個是歌曲下載的service,關於service一直在後臺執行的問題,請參考我的博文:實現音樂播放器後臺Service服務一直存在的解決思路
根據這篇博文的說明,很容易設計application類的實現,application類實現程式碼如下:
/**
* 2015年8月15日 16:34:37
* 博文地址:http://blog.csdn.net/u010156024
*/
public class App extends Application {
public static Context sContext;
public static int sScreenWidth;
public static int sScreenHeight;
@Override
public void onCreate() {
super.onCreate();
sContext = getApplicationContext();
startService(new Intent(this, PlayService.class));
startService(new Intent(this, DownloadService.class));
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
sScreenWidth = dm.widthPixels;
sScreenHeight = dm.heightPixels;
}
}
application類中啟動了上面的兩個service服務,同時獲取了手機螢幕的寬和高。手機寬和高是為了後i面設計介面使用的。
有了application之後就可以設計Activity類,首先設計BaseActivity類,把複用的程式碼放在基類中,子類覆蓋或重寫BaseActivity中的方法,程式碼如下:
/**
* 2015年8月15日 16:34:37
* 博文地址:http://blog.csdn.net/u010156024
*/
public abstract class BaseActivity extends FragmentActivity {
protected PlayService mPlayService;
protected DownloadService mDownloadService;
private final String TAG = BaseActivity.class.getSimpleName();
private ServiceConnection mPlayServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
L.l(TAG, "play--->onServiceDisconnected");
mPlayService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mPlayService = ((PlayService.PlayBinder) service).getService();
mPlayService.setOnMusicEventListener(mMusicEventListener);
onChange(mPlayService.getPlayingPosition());
}
};
private ServiceConnection mDownloadServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
L.l(TAG, "download--->onServiceDisconnected");
mDownloadService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mDownloadService = ((DownloadService.DownloadBinder) service).getService();
}
};
/**
* 音樂播放服務回撥介面的實現類
*/
private PlayService.OnMusicEventListener mMusicEventListener =
new PlayService.OnMusicEventListener() {
@Override
public void onPublish(int progress) {
BaseActivity.this.onPublish(progress);
}
@Override
public void onChange(int position) {
BaseActivity.this.onChange(position);
}
};
/**
* Fragment的view載入完成後回撥
*
* 注意:
* allowBindService()使用繫結的方式啟動歌曲播放的服務
* allowUnbindService()方法解除繫結
*
* 在SplashActivity.java中使用startService()方法啟動過該音樂播放服務了
* 那麼大家需要注意的事,該服務不會因為呼叫allowUnbindService()方法解除繫結
* 而停止。
*/
public void allowBindService() {
getApplicationContext().bindService(new Intent(this, PlayService.class),
mPlayServiceConnection,
Context.BIND_AUTO_CREATE);
}
/**
* fragment的view消失後回撥
*/
public void allowUnbindService() {
getApplicationContext().unbindService(mPlayServiceConnection);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//繫結下載服務
bindService(new Intent(this, DownloadService.class),
mDownloadServiceConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(mDownloadServiceConnection);
super.onDestroy();
}
public DownloadService getDownloadService() {
return mDownloadService;
}
/**
* 更新進度
* 抽象方法由子類實現
* 實現service與主介面通訊
* @param progress 進度
*/
public abstract void onPublish(int progress);
/**
* 切換歌曲
* 抽象方法由子類實現
* 實現service與主介面通訊
* @param position 歌曲在list中的位置
*/
public abstract void onChange(int position);
}
下面給出啟動介面,啟動介面非常簡單,延時2秒進入主介面,程式碼如下:
/**
* 2015年8月15日 16:34:37
* 博文地址:http://blog.csdn.net/u010156024
*/
public class SplashActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// no title
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.splash_layout);
// 2s跳轉到主介面
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
}, 2000);
}
}
以上算是準備工作,有了上面的準備,可以設計主介面和主機面中的兩個Fragment了。下面一篇博文講述主介面的實現。
PS:
程式碼已更新,本地手機沒有MP3檔案的話,也不會出現崩潰。