Android本地及网络音乐播放器-播放本地音乐(一)

 入职没多久,自学了一段时间的安卓基础知识,抱着巩固下基础以及学会对知识点的基本运用的初衷写了一个音乐播放器,因此用到的东西都是很基础的,功能什么的大部分都是按照自己的想法来实现的,如果看完感觉哪些地方写的不行或有好的建议欢迎给我留言.
  该Android音乐播放器代码量稍微有点多,这里我将以实现功能的顺序为参考将音乐播放器分为几篇博客发布.该播放器实现的主要功能如下(结尾将会附上源代码下载地址):
  
1.本地音乐的播放及控制;
2.音乐播放界面的展示;
3.在线音乐的搜索及展示(包含使用json解析数据);
4.在线音乐的试听及下载;
5.下载控制界面-下载歌曲的暂停/继续/删除(可以查看并删除已下载音乐);
6.播放界面歌手专辑图片及歌词的下载和显示;
7.歌词的滚动显示以及滑动歌词改变音乐进度的监听;
8.音乐的断点下载;
9.基于PopupWindow的弹出式菜单(支持透明度修改和自定义背景);
10.后台任务栏显示与控制音乐的播放;
本地音乐列表            
本地音乐列表
          
音乐播放界面            
音乐播放界面

搜索网络音乐            
搜索网络音乐

网络音乐的试听和下载             
网络音乐的试听和下载

音乐下载控制界面            
音乐下载控制界面

已下载音乐的查看和删除            
已下载音乐的查看和删除

播放界面专辑图片的加载            
播放界面专辑图片的加载

播放界面歌词的加载            
播放界面歌词的加载

基于popupwindow的menu            
基于popupwindow的menu

基于popupwindow的menu            
基于popupwindow的menu

基于popupwindow的menu            
基于popupwindow的menu

后台任务栏显示与控制播放            
后台任务栏显示与控制播放

下面讲述项目需要实现的第一步功能-本地音乐播放的实现
这里主要涉及三个类:
1.MainActivity.java 负责整个项目的业务控制,包括滑动切换Fragment,控制音乐播放,呼出菜单等;
2.MusicListFragment.java 第一个Fragment展示在用户面前,主要展示本地音乐提供给用户点击播放;
3.MusicService.java 负责后台运行播放MediaPlayer
主要业务代码如下:
1MainActivity.java

package com.example.comfortmusic_1;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

import com.example.comfortmusic_1.fragment.DownloadFragment;
import com.example.comfortmusic_1.fragment.MusicListFragment;
import com.example.comfortmusic_1.fragment.NetFragment;
import com.example.comfortmusic_1.service.MusicService;


