android播放器(music player)源码分析3,android播放器(music player)源码分析1-Service,Binder,ServiceConnection...

2023-05-16

Android SDK 提供了两种类型的 Service ,用于类似 *nix 守护进程或者 windows 的服务

1.本地服务 Local Service:用于应用程序内部

2.远程服务 Remote Service:用于 android 系统内部的应用程序之间

前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程式比如 Activity 所属线程,而是单开线程后台执行,这样用户体验比较好。

后者可被其他应用程序服用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

不需要和 Activitye 交互的本地服务

本地服务编写比较简单。首先,要创建一个 Service 类,该类继承 android 的 Service 类。然后在 Activity 中的 onCreate 和 onDestory 中分别执行以下语句开启服务和停止服务。

this .startService( new Intent( this , ServiceImpl. class ));

this .stopService( new Intent( this , ServiceImpl. class ));

需要和 Activity 交互的远程服务

上面的示例是通过 startService 和 stopService 启动关闭服务的。适用于服务和 activity 之间没有调用交互的情况。如果之间需要传递参数或者方法调用。需要使用 bind 和 unbind 方法。

具体做法是,服务类需要增加接口,比如 ServiceInterface ,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承 Binder 类并实现 ServiceInterface 接口。还有,就是要实现 Service 的 onBind 方法,不能只传回一个 null 了。

在 android 的 musicplayer 源码中 MediaPlaybackService 使用了以上的服务方式,针对该源码进行分析:

首先需要了解进程间通信、需要 AIDL (以及 Binder )

关于 AIDL 的介绍在文档: docs/guide/developing/tools/aidl.html

关于 IBinder 的介绍在文档: docs/reference/android/os/IBinder.html

以及 Binder : docs/reference/android/os/Binder.html

manifest 中 Service 的语法,见 docs/guide/topics/manifest /service-element.html

步骤一:建立 aidl 文件

通过 aidl.exe 会在 gen 中生成该 service 类,该类中的成员变量 stub 实现了以下功能:

extends Binderimplements ServiceInterface,源码如下

Java代码

interfaceIMediaPlaybackService

{

voidopenfile(String path);

voidopenfileAsync(String path);

voidopen(inint[] list,intposition);

...................//接口方法

}

interface IMediaPlaybackService

{

void openfile(String path);

void openfileAsync(String path);

void open(in int [] list, int position);

...................//接口方法

}

Java代码

publicinterfaceIMediaPlaybackServiceextendsandroid.os.IInterface {

/**生成binder类 */

publicstaticabstractclassStubextendsandroid.os.Binderimplements

com.android.mymusic.IMediaPlaybackService {

privatestaticfinaljava.lang.String DESCRIPTOR ="com.android.mymusic.IMediaPlaybackService";

/** Construct the stub at attach it to the interface. */

publicStub() {

this.attachInterface(this, DESCRIPTOR);

}

...................

...................

...................//binder 方法

}

publicvoidopenfile(java.lang.String path)

throwsandroid.os.RemoteException;

...................

...................//接口方法

...................

}

public interface IMediaPlaybackService extends android.os.IInterface {

/**生成binder类 */

public static abstract class Stub extends android.os.Binder implements

com.android.mymusic.IMediaPlaybackService {

private static final java.lang.String DESCRIPTOR = "com.android.mymusic.IMediaPlaybackService";

/** Construct the stub at attach it to the interface. */

public Stub() {

this.attachInterface(this, DESCRIPTOR);

}

...................

...................

...................//binder 方法

}

public void openfile(java.lang.String path)

throws android.os.RemoteException;

...................

...................//接口方法

...................

}

步骤二:编写服务的实现类 MediaPlaybackService

Java代码

publicclassMediaPlaybackServiceextendsService {

......

@Override

publicIBinder onBind(Intent intent) {

mDelayedStopHandler.removeCallbacksAndMessages(null);

mServiceInUse =true;

returnmBinder;

}

privatefinalIMediaPlaybackService.Stub mBinder =newIMediaPlaybackService.Stub()

{

...................//实现接口方法

};

}

public class MediaPlaybackService extends Service {

......

@Override

public IBinder onBind(Intent intent) {

mDelayedStopHandler.removeCallbacksAndMessages(null);

mServiceInUse = true;

return mBinder;

}

private final IMediaPlaybackService.Stub mBinder = new IMediaPlaybackService.Stub()

{

...................//实现接口方法

};

}

步骤三:编写一个消费这个服务的 Activity : MediaPlaybackActivity: (除此之外还有其他类)

