自己动手实现音乐播放器app

本文详细介绍了如何实现一个音乐播放器APP,包括MainActivity的实现,使用TabHost绑定标签、图标和内容,以及在切换Fragment时遇到的问题和解决方案。在退出前通过重写onDestroy方法保存playlist数据。此外,探讨了全局变量musicList和playList在单例模式下的应用,以及如何避免空指针异常。还涉及到MusicService和MusicPlayActivity的实现。最后,讲解了ContentProvider的作用,它是Android中不同应用间数据共享的标准API,以及如何通过ContentResolver进行数据操作。
摘要由CSDN通过智能技术生成

MainActivity实现:
1.调用TabHost绑定不同的tags,图标,和content。

mTabHost = (TabHost) findViewById(R.id.mTabHost);
        mTabHost.setup();
        for (int i = 0; i < titles.length; i++) {//循环添加选项卡
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(tags[i]);//创建一个选项,并指定其标记
            View view = getLayoutInflater().inflate(R.layout.tab, null);
            TextView titleView = (TextView) view.findViewById(R.id.title);
            ImageView iconView = (ImageView) view.findViewById(R.id.icon);
            titleView.setText(titles[i]);//设置标题
            iconView.setImageResource(icons[i]);//设置图标
            tabSpec.setIndicator(view);//为选项设置标题和图标
            tabSpec.setContent(R.id.realContent);//为每个选项设置内容
            mTabHost.addTab(tabSpec);//将选项添加到选项卡中
        }
        mTabHost.setOnTabChangedListener(new MyTabChangedListener());//添加选项改变事件处理
        mTabHost.setCurrentTab(1);//默认显示第二个

2.切换至不同的按钮时,用新创建的fragment替换之前设置的content,但是我始终没有解决切换fragment后,再回到原fragment状态依然不改变。我初步认定是切换不同tab时,系统会强制将当前创建的fragment销毁。
点击不同tab,显示不同fragemnt

public void onTabChanged(String tabTag){
fragmentTransaction = getFragemntManager().begingTransaction();
if(tabTag.equalsIgnoreCase("artist")){
  //切换到艺术家列表
fragmentTransaction.replace(R.id.realContent,new ArtistFragemnt());
}
fragmentTracsaction.commit();//提交事务
}

3.重写ondestroy方法,在退出前保存playlist中的数据

@Override
    protected void onDestroy() {
  //关闭的时候将播放列表中的数据保存到数据库
        mDatabase.execSQL("delete from music_tb");//删除已有的所有数据
        for (int i = 0; i < Constants.playlist.size(); i++) {
  //循环遍历播放列表中的音乐
            Music music = Constants.playlist.get(i);
            mDatabase.execSQL("insert into music_tb(title,artist,album,album_id,time,url)values(?,?,?,?,?,?)", new String[]{music.getTitle(), music.getSinger(), music.getAlbum(), music.getAlbum_id() + "", music.getTime() + "", music.getUrl()});
            //将音乐信息保存到数据库
        }
        super.onDestroy();
    }

定义一些常量

package com.example.zengqi.musicplayer;

import android.net.Uri;

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


public class Constants {
   
    public static List<Music> musicList = new ArrayList<>();//所有音乐的集合
    public static List<Music> playlist = new ArrayList<>();//音乐播放列表
    public static final String CONTROL_ACTION = "com.example.zengqi.control";//控制音乐播放动作,即播放或暂停
    public static final String SEEKBAR_ACTION = "com.example.zengqi.seekbar";//音乐进度发送变化动作
    public static final String COMPLETE_ACTION = "com.example.zengqi.complete";//音乐播放结束动作
    public static final String UPDATE_ACTION = "com.example.zengqi.update";//更新进度条
    public static final String UPDATE_STYLE = "com.example.zengqi.style";//更新播放形式