import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.ActionBar.Tab;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.app.FragmentTransaction;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.NavUtils;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.method.ScrollingMovementMethod;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RemoteViews;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends FragmentActivity implements MusicListFragment.Callbacks {



    public static boolean isPlaying = false;//全局变量,表征当前是否在播放
    /**
     * 当前播放音乐的信息
     */
    public static int currentMusicPosition;
    public static String currentMusicTitle;
    public static String currentMusicArtist;
    public static String currentMusicDuration;  
    public static String currentMusicUrl;
    /**
     * 循环控制-CYCLE表示当前循环模式
     */
    public static final int CYCLE_LIST = 1;
    public static final int CYCLE_RANDOM = 2;
    public static final int CYCLE_SINGLE = 3;
    public static int CYCLE = CYCLE_LIST;
    /**
     * 发送给MusicService的播放信息MSG:从头开始播放/暂停/继续播放/换歌
     */
    public static final int MSG_PLAY = 0;
    public static final int MSG_PAUSE = 1;
    public static final int MSG_CONTINUEPLAYING = 2;
    public static final int MSG_CHANGESONG = 3;
    public static int MSG = MSG_PLAY;

    //屏幕的长度和宽度
    public static int screenWidth;
    public static int screenHeight;
    //上一首歌曲位置,用来判断是从头播放还是继续播放,若prePosition=currentMusicPosition则继续播放,反之从头播放
    public static int prePosition;
    //程序启动时获取音频数据库中的音乐信息并保存到dbMusic中
    public static List<Map<String, Object>> dbMusic = new ArrayList<Map<String, Object>>();
    public static String TAG = "MainActivity";

    //activity切换fragment的工具
    SectionsPagerAdapter mSectionsPagerAdapter;
    ViewPager mViewPager;

    ActionBar actionBar;
    //tv1, tv2, tv3分别显示三个fragment的标题
    TextView tv1, tv2, tv3, currentMusic;
    //三个fragment的标题下动态表征切换页面的红条,红条宽度-bottomLine=screenWidth/页面数
    LinearLayout bottomLine;
    int bottomLineWidth;
    //下方播放区域,音乐图标,上一曲,播放/暂停/下一曲
    LinearLayout playArea;
    ImageView playTag;
    ImageButton buttonPre, buttonPlayAndPause, buttonNext;

    //启动MusicService的intent
    Intent ServiceIntent = null;
    //当前页面/fragment
    int currentItem = 0;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Toast.makeText(MainActivity.this, "CYCLE=" + CYCLE, 300).show();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        actionBar = getActionBar();       
        actionBar.hide();
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
        getScreenWidth();
        initTab();
        initView();       
        bottomLine = (LinearLayout) findViewById(R.id.bottomline);
        bottomLine.setX(bottomLineWidth);
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);
        mViewPager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageScrollStateChanged(int arg0) {            
            }

            @Override
            public void onPageScrolled(int item, float percent, int offset) {
                bottomLine.setX(item * bottomLineWidth +  offset/3);
            }

            @Override
            public void onPageSelected(int position) {
                currentItem = position;
                changeTabState(position);
            }           
        });

        mViewPager.setCurrentItem(0);
        registerMyReceiver();
        ServiceIntent = new Intent(this, MusicService.class);
        startService(ServiceIntent);
    }

    private void registerMyReceiver() {
        IntentFilter intentFilter = new IntentFilter();  
        intentFilter.addAction("action.nextsong");
        intentFilter.addAction("action.play"); 
        intentFilter.addAction("action.pause"); 
        intentFilter.addAction("action.pre"); 
        intentFilter.addAction("action.next"); 
        registerReceiver(completeReceiver, intentFilter);       
    }

    //获取屏幕的长度和高度
    private void getScreenWidth() {
        DisplayMetrics dm = new DisplayMetrics();
        this.getWindowManager().getDefaultDisplay().getMetrics(dm);
        screenWidth = dm.widthPixels;
        screenHeight = dm.heightPixels;
        bottomLineWidth = dm.widthPixels / (mSectionsPagerAdapter.getCount());
    }

    //标红当前fragment标题并添加监听点击即可跳转到对应fragment
    private void initTab() {
        tv1 = (TextView) findViewById(R.id.tab1);
        tv1.setTextColor(Color.RED);
        tv2 = (TextView) findViewById(R.id.tab2);
        tv3 = (TextView) findViewById(R.id.tab3);
        tv1.setOnClickListener(new MyOnClickListener(0));
        tv2.setOnClickListener(new MyOnClickListener(1));
        tv3.setOnClickListener(new MyOnClickListener(2));       
    }


    public void initView() {

        playArea = (LinearLayout) findViewById(R.id.playarea);
        currentMusic = (TextView) findViewById(R.id.currentmusic);
        currentMusic.setTextColor(Color.RED);
        buttonPre = (ImageButton) findViewById(R.id.pre);
        buttonPlayAndPause = (ImageButton) findViewById(R.id.playandpause);
        buttonNext = (ImageButton) findViewById(R.id.next);
        playArea.setOnClickListener(new MyPlayListener());
        playArea.setPaddingRelative(0, 0, 0, 0);
        playTag = (ImageView)findViewById(R.id.playtag);
        buttonPre.setOnClickListener(new MyPlayListener());
        buttonPlayAndPause.setOnClickListener(new MyPlayListener());
        buttonNext.setOnClickListener(new MyPlayListener());
        getMusicFromDb();
        //开始默认将dbMusic中的第一首歌设置为当前歌曲
        if(dbMusic.size() != 0) {
            Map<String, Object> map = dbMusic.get(currentMusicPosition);
            currentMusicTitle = (String)map.get("title");
            currentMusicArtist = (String)map.get("artist");
            currentMusicUrl = (String)map.get("url");
            currentMusicDuration =(String)map.get("duration");
            currentMusic.setText(currentMusicTitle + "—" + currentMusicArtist);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.d(TAG, "onCreateOptionsMenu");
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            Fragment fragment = null;
            switch (position) {
            case 0:
                fragment = new MusicListFragment();
                break;
            case 1:
                fragment = new NetFragment();
                break;
            case 2:
                fragment = new DownloadFragment();
                break;
            }
            return fragment;
        }

        @Override
        public int getCount() {
            return 3;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            Locale l = Locale.getDefault();
            switch (position) {
                case 0:
                    return getString(R.string.title_section1).toUpperCase(l);//R.string.title_section1 = "本地音乐"
                case 1:
                    return getString(R.string.title_section2).toUpperCase(l);//R.string.title_section1 = "网络音乐"
                case 2:
                    return getString(R.string.title_section3).toUpperCase(l);//R.string.title_section1 = "下载列表"
            }
            return null;
        }
    }


    //从手机音乐数据库中提取音乐并保存到dbMusic中
    private void getMusicFromDb() {
        if (dbMusic.size() > 0) dbMusic.clear();
                //从sd卡读取歌曲
                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);
            }

    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形式
    public static 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 class MyPlayListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            int id = v.getId();
            switch (id) {
            case R.id.pre:
                pre();
                break;
            case R.id.playandpause:
                if (isPlaying) {
                    pause();
                } else {
                    play();
                }
                break;
            case R.id.next:
                next();
                break;
            case R.id.playarea:
                break;
            default:
                break;
            }
        }       
    }


    //通信后台MusicService更新播放信息
    public void notifyPlayService() {
        Log.d("MainActivity", "notifyPlayService");
        Toast.makeText(this, "notify play service" + "position = " + currentMusicPosition , 300).show();
        Log.d("MainActivity", "dbMusic.size() = " + dbMusic.size());
        if (dbMusic.size() == 0) return;
        Map<String, Object> map = dbMusic.get(currentMusicPosition);
        currentMusicTitle = (String)map.get("title");
        currentMusicArtist = (String)map.get("artist");
        currentMusicUrl = (String)map.get("url");
        Log.d("MainActivity", "url = " + currentMusicUrl);
        currentMusicDuration =(String)map.get("duration");

        Intent musicIntent = new Intent();
        musicIntent.setAction("action.changesong");
        this.sendBroadcast(musicIntent);    

        refreshPlayState();
    }

    //上一首
    public void pre() {
        Log.d("MainActivity", "pre");
        if (dbMusic.size() == 0) return;

        if (CYCLE == CYCLE_RANDOM) {
            currentMusicPosition = new Random().nextInt(dbMusic.size() - 1);
        }  else if (CYCLE == CYCLE_SINGLE|| CYCLE == CYCLE_LIST) {
            if (currentMusicPosition == 0) {
                currentMusicPosition = dbMusic.size() - 1;
            } else {
                currentMusicPosition--;
            }
        }
        isPlaying = true;
        MSG = MSG_PLAY;
        notifyPlayService();
    }

    //播放
    public void play() {
        Log.d("MainActivity", "play");
        if (prePosition != 0 && prePosition == currentMusicPosition) {
            MSG = MSG_CONTINUEPLAYING;
        } else {
            MSG = MSG_PLAY;
        }
        isPlaying = true;
        notifyPlayService();
    }

    //暂停
    public void pause() {
        Log.d("MainActivity", "pause");
        MSG = MSG_PAUSE;
        prePosition = currentMusicPosition;
        isPlaying = false;
        notifyPlayService();
    }

    //下一首
    public void next() {
Log.d("MainActivity", "next");
        if (dbMusic.size() == 0) return;
        if (CYCLE == CYCLE_RANDOM) {
            currentMusicPosition = new Random().nextInt(dbMusic.size() - 1);
        }  else if (CYCLE == CYCLE_SINGLE|| CYCLE == CYCLE_LIST) {
            if (currentMusicPosition == dbMusic.size() - 1) {
                currentMusicPosition = 0;
            } else {
                currentMusicPosition++;
            }
        }
        isPlaying = true;
        MSG = MSG_PLAY;
        notifyPlayService();
    }

    //接收到MusicService播放完之后的广播后自动播放下一首
    private void autoChangeSong() {
        Log.d("MainActivity", "autoChangeSong");
        Toast.makeText(MainActivity.this, "MainActivity_autoChangeSong_CYCLE = " + CYCLE, 300).show();
        if (CYCLE == CYCLE_RANDOM) {
            currentMusicPosition = new Random().nextInt(dbMusic.size() - 1);
        }  else if (CYCLE == CYCLE_LIST) {
            if (currentMusicPosition == dbMusic.size() - 1) {
                currentMusicPosition = 0;
            } else {
                currentMusicPosition++;
            }           
        }
        isPlaying = true;
        MSG = MSG_PLAY;
        notifyPlayService();
        }

    //更新播放界面状态
    public void refreshPlayState() {
        Log.d("MainActivity", "refreshPlayState");
        currentMusic.setText(currentMusicTitle + "—" + currentMusicArtist);
        currentMusic.requestFocus();
        currentMusic.setMovementMethod(ScrollingMovementMethod.getInstance());
        if (isPlaying) {
            buttonPlayAndPause.setImageResource(android.R.drawable.ic_media_pause);
            //animation
            TranslateAnimation animation= new TranslateAnimation(-playTag.getWidth()-currentMusic.getWidth()
                    ,-currentMusic.getWidth(),0,  0);
            animation.setDuration(10000);
            animation.setRepeatCount(Animation.INFINITE);
            animation.setRepeatMode(Animation.RESTART);
//          currentMusic.startAnimation(animation);
        } else {
            buttonPlayAndPause.setImageResource(android.R.drawable.ic_media_play);
            //clear animation
            currentMusic.clearAnimation();
        }
    }   

    //页面/fragment标题的监听类
    public class MyOnClickListener implements View.OnClickListener {

        int item;

        public MyOnClickListener(int item) {
            this.item = item;
        }
        @Override
        public void onClick(View v) {
            mViewPager.setCurrentItem(item);
            changeTabState(item);
            currentItem = item;
        }

    }     

    //标红当前页面标题
    public void changeTabState(int item) {
//      Toast.makeText(this, "current item = " + currentItem, 300).show();
        switch (item) {
        case 0:
            tv1.setTextColor(Color.RED);
            tv2.setTextColor(Color.BLACK);
            tv3.setTextColor(Color.BLACK);
            break;
        case 1:
            tv2.setTextColor(Color.RED);
            tv3.setTextColor(Color.BLACK);
            tv1.setTextColor(Color.BLACK);          
            break;
        case 2:
            tv3.setTextColor(Color.RED);
            tv1.setTextColor(Color.BLACK);
            tv2.setTextColor(Color.BLACK);          
            break;
        }
//      Toast.makeText(this, "item = " + item, 300).show();

    }

    @Override
    public void onItemSelected(Integer id) {//实现MusicListFragment的回调接口
        Log.d("MainActivity", "onItemSelected");
        Log.d("MainActivity", "item" + id + " clicked!");
        notifyPlayService();
    }

    //接受广播并改变播放状态
    private BroadcastReceiver completeReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();  
            if (action.equals("action.nextsong")) {  
                  autoChangeSong();
              } else if (action.equals("action.pre")) {
                  pre();
              } else if (action.equals("action.play")) {
                  play();
              } else if (action.equals("action.pause")) {
                  pause();
              } else if (action.equals("action.next")) {
                  next();
              } else if (action.equals("action.exit")) {
                  closeApplication();
              }
        }

    };


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {//返回按键监听
        if (keyCode == KeyEvent.KEYCODE_BACK  && event.getAction() == KeyEvent.ACTION_DOWN) {           
            if (mViewPager.getCurrentItem() != 0) {
                mViewPager.setCurrentItem(mViewPager.getCurrentItem()-1);
                return false;
            } else {
                closeApplication();
                return false;
            } 

        }  
        return super.onKeyDown(keyCode, event);
    }   

    private void closeApplication() {
        MainActivity.this.finish();
    }
    //转到手机桌面
    public void toHomeTable(){
        Intent intent = new Intent();
        intent.setAction("android.intent.action.MAIN");
        intent.addCategory("android.intent.category.HOME");
        startActivity(intent);
    }   

    @Override
    protected void onStop() {
        Log.d("MainActivity", "onStop");
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        Log.d("MainActivity", "onStop");
        this.unregisterReceiver(completeReceiver);
        MainActivity.this.stopService(ServiceIntent);
        isPlaying = false;
        super.onDestroy();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
    }

}