Java代码

publicclassMediaPlaybackActivityextendsActivityimplementsMusicUtils.Defs,

View.OnTouchListener, View.OnLongClickListener

{

privateIMediaPlaybackService mService =null;

@Override

publicvoidonStart() {

super.onStart();

...................//其他代码

if(false== MusicUtils.bindToService(this, serviecConnection)) {

// something went wrong

...................//其他代码

}

privateServiceConnection serviecConnection =newServiceConnection() {

publicvoidonServiceConnected(ComponentName classname, IBinder obj) {

mService = IMediaPlaybackService.Stub.asInterface(obj);

if(MusicUtils.sService ==null) {

MusicUtils.sService = mService;

...................//其他代码

}

}

publicvoidonServiceDisconnected(ComponentName classname) {

}

};

}

//MusicUtils类:定义了播放器所需要的操作以及service和Activity之间的相互作用的操作

publicclassMusicUtils {

...................//其他代码

publicstaticbooleanbindToService(Context context, ServiceConnection callback) {

context.startService(newIntent(context, MediaPlaybackService.class));

ServiceBinder sb =newServiceBinder(callback);

sConnectionMap.put(context, sb);

returncontext.bindService((newIntent()).setClass(context,

MediaPlaybackService.class), sb,0);

}

...................//其他代码

}

public class MediaPlaybackActivity extends Activity implements MusicUtils.Defs,

View.OnTouchListener, View.OnLongClickListener

{

private IMediaPlaybackService mService = null;

@Override

public void onStart() {

super.onStart();

...................//其他代码

if (false == MusicUtils.bindToService(this, serviecConnection)) {

// something went wrong

...................//其他代码

}

private ServiceConnection serviecConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName classname, IBinder obj) {

mService = IMediaPlaybackService.Stub.asInterface(obj);

if (MusicUtils.sService == null) {

MusicUtils.sService = mService;

...................//其他代码

}

}

public void onServiceDisconnected(ComponentName classname) {

}

};

}

//MusicUtils类:定义了播放器所需要的操作以及service和Activity之间的相互作用的操作

public class MusicUtils {

...................//其他代码

public static boolean bindToService(Context context, ServiceConnection callback) {

context.startService(new Intent(context, MediaPlaybackService.class));

ServiceBinder sb = new ServiceBinder(callback);

sConnectionMap.put(context, sb);

return context.bindService((new Intent()).setClass(context,

MediaPlaybackService.class), sb, 0);

}

...................//其他代码

}

需要注意:

远程服务往往不只是传递 java 基本数据类型。这时需要注意 android 的一些限制和规定:

以下转自 http://yangguangfu.javaeye.com/blog/699306

1.android 支持 String 和 CharSequence

2.如果需要在 aidl 中使用其他 aidl 接口类型,需要 import ,即使是在相同包结构下;

3.android 允许传递实现 Parcelable 接口的类,需要 import ;

4.android 支持集合接口类型 List 和 Map ,但是有一些限制,元素必须是基本型或者上述三种情况,不需要 import 集合接口类,但是需要对元素涉及到的类型 import ;

非基本数据类型,也不是 String 和 CharSequence 类型的,需要有方向指示,包括 in 、 out 和 inout , in 表示由客户端设置, out 表示由服务端设置, inout 是两者均可设置。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

