结合百度搜到的,自己再优化深入,终于实现,结合网上搜的其他大神写的地址找不到了
----------一些细节没有做,主要看大功能咯----------
逻辑思路:
1.书写aidl接口
2.绑定service服务
3.activity实现业务逻辑
上干货不废话:
IServicePlayer.aidl
interface IServicePlayer { void play(); void pause(); void stop(); int getDuration(); int getCurrentPosition(); void seekTo(int current); boolean setLoop(boolean loop); void reset(); void setDataSource(String path); void prepare(); void release(); boolean isPlaying(); void prepareAsync(); void setPlayingFinish(); }
MusicService.java
public class MusicService extends Service { public static MediaPlayer mPlayer; IServicePlayer.Stub stub = new IServicePlayer.Stub() { @Override public void play() throws RemoteException { mPlayer.start(); } @Override public void pause() throws RemoteException { mPlayer.pause(); } @Override public void stop() throws RemoteException { mPlayer.stop(); } @Override public int getDuration() throws RemoteException { return mPlayer.getDuration(); } @Override public int getCurrentPosition() throws RemoteException { return mPlayer.getCurrentPosition(); } @Override public void seekTo(int current) throws RemoteException { mPlayer.seekTo(current); } @Override public boolean setLoop(boolean loop) throws RemoteException { return false; } @Override public void reset() throws RemoteException { mPlayer.reset(); } @Override public void setDataSource(String path) throws RemoteException { try { mPlayer.setDataSource(path); } catch (IOException e) { e.printStackTrace(); } } @Override public void prepare() throws RemoteException { try { mPlayer.prepare(); } catch (IOException e) { e.printStackTrace(); } } @Override public void release() throws RemoteException { mPlayer.release(); } @Override public boolean isPlaying() throws RemoteException { return mPlayer.isPlaying(); } @Override public void prepareAsync() throws RemoteException { mPlayer.prepareAsync(); } @Override public void setPlayingFinish() throws RemoteException { mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.d(Content.TAG,"play finish--------------"); Intent intent = new Intent(); intent.setAction(Content.ACTION_FINISH); sendBroadcast(intent); } }); } }; @Nullable @Override public IBinder onBind(Intent intent) { return stub; } @Override public void onCreate() { super.onCreate(); Log.d(Content.TAG, "------onCreate------"); mPlayer = new MediaPlayer(); } }
MusicActivity.java
public class MusicActivity extends Activity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, AdapterView.OnItemClickListener{ private final static String TAG = "MusicActivity"; protected static final int SEARCH_MUSIC_SUCCESS = 0;// 搜索成功标记 private SeekBar music_progress; private ImageView pre; private ImageView play; private ImageView next; private ListView music_listview; private MusicListAdapter mMusicListAdapter; private TextView total_time, play_time, music_title; private int currIndex = 0;// 表示当前播放的音乐索引 // 定义当前播放器的状态״̬ private static final int IDLE = 0; private static final int PAUSE = 1; private static final int START = 2; private static final int CURR_TIME_VALUE = 1; private int currState = IDLE; // 当前播放器的状态 private boolean flag = true;//控制进度条线程标记 String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/memoryCat/"; //定义线程池(同时只能有一个线程运行) ExecutorService mExecutorService = Executors.newSingleThreadExecutor(); List<String> list = new ArrayList<>(); IServicePlayer iPlayer; private MyBroadcast mMyBroadcast; private Handler hander = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case SEARCH_MUSIC_SUCCESS: //搜索音乐文件结束时 mMusicListAdapter = new MusicListAdapter(); music_listview.setAdapter(mMusicListAdapter); break; case CURR_TIME_VALUE: //设置当前时间 play_time.setText(msg.obj.toString()); try { music_progress.setProgress(iPlayer.getCurrentPosition()); music_progress.setMax(iPlayer.getDuration()); total_time.setText(toTime(iPlayer.getDuration())); } catch (RemoteException e) { e.printStackTrace(); } break; default: break; } } }; ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "-----onServiceConnected-----"); iPlayer = IServicePlayer.Stub.asInterface(service); try { if (iPlayer != null &&iPlayer.isPlaying()){ music_progress.setMax(iPlayer.getDuration()); music_progress.setProgress(iPlayer.getCurrentPosition()); play_time.setText(toTime(iPlayer.getCurrentPosition())); total_time.setText(toTime(iPlayer.getDuration())); play.setImageResource(R.drawable.pause); mExecutorService.execute(new Runnable() { @Override public void run() { runSeekBar(); } }); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); Log.d(Content.TAG,"onCreate"); getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_music); mMyBroadcast = new MyBroadcast(); IntentFilter mIntentFilter = new IntentFilter(); mIntentFilter.addAction(Content.ACTION_FINISH); registerReceiver(mMyBroadcast,mIntentFilter); init(); list.clear(); //是否有外部存储设备 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { new Thread(new Runnable() { String[] ext = {".mp3"}; File file = new File(path); public void run() { search(file, ext); hander.sendEmptyMessage(SEARCH_MUSIC_SUCCESS); } }).start(); } else { Toast.makeText(this, "请插入外部存储设备..", Toast.LENGTH_LONG).show(); } } private void init() { music_progress = (SeekBar) findViewById(R.id.music_progress); play = (ImageView) findViewById(R.id.play); pre = (ImageView) findViewById(R.id.pre); next = (ImageView) findViewById(R.id.next); music_listview = (ListView) findViewById(R.id.music_list); total_time = (TextView) findViewById(R.id.total_time); play_time = (TextView) findViewById(R.id.play_time); music_title = (TextView) findViewById(R.id.music_title); // setPlayingFinish bindService(new Intent(this, MusicService.class), conn, Context.BIND_AUTO_CREATE); startService(new Intent(MusicActivity.this, MusicService.class)); music_progress.setOnSeekBarChangeListener(this); pre.setOnClickListener(this); next.setOnClickListener(this); play.setOnClickListener(this); music_listview.setOnItemClickListener(this); } private String toTime(int time) { int minute = time / 1000 / 60; int s = time / 1000 % 60; String mm = null; String ss = null; if (minute < 10) mm = "0" + minute; else mm = minute + ""; if (s < 10) ss = "0" + s; else ss = "" + s; return mm + ":" + ss; } @Override public void onClick(View v) { try { iPlayer.setPlayingFinish(); } catch (RemoteException e) { e.printStackTrace(); } switch (v.getId()) { case R.id.play: try { play(); } catch (Exception e) { e.printStackTrace(); } break; case R.id.pre: previous(); break; case R.id.next: next(); break; } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { try { if (fromUser) { iPlayer.seekTo(progress); } } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { currIndex = position; start(); } private void runSeekBar() { flag = true; while (flag) { try { if (iPlayer.getCurrentPosition() < music_progress.getMax()) { music_progress.setProgress(iPlayer.getCurrentPosition()); Message msg = hander.obtainMessage(CURR_TIME_VALUE, toTime(iPlayer.getCurrentPosition())); hander.sendMessage(msg); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } else { flag = false; } } catch (RemoteException e) { e.printStackTrace(); } } } class MusicListAdapter extends BaseAdapter { @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = getLayoutInflater().inflate(R.layout.musiclist_item, null); } TextView tv_music_name = (TextView) convertView.findViewById(R.id.title); ViewGroup item_bg = (ViewGroup) convertView.findViewById(R.id.item_bg); if (list.get(currIndex).replace(path, "").replace(".mp3", "") .equals(list.get(position).replace(path, "").replace(".mp3", ""))) { item_bg.setBackgroundResource(R.drawable.item_bg); }else { item_bg.setBackground(null); } tv_music_name.setText(list.get(position).replace(path, "").replace(".mp3", "")); return convertView; } } private void play() throws Exception { switch (currState) { case IDLE: play.setImageResource(R.drawable.pause); start(); break; case PAUSE: iPlayer.pause(); play.setImageResource(R.drawable.play); currState = START; break; case START: iPlayer.play(); play.setImageResource(R.drawable.pause); currState = PAUSE; } } //上一首 private void previous() { if ((currIndex - 1) >= 0) { currIndex--; start(); mMusicListAdapter.notifyDataSetChanged(); } else { Toast.makeText(this, "当前已经是第一首歌曲了", Toast.LENGTH_SHORT).show(); } } //下一首 private void next() { if (currIndex + 1 < list.size()) { currIndex++; start(); mMusicListAdapter.notifyDataSetChanged(); } else { currIndex = 0; start(); Toast.makeText(this, "当前已经是最后一首歌曲了", Toast.LENGTH_SHORT).show(); } } //开始播放 private void start() { if (list.size() > 0 && currIndex < list.size()) { String SongPath = list.get(currIndex); try { iPlayer.reset(); iPlayer.setDataSource(SongPath); iPlayer.prepare(); iPlayer.play(); mExecutorService.execute(new Runnable() { @Override public void run() { runSeekBar(); } }); music_title.setText(list.get(currIndex).replace(path, "").replace(".mp3", "")); mMusicListAdapter.notifyDataSetChanged(); /* btnPlay.setImageResource(R.drawable.ic_media_pause);*/ currState = PAUSE; } catch (Exception e) { e.printStackTrace(); } } else { Toast.makeText(this, "播放列表为空", Toast.LENGTH_SHORT).show(); } } // 搜索音乐文件 private void search(final File file, final String[] ext) { if (file != null) { if (file.isDirectory()) { File[] listFile = file.listFiles(); if (listFile != null) { for (int i = 0; i < listFile.length; i++) { search(listFile[i], ext); } } } else { String filename = file.getAbsolutePath(); for (int i = 0; i < ext.length; i++) { if (filename.endsWith(ext[i])) { list.add(filename); break; } } } } } @Override protected void onDestroy() { mExecutorService.shutdownNow(); super.onDestroy(); } public class MyBroadcast extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { next(); } } }
MusicActivity加载的布局 :
activity_music.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg_music"> <RelativeLayout android:id="@+id/music_title_layout" android:layout_width="302dp" android:layout_height="133dp" android:layout_marginLeft="12dp" android:layout_marginTop="15dp" android:background="@drawable/bg_music_title" android:orientation="vertical"> <TextView android:id="@+id/music_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@string/music_title" android:textSize="14sp" android:textColor="#FFF57711" android:layout_marginTop="60dp"/> <LinearLayout android:layout_below="@+id/music_title" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/play_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:text="00:00" android:textSize="14sp" android:layout_marginLeft="20dp" android:textColor="#FF00984F"/> <SeekBar android:id="@+id/music_progress" android:layout_marginTop="7dp" android:layout_width="180dp" android:layout_marginLeft="5dp" android:progressDrawable="@drawable/po_seekbar" android:thumb="@null" android:layout_height="6dp" android:gravity="center_vertical" /> <TextView android:id="@+id/total_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:text="00:00" android:textSize="14sp" android:layout_marginLeft="5dp" android:textColor="#FF00984F"/> </LinearLayout> </RelativeLayout> <RelativeLayout android:id="@+id/play_control_layout" android:layout_width="250dp" android:layout_height="100dp" android:layout_alignParentBottom="true" android:layout_marginBottom="15dp" android:layout_marginLeft="40dp"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:gravity="center" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/pre" android:layout_gravity="center" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/pre" android:scaleType="centerInside" android:background="@drawable/button_bg"/> <View android:layout_width="100dp" android:layout_height="70dp" /> <ImageView android:id="@+id/next" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/next" android:scaleType="centerInside" android:background="@drawable/button_bg"/> </LinearLayout> <ImageView android:id="@+id/play" android:layout_width="70dp" android:layout_height="70dp" android:src="@drawable/play" android:layout_gravity="center" android:scaleType="centerInside" android:background="@drawable/button_bg"/> </FrameLayout> </RelativeLayout> <FrameLayout android:layout_alignTop="@id/music_title_layout" android:layout_alignParentRight="true" android:layout_marginRight="12dp" android:layout_width="196dp" android:layout_height="295dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="295dp" android:orientation="vertical" android:background="@drawable/bg_music_list"> <TextView android:id="@+id/music_list_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:gravity="center_horizontal" android:text="@string/music_list_title" android:textSize="16sp" android:textColor="#FF00984F" /> <ListView android:id="@+id/music_list" android:paddingTop="10dp" android:paddingBottom="30dp" android:paddingLeft="30dp" android:paddingRight="30dp" android:layout_width="match_parent" android:layout_height="match_parent"></ListView> </LinearLayout> <View android:background="#FF00984F" android:layout_gravity="center_horizontal" android:layout_width="150dp" android:layout_marginTop="50dp" android:layout_height="1dp" ></View> </FrameLayout> </RelativeLayout>
public class Content { public final static String TAG = "WPTAG"; public final static String ACTION_FINISH = "com.along.memorycat.FINISH"; }
主布局文件:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen"> <activity android:name=".MainActivity" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".MusicActivity" android:screenOrientation="landscape" /> <service android:name=".MusicService" android:enabled="true" android:exported="true" /> </application>