2.MusicListFragment.java

package com.example.comfortmusic_1.fragment;


import java.util.Map;

import com.example.comfortmusic_1.MainActivity;
import com.example.comfortmusic_1.R;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AbsListView.LayoutParams;
import android.widget.AdapterView.OnItemClickListener;

public class MusicListFragment extends Fragment {

    private Callbacks mCallbacks;
    public static ListView musicList;//音乐列表
    BaseAdapter musicListAdapter;//音乐列表适配器

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        IntentFilter intentFilter = new IntentFilter();  
        intentFilter.addAction("action.refreshmusiclistFragment");
        this.getActivity().registerReceiver(refreshReceiver, intentFilter);

    }   

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.musiclist_main, container, false);
        musicList = (ListView) rootView.findViewById(R.id.musiclist);
        musicListAdapter = getAdapter();
        musicList.setAdapter(musicListAdapter);
        musicList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,long id) {//播放选中歌曲
                MainActivity.currentMusicPosition = position;
                MainActivity.isPlaying = true;
                MainActivity.MSG = MainActivity.MSG_PLAY;
                mCallbacks.onItemSelected(position);//回调实现Callbacks的MainActivity.onItemSelected(position);

            }           
        });
        musicList.setOnItemLongClickListener(new OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                // TODO Auto-generated method stub
                return false;
            }

        });

        return rootView;
    }


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("activity 必须实现Callbacks接口!");
        }
        mCallbacks = (Callbacks)activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = null;
    }



    public interface Callbacks {
        public void onItemSelected(Integer id); 
    }


    public BaseAdapter getAdapter() {

        BaseAdapter adapter = new BaseAdapter() {

            @Override
            public int getCount() {
                return MainActivity.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 view, ViewGroup parent) {
                Map<String, Object> item = MainActivity.dbMusic.get(position);
                LinearLayout line = new LinearLayout(MusicListFragment.this.getActivity());
                line.setOrientation(LinearLayout.VERTICAL);

                LinearLayout upLayout = new LinearLayout(MusicListFragment.this.getActivity());
                upLayout.setOrientation(LinearLayout.HORIZONTAL);

                ImageView musicTag = new ImageView(MusicListFragment.this.getActivity());
                musicTag.setImageResource(R.drawable.music);
                musicTag.setLayoutParams(new LayoutParams(80,80));


                TextView musicTitle = new TextView(MusicListFragment.this.getActivity());
                TextView musicArtist = new TextView(MusicListFragment.this.getActivity());
                TextView musicDuration = new TextView(MusicListFragment.this.getActivity());

                musicTitle.setText((String)item.get("title"));
                musicTitle.setWidth(MainActivity.screenWidth/2);
                musicTitle.setTextSize(18); 
                musicTitle.setTextColor(Color.MAGENTA);
                musicTitle.setMaxLines(1);

                musicDuration.setText((String)item.get("duration"));
                musicDuration.setWidth(MainActivity.screenWidth/2);
                musicDuration.setGravity(Gravity.RIGHT);
                musicDuration.setTextColor(Color.MAGENTA);
                musicDuration.setPaddingRelative(0, 0, 50, 0);
                musicDuration.setMaxLines(1);

                musicArtist.setText((String)item.get("artist"));
//              musicArtist.setWidth(MainActivity.screenWidth/4);
                musicArtist.setMaxLines(1);
//              musicArtist.setTextColor(Color.argb(50, 255, 100, 0));
                musicArtist.setPaddingRelative(80, 0, 0, 0);    

                upLayout.addView(musicTag);
                upLayout.addView(musicTitle);
                upLayout.addView(musicDuration);
                line.addView(upLayout);
                line.addView(musicArtist);

                return line;
            }

        };
        return adapter;
    }           

        @Override
        public void onDestroy() {
            super.onDestroy();
            this.getActivity().unregisterReceiver(refreshReceiver);
        }

        private BroadcastReceiver refreshReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();  
                if (action.equals("action.refreshmusiclistFragment"))  { 
                    Log.d("MusicListFragment", "receive refresh music list!");
//                  Toast.makeText(MusicListFragment.this.getActivity(), "receive update progress!", 200).show();
                    musicList.setAdapter(getAdapter());
                }               
            }
        };

}