    public static final Uri ALBUM_URI = Uri.parse("content://media/external/audio/albumart");
    public static final String LIST_LOOP = "列表循环";
    public static final String SINGLE_LOOP = "单曲循环";
    public static final String OVER_FINISH = "结束后暂停";
    public static final String RANDOM_PLAY = "随机播放";

    public static final int NEW = 6;//开始一首新的音乐
    public static final int PLAY = 1;//播放
    public static final int PAUSE = 2;//暂停
    public static final int ALL_MUSIC = 0x11;//播放所有的音乐
    public static final int PLAY_LIST_MUSIC = 0x12;//播放播放列表中的音乐

}

重点是这里使用的musicList和playList,他们是全局状态下的变量,单例模式,用于在不同fragment间通信,所有fragment将值存入其中,同时也从中取值。

public static List<Music> getDataFromDB(SQLiteDatabase db) {
        //数据库中未存入size,name的信息
        //从数据库中获取播放列表的内容

        List<Music> musics = new ArrayList<>();
        Cursor cursor = db.rawQuery("select * from music_tb", null);
        if (cursor == null || cursor.getCount() == 0) {
            return null;
        }
        while (cursor.moveToNext()) {
            Music music = new Music();
            music.setTitle(cursor.getString(cursor.getColumnIndex("title")));
            music.setSinger(cursor.getString(cursor.getColumnIndex("artist")));
            music.setAlbum(cursor.getString(cursor.getColumnIndex("album")));
            music.setAlbum_id(cursor.getInt(cursor.getColumnIndex("album_id")));
            music.setUrl(cursor.getString(cursor.getColumnIndex("url")));
            music.setTime(cursor.getInt(cursor.getColumnIndex("time")));
            musics.add(music);
        }
        return musics;
    }

这里注意在每次调用该函数时,都应该检察其值是否为null,例如下面:

if(MusicUtils.getDataFromDB(mDatabase)==null){
            Constants.playlist = new ArrayList<>();
        }else{
  //if与else语法!!!小心!!!
            Constants.playlist = MusicUtils.getDataFromDB(mDatabase);//初始化播放列表
        }

这样playlist就被合理的初始化了,这样接下来就可以安心调用其方法了,而不会空指针异常。这里需要注意,if与else,我刚开始不够心细,只写了if,导致在从数据库中读取不到playlist的情况下,playlist永远不能够被初始化!

关于MusicService:

package com.example.zengqi.musicplayer;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.Notification.Builder;
<
创建一个基于Android Studio的音乐播放器应用通常涉及多个步骤和关键组件。以下是一个简要概述: 1. **项目设置**: - 在Android Studio中,选择"Start a new Android Studio project",选择"Empty Activity"模板,命名你的项目并选择目标Android API。 2. **界面设计**: - 使用XML布局文件(如activity_main.xml)设计主界面,包括一个RecyclerView显示歌曲列表、一个歌词滚动视图、以及播放/暂停按钮等。 3. **数据结构**: - 创建一个Song类,包含属性如title, artist, URI等,用于存储歌曲信息。 4. **音乐播放库**: - 选择一个音乐播放库,如ExoPlayer或Android内置的MediaPlayer。ExoPlayer更强大且易于集成。 5. **播放功能实现**: - 设置播放服务(Service)并实现播放、暂停、上一曲、下一曲、音量控制等功能。 - 当用户点击列表中的歌曲时,从网络或本地加载Song实例,并调用播放方法。 6. **歌曲列表管理**: - 使用SQLite数据库或网络API获取歌曲列表,并将其添加到RecyclerView中。 7. **歌词同步**: - 可能需要使用第三方库或API来获取歌词,然后与音乐播放同步显示。 8. **用户界面状态管理**: - 使用ViewModel或Repository模式来管理UI与数据之间的交互,保持状态的统一。 9. **资源管理**: - 确保处理好音频文件的加载、缓存和解码,防止内存泄漏。 10. **错误处理与调试**: - 添加适当的错误处理代码,如网络请求失败、文件读取错误等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值