播放器程序的主要流程图在这里:
先介绍下MainContentActivity,后面所有的Activity和Fragment都是基于这个类之上,看下代码:
package com.ldw.music.activity; import java.util.ArrayList; import java.util.List; import android.annotation.SuppressLint; import android.app.AlarmManager; import android.app.Dialog; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.app.FragmentActivity; import android.text.TextUtils; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.ldw.music.MusicApp; import com.ldw.music.R; import com.ldw.music.db.MusicInfoDao; import com.ldw.music.fragment.MainFragment; import com.ldw.music.fragment.MenuFragment; import com.ldw.music.slidemenu.SlidingMenu; import com.ldw.music.utils.MusicUtils; import com.ldw.music.utils.SplashScreen; /** * 主类,首次进入应用会到这里 * 该类提供了首页MainFragment的显示和侧滑MenuFragment的显示 * @author longdw * */ @SuppressLint("HandlerLeak") public class MainContentActivity extends FragmentActivity implements IConstants { public static final String ALARM_CLOCK_BROADCAST = "alarm_clock_broadcast"; public SlidingMenu mSlidingMenu; private List<OnBackListener> mBackListeners = new ArrayList<OnBackListener>(); public MainFragment mMainFragment; private Handler mHandler; private MusicInfoDao mMusicDao; private SplashScreen mSplashScreen; private int mScreenWidth; public interface OnBackListener { public abstract void onBack(); } @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); DisplayMetrics metric = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metric); mScreenWidth = metric.widthPixels; initSDCard(); IntentFilter filter = new IntentFilter(); filter.addAction(ALARM_CLOCK_BROADCAST); registerReceiver(mAlarmReceiver, filter); setContentView(R.layout.frame_main); mSplashScreen = new SplashScreen(this); mSplashScreen.show(R.drawable.image_splash_background, SplashScreen.SLIDE_LEFT); // set the Above View mMainFragment = new MainFragment(); getSupportFragmentManager().beginTransaction() .replace(R.id.frame_main, mMainFragment).commit(); // configure the SlidingMenu mSlidingMenu = new SlidingMenu(this); mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN); mSlidingMenu.setMode(SlidingMenu.RIGHT); mSlidingMenu.setShadowWidthRes(R.dimen.shadow_width); mSlidingMenu.setShadowDrawable(R.drawable.shadow); mSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset); mSlidingMenu.setFadeDegree(0.35f); mSlidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT); mSlidingMenu.setMenu(R.layout.frame_menu); getSupportFragmentManager().beginTransaction() .replace(R.id.frame_menu, new MenuFragment()).commit(); mMusicDao = new MusicInfoDao(this); mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); mSplashScreen.removeSplashScreen(); } }; getData(); } private void initSDCard() { IntentFilter intentFilter = new IntentFilter(); intentFilter.setPriority(1000);// 设置最高优先级 intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);// sd卡被插入,且已经挂载 intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);// sd卡存在,但还没有挂载 intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);// sd卡被移除 intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);// sd卡作为 // USB大容量存储被共享,挂载被解除 intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);// sd卡已经从sd卡插槽拔出,但是挂载点还没解除 // intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);// 开始扫描 // intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);// 扫描完成 intentFilter.addDataScheme("file"); registerReceiver(sdCardReceiver, intentFilter);// 注册监听函数 } private void getData() { new Thread(new Runnable() { @Override public void run() { if (mMusicDao.hasData()) { // 如果有数据就等三秒跳转 mHandler.sendMessageDelayed(mHandler.obtainMessage(), 3000); } else { MusicUtils.queryMusic(MainContentActivity.this, START_FROM_LOCAL); MusicUtils.queryAlbums(MainContentActivity.this); MusicUtils.queryArtist(MainContentActivity.this); MusicUtils.queryFolder(MainContentActivity.this); mHandler.sendEmptyMessage(1); } } }).start(); } public void registerBackListener(OnBackListener listener) { if (!mBackListeners.contains(listener)) { mBackListeners.add(listener); } } public void unRegisterBackListener(OnBackListener listener) { mBackListeners.remove(listener); } @Override public void onBackPressed() { if (mSlidingMenu.isMenuShowing()) { mSlidingMenu.showContent(); } else { if (mBackListeners.size() == 0) { // super.onBackPressed(); // 在activity中调用 moveTaskToBack (boolean nonRoot)方法即可将activity // 退到后台,注意不是finish()退出。 // 参数为false代表只有当前activity是task根,指应用启动的第一个activity时,才有效; moveTaskToBack(true); } for (OnBackListener listener : mBackListeners) { listener.onBack(); } } } private final BroadcastReceiver sdCardReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals("android.intent.action.MEDIA_REMOVED")// 各种未挂载状态 || action.equals("android.intent.action.MEDIA_UNMOUNTED") || action.equals("android.intent.action.MEDIA_BAD_REMOVAL") || action.equals("android.intent.action.MEDIA_SHARED")) { finish(); Toast.makeText(MainContentActivity.this, "SD卡以外拔出,本地数据没法初始化!", Toast.LENGTH_SHORT).show(); } } }; public void showSleepDialog() { if (MusicApp.mIsSleepClockSetting) { cancleSleepClock(); Toast.makeText(getApplicationContext(), "已取睡眠模式!", Toast.LENGTH_SHORT).show(); return; } View view = View.inflate(this, R.layout.sleep_time, null); final Dialog dialog = new Dialog(this, R.style.lrc_dialog); dialog.setContentView(view); dialog.setCanceledOnTouchOutside(false); Window dialogWindow = dialog.getWindow(); WindowManager.LayoutParams lp = dialogWindow.getAttributes(); dialogWindow.setGravity(Gravity.CENTER); // lp.x = 100; // 新位置X坐标 // lp.y = 100; // 新位置Y坐标 lp.width = (int) (mScreenWidth * 0.7); // 宽度 // lp.height = 400; // 高度 // 当Window的Attributes改变时系统会调用此函数,可以直接调用以应用上面对窗口参数的更改,也可以用setAttributes // dialog.onWindowAttributesChanged(lp); dialogWindow.setAttributes(lp); dialog.show(); final Button cancleBtn = (Button) view.findViewById(R.id.cancle_btn); final Button okBtn = (Button) view.findViewById(R.id.ok_btn); final EditText timeEt = (EditText) view.findViewById(R.id.time_et); OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { if (v == cancleBtn) { dialog.dismiss(); } else if (v == okBtn) { String timeS = timeEt.getText().toString(); if (TextUtils.isEmpty(timeS) || Integer.parseInt(timeS) == 0) { Toast.makeText(getApplicationContext(), "输入无效!", Toast.LENGTH_SHORT).show(); return; } setSleepClock(timeS); dialog.dismiss(); } } }; cancleBtn.setOnClickListener(listener); okBtn.setOnClickListener(listener); } /** * 设置睡眠闹钟 * * @param timeS */ private void setSleepClock(String timeS) { Intent intent = new Intent(ALARM_CLOCK_BROADCAST); PendingIntent pendingIntent = PendingIntent.getBroadcast( MainContentActivity.this, 0, intent, 0); // 设置time时间之后退出程序 int time = Integer.parseInt(timeS); long longTime = time * 60 * 1000L; AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); am.set(AlarmManager.RTC, System.currentTimeMillis() + longTime, pendingIntent); MusicApp.mIsSleepClockSetting = true; Toast.makeText(getApplicationContext(), "将在"+timeS+"分钟后退出软件", Toast.LENGTH_SHORT) .show(); } /** * 取消睡眠闹钟 */ private void cancleSleepClock() { Intent intent = new Intent(ALARM_CLOCK_BROADCAST); PendingIntent pendingIntent = PendingIntent.getBroadcast( MainContentActivity.this, 0, intent, 0); AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); am.cancel(pendingIntent); MusicApp.mIsSleepClockSetting = false; } private BroadcastReceiver mAlarmReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { //退出程序 finish(); } }; @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(sdCardReceiver); unregisterReceiver(mAlarmReceiver); MusicApp.mServiceManager.exit(); MusicApp.mServiceManager = null; MusicUtils.clearCache(); cancleSleepClock(); System.exit(0); } }
该类使用SlideMenu控制着MainFragment和MenuFragment,监听SD卡的变化,具体的实现代码中写的很详细,接下来看看MainFragment:
package com.ldw.music.fragment; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Bitmap; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.ldw.music.MusicApp; import com.ldw.music.R; import com.ldw.music.activity.IConstants; import com.ldw.music.aidl.IMediaService; import com.ldw.music.db.AlbumInfoDao; import com.ldw.music.db.ArtistInfoDao; import com.ldw.music.db.FavoriteInfoDao; import com.ldw.music.db.FolderInfoDao; import com.ldw.music.db.MusicInfoDao; import com.ldw.music.interfaces.IOnServiceConnectComplete; import com.ldw.music.model.MusicInfo; import com.ldw.music.service.ServiceManager; import com.ldw.music.uimanager.MainBottomUIManager; import com.ldw.music.uimanager.SlidingDrawerManager; import com.ldw.music.uimanager.UIManager; import com.ldw.music.uimanager.UIManager.OnRefreshListener; import com.ldw.music.utils.MusicTimer; /** * 首页内容 * 该类展示了软件的几大模块 * 另外要注意嵌套的两层ViewPager * @author longdw * */ public class MainFragment extends Fragment implements IConstants, IOnServiceConnectComplete, OnRefreshListener, OnTouchListener { private GridView mGridView; private MyGridViewAdapter mAdapter; protected IMediaService mService; private MusicInfoDao mMusicDao; private FolderInfoDao mFolderDao; private ArtistInfoDao mArtistDao; private AlbumInfoDao mAlbumDao; private FavoriteInfoDao mFavoriteDao; public UIManager mUIManager; private MusicTimer mMusicTimer; private MusicPlayBroadcast mPlayBroadcast; private MainBottomUIManager mBottomUIManager; private SlidingDrawerManager mSdm; private RelativeLayout mBottomLayout, mMainLayout; private Bitmap defaultArtwork; private ServiceManager mServiceManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mMusicDao = new MusicInfoDao(getActivity()); mFolderDao = new FolderInfoDao(getActivity()); mArtistDao = new ArtistInfoDao(getActivity()); mAlbumDao = new AlbumInfoDao(getActivity()); mFavoriteDao = new FavoriteInfoDao(getActivity()); mServiceManager = MusicApp.mServiceManager; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.frame_main1, container, false); mGridView = (GridView) view.findViewById(R.id.gridview); mAdapter = new MyGridViewAdapter(); mMainLayout = (RelativeLayout) view .findViewById(R.id.main_layout); mMainLayout.setOnTouchListener(this); mBottomLayout = (RelativeLayout) view.findViewById(R.id.bottomLayout); MusicApp.mServiceManager.connectService(); MusicApp.mServiceManager.setOnServiceConnectComplete(this); mGridView.setAdapter(mAdapter); mUIManager = new UIManager(getActivity(), view); mUIManager.setOnRefreshListener(this); mSdm = new SlidingDrawerManager(getActivity(), mServiceManager, view); mBottomUIManager = new MainBottomUIManager(getActivity(), view); mMusicTimer = new MusicTimer(mSdm.mHandler, mBottomUIManager.mHandler); mSdm.setMusicTimer(mMusicTimer); mPlayBroadcast = new MusicPlayBroadcast(); IntentFilter filter = new IntentFilter(BROADCAST_NAME); filter.addAction(BROADCAST_NAME); getActivity().registerReceiver(mPlayBroadcast, filter); return view; } private class MyGridViewAdapter extends BaseAdapter { private int[] drawable = new int[] { R.drawable.icon_local_music, R.drawable.icon_favorites, R.drawable.icon_folder_plus, R.drawable.icon_artist_plus, R.drawable.icon_album_plus }; private String[] name = new String[] { "我的音乐", "我的最爱", "文件夹", "歌手", "专辑" }; private int musicNum = 0, artistNum = 0, albumNum = 0, folderNum = 0, favoriteNum = 0; @Override public int getCount() { return 5; } @Override public Object getItem(int arg0) { return null; } @Override public long getItemId(int position) { return position; } public void setNum(int music_num, int artist_num, int album_num, int folder_num, int favorite_num) { musicNum = music_num; artistNum = artist_num; albumNum = album_num; folderNum = folder_num; favoriteNum = favorite_num; notifyDataSetChanged(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); convertView = getActivity().getLayoutInflater().inflate( R.layout.main_gridview_item, null); holder.iv = (ImageView) convertView .findViewById(R.id.gridview_item_iv); holder.nameTv = (TextView) convertView .findViewById(R.id.gridview_item_name); holder.numTv = (TextView) convertView .findViewById(R.id.gridview_item_num); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } switch (position) { case 0:// 我的音乐 holder.numTv.setText(musicNum + ""); break; case 1:// 我的最爱 holder.numTv.setText(favoriteNum + ""); break; case 2:// 文件夹 holder.numTv.setText(folderNum + ""); break; case 3:// 歌手 holder.numTv.setText(artistNum + ""); break; case 4:// 专辑 holder.numTv.setText(albumNum + ""); break; } convertView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int from = -1; switch (position) { case 0:// 我的音乐 from = START_FROM_LOCAL; break; case 1:// 我的最爱 from = START_FROM_FAVORITE; break; case 2:// 文件夹 from = START_FROM_FOLDER; break; case 3:// 歌手 from = START_FROM_ARTIST; break; case 4:// 专辑 from = START_FROM_ALBUM; break; } mUIManager.setContentType(from); } }); holder.iv.setImageResource(drawable[position]); holder.nameTv.setText(name[position]); return convertView; } private class ViewHolder { ImageView iv; TextView nameTv, numTv; } } @Override public void onServiceConnectComplete(IMediaService service) { // service绑定成功会执行到这里 refreshNum(); } public void refreshNum() { int musicCount = mMusicDao.getDataCount(); int artistCount = mArtistDao.getDataCount(); int albumCount = mAlbumDao.getDataCount(); int folderCount = mFolderDao.getDataCount(); int favoriteCount = mFavoriteDao.getDataCount(); mAdapter.setNum(musicCount, artistCount, albumCount, folderCount, favoriteCount); } private class MusicPlayBroadcast extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(BROADCAST_NAME)) { MusicInfo music = new MusicInfo(); int playState = intent.getIntExtra(PLAY_STATE_NAME, MPS_NOFILE); int curPlayIndex = intent.getIntExtra(PLAY_MUSIC_INDEX, -1); Bundle bundle = intent.getBundleExtra(MusicInfo.KEY_MUSIC); if (bundle != null) { music = bundle.getParcelable(MusicInfo.KEY_MUSIC); } switch (playState) { case MPS_INVALID:// 考虑后面加上如果文件不可播放直接跳到下一首 mMusicTimer.stopTimer(); mSdm.refreshUI(0, music.duration, music); mSdm.showPlay(true); mBottomUIManager.refreshUI(0, music.duration, music); mBottomUIManager.showPlay(true); break; case MPS_PAUSE: mMusicTimer.stopTimer(); mSdm.refreshUI(mServiceManager.position(), music.duration, music); mSdm.showPlay(true); mBottomUIManager.refreshUI(mServiceManager.position(), music.duration, music); mBottomUIManager.showPlay(true); mServiceManager.cancelNotification(); break; case MPS_PLAYING: mMusicTimer.startTimer(); mSdm.refreshUI(mServiceManager.position(), music.duration, music); mSdm.showPlay(false); mBottomUIManager.refreshUI(mServiceManager.position(), music.duration, music); mBottomUIManager.showPlay(false); break; case MPS_PREPARE: mMusicTimer.stopTimer(); mSdm.refreshUI(0, music.duration, music); mSdm.showPlay(true); mBottomUIManager.refreshUI(0, music.duration, music); mBottomUIManager.showPlay(true); // 读取歌词文件 mSdm.loadLyric(music); break; } } } } @Override public void onRefresh() { refreshNum(); } int oldY = 0; @Override public boolean onTouch(View v, MotionEvent event) { int bottomTop = mBottomLayout.getTop(); System.out.println(bottomTop); if (event.getAction() == MotionEvent.ACTION_DOWN) { oldY = (int) event.getY(); if (oldY > bottomTop) { mSdm.open(); } } return true; } }
布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg" android:gravity="center" android:orientation="vertical" > <LinearLayout android:id="@+id/top_layout" android:layout_width="fill_parent" android:layout_height="50dip" android:background="@color/half_transparent" android:gravity="center" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我的首页" android:textColor="@color/white" android:textSize="@dimen/title_text_sp" /> </LinearLayout> <RelativeLayout android:id="@+id/bottomLayout" android:layout_width="fill_parent" android:layout_height="64dip" android:layout_alignParentBottom="true" android:background="@color/bottom_color" > <ImageView android:id="@+id/headicon_iv" android:layout_width="64dip" android:layout_height="64dip" android:background="@drawable/img_album_background" /> <ImageButton android:id="@+id/btn_menu2" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_margin="4.0dip" android:background="@drawable/selector_music_btn" android:padding="6.0dip" android:src="@drawable/icon_menu_point" /> <View android:id="@+id/split" android:layout_width="1.5dip" android:layout_height="64dip" android:layout_marginLeft="6.0dip" android:layout_marginRight="6.0dip" android:layout_toLeftOf="@id/btn_menu2" android:background="#6a5e8a" /> <ImageButton android:id="@+id/btn_playNext2" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_centerVertical="true" android:layout_toLeftOf="@id/split" android:background="@drawable/selector_music_btn" android:padding="6.0dip" android:src="@drawable/icon_next_normal" /> <FrameLayout android:id="@+id/playLayout" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_centerVertical="true" android:layout_marginRight="12.0dip" android:layout_toLeftOf="@id/btn_playNext2" > <ImageButton android:id="@+id/btn_pause2" android:layout_width="wrap_content" android:layout_height="fill_parent" android:background="@drawable/selector_music_btn" android:padding="6.0dip" android:src="@drawable/icon_pause_normal" android:visibility="gone" /> <ImageButton android:id="@+id/btn_play2" android:layout_width="wrap_content" android:layout_height="fill_parent" android:background="@drawable/selector_music_btn" android:padding="6.0dip" android:src="@drawable/icon_play_normal" /> </FrameLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="6.0dip" android:layout_toLeftOf="@id/playLayout" android:layout_toRightOf="@id/headicon_iv" android:orientation="vertical" > <com.ldw.music.view.AlwaysMarqueeTextView android:id="@+id/artist_tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:marqueeRepeatLimit="marquee_forever" android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" android:textSize="12sp" /> <com.ldw.music.view.AlwaysMarqueeTextView android:id="@+id/musicname_tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:marqueeRepeatLimit="marquee_forever" android:scrollHorizontally="true" android:singleLine="true" android:textColor="@color/white" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/position_tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/white" android:text="00:00" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" - " android:textColor="@color/white" /> <TextView android:id="@+id/duration_tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/white" android:text="00:00" /> </LinearLayout> </LinearLayout> </RelativeLayout> <ProgressBar android:id="@+id/playback_seekbar2" style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@id/bottomLayout" android:max="100" android:maxHeight="2.0dip" android:minHeight="2.0dip" android:progressDrawable="@drawable/playback_seekbar2" /> <GridView android:id="@+id/gridview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@id/top_layout" android:layout_above="@id/playback_seekbar2" android:layout_margin="8.0dip" android:horizontalSpacing="6.0dip" android:numColumns="3" android:verticalSpacing="6.0dip" /> <com.ldw.music.view.MySlidingDrawer android:id="@+id/slidingDrawer" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/sliding_bg" android:content="@+id/content" android:handle="@+id/handle" android:visibility="invisible" > <include layout="@layout/sliding_handle" /> <include layout="@layout/sliding_content" /> </com.ldw.music.view.MySlidingDrawer> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="invisible" > </android.support.v4.view.ViewPager> <android.support.v4.view.ViewPager android:id="@+id/viewPagerSub" android:layout_width="fill_parent" android:layout_height="fill_parent" android:visibility="invisible" > </android.support.v4.view.ViewPager> </RelativeLayout>
MainFragment控制着主要的UI部分,从布局文件中可以看出,我这里用了两个ViewPager,原因是从文件夹、列表、歌手进入的时候会有两级目录才能进入歌曲列表,当然天天动听不是这么做的,我这里为了方便用了现成的ViewPager来控制,效果还行。还有就是UIManager类,该类控制从主页的GridView进入其他界面。
还有一些诸如自定义View之类的我这里就不做介绍了,大家可以看下源码就知道了,下面是项目在github上的地址,发帖不容易,希望大家多提提宝贵的意见也算是给我的鼓励。
sdcard的监听是怎样实现的,难道是定义了那个sdCardReceiver,可是它并没有处理如何扫描文件
sdcard监听没有处理扫描哦,很简单的,在onReceive里面监听到sd卡发生了变化就重新扫描就行了,我这里只是做了sd卡没有mount的情况。
想学习,望把原工程发到1061354225@qq.com,谢谢了
github上面有的
为什么需要用到aidl?
aidl,进程间通信,也就是你其他进程也可以访问到,音乐播放器这个应用其实用不用aidl无所谓的,我主要是为了方便操作service
还没看代码,简单看了下功能。发现一个小BUG:点击换肤的时候会出一点小问题。比如在(1)首页——>(2)歌手——>(3)张杰 ——>进入音频列表。此时换肤,(1)(3)成功换肤,但是(2)还没换过来,需要刷新一下再次感谢隆笛大神,您的开源让我收益良多。
本人java开发,现在在学android呢,看到你的代码,学习了,我QQ:895713007
服务器端代码开源吗 求分享yanlei_man@outlook.com
大神,你的功底真的深厚。
为什么歌手列表和专辑列表没有显示啊?