基于android的网络音乐播放器-本地音乐的加载和后台播放(一)

作为android初学者,最近把疯狂android讲义和疯狂Java讲义看了一遍,看到书中介绍的知识点非常多,很难全部记住,为了更好的掌握基础知识点,我将开发一个网络音乐播放器-EasyMusic来巩固下,也当作是练练手。感兴趣的朋友可以看看,有设计不足的地方也欢迎指出。

开发之前首先介绍下该音乐播放器将要开发的功能(需求):

1.本地音乐的加载和播放;

2.网络音乐的搜索,试听和下载;

3.音乐的断点下载;

4.点击播放图标加载专辑图片,点击歌词加载歌词并滚动显示(支持滑动歌词改变音乐播放进度);

5.支持基于popupWindow的弹出式菜单;

6.支持后台任务栏显示和控制。

该篇主要实现本地音乐的加载和播放,主要代码如下:
1. MainActivity.java

package com.sprd.easymusic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.sprd.easymusic.service.PlayMusicService;

import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
    private String TAG = "MainActivity";
    //dbMusic保存媒体库中的所有音乐
    private List<Map<String,Object>> dbMusic = new ArrayList<>();
    private ListView musicListView;
    private LayoutInflater inflater;
    private Context mContext;
    PlayMusicService playService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = this;
        musicListView = (ListView)findViewById(R.id.musicList);
        getMusicFromDb();
        bindToService();
        inflater = LayoutInflater.from(mContext);
        //音乐列表musicListView的adapter定义
        SimpleAdapter adapter = new SimpleAdapter(this, dbMusic, R.layout.musiclist_item,
                new String[] {"title", "artist"}, new int[] {R.id.musicTitle, R.id.musicArtist});
        musicListView.setAdapter(musicListAdapter);
        musicListView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                playMusic(position);
                Toast.makeText(mContext, "click on position " + position, Toast.LENGTH_LONG).show();
            }
        });
    }

    //绑定服务时的ServiceConnection参数
    private ServiceConnection conn = new ServiceConnection() {

        //绑定成功后该方法回调,并获得服务端IBinder的引用
        public void onServiceConnected(ComponentName name, IBinder service) {
            //通过获得的IBinder获取PlayMusicService的引用
            playService = ((PlayMusicService.MusicBinder)service).getService();
            Toast.makeText(mContext, "onServiceConnected", Toast.LENGTH_LONG).show();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected");
        }

    };

    //绑定服务PlayMusicService
    private void bindToService() {
        bindService(new Intent(mContext, com.sprd.easymusic.service.PlayMusicService.class),
                conn, Service.BIND_AUTO_CREATE);
    }

    //通过获得的PlayMusicService引用调用播放音乐的方法,方法传进去的参数为音乐url
    protected void playMusic(int position) {
        if (playService != null) {
            playService.play((String)dbMusic.get(position).get("url"));
        }
    }

    //从媒体库中查询音乐
    private void getMusicFromDb() {
        if (dbMusic.size() > 0) dbMusic.clear();
                Cursor musicCursor1 = this.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                        null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
                //从外部存储获取
                getMusic(musicCursor1);
                Cursor musicCursor2 = this.getContentResolver().query(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,
                        null, null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
                //从内部存储获取
                getMusic(musicCursor2);
    }

    //获取到的音乐以Map的形式存储在dbMusic中
    private void getMusic(Cursor musicCursor) {
        while (musicCursor.moveToNext()) {
            Map<String, Object> item = new HashMap<String, Object>();
            long id = musicCursor.getLong(musicCursor.getColumnIndex(MediaStore.Audio.Media._ID));
            String title = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
            String artist = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
            if (artist != null && artist.equals("<unknown>")) {
                continue;
            }
            long duration = musicCursor.getLong(musicCursor.getColumnIndex(MediaStore.Audio.Media.DURATION));
            long size = musicCursor.getLong(musicCursor.getColumnIndex(MediaStore.Audio.Media.SIZE));
            String url = musicCursor.getString(musicCursor.getColumnIndex(MediaStore.Audio.Media.DATA));
            int isMusic = musicCursor.getInt(musicCursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));
            if (isMusic != 0) {
                item.put("id", id);
                item.put("title", title);
                item.put("artist", artist);
                item.put("duration", formatDuration(duration));
                item.put("size", size);
                item.put("url", url);
                Log.d("MainActivity", "MusicTitle = " + title);
                Log.d("MainActivity", "MusicArtist = " + artist);
                Log.d("MainActivity", "MusicUrl = " + url);
                dbMusic.add(item);
            }

        }       
    }
    //将音乐时长转换为00:00格式
    private String formatDuration(long dur) {
        long totalSecond = dur / 1000;
        String minute = totalSecond / 60 + "";
        if (minute.length() < 2) minute = "0" + minute ;
        String second = totalSecond % 60 + "";
        if (second.length() < 2) second = "0" + second;
        return minute + ":" + second;
    }

    private BaseAdapter musicListAdapter = new BaseAdapter() {

        @Override
        public int getCount() {
            return dbMusic.size();
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = convertView;
            Map<String, Object> item = dbMusic.get(position);
            if (convertView == null) {
                view = inflater.inflate(R.layout.musiclist_item, null);
            }
            TextView musicTitle = (TextView)view.findViewById(R.id.musicTitle);
            TextView musicArtist = (TextView)view.findViewById(R.id.musicArtist);
            musicTitle.setText((String)item.get("title"));
            musicTitle.setText((String)item.get("artist"));
            return view;
        }

    };

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