3.MusicService.java

package com.example.comfortmusic_1.service;

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

import com.example.comfortmusic_1.MainActivity;



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

public class MusicService extends Service {

    private MediaPlayer musicPlayer = new MediaPlayer();
    public static int musicPosition;
    private Timer timer;

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "musicservice_onStartCommand",500).show();     
        Log.d("MusicService", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }   

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("MusicService", "_onCreate");
        IntentFilter intentFilter = new IntentFilter();   
        intentFilter.addAction("action.changesong"); 
        registerReceiver(updateReceiver, intentFilter);
        timer = new Timer();
    }

    //根据播放信息准备播放音乐
    private void prepareMusic(Intent intent) {
        Log.d("MusicService", "prepareMusic");
        if (MainActivity.MSG == MainActivity.MSG_PLAY ) {
            play();//从头开始播放一首歌
        } else if (MainActivity.MSG == MainActivity.MSG_PAUSE) {
            pause();//暂停播放当前歌曲
        } else if (MainActivity.MSG == MainActivity.MSG_CONTINUEPLAYING) {
            continuePlaying();//继续播放未完的歌曲
        }   
    }

    //继续播放
    private void continuePlaying() {
        Log.d("MusicService", "continuePlaying");
        musicPlayer.start();
    }
    //从头开始播放一首歌
    private  void play() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (musicPlayer.isPlaying()) {
                    musicPlayer.stop();
                }
                try {
                    musicPosition = 0;
                    musicPlayer.reset();
                    musicPlayer.setDataSource(MainActivity.currentMusicUrl);
                    musicPlayer.prepare();
                    musicPlayer.start();
                    musicPlayer.setOnCompletionListener(new OnCompletionListener() {

                        @Override
                        public void onCompletion(MediaPlayer arg0) {
                            Intent completeIntent = new Intent();
                            completeIntent.setAction("action.nextsong");  
                            sendBroadcast(completeIntent);
                            Log.d("MusicService", "sendBroadcast");
                        }               
                    });     
                } catch (IOException e) {
                    e.printStackTrace();
                    Toast.makeText(MusicService.this, "加载音乐失败,请检查网络链接!",500).show();
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        }).start();

    }

    //暂停播放
    private void pause() {
        Log.d("MusicService", "pause");
        musicPlayer.pause();
        musicPosition = musicPlayer.getCurrentPosition();
        timer.cancel();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (musicPlayer != null) {
            if (musicPlayer.isPlaying()) timer.cancel();
            musicPlayer.stop();
            musicPlayer.release();
        }
        this.unregisterReceiver(updateReceiver);
    }


    private BroadcastReceiver updateReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();  
             if (action.equals("action.changesong")) {
                  prepareMusic(intent);
             }
        }

    };


}