android播放器(music player)源码分析3,android播放器(music player)源码分析1-Service,Binder,ServiceConnection... 的相关文章

  • 意图?如何注册以获得传入电子邮件提醒?

    这里是极限 Android 开发新手 好吧 Android 开发新手 而不是一般开发 我想编写一个应用程序 当电子邮件进入设备时会收到通知 并根据电子邮件中的数据 主题 发件人 收件人等 采取各种操作 我认为我要做的是创建一个带有 Inte
  • 不同 Android 设备上 box2D 中出现奇怪的“口吃”

    我正在用 C 同时开发引擎和游戏 并使用 box2D 作为物理后端 我正在不同的 Android 设备上进行测试 在三分之二的设备上 游戏运行良好 物理效果也很好 然而 在我的 Galaxy Tab 10 1 上 我偶尔会遇到某种 口吃 的
  • 如何使用retrofit2进行GET请求?

    我有一个在本地主机上运行的安静的 Web 服务 我想在该剩余 URL 上发出 Retrofit2 GET 请求 MainActivity java private void requestData public static final S
  • OPENGL ES 不工作:无当前上下文

    我尝试了 OpenGL ES2 for Android 一书中所示的程序 但它不起作用 我已经在Odroid E 三星s3 三星y 三星star上进行了测试 the gl version suported returns 2 but i g
  • Android 中的 java.util.Observable 是线程安全的吗?

    Android 中的 java util Observable 是线程安全的吗 这文档 http developer android com reference java util Observable html说只有deleteObser
  • 如何忽略 LeakCanary 中的某些类?

    有人能给我一个如何忽略 LeakCanary 中的某些类的有效示例吗 我正在查看这个示例 以忽略 LeakCanary 中第三方库中的某些类 但我不知道将其放在应用程序中的何处 我把它放在我的应用程序类中 但这些变量和方法有错误 isInA
  • FLAG_ACTIVITY_REORDER_TO_FRONT 被忽略

    我有一个包含项目列表的 FragmentActivity 当应用程序处于后台时 可以推送该项目列表 发生这种情况时 我想创建一个状态栏通知并提醒用户更新 当用户单击通知时 活动应重新排序到前面并显示在屏幕上 同时在列表底部显示新项目 所以我
  • Android 8.1 中 Activity 自行旋转并恢复正常

    我的应用程序在所有 Android 版本上运行良好 但我注意到在 Android 8 1 0 Oreo 中 当我将屏幕从纵向活动转到横向活动时 以及当我按后退按钮时 它会显示异常行为 屏幕自动从横向旋转并恢复正常 看起来 Activity
  • 在 Android 中始终以横向模式打开相机

    在我的 Android 应用程序中 单击按钮后我希望相机以横向模式打开 即使我将手机旋转为纵向模式 相机也应始终处于横向模式或纵向模式 使用此代码在横向模式下打开相机 Intent cameraIntent new Intent Media
  • 无法在云控制台中启用 Maps SDK for Android

    我在云控制台中启用适用于 Android 的 Maps SDK 时遇到此问题 https console cloud google com https console cloud google com 它会抛出以下错误 附截图 我收到错误消
  • 如何在android中画一条曲线?

    我是 Android 新手 正在开发一个关于绘制线条的示例项目 我想画一条连接两点的曲线或高架线 x1 y1 and x2 y2 我试过canvas drawArc 方法 但是RectF内的值drawArc方法只是圆的 x y 中心点 它在
  • Android Drawable 绘图性能?

    在我看来 我有一个简单的 ARGB 可绘制对象 大约需要 2 毫秒才能绘制 但我可以在 0 5 毫秒内绘制与位图相同的文件 只是一些快速代码 我真的不能认为它是一个选项 优化可绘制对象的绘制速度的最佳方法是什么 这取决于可绘制的数量以及每个
  • 按名称获取 ArrayList

    这是正确的获取方式吗ArrayList
  • 无法登录 Google Play 游戏服务

    我在开发者控制台上使用包名称和正确的签名证书设置了我的游戏 并为其创建了排行榜 但没有创建任何成就 然后 我从以下位置下载了示例 Type A Number Challenge 和 BaseGameUtils https developer
  • BitmapFactory.decodeResource() 忽略 jpg 图像的 inPreferredConfig 选项

    我尝试将jpeg资源图像加载到ARGB 8888格式的位图 BitmapFactory Options opts new BitmapFactory Options opts inPreferredConfig Bitmap Config
  • 在片段之间切换时底部导航栏会向下推

    在我的活动中 我有一个底部导航栏和框架布局来显示片段 一切正常 但问题是当我开始按顺序从 1 4 移动时 底部导航栏保持在其位置 但当我突然从 4 跳到2 然后底部导航栏就会超出屏幕 当再次单击同一项目时 它就会回到正常位置 该视频将清楚地
  • Android 4.2 - Environment.getExternalStorageDirectory().getPath() 行为

    我一直在开发一个android应用程序 在上次更新到4 2之前 我使用 Environment getExternalStorageDirectory getPath 它返回了我 storage sdcard0 但自从更新后我现在得到了 s
  • 应用程序中空指针异常[重复]

    这个问题在这里已经有答案了 我正在尝试在我的应用程序中实施应用程序内计费 我写了这段代码 public class Settings extends PreferenceFragment ServiceConnection mService
  • Android复杂布局线性和相对

    I have to implement a layout like shown in the diagram and I do not know the best combination to achieve the required de
  • Android Jasper 报告

    Jasper Reporting 可以集成到 Android 应用程序中吗 我正在尝试从 jrxml 文件生成 PDF CSV 文本和 XLS 报告 但是 我没有看到 Android SDK 支持 net sf jasperreports

随机推荐