布局文件就一个ListView就不贴出来了,这里贴一下musicListAdapter的item布局:
musiclist_item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical"
    android:orientation="horizontal"
    android:padding="5dp" >

    <ImageView
        android:id="@+id/musicTag"
        android:layout_width="50dp"
        android:layout_height="40dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_centerVertical="true"
        android:src="@drawable/music" />

    <TextView
        android:id="@+id/musicTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@id/musicTag"
        android:text="TextView" />

    <TextView
        android:id="@+id/musicArtist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/musicTag"
        android:layout_below="@+id/musicTitle"
        android:text="TextView" />

    <ImageView
        android:id="@+id/love"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/musicTag"
        android:layout_alignParentRight="true"
        android:src="@android:drawable/btn_star_big_off" />

</RelativeLayout>

2 PlayMusicService.java 这是后台播放音乐的服务

package com.sprd.easymusic.service;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class PlayMusicService extends Service {
    private final String TAG = "PlayMusicService";
    private MediaPlayer mPlayer = new MediaPlayer();
    //后台播放音乐的线程
    private PlayThread myPlayThread = new PlayThread(); 

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }
    /*
     * MainActivity调用bindService后该方法回调,紧接着MainActivity的ServiceConnection的
     * onServiceConnected方法回调,onBind回调的返回值传递给onServiceConnected中的参数service
     * 从而MainActivity就可以通过Binder的getService方法获得PlayMusicService的引用,后续的音乐播放
     * 控制就简单了
     */
    public IBinder onBind(Intent intent) {
        Toast.makeText(this, "onBind", Toast.LENGTH_LONG).show();
        return new MusicBinder();
    }

    public class MusicBinder extends Binder {

        public PlayMusicService getService() {
            return PlayMusicService.this;
        }
    }

    public void play(String url) {
        myPlayThread.setUrl(url);
        myPlayThread.start();
    }

    //后台播放音乐的线程定义
    private class PlayThread extends Thread {
        //歌曲的url
        private String url = null;

        public PlayThread() {
        }

        public PlayThread(String url) {
            this.url = url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public void run() {
            if (mPlayer.isPlaying()) {
                mPlayer.stop();
            }
            try {
                mPlayer.reset();
                Log.d("MusicService", "play reset ");
                mPlayer.setDataSource(url);
                Log.d("MusicService", "play setDataSource ");
                mPlayer.prepare();
                Log.d("MusicService", "play prepare ");
                mPlayer.start();
                Log.d("MusicService", "play start ");
                mPlayer.setOnCompletionListener(new OnCompletionListener() {

                    @Override
                    public void onCompletion(MediaPlayer player) {

                    }               
                });     
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

}

然后不要忘了在manifest文件里面注册service和添加权限(媒体库查询外部存储的音乐)

<service android:name="com.sprd.easymusic.service.PlayMusicService"></service>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

该文章只介绍这些内容,后续会更新进度;代码有问题或错误的地方欢迎指出和给出修改意见。

音乐播放器已完成,下载地址:
Android音乐播放器

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值