Android 音乐播放器的开发教程(六)service的运用及音乐列表点击播放 ----- 小达

来源:互联网 发布:jsp个人博客系统源码 编辑:程序博客网 时间:2024/05/16 06:12

service的运用及音乐列表点击播放



         按照前几篇博客的步骤,应该能看到自己手机里的音乐列表了,但是现在还只能看,不能点,还需要再给ListView添加点击事件的监听,接着启动一个Service来播放音乐,service是android四大组件之一,在官方的文档上是这样解释的:


A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.

        也就是说,Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。


        我们先来给列表注册监听器,由于列表是显示在MyMusicFragment上面的,故注册监听器也应该在MyMusicFragment.java这个文件里面注册了,下面给出代码,红色部分为改动的地方:

package com.example.dada.myapplication;import android.app.Activity;import android.net.Uri;import android.os.Bundle;import android.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.ListView;import java.util.List;public class MyMusicFragment extends Fragment {    private FindSongs finder;                                              //查找歌曲的类的实例    private Activity MyActivity;    private List<Mp3Info> mp3Infos;    private MusicListAdapter musicListAdapter;    private OnFragmentInteractionListener mListener;
<span style="color:#222222;">    public static MyMusicFragment newInstance() {        MyMusicFragment fragment = new MyMusicFragment();        Bundle args = new Bundle();        fragment.setArguments(args);        return fragment;    }    public MyMusicFragment() {        // Required empty public constructor    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        MyActivity = getActivity();        finder = new FindSongs();        mp3Infos = finder.getMp3Infos(MyActivity.getContentResolver());        musicListAdapter = new MusicListAdapter(MyActivity.getApplicationContext(),mp3Infos);    }    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,                             Bundle savedInstanceState) {        finder = new FindSongs();        View rootView = inflater.inflate(R.layout.fragment_my_music, container, false);        /*        切换至我的音乐Fragment按钮监器        调用了在activity中已经重写了的方法onMyMusicFragmentInteraction         */        rootView.findViewById(R.id.top_layout_right_ImageView).                setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mListener.onMyMusicFragmentInteraction(AppConstant.PlayerMsg.BACK_TO_MAIN_FRAGMENT);            }        });        </span><span style="color:#ff0000;">/*        音乐列表的点击监听器        点击后调用的方法,是一个回调方法,用来告诉activity        列表里面的哪个项被点击了        让activity做出反应         */        ((ListView)rootView.findViewById(R.id.music_list)).                setOnItemClickListener(new AdapterView.OnItemClickListener() {                    @Override                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                        if (mp3Infos != null) {                            mListener.onMyMusicFragmentInteraction(AppConstant.PlayerMsg.LIST_CLICK, position);                        }                    }                });</span><span style="color:#222222;">        finder.setListAdpter(MyActivity.getApplicationContext(),                mp3Infos,(ListView)rootView.findViewById(R.id.music_list));        return rootView;    }    // TODO: Rename method, update argument and hook method into UI event    public void onButtonPressed() {        if (mListener != null) {        }    }    @Override    public void onAttach(Activity activity) {        super.onAttach(activity);        try {            mListener = (OnFragmentInteractionListener) activity;        } catch (ClassCastException e) {            throw new ClassCastException(activity.toString()                    + " must implement OnFragmentInteractionListener");        }    }    @Override    public void onDetach() {        super.onDetach();        mListener = null;    }    public interface OnFragmentInteractionListener {        public void onMyMusicFragmentInteraction(int msg);       </span><span style="color:#ff0000;"> public void onMyMusicFragmentInteraction(int msg,int position);      //这个方法要在MainActivity中再次重写一遍</span><span style="color:#222222;">    }}</span>



         上面的监听器注册完毕之后,就换到MainActivity.java中去对点击时间做出处理,启动一个service.我们需要先在MainActivity中写一个初始化service的方法,MainActivity代码如下,红色部分为修改的部分:

package com.example.dada.myapplication;import android.app.FragmentManager;import android.app.FragmentTransaction;import android.content.Intent;import android.net.Uri;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.widget.ImageButton;import java.util.List;public class MainActivity extends ActionBarActivity        implements MainFragment.OnFragmentInteractionListener,                   MyMusicFragment.OnFragmentInteractionListener{    <span style="color:#ff0000;">private boolean isPause;                                               //记录当前播放器的状态</span>    private FragmentManager fragmentManager;    private FragmentTransaction fragmentTransaction;    private MyMusicFragment myMusicFragment;    private MainFragment mainFragment;    <span style="color:#ff0000;">private FindSongs finder;                                              //查找歌曲的类    public static List<Mp3Info> mp3Infos;                                  //歌曲列表    public static int music_position;                                      //音乐的位置    private ImageButton play_button;                                       //播放按钮控件</span>    /*    这个方法是activity和fragment通信的一种方法    在MainFragment中调用这个方法,可以在activity中做出相应的反应     */    public void onMainFragmentInteraction(int msg){        /*        对其中的参数msg做出判断,如果为CHANGE_TO_MY_MUSIC_FRAGMENT        则执行跳转         */        if(msg == AppConstant.PlayerMsg.CHANGE_TO_MY_MUSIC_FRAGMENT){            /*            在这里并没有直接切换Fragment            而是调用了activity实现MyMusicFragment的那个接口            对后面的开发能带来一点便利之处             */            onMyMusicFragmentInteraction(AppConstant.PlayerMsg.CHANGE_TO_MY_MUSIC_FRAGMENT);        }    }    public void onMyMusicFragmentInteraction(int msg){        myMusicFragment = new MyMusicFragment();       //创建了MyMusicFragment的实例        FragmentManager fragmentManager = getFragmentManager();   //得到FragmentManager        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); //得到fragmentTransaction        if(msg == AppConstant.PlayerMsg.CHANGE_TO_MY_MUSIC_FRAGMENT){            fragmentTransaction.replace(R.id.fragment_layout, myMusicFragment);
            fragmentTransaction.addToBackStack(null);        //这句话是将被替换的MainFragment加入到一个专门存放fragment的栈中,在回退的时候显示上一个Fragment            fragmentTransaction.commit();        }        if(msg == AppConstant.PlayerMsg.BACK_TO_MAIN_FRAGMENT){            fragmentTransaction.replace(R.id.fragment_layout, mainFragment);            fragmentTransaction.addToBackStack(null);            fragmentTransaction.commit();        }    }    <span style="color:#ff0000;">public void onMyMusicFragmentInteraction(int msg,int position){        if(msg == AppConstant.PlayerMsg.LIST_CLICK){            if (mp3Infos != null) {                isPause = false;                initService(position);            }        }    }</span>    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        music_position = 0;        finder = new FindSongs();        mp3Infos = finder.getMp3Infos(getContentResolver());        play_button = (ImageButton)findViewById(R.id.play_button);        mainFragment = new MainFragment();           //创建了刚才定义的MainFragment实例        fragmentManager = getFragmentManager();      //得到FragmentManager        fragmentTransaction = fragmentManager.beginTransaction();   //得到fragmentTransaction,用于管理fragment的切换        fragmentTransaction.replace(R.id.fragment_layout, mainFragment).commit();  //将MainActivity里的布局模块fragment_layout替换为mainFragment    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.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();        //noinspection SimplifiableIfStatement        if (id == R.id.action_settings) {            return true;        }        return super.onOptionsItemSelected(item);    }    <span style="color:#ff0000;">private void initService(int position) {        music_position = position;        Mp3Info mp3Info = mp3Infos.get(position);        /*        这里新建了一个Intent        里面存放各种即将传给Service的数据        要启动自定义PlayerService类        还需要在AndroidManifest中加入如下代码        <service            android:name="com.example.dada.myapplication.PlayerService"            android:exported="false"            >        </service>         */        Intent intent = new Intent("com.example.communication.MSG_ACTION");        play_button.setImageResource(R.drawable.pause_photo);        intent.putExtra("url", mp3Info.getUrl());        intent.putExtra("title", mp3Info.getTitle());        intent.putExtra("artist", mp3Info.getArtist());        intent.putExtra("album", mp3Info.getAlbum());        intent.putExtra("album_id", mp3Info.getAlbum_id());        intent.putExtra("MSG", AppConstant.PlayerMsg.PLAY_MSG);        intent.setClass(MainActivity.this, PlayerService.class);        startService(intent);    }</span>}


        上面的startService(intent)是启动service的一种方法,将intent传给新启动的PlayerService,接下来就是自定义的一个PlayerService类,里面对传进来的intent进行各种判断和处理.新建一个java类,名为PlayerService.java,代码如下:

package com.example.dada.myapplication;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;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.os.Handler;import android.os.IBinder;import android.os.Looper;import android.os.Message;import android.view.animation.AnimationUtils;import android.widget.RemoteViews;import java.io.IOException;import java.util.ArrayList;import java.util.List;public class PlayerService extends Service implements AppConstant {    private int current_position;    private String musicPath;    private String music_artist;    private String music_title;    private String notification_msg;    @Override    public IBinder onBind(Intent intent) {        return null;    }
/*
onStartCommand()方法就是刚启动service时调用的一个方法
里面第一个参数intent就是在activity中的那个intent
因此里面包含着被点击的歌曲相关信息
*/    public int onStartCommand(Intent intent, int flags, int startId) {
    public static MediaPlayer mediaPlayer = new MediaPlayer();                        //MediaPlayer是android中自带的一个播放器类,直接实例化后使用即可
        try {            int msg = intent.getIntExtra("MSG", 0);            musicPath = intent.getStringExtra("url");   //从intent中拿出歌曲的路径            if (msg == AppConstant.PlayerMsg.PLAY_MSG) {                playMusic(0);            }        } catch (Exception e) {            e.printStackTrace();        }        return 0;    }    private void playMusic(int position) {        try {            mediaPlayer.reset();            mediaPlayer.setDataSource(musicPath);            mediaPlayer.prepare();            mediaPlayer.setOnPreparedListener(new MyPreparedListener(position));        } catch (IOException e) {            e.printStackTrace();        }    }    private class MyPreparedListener implements MediaPlayer.OnPreparedListener {        private int position;        public MyPreparedListener(int position) {            this.position = position;        }        public void onPrepared(MediaPlayer mp) {            if (position > 0)                mediaPlayer.seekTo(position);            mediaPlayer.start();        }    }    private void stopMusic() {        if (mediaPlayer != null) {            mediaPlayer.pause();        }    }    public void onDestory() {        if (mediaPlayer != null) {            mediaPlayer.stop();            mediaPlayer.release();        }    }}

        上面的函数命名也都很简单,相信大家能够看懂,如果有什么问题,直接给我留言把,我会解答的哈.......2333333


        做到了这一步,现在的播放器就可以点击并且播放歌曲了,点什么唱什么有木有大笑,但是还是觉得怪怪的对不对,尴尬,因为还不能暂停和切歌,不要担心,下一篇的博客中,将继续介绍如何把按钮的监听事件给加上去,到时候播放器的功能就差不多咯.今天就说这么多了,88






2 0
原创粉丝点击