1. 程式人生 > >android-音樂播放器實現及原始碼下載(一)

android-音樂播放器實現及原始碼下載(一)

從本文開始,詳細講述一個音樂播放器的實現,以及從網路解析資料獲取最新推薦歌曲以及歌曲下載的功能。
功能介紹如下:
1、獲取本地歌曲列表,實現歌曲播放功能。
2、利用硬體加速感應器,搖動手機實現切換歌曲的功能
3、利用jsoup解析網頁資料,從網路獲取歌曲列表,同時實現歌曲和歌詞下載到手機本地的功能。
4、通知欄提醒,實現仿QQ音樂播放器的通知欄功能.
涉及的技術有:
1、jsoup解析網路網頁,從而獲取需要的資料
2、android中訪問網路,獲取檔案到本地的網路請求技術,以及下載檔案到本地實現斷點下載
3、執行緒池
4、圖片快取
5、service一直在後臺執行
6、手機硬體加速器
7、notification通知欄設計
8、自定義廣播
9、android系統檔案管理
主要技術是這些,其中,利用jsoup解析網路網頁,從而獲取需要的資料,請參考我的博文:

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檔案的話,也不會出現崩潰。