Android 音乐播放器的开发教程(十二)SQLite的使用及我的最爱歌曲的实现 ----- 小达

SQLite的使用及我的最爱歌曲的实现


       早上好~~~~各位,今天接着昨天的android上数据库SQLite的使用来说说,怎么在昨天的基础上,实现歌曲添加入我的最爱.先上理想的效果图,进入播放界面之后就可以点击爱心添加为最爱歌曲,并放入数据库,在我的最爱栏目也可以看的到,再次点击红心就可以取消我的最爱,丛数据库再拿出来(讲解的话,主要在代码的注释里面):

Android 音乐播放器的开发教程(十二)SQLite的使用及我的最爱歌曲的实现 ----- 小达_第1张图片Android 音乐播放器的开发教程(十二)SQLite的使用及我的最爱歌曲的实现 ----- 小达_第2张图片Android 音乐播放器的开发教程(十二)SQLite的使用及我的最爱歌曲的实现 ----- 小达_第3张图片Android 音乐播放器的开发教程(十二)SQLite的使用及我的最爱歌曲的实现 ----- 小达_第4张图片


       先来实现点击主界面上的我的最爱后切换至我的最爱fragment,一个MyFavoriteFragment.java和一个fragment_favorite_layout.xml,先给出布局文件:




    

        

        


    

    

        
        
    


     下面是MyFavoriteFragment.java的代码,需要注意的是要在MainActivity中implements相应的接口,并且重写对应的函数,还需要在MainFragment中加入相应的点击事件响应, 切换至MyFavoriteFragment, 在PlayFragment中显示那颗爱心的状态,后面也一并给出部分代码:

package com.example.dada.myapplication;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
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;

public class MyFavoriteFragment extends Fragment {


    private OnFragmentInteractionListener mListener;

    public static MyFavoriteFragment newInstance() {
        MyFavoriteFragment fragment = new MyFavoriteFragment();
        Bundle args = new Bundle();
        fragment.setArguments(args);
        return fragment;
    }

    public MyFavoriteFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_my_favorite, container, false);

        initialize(rootView);           //自定义初始化函数

        return rootView;
    }

    private void initialize(View rootView){

        rootView.findViewById(R.id.favorite_fragment_to_main_fragment)                               //回到主Fragment
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        MainFragment mainFragment = new MainFragment();
                        FragmentManager fragmentManager = getFragmentManager();
                        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                        fragmentTransaction.replace(R.id.fragment_layout, mainFragment);
                        fragmentTransaction.addToBackStack(null);
                        fragmentTransaction.commit();
                    }
                });

        ((ListView) rootView.findViewById(R.id.favorite_music_list)).setOnItemClickListener(          //我的最爱列表点击事件
                new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView parent, View view, int position, long id) {
                        mListener.onFavoriteFragmentInteraction(AppConstant.PlayerMsg.LIST_CLICK,position);
                    }
                }
        );

        /*
        更新列表的adapter
        给列表设置一个新的adapter
         */
        MainActivity.myDataBase.Update_adapter();          
        MainActivity.myDataBase.SetAdapter((ListView)rootView.findViewById(R.id.favorite_music_list));

    }

    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 {
        // TODO: Update argument type and name
        public void onFavoriteFragmentInteraction(int msg,int position);
    }

}

PlayFragment的界面上有颗爱心,根据当前歌曲是否为喜爱的歌曲来显示状态,直接放在PlayFragment.java的onCreateView方法里面即可:

if(MainActivity.isFavorite){
            (v.findViewById(R.id.my_favorite_button)).setBackgroundResource(R.drawable.img_favourite_selected);
        }
        else{
            (v.findViewById(R.id.my_favorite_button)).setBackgroundResource(R.drawable.img_favourite_normal);
        }


        (v.findViewById(R.id.my_favorite_button))
                .setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(MainActivity.isFavorite){
                            Toast.makeText(getActivity().getApplicationContext(),"已经取消我的最爱",Toast.LENGTH_SHORT).show();
                            (v.findViewById(R.id.my_favorite_button)).setBackgroundResource(R.drawable.img_favourite_normal);
                            mListener.onPlayFragmentInteraction(AppConstant.PlayerMsg.DELETE_FROM_FAVORITE);
                        }
                        else{
                            Toast.makeText(getActivity().getApplicationContext(),"已经加入我的最爱",Toast.LENGTH_SHORT).show();
                            (v.findViewById(R.id.my_favorite_button)).setBackgroundResource(R.drawable.img_favourite_selected);
                            mListener.onPlayFragmentInteraction(AppConstant.PlayerMsg.ADD_TO_FAVORITE);
                        }
                    }
                });


  在MainFragment.java中添加点击事件的相应,代码添加进onCreateView方法里:

rootView.findViewById(R.id.myFavoriteButton).                                              //切换至我的最爱Fragment
                setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                MyFavoriteFragment myFavoriteFragment = new MyFavoriteFragment();
                FragmentManager fragmentManager = getFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();               
                fragmentTransaction.replace(R.id.fragment_layout, myFavoriteFragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
            }
        });


