Android开发之第一个小项目--我的MP3播放器之主界面的实现(二)
来源:互联网 发布:江门美工家具定制 编辑:程序博客网 时间:2024/05/17 22:34
嗯 先上两张图~~
这里两张图片,第一张是列表界面,也是主界面,能显示歌曲界面个下面的播放栏,播放栏点击能进入第二个界面,也能够控制歌曲的播放个暂停。
第二个界面是播放界面,这个界面的解析下一篇说道,这里先列出这里是为了让你们理解这两个界面的关系,好看注释时别弄混了。
其实我还是想实现歌曲分组和专辑分组的,可是到了后面,我发现太多代码写在这个主界面了,不好修改。当时也没什么时间,也就没改了,不过这样看上去还不错。material design的效果看上去还不错。
就是这么多了,我把对代码的解析全写在注释里了,一来,我方便些,二来你们也方便看,如果有什么问题,可以留言给我。
/** * AppControl.JUDGE_DESTORY_ONCREATE 这个有时候会失灵的问题还是没解决 * author:verzqli */public class MainActivity extends AppCompatActivity implements View.OnClickListener, PlatformActionListener { private Button mainPlaySong; //主页的播放/暂停按键 private ImageView imSongPlaying; //下面正在播放的歌曲图片 private List<Song> songList; private ListView songListView; //歌曲列表显示 private SongListAdapter songListAdapter; //歌曲列表适配器 private Intent intent; //跳转activity private MainReceiver mainReceiver; //列表广播接收器 private int songListPosition = 0; //选择音乐位置 private int currentTime; //当前播放时间 private long duration; //当前播放歌曲长度 private LinearLayout linMainButtom; //列表下正在播放 private boolean isPlayingBtn; //判断开始音乐按键 private ContentValues values; //存入数据库的歌曲状态 private Toolbar toolbar; private TextView songTitlePlay; private TextView songTitleArt; private SongBitmapThread songBitmapThread; private NotificationManager notificationManager; private RemoteViews contentView; private Boolean isRealDestroy; //更新主页面下面按键状态的变化(即后面如果按了暂停,前面列表这里的图标会改变) public static final String SONG_STATE_UPDATE = "com.verzqli.SONG_STATE_UPDATE"; //更新主页面的按键状态到播放页面中,即主页面如果按了暂停,播放界面的图标会改变 public static final String SONG_STATE_PRESS = "com.verzqli.SONG_STATE_PRESS"; //音乐当前时间改变事件 public static final String MUSIC_CURRENT = "com.verzqli.action.MUSIC_CURRENT"; //音乐播放长度改变事件 public static final String MUSIC_DURATION = "com.verzqli.action.MUSIC_DURATION"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ShareSDK.initSDK(this); setContentView(R.layout.content_main); toolbar = (Toolbar) findViewById(R.id.id_toolbar); isRealDestroy = false; setSupportActionBar(toolbar); toolbar.setNavigationIcon(R.drawable.title_icon); /** * 这里是主界面右上角的分享功能,用了shareSDK来完成QQ分享 */ toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { String msg = ""; switch (menuItem.getItemId()) { case R.id.action_share: Platform.ShareParams qq = new Platform.ShareParams(); qq.setTitle("分享歌曲"); qq.setTitleUrl("http://mob.com"); qq.setText("给你们分享一首歌:" + songList.get(songListPosition).getTitle()); qq.setImageUrl("http://p0.so.qhimg.com/dmt/73_100_/t01d66f2efb44823d25.jpg"); qq.setMusicUrl("http://music.baidu.com/search?key=" + songList.get(songListPosition).getTitle()); Platform qqq = ShareSDK.getPlatform(MainActivity.this, QQ.NAME); qqq.setPlatformActionListener(MainActivity.this); qqq.share(qq); break; case R.id.action_settings: unregisterReceiver(mainReceiver); Intent intent = new Intent(MainActivity.this,MusicPlayService.class); stopService(intent); isRealDestroy = true; MainActivity.this.finish(); break; } if (!msg.equals("")) { Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } return true; } }); // getSupportActionBar().setDisplayHomeAsUpEnabled(false);左上角那个箭头 values = new ContentValues(); /** * 这下面的功能是保存当前正在播放的歌曲的信息,因为我写的功能是退出了主界面之后,歌曲在后台播放, * 但是我一旦点击程序,下面还是能够与显示当前正在播放的歌曲,这个就要保存数据了,所以我先建立了一个数据库, * 后面换了歌曲的话会把当前播放的歌曲信息在这个数据库中更新,但是,要先这个数据库中有数据才能更新,所以我 * 先往这个数据库中先存入了一个数据,就是列表的第一首歌,好方便后面更新。 */ int result = DataSupport.count(PlaySong.class); if (result == 0) { //当前播放歌曲的实体类 PlaySong playSong = new PlaySong(); playSong.setId(1); playSong.setSongPosition(-1); playSong.setPlaying(false); playSong.save(); } /** * 这是一个加载图片的线程,没一个歌曲都有它的对应图片,这个线程是取出歌曲里面的图片 * ,然后剪切成圆形,给后面使用 */ if (songBitmapThread == null) { songBitmapThread = new SongBitmapThread(); } //初始化View createView(); //设置数据 setAdapter(); } // 通知栏显示当前播放信息 public void showNotification() { notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification notification = new Notification(R.drawable.like, "歌曲:"+songList.get(songListPosition).getTitle() + "--" + "歌手:"+songList.get(songListPosition).getArtist(), System.currentTimeMillis()); notification.icon = R.drawable.bg;//notification通知栏图标 //自定义布局 contentView = new RemoteViews(getPackageName(), R.layout.notification_item); if (songList.get(songListPosition).getBitmap() == null) { Resources res = getResources(); Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.morenbgsamall); contentView.setImageViewBitmap(R.id.im, bmp); } else { contentView.setImageViewBitmap(R.id.im, songList.get(songListPosition).getBitmap()); } /** * 这下面一大段是通知栏上的按键来控制歌曲的播放, * 这个不懂的话可以去查找下Notification的用法 * prev 前一首 * play 播放or暂停 * next 下一首 */ contentView.setTextViewText(R.id.notification_title,songList.get(songListPosition).getTitle()); contentView.setTextViewText(R.id.notification_artist,songList.get(songListPosition).getArtist()); Intent noticifitionMsg = new Intent(AppControl.NOTIFICATION_ACTION); noticifitionMsg.putExtra("INTENT_BUTTONID_TAG", "prev"); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1, noticifitionMsg, PendingIntent.FLAG_CANCEL_CURRENT); contentView.setOnClickPendingIntent(R.id.last, pendingIntent); noticifitionMsg.putExtra("INTENT_BUTTONID_TAG", "play"); PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this, 2, noticifitionMsg, PendingIntent.FLAG_CANCEL_CURRENT); contentView.setOnClickPendingIntent(R.id.now, pendingIntent2); noticifitionMsg.putExtra("INTENT_BUTTONID_TAG", "next"); PendingIntent pendingIntent3 = PendingIntent.getBroadcast(this, 3, noticifitionMsg, PendingIntent.FLAG_CANCEL_CURRENT); contentView.setOnClickPendingIntent(R.id.future, pendingIntent3); notification.contentView = contentView; PendingIntent contentIntent = PendingIntent.getActivity(this, 0, getIntent(), 0); //notifcation.flags = Notification.FLAG_NO_CLEAR;// 永久在通知栏里 notification.flags = Notification.FLAG_AUTO_CANCEL; //使用自定义下拉视图时,不需要再调用setLatestEventInfo()方法,但是必须定义contentIntent notification.contentIntent = contentIntent; notificationManager.notify(123, notification);//123是notification的唯一标识(id) } @Override protected void onPause() { super.onPause(); } @Override protected void onResume() { super.onResume(); AppControl.JUDGE_DESTORY_ONCREATE += 1; initSongData(); setPlayData(songListPosition); } @Override public void onStart() { super.onStart(); mainReceiver = new MainReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(SONG_STATE_UPDATE); filter.addAction(MUSIC_CURRENT); filter.addAction(MUSIC_DURATION); filter.addAction(SONG_STATE_PRESS); filter.addAction(AppControl.SERVICE_STOP); registerReceiver(mainReceiver, filter); } private void initSongData() { PlaySong playSong = DataSupport.find(PlaySong.class, 1); isPlayingBtn = playSong.isPlaying();//获得播放界面返回来的按键boolean值 long durate = playSong.getDuration(); int current = playSong.getCurrentTime(); int position = playSong.getSongPosition(); if (durate != 0) { duration = durate; } if (current != 0) { currentTime = current; } if (position != -1) { songListPosition = position; } if (AppControl.JUDGE_DESTORY_ONCREATE == 0) { isPlayingBtn = false; } if (isPlayingBtn) { mainPlaySong.setBackgroundResource(R.drawable.play_normal); } else { mainPlaySong.setBackgroundResource(R.drawable.play_pressed); } } private void setAdapter() { //读取图片线程开启 songBitmapThread.run(); if (songList.size() == 0) { Toast.makeText(MainActivity.this, "您的手机暂无歌曲信息", Toast.LENGTH_SHORT).show(); } else { //配置歌曲列表适配器 songListAdapter = new SongListAdapter(MainActivity.this, songList); songListView.setAdapter(songListAdapter); /** * 这里我要详细的说一下, * 这里我主要实现了这样一个功能:比如我点击了歌曲A,进入了播放界面, * 然后点击返回退出了播放界面进入列表界面,我再点击歌曲A,他不会重头开始播放, * 然后我再点击B歌曲,他开始重头播放B。 * * 不过这里我传给播放界面的参数我自己感觉有点繁琐,你们可以自己试着省略下 */ songListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //点击歌曲进入播放界面 intent = new Intent(MainActivity.this, MusicPlayActivity.class); /** * songListPosition 这个表示的是当前正在播放的歌曲position * 如果,两者相同,那就穿一些后面播放界面需要显示的状态过去,比如当前播放状态, * 让播放界面的图标能够更新 */ if (position == songListPosition) { intent.putExtra("mainCurrentTime", currentTime); intent.putExtra("isPlaying", isPlayingBtn); intent.putExtra("MSSG", AppControl.MEDIA_PLAYING_SONG_IS_PLAYING); intent.putExtra("isOncreate", AppControl.JUDGE_DESTORY_ONCREATE); } else { /** *如果两个值不一样,证明你重新点击了一首歌 * MSSG 传的就和上面不一样了,使后面的播放界面做不同的处理 */ intent.putExtra("isPlaying", isPlayingBtn); intent.putExtra("mainCurrentTime", currentTime); intent.putExtra("isPlaying", true); intent.putExtra("MSSG", AppControl.MEDIA_PLAYING_SONG_AT_LIST); } /** * * */ intent.putExtra("position", position); intent.putExtra("duration", songList.get(position).getDuration()); //这里当初图省事,这个传的是歌曲的循环状态,我当初写了个2,就是顺序播放,这个你们需要的可以自己改 intent.putExtra("repeatState", 2); intent.putExtra("url", songList.get(position).getData()); songListPosition = position; startActivity(intent); //这个是主页面下面播放栏状态的更换 setPlayData(position); } }); } } @Override public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) { } @Override public void onError(Platform platform, int i, Throwable throwable) { } @Override public void onCancel(Platform platform, int i) { } /** * 开线程存图片 */ private class SongBitmapThread implements Runnable { @Override public void run() { songList = MusicLoader.getInstance(getApplicationContext().getContentResolver()).queryData(); for (int i = 0; i < songList.size(); i++) { Bitmap bitmap = getBlurBitmap(MusicBitmap.getArtwork(MainActivity.this, songList.get(i).getId(), songList.get(i).getAlbumId(), true, true), MainActivity.this); songList.get(i).setBitmap(bitmap); } } } /** * 设置点击播放时下面播放栏的数据 */ private void setPlayData(int position) { songTitlePlay.setText(songList.get(position).getTitle()); songTitleArt.setText(songList.get(position).getArtist()); LogUtil.itSelf.Log("setPlayData" + songList.get(position).getTitle() + songList.get(position).getBitmap()); if (songList.get(position).getBitmap() == null) { Resources res = getResources(); Bitmap bmp = BitmapFactory.decodeResource(res, R.drawable.morenbgsamall); imSongPlaying.setImageBitmap(bmp); } else { imSongPlaying.setImageBitmap(songList.get(position).getBitmap()); } } public static Bitmap getBlurBitmap(Bitmap rootView, Context context) { try { if (rootView == null || context == null) { return null; } Bitmap bgBitmap = Bitmap.createBitmap(rootView); return GetRoundBitmap.getInstance().getOvalBitmap(bgBitmap); } catch (Exception e) { e.printStackTrace(); } return null; } private void createView() { //歌曲列表 songList = new ArrayList<Song>(); //列表下面那个歌曲显示界面,有图片个按键那个linearlayout linMainButtom = (LinearLayout) findViewById(R.id.lin_main_buttom); //控制播放按键 mainPlaySong = (Button) findViewById(R.id.main_play); //歌曲列表listveiw songListView = (ListView) findViewById(R.id.song_list); songTitlePlay = (TextView) findViewById(R.id.song_title_play); songTitleArt = (TextView) findViewById(R.id.song_album_play); imSongPlaying = (ImageView) findViewById(R.id.im_song_playing); linMainButtom.setOnClickListener(this); mainPlaySong.setOnClickListener(this); } @Override protected void onDestroy() { super.onDestroy(); if(!isRealDestroy){ showNotification(); } } /** * 下面三个按键的点击触发事件 * 这里别看下面这么一大段代码,其实你去掉那些intent就是一点 * 这里主要实现了两个功能 * 1.点击下面的播放栏,能够进入播放界面 * 2.点击按键能控制歌曲的暂停去播放 * 3.AppControl.JUDGE_DESTORY_ONCREATE 这个是一个信号 * 是为了控制当你用菜单栏的形式强行关掉程序时,进来程序的时候,这个点击播放栏界面 * 不但要能进入播放界面,还要让歌曲开始播放,所以加了这么一个控制后面服务开始的功能 * @param v */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.main_play: if (isPlayingBtn) { Intent intent = new Intent(this, MusicPlayService.class); intent.setAction("com.verzqli.media.play"); intent.putExtra("MSG", AppControl.MEDIA_PLAYING_SONG_PAUSE); intent.putExtra("isOncreate", AppControl.JUDGE_DESTORY_ONCREATE); mainPlaySong.setBackgroundResource(R.drawable.play_pressed); startService(intent); isPlayingBtn = false; } else { if (AppControl.JUDGE_DESTORY_ONCREATE == 0) { Intent intent = new Intent(this, MusicPlayService.class); intent.setAction("com.verzqli.media.play"); intent.putExtra("position", songListPosition); intent.putExtra("url", songList.get(songListPosition).getData()); intent.putExtra("title", songList.get(songListPosition).getTitle()); intent.putExtra("MSG", AppControl.MEDIA_PLAYING_FIRST_PRESS); intent.putExtra("progress", 0); startService(intent); mainPlaySong.setBackgroundResource(R.drawable.play_normal); isPlayingBtn = true; } else { Intent intent = new Intent(this, MusicPlayService.class); intent.setAction("com.verzqli.media.play"); intent.putExtra("MSG", AppControl.MEDIA_PLAYING_SONG_CONTINUE); mainPlaySong.setBackgroundResource(R.drawable.play_normal); isPlayingBtn = true; startService(intent); } } values.put("playing", isPlayingBtn); DataSupport.update(PlaySong.class, values, 1); break; case R.id.lin_main_buttom: intent = new Intent(MainActivity.this, MusicPlayActivity.class); LogUtil.itSelf.Log("lin_main_buttom" + currentTime); intent.putExtra("mainCurrentTime", currentTime); intent.putExtra("isPlaying", isPlayingBtn); intent.putExtra("MSSG", AppControl.MEDIA_PLAYING_SONG_IS_PLAYING); intent.putExtra("position", songListPosition); intent.putExtra("duration", songList.get(songListPosition).getDuration()); intent.putExtra("repeatState", 2); intent.putExtra("url", songList.get(songListPosition).getData()); intent.putExtra("isOncreate", AppControl.JUDGE_DESTORY_ONCREATE); startActivity(intent); break; } } /** * 广播接收器 * 接受后台服务传过来的信息来更新界面 * 这里没什么,不懂的话可以评论留言,我会回答的 */ private class MainReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(MUSIC_CURRENT)) { //currentTime代表当前播放的时间 currentTime = intent.getIntExtra("currentTime", -1); } else if (action.equals(MUSIC_DURATION)) { duration = intent.getIntExtra("duration", -1); } else if (action.equals(SONG_STATE_UPDATE)) { //获取Intent中的current消息,current代表当前正在播放的歌曲 songListPosition = intent.getIntExtra("currentSongPosition", -1); setPlayData(songListPosition); } if (action.equals(SONG_STATE_PRESS)) { isPlayingBtn = intent.getBooleanExtra("isPlaying", true); if (isPlayingBtn) { mainPlaySong.setBackgroundResource(R.drawable.play_normal); } else { mainPlaySong.setBackgroundResource(R.drawable.play_pressed); } }if(action.equals(AppControl.SERVICE_STOP)) { unregisterReceiver(mainReceiver); Intent service = new Intent(MainActivity.this,MusicPlayService.class); stopService(service); isRealDestroy = true; } } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return super.onCreateOptionsMenu(menu); }}
0 0
- Android开发之第一个小项目--我的MP3播放器之主界面的实现(二)
- Android开发之第一个小项目--我的MP3播放器之播放界面的实现(三)
- Android开发之第一个小项目--我的MP3播放器(一)
- Android开发之第一个小项目--我的MP3播放器之后台服务Service的实现(四)
- Android开发之第一个小项目--我的MP3播放器之最后一点结束的话(终)
- 我的Android进阶之旅------>Android MediaPlayer播放mp3的实例--简易mp3播放器
- 我的第一个Android项目开发(二)-环境配置
- 我的第一个android小项目——秒表计时器之感受
- Android练习项目 Mp3播放器实现(二)
- 安卓MP3播放器开发实例(3)之进度条和歌词更新的实现
- Android学习之路(二)之 我的第一个Android应用程序
- Android之mp3播放器开发过程
- 我的第一个Android项目开发(一)
- 我的Android进阶之旅------>Android MediaPlayer播放网络音频的实例--网络mp3播放器
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之开发游戏界面(二)
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之开发游戏界面(二)
- 我的Android进阶之旅------>Android疯狂连连看游戏的实现之开发游戏界面(二)
- Android之我的第一个程序
- vfio内核实现分析-(2)相关内核组件及数据结构概图
- 多线程下载的原理(1) java事例
- 安卓中对数据库的操作(增删改查)
- 【杭电】[2054]A==B
- 杭电2546 饭卡 (变形0-1背包)
- Android开发之第一个小项目--我的MP3播放器之主界面的实现(二)
- 【杭电】[2029]Palindromes _easy version
- UESTC 1269 ZhangYu Speech 预处理、前缀和
- android-Wi-Fi Peer-to-Peer
- git命令
- NFV SDN
- 关闭应用程序
- c#知识点整理
- UITableViewCell中如何添加图片数组