Android(安卓)AIDL和远程Service调用(一)
第一、我们知道在AndroId中如果需要进行音乐播放,最方面的方法就是使用自带的MediaPlayer对象,如果我们在Activity中控制MediaPlayer对象进行播放,那么一旦你打开了另外一个程序譬如浏览器,那么歌声就会立刻停止,这当然不是我们需要的结果。 我们需要的是在做其他事情的同时能够在后台听歌,于是我们就需要把对MediaPlayer对象的操作放在后台Service中去。
第二、我们已经把对MediaPlayer的操作转移到Service中去了,按照我们以前的做法,我们在Activity中发送一个Intent对象给Service对象,在Intent中传送播放啊、暂停啊一类的信息给Service,这样Service就知道该怎么做了。这一切看起来很美好,可是现在出了一个新问题,那就是我想在Activity中显示一个进度条,这个进度条要跟着Service中的MediaPlayer中的歌曲进度同步向前走,而且如果我点击进度条中的某一个位置,还想让歌曲跳转到新的时间点继续播放,这个,该怎么实现?
第三、我们需要在Activity中操作Service中的MediaPlayer对象,就好像这个对象是自己的一样。我们可以采用Android接口定义语言 AIDL(Android Interface Definition Language)技术:
1、把Service中针对MediaPlayer的操作封装成一个接口(.aidl文件)
2、在Service中建个子类实现这接口的存根(stub)对象
3、并在onBind()方法中返回这个存根对象。
4、在Activity中使用绑定服务的方式连接Service,但是不用Intent来传递信息,而是在ServiceConnection的onServiceConnected方法里,获得Service中Stub对象的客户端使用代理。我们通过操作Activity中的代理就可以达到操作Service中的MediaPlayer对象的目的。这样我们就可以想用本地对象一样操作Service中的对象了,那么进度条一类的需求自然也就迎刃而解。
1、新建一个项目 App_elfPlayer ,启动Activity是个启动画面:CoverActivity
2、AndroidManifest.xml 的内容如下:
java代码:
<?xml version="1.0" encoding="utf-8"?> <MANIFEST android:versionname="1.0" android:versioncode="1" xmlns:android=http://schemas.android.com/apk/res/android"package="eoe.demo"> <USES android:minsdkversion="7" -sdk /><USES android:name="android.permission.WRITE_EXTERNAL_STORAGE" -permission></USES><APPLICATION android:icon="@drawable/icon" android:label="@string/app_name"> <ACTIVITY android:name=".CoverActivity"> <INTENT -filter> <ACTION android:name="android.intent.action.MAIN" /> <CATEGORY android:name="android.intent.category.LAUNCHER" /> </INTENT> </ACTIVITY> <ACTIVITY android:name=".PlayerActivity"> </ACTIVITY> <SERVICE android:name=".MusicService" android:enabled="true"> </SERVICE> </APPLICATION> </MANIFEST>
我们注意到有2个Activity,1个Service,还有读写外部存储的权限声明
3、CoverActivity.java的代码如下:这是个全屏的启动画面,2秒后会跳转到PlayerActivity
java代码:
package eoe.demo; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.Window; import android.view.WindowManager; public class CoverActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.cover); new Handler().postDelayed(new Runnable(){ @Override public void run() { Intent mainIntent = new Intent(CoverActivity.this,PlayerActivity.class); CoverActivity.this.startActivity(mainIntent); CoverActivity.this.finish(); } }, 2000); } }
4、PlayerActivity.java的代码如下:
java代码:
package eoe.demo; import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message; import android.os.RemoteException;import android.util.Log;import android.view.View;import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener;public class PlayerActivity extends Activity {public static final int PLAY = 1; public static final int PAUSE = 2; ImageButton imageButtonFavorite; ImageButton imageButtonNext; ImageButton imageButtonPlay; ImageButton imageButtonPre; ImageButton imageButtonRepeat; SeekBar musicSeekBar; IServicePlayer iPlayer; boolean isPlaying = false; boolean isLoop = false;@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.player); imageButtonFavorite = (ImageButton) findViewById(R.id.imageButtonFavorite); imageButtonNext = (ImageButton) findViewById(R.id.imageButtonNext);imageButtonPlay = (ImageButton) findViewById(R.id.imageButtonPlay);imageButtonPre = (ImageButton) findViewById(R.id.imageButtonPre);imageButtonRepeat = (ImageButton) findViewById(R.id.imageButtonRepeat);musicSeekBar = (SeekBar) findViewById(R.id.musicSeekBar);bindService(new Intent(PlayerActivity.this, MusicService.class), conn, Context.BIND_AUTO_CREATE); startService(new Intent(PlayerActivity.this, MusicService.class));imageButtonPlay.setOnClickListener(new View.OnClickListener() {@Override public void onClick(View v) { Log.i("yao", "imageButtonPlay -> onClick"); if (!isPlaying) { try { iPlayer.play(); } catch (RemoteException e) { e.printStackTrace(); } imageButtonPlay.setBackgroundResource(R.drawable.pause_button); isPlaying = true; } else { try { iPlayer.pause(); } catch (RemoteException e) { e.printStackTrace(); } imageButtonPlay.setBackgroundResource(R.drawable.play_button);isPlaying = false;}}}); musicSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {@Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (iPlayer != null) { try { iPlayer.seekTo(seekBar.getProgress()); } catch (RemoteException e) { e.printStackTrace(); }}}}); handler.post(updateThread); } private ServiceConnection conn = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { Log.i("yao", "ServiceConnection -> onServiceConnected"); iPlayer = IServicePlayer.Stub.asInterface(service); } public void onServiceDisconnected(ComponentName className) { }; }; Handler handler = new Handler() {@Override public void handleMessage(Message msg) { }; }; private Runnable updateThread = new Runnable() { @Override public void run() { if (iPlayer != null) { try { musicSeekBar.setMax(iPlayer.getDuration()); musicSeekBar.setProgress(iPlayer.getCurrentPosition()); } catch (RemoteException e) { e.printStackTrace(); } } handler.post(updateThread); } }; }
更多相关文章
- 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
- android文档查询小工具
- ym—— Android(安卓)5.0学习之感想篇(含Demo)
- Android本地视频播放器开发--搜索本地视频(2)
- Android(安卓)MultiMedia框架完全解析 - 概览
- android实现软键盘弹出,editText随键盘上移,背景不动
- Android的Socket 通信
- Android菜鸟的成长笔记(5)——Android系统源代码你下载了吗?
- Android(安卓)SDK中的必会工具——ADB是真的香