其中NetFragment和DownloadFragment只需继承Fragment即可看到程序运行效果
Android本地及网络音乐播放器源码下载

  • 17
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
1. 创建一个新项目 首先,在Android Studio中创建一个新项目。可以选择任何名称和默认设置,但需要确保应用程序具有网络连接权限。创建完成后,可以开始构建应用程序。 2. 创建音乐播放器界面 在MainActivity.java文件中,使用布局文件创建音乐播放器界面。可以使用LinearLayout或RelativeLayout等布局容器,添加控件元素,例如TextView、ImageView和Button等。 3. 实现本地服务 在Android中,服务是一种后台运行的组件,可以执行长时间运行的任务而不会干扰用户界面。为实现音乐播放器功能,需要创建本地服务。 创建一个名为MusicService.java的新类,并继承Service类。在MusicService类中,可以实现音乐播放器的逻辑,例如播放、暂停、停止和跳转等。 4. 实现播放器控制器 为了控制音乐播放器,需要创建一个控制器类。控制器类应该包含所有需要控制的方法,例如播放、暂停、跳转、获取当前位置等。 5. 实现绑定服务 为了使控制器类能够使用MusicService类,需要实现绑定服务。在MainActivity.java文件中,创建MusicServiceConnection类并继承ServiceConnection类。MusicServiceConnection类将MusicService类与MainActivity类绑定在一起,并允许控制器类访问MusicService类中的所有方法。 6. 实现控制器类 在MainActivity.java文件中,创建MusicController类并实现控制器的逻辑,例如播放、暂停、跳转和获取当前位置等。MusicController类应该使用MusicServiceConnection类和MusicService类中的方法。 7. 在MainActivity类中启动和停止服务 在MainActivity.java文件中,可以使用startService()和stopService()方法启动和停止MusicService类。当用户在应用程序中打开音乐播放器时,使用startService()方法启动MusicService类。当用户退出应用程序时,使用stopService()方法停止MusicService类。 8. 在MainActivity类中绑定和解绑服务 在MainActivity.java文件中,可以使用bindService()和unbindService()方法绑定和解绑MusicService类。当用户需要控制音乐播放器时,使用bindService()方法绑定MusicService类。当用户完成控制时,使用unbindService()方法解绑MusicService类。 9. 测试应用程序 在Android Studio中运行应用程序,并测试音乐播放器功能。可以使用控制器类控制音乐播放器,在应用程序中播放、暂停、跳转和获取当前位置等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值