MainActivity中的部分代码如下(这些代码分布在不同的地方,我会详细的说明的):

    public static boolean isFavorite = false;                        //声明一个静态的boolean变量,用来记录当前的播放歌曲是否为我的最爱


    public void onPlayFragmentInteraction(int message){                     //PlayFragment的回调函数

        Mp3Info mp3_Info = mp3Infos.get(music_position);                   //得到当前歌曲类(自定义类)的实例

        switch (message){
            case AppConstant.PlayerMsg.DISMISS_CLICK:                        //回退到MainFragmnet
                myMusicFragment = new MyMusicFragment();
                FragmentManager fragmentManager = getFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();              
                fragmentTransaction.replace(R.id.fragment_layout, mainFragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
                break;

            case AppConstant.PlayerMsg.ADD_TO_FAVORITE:               //将当前歌曲添加到我的最爱列表里
                isFavorite = true;
                mp3_Info.setFavorite(isFavorite); 

                myDataBase.AddData(                                                         //添加入数据库的表格中
                        MyDataBase.TABLE_NAME_FAVORITE,
                        (int)mp3_Info.getId(),
                        mp3_Info.getTitle(),
                        mp3_Info.getArtist(),
                        mp3_Info.getDuration(),
                        mp3_Info.getUrl(),
                        (int)mp3_Info.getAlbum_id()
                );
                break;


            case AppConstant.PlayerMsg.DELETE_FROM_FAVORITE:                     //从数据库对应表格里面删除
                isFavorite = false;
                mp3Infos.get(music_position).setFavorite(isFavorite);
                myDataBase.DeleteData(
                        MyDataBase.TABLE_NAME_FAVORITE,
                        (int)mp3_Info.getId());

                break;

        }
    }

    public void onFavoriteFragmentInteraction(int msg,int position){                  //点击我的最爱列表里的歌曲实现播放
      if(msg == AppConstant.PlayerMsg.LIST_CLICK){
            if (mp3Infos != null) {
                isPause = false;
                initService(position);
            }
        }
    }


isFavorite = mp3_Info.getFavorite();                      //这句话加入到changeMusic函数里面去,因为每切一首歌,都要重置activity中的这个变量,以保证该变量指示的是当前播放歌曲,可以同步那个红心的显示


           上面有两个涉及到数据库操作的函数,下面就给出MyDataBase.java的全部代码,红色是在昨天的基础上添加的新的部分,代码有点多,大家选重点的看哈:

package com.example.dada.myapplication;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.widget.Adapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import java.util.ArrayList;
import java.util.List;

public class MyDataBase {

    private int dataCount;
    private static Context context;
    public static ListAdapter adapter;

    /*
    下面一大串是需要用到的常量
    直接弄成了静态final的
     */

    public final static String DATABASE_NAME   = "MyMusicDataBase";
    public final static String TABLE_NAME      = "RecentlyPlayTable1";
    public final static String TABLE_NAME_FAVORITE = "FavoriteTable";
    public final static String TABLE_NAME_PLAYLIST = "PlayListTable";
    public final static String TABLE_MUSIC_ID  = "_id";
    public final static String TABLE_MUSIC_TITLE = "music_title";
    public final static String TABLE_ARTIST = "artist";
    public final static String TABLE_DURATION = "druation";
    public final static String TABLE_MUSIC_URL = "music_url";
    public final static String TABLE_ALBUM_ID = "album_id";
    public final static String TABLE_CURRENT_TIME = "current_time";
    public final static String TABLE_LIST_NAME = "list_name";

    /*
    创建数据库的语句
    写好了直接可以执行的
     */
    public final static String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS " +
            TABLE_NAME + " (" + TABLE_MUSIC_ID + " INTEGER PRIMARY KEY,"
            + TABLE_MUSIC_TITLE + " STRING," + TABLE_ARTIST + " STRING,"
            + TABLE_DURATION + " LONG," + TABLE_MUSIC_URL + " STRING,"
            + TABLE_ALBUM_ID + " INTEGER," + TABLE_CURRENT_TIME + " LONG)";

    public final static String CREATE_FAVORITE_TABLE =  "CREATE TABLE IF NOT EXISTS " +
            TABLE_NAME_FAVORITE + " (" + TABLE_MUSIC_ID + " INTEGER PRIMARY KEY,"
            + TABLE_MUSIC_TITLE + " STRING," + TABLE_ARTIST + " STRING,"
            + TABLE_DURATION + " LONG," + TABLE_MUSIC_URL + " STRING,"
            + TABLE_ALBUM_ID + " INTEGER," + TABLE_CURRENT_TIME + " LONG)";

    /*
    直接持有一个SQLiteDatabase的实例
    后面就直接对这个实例进行操作
     */
    public static SQLiteDatabase recentPlaySQLiteDatabase = null;                //最近播放的数据库

    public MyDataBase(Context context,ListView listView){
        this.context = context;
        this.dataCount = 0;
        this.adapter = null;
    }

    /*
    自定义的创建数据库函数
    在activity的onCreate()里面调用
     */
    public static void CreateDataBase(){
        recentPlaySQLiteDatabase = context.openOrCreateDatabase(DATABASE_NAME,Context.MODE_PRIVATE,null);
        recentPlaySQLiteDatabase.execSQL(CREATE_TABLE);
        recentPlaySQLiteDatabase.execSQL(CREATE_FAVORITE_TABLE);

    }

    /*
    向数据库的表格中添加数据
    这里用到的是添加的其中一种方法
    利用ContentValues将数据封装好了之后再添加
    另外一种是直接用SQL语句向表格里面插入
     */
    public static void AddData(String table_name,int music_id,String music_title,
                               String music_artist,long music_duration,
                               String music_url,int album_id,long current_time){
        ContentValues cv = new ContentValues();
        cv.put(TABLE_MUSIC_ID,music_id);
        cv.put(TABLE_MUSIC_TITLE,music_title);
        cv.put(TABLE_ARTIST,music_artist);
        cv.put(TABLE_DURATION,MusicListAdapter.formatTime(music_duration));
        cv.put(TABLE_MUSIC_URL,music_url);
        cv.put(TABLE_ALBUM_ID,album_id);
        cv.put(TABLE_CURRENT_TIME,current_time);
        recentPlaySQLiteDatabase.insert(table_name,null,cv);
    }

/*
这部分代码和上面那个函数功能是差不多的
注释就看上面的
*/

    public static void AddData(String table_name,int music_id,String music_title,
                               String music_artist,long music_duration,
                               String music_url,int album_id){
        ContentValues cv = new ContentValues();
        cv.put(TABLE_MUSIC_ID,music_id);
        cv.put(TABLE_MUSIC_TITLE,music_title);
        cv.put(TABLE_ARTIST,music_artist);
        cv.put(TABLE_DURATION,MusicListAdapter.formatTime(music_duration));
        cv.put(TABLE_MUSIC_URL,music_url);
        cv.put(TABLE_ALBUM_ID,album_id);

        recentPlaySQLiteDatabase.insert(table_name,null,cv);
    }

    /*
    由于在最近播放里面可能会存在一首歌曲播放两次
    所以在AddData之前需要先查询是否存在歌曲
    存在的话直接UpdateData()更新歌曲播放的时间
    不存在就插入数据
     */
    public static void UpdateData(String table_name,int music_id,long current_time){

        String str = "UPDATE " + table_name + " SET " + TABLE_CURRENT_TIME + "=" + current_time + " WHERE "
                + TABLE_MUSIC_ID + "=" + music_id;

        recentPlaySQLiteDatabase.execSQL(str);
    }

    public static boolean IsExistData(String table_name,int music_id){

        String str = "SELECT * FROM " + table_name + " WHERE " + TABLE_MUSIC_ID + "=" +music_id;

        if(recentPlaySQLiteDatabase.rawQuery(str,null).getCount() == 0)
            return false;
        else
            return true;
    }

    /*
    更新列表的adapter
    可以更新列表的显示
    里面用到了Cursor,执行query后,返回了一个Cursor对象
    通过解析这个对象来获取需要的信息

     */
    public static void UpdateAdapter(){
        try{
            Cursor cur = recentPlaySQLiteDatabase.
                    query(TABLE_NAME,new String[] {
                            TABLE_MUSIC_ID,
                            TABLE_MUSIC_TITLE,
                            TABLE_ARTIST,
                            TABLE_DURATION,
                            TABLE_MUSIC_URL,
                            TABLE_ALBUM_ID}
                            ,null,null,null,null,null);

            /*
            这里的adapter用到了simpleCursorAdapter
            关于SimpleCursorAdapter的使用需要注意的是,在我们的结果集中必须要包含一个“_id”的列
            小达先开始在创建表格的时候,根本没有_id这一列,经常报错
            卡了好久好久的,对于这个问题有三种解决办法:
            第一,建表时根据规范去做
            第二,查询时用别名,例如:SELECT id AS _id FROM person
            第三,在CursorWrapper里做文章,在代码后面讲解下.
             */

            if(cur !=null && cur.getCount() >= 0){
                adapter = new SimpleCursorAdapter(
                        context,
                        R.layout.recently_play_item_layout,
                        cur,
                        new String[] {
                                TABLE_MUSIC_TITLE,
                                TABLE_ARTIST,
                                TABLE_DURATION},
                        new int[] {R.id.recently_play_music_title,
                                R.id.recently_play_music_Artist,
                                R.id.recently_play_music_duration}
                );
            }

            MainActivity.mp3Infos.clear();
            while(cur.moveToNext()){
                Mp3Info mp3Info = new Mp3Info();
                mp3Info.setUrl(cur.getString(cur.getColumnIndex(TABLE_MUSIC_URL)));
                //mp3Info.setAlbum_id(cur.getLong(cur.getColumnIndex(TABLE_ALBUM_ID)));
                mp3Info.setArtist(cur.getString(cur.getColumnIndex(TABLE_ARTIST)));
                String time = cur.getString(cur.getColumnIndex(TABLE_DURATION));
                long Time = changeTime(time);
                mp3Info.setDuration(Time);
                mp3Info.setId(cur.getInt(cur.getColumnIndex(TABLE_MUSIC_ID)));
                mp3Info.setTitle(cur.getString(cur.getColumnIndex(TABLE_MUSIC_TITLE)));
                MainActivity.mp3Infos.add(mp3Info);
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
    
    /*
    从我的最爱列表里面删除该歌曲
    也就是取消我的最爱收藏
    直接执行数据库语句DELETE
     */

    public static void DeleteData(String table_name,int music_id){

        String str = "DELETE FROM " + MyDataBase.TABLE_NAME_FAVORITE +
                " WHERE " + MyDataBase.TABLE_MUSIC_ID + "=" +music_id;

        recentPlaySQLiteDatabase.execSQL(str);
    }

    public static void SetAdapter(ListView listView){

        listView.setAdapter(adapter);
    }

    /*
    更新我的最爱列表的adapter
     */
    public static void Update_adapter(){
        try{
            Cursor cur = recentPlaySQLiteDatabase.
                    query(TABLE_NAME_FAVORITE,new String[] {
                            TABLE_MUSIC_ID,
                            TABLE_MUSIC_TITLE,
                            TABLE_ARTIST,
                            TABLE_DURATION,
                            TABLE_MUSIC_URL,
                            TABLE_ALBUM_ID}
                            ,null,null,null,null,null);

            if(cur !=null && cur.getCount() >= 0){
                adapter = new SimpleCursorAdapter(
                        context,
                        R.layout.recently_play_item_layout,
                        cur,
                        new String[] {
                                TABLE_MUSIC_TITLE,
                                TABLE_ARTIST,
                                TABLE_DURATION},
                        new int[] {R.id.recently_play_music_title,
                                R.id.recently_play_music_Artist,
                                R.id.recently_play_music_duration}
                );
            }

            /*
            这里是将Activity中的List清空,
            将我的最爱列表里的歌曲全部放入里面
            为我的最爱列表点击做准备
             */
            MainActivity.mp3Infos.clear();
            while(cur.moveToNext()){
                Mp3Info mp3Info = new Mp3Info();
                mp3Info.setUrl(cur.getString(cur.getColumnIndex(TABLE_MUSIC_URL)));
                mp3Info.setAlbum_id(cur.getLong(cur.getColumnIndex(TABLE_ALBUM_ID)));
                mp3Info.setArtist(cur.getString(cur.getColumnIndex(TABLE_ARTIST)));
                String time = cur.getString(cur.getColumnIndex(TABLE_DURATION));
                long Time = changeTime(time);
                mp3Info.setDuration(Time);
                mp3Info.setId(cur.getInt(cur.getColumnIndex(TABLE_MUSIC_ID)));
                mp3Info.setTitle(cur.getString(cur.getColumnIndex(TABLE_MUSIC_TITLE)));
                MainActivity.mp3Infos.add(mp3Info);
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
    private static long changeTime(String time){                     //将歌曲的时间转换为分秒的制度
        long Time = 0;
        String[] str = time.split(":");
        Time = (Integer.valueOf(str[0])*60 + Integer.valueOf(str[1]))*1000;
        return Time;
    }
}


        上面的一大批代码加注释,现在的播放器就能实现我们在最开始的理想功能咯,各位上手试试把 ,代码搞得有点乱,可能会有什么地方漏掉了一点东西,如果有问题直接给我留言,我会尽快改掉的~~~.


         其实到这里,整个播放器的教程也就做完了,分了十二期博客将这个东西讲完了,刚开始写的时候感觉还有好多好多东西要弄上去,结果自己一点点的往上写,慢慢的播放器原型就出来了,感觉自己也把整个开发的流程复习了一变,好多知识点又有了新的认识.

         先没感觉写博客的好处,真的投入到其中了才会享受这个过程,理清自己思路的一个过程,个人很推荐大家都将自己的经验或者经历同大家分享,双利的好处只有经历过的人才会懂,身为程序员的我们更应该如此.好咯,不废话了.整个专栏就到这里结束了,小达以后再有什么好的东西,一定会拿上来和大家分享的,.

          还是栏目刚开始的那句话,不能怂,就是干,怂就输一半儿~~~~~~,大家一起加油把,嘿嘿.

你可能感兴趣的:(Android 音乐播放器的开发教程(十二)SQLite的使用及我的最爱歌曲的实现 ----- 小达)