2025年pass around服务(passport服务)

pass around服务(passport服务)1 1 基本概念 Service 只能在后台运行 适合那些不需要界面的操作 像是播放音乐或者监听动作等 因为它 的名字就已经提示了 它就是一个服务 Service 同样也是运行在主线程中 所以不能用它来做耗时的请求或者动作 否则就会阻塞住主线程 如果真的要这么做 可以跟 Activity 一样的做法 新开一个线程 1 2 启动方式 Service 根据启动方式分为两类 Started 和 Bound

大家好,我是讯享网,很高兴认识大家。



1.1基本概念

Service只能在后台运行,适合那些不需要界面的操作,像是播放音乐或者监听动作等,
因为它 的名字就已经提示了:它就是一个服务。
Service同样也是运行在主线程中,所以不能用它来做耗时的请求或者动作,
否则就会阻塞住主线程。如果真的要这么做,可以跟Activity一样的做法:新开一个线程。

1.2启动方式

Service根据启动方式分为两类:Started和Bound。其中,Started()是通过startService()来启动,主要用于程序内 部使用的Service,而Bound是通过bindService()来启动,允许多个应用程序共享同一个Service。

如果单单只是为了使用Service,两种方式都可以,但正如我们上面所看到 的,Bound启动的Service可以允许多个应用程序绑定到Service,所以,如果该Service是多个程序共享的,必须使用Bound来启动 Service。

1,声明Service:

2,共享Service:

如果没有定义Intent Filters,默认下是私有的,无法访问,当然,我们也可以显示的指定该访问权限:android:exported=false。


startService(); 服务一旦开启就跟开启者(activity)没有什么关系.activity挂了,服务还会开心的在后台运行.

创建Service,定义类继承Service,AndroidManifest.xml中定义

开启Service,在其他组件中调用startService方法

停止Service,调用stopService方法


bindService(); 服务跟activity就有了千丝万缕的联系. 如果调用者activity挂了
服务也跟着挂了. 不求同时生,但求同时死.
服务只能被显示的解除绑定一次,多次的解除绑定服务 应用程序会报异常

创建Service,定义类继承Service,AndroidManifest.xml中定义

开启Service,在其他组件中调用Context.bindService()来启动

绑定Service,onBind()

解绑Service,onUnbind()

停止Service,调用stopService方法

混合开启服务

需求: 服务长期的后台运行, 又想调用服务里面的方法.

startservice 开启服务 (保证服务长期后台运行)

unbindService 解除绑定服务
//解除绑定,不解除无法直接关闭服务
stopService 停止服务.

1.3 生命周期

Commons daemon services runner是什么服务_应用程序
讯享网

Service

常用的回调方法

Started

Service的生命周期不像Activity那样复杂,当我们通过Context.startService()启动Service的时候,系统就会调 用Service的onCreate(),接着就是onStartCommand(Intent, int, int),过去这个方法是onStart(),但现在onStart()已经不被鼓励使用了,onStartCommand()里面的代码就是我们 Service所要执行的操作,接着就是onDestroy(),关闭Service。

Bound

通过Context.bindService()来启动,系统同样会调用Service的onCreate(),接着并不是 onStartCommand()而是onBind(),它会将多个客户端绑定到同一个服务中。如果我们想要停止Service,必须先对客户端解绑,也 就是调用onUnbind(),然后就是onDestroy()。

混合模式

如果先采用startService()方法启动服务,然后调用bindService()方法绑定到服务,再调用unbindService()方法解除绑定,最后调用bindService()方法再次绑定到服务

注意:

服务一旦被创建,就不会重新创建了.
服务的oncreate方法只会执行一次,如果服务已经开启,就不会再去执行oncreate方法
服务在停止的时候,会调用ondestroy方法
每一次开启服务的时候 都会调用 onStartCommand() onStart();

1.4 Started Service 详细用法

接下来我们就来创建一个简单的Service:MyService,用于在后台播放MP3。这是介绍Service时经常用到的例子。

定义好Service后,我们就可以在Activity中启动该Service:

如果是当用户使用我们的应用程序,像是点击按钮的时候,才执行一个在主线程外面的操作,我们需要的就是一个Thread而不是Service。

还是我们上面的例子,如果我们想要播放音乐是在我们应用程序运行的时候,那么我们可以再onCreate()中新建一个Thread, 然后在onStartCommand()中开始该Thread,接着是在onStop()中停止该Thread。这样的做法非常自然,是一般的新手都会想 到的,但是android鼓励我们使用AsyncTask或者HandlerThread来处理这个过程。

当我们开启了一个Service,我们就有义务去决定什么时候关闭该Service。可以通过stopSelf()让Service自己关闭自己或者调用stopService()来关闭该Service。
当内存不够的时候,系统也会自动关闭Service。这时系统是如何选择哪些Service应该被关闭呢?如果一个Service被绑定到 Activity并且得到用户的焦点,那么它就很少可能会被关闭,但如果它是被声明运行在前台,它就永远也不可能会被关闭。
知道这个事实对我们有什么用呢?当然是考虑如果内存足够的时候我们如何重启Service。
解决这个问题的关键就在于onStartCommand()的返回值。

onStartCommand()指定要求返回一个整数值,这个整数值描述的就是系统应该以何种方式来重启该Service,一共有下面三种方式:

1.START_NOT_STICKY:系统在关闭Service后,不需要重新创建该Service,除非我们传递Intent要求创建Service。这是避免不必要的Service运行的最安全的方式,因为我们可以自己指定什么时候重新启动该Service。

关闭Service有两种方式:stopSelf()和stopService()
它们是有区别的,而且区别非常大。如果我们在一个应用程序中开启了多 个Service,那么我们就不能贸然的使用stopService()来关闭Service,因为前一个Service的关闭可能会影响到后面 Service的使用。这时我们就需要使用stopSelf(int startId)来决定关闭哪个Service。
关闭Service是非常重要的,这对于减少内存消耗和电量消耗来说,都是一件好事。
Service是在后台运行的,但是有时候我们需要向用户发送一些提示,像是下载完成之类的,这时就可以通过Toast或者Status Bar了。

我们上面提到,Service可以运行在前台,这点就非常奇怪了:Service不是后台运行的吗?其实不然,有时候我们也想要清楚的知 道Service的进度,像是下载文件的进度或者歌曲的播放进度。这种Service一般都会在android手机上显示”正在进行的”的提示框里可以看 到(就是我们手机上可以拉下来的那个框)。

这种Service一般都是通过Status Bar来提示进度,只有Service完成工作后才会消失:
···
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

IntentService就像是一个封装好的Service,方便我们处理多个Intent的情况,但如果我们想要覆写其他方法,也是可以的,但要确保每个方法最后都有调用super的实现。


要想创建Bound Service,我们就必须定义一个IBinder,它用于说明客户端是如何和服务通信的。Bound Service是一个非常大的话题,因为它涉及到本地服务还有远程服务。

  1. 在activity 采用bindService方式开启服务…
  2. 写一个实现类 MyConn implements ServiceConnection
  3. 接口里面有一个方法onServiceConnected 在服务成功绑定的时候调用的方法
  4. 在service代码 实现 onBind方法 返回一个IBinder接口的实现( 里面必须一个调用服务方法的api)
  5. 在服务成功绑定的时候 服务里面返回的IBinder对象会传给 activity里面onServiceConnected 方法
  6. 获取IBinder对象 中间人, 调用中间人的方法. 间接调用了服务里面的方法

应用
音乐播放器 : 音乐后台长期播放. service. 绑定本地服务.
我们先从简单的本地服务开始:

这个例子非常简单,就是为每个绑定到该服务的客户产生一个0-100的随机数。
我们首先必须提供一个IBinder的实现类,该类返回的是我们Service的一个实例,这是为了方便客户调用Service的公共方法,接着我们在onBind()方法中返回这个IBinder的实现类。
这种做法适合Service只在应用程序内部共享,我们可以这样使用这个Service:

我们通过bindService()将Activity和Service绑定到一起,接着必须定义一个 ServiceConnection,为的就是通过绑定的IBinder的getService()方法来获得Service,然后我们再调用 Service的getRandomNumber()。使用完后,我们需要通过unbindService()来解除绑定。

这里充分利用了回调的价值。这种方式仅仅适合客户和服务都在同一个应用程序和一个进程内,像是音乐程序的后台播放。

混合调用:
结合我们上面有关Started Service的讨论,我们知道,可以用两种方式来开启服务,StartedService完全可以变成Bound Service,这样我们就不用显式的关闭服务,当没有任何客户和该Service绑定的时候,系统会自动的关闭该Service。但如果我们在一个 Started Service中也同样使用了onBind()呢?像是这样的情况:我们在一个音乐播放程序中利用Started Service开启音乐播放,然后用户离开程序后,音乐会在后台播放,当用户重新返回到程序中时,Activity可以绑定到Service上以便对音乐 进行控制。我们可以使用onRebind()方法来做到这点。
这就是既是Started Service又是Bound Service的整个生命周期。

1.5.2. 远程服务

1.5.2.1. 通过Messenger实现进程间通信
但我们有时候需要和远程的进程进行通信,这时就需要使用Messenger,这是为了实现进程间通信但又不想使用AIDL的唯一方式。
我们还是先来个简单例子:

可以看到,我们必须先在Service里面实现一个Handler,然后将这个Handler传递给Messenger,然后在onBind()中返回的是该Messenger的getBinder()的返回值。

Activity所要做的就是创建一个Messenger,该Messenger拥有Service返回的IBinder,接着就是发送消息给 Service,然后Service中的Handler根据消息进行处理。我们可以看到,Messenger之所以能够实现进程间的通信,靠的还是 Handler。

AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,供编译器生成代码,实现Android设备上的两个进程间通信(IPC)。AIDL的IPC机制和EJB (Enterprise Java Bean JAVA中的商业应用组件技术) 所采用的CORBA (Common Object Request Broker Architecture 是一组用来定义“分布式对象系统”的标准) 很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后再转换成相应的对象。由于进程之间的通信信息需要双向转换,所以android采用代理类在背后实现了信息的双向转换,代理类由android编译器生成,对开发人员来说是透明的。

实现进程通信,一般需要下面四个步骤:

假设A应用需要与B应用进行通信,调用B应用中的download(String path)方法,B应用以Service方式向A应用提供服务。需要下面四个步骤:

1>

package cn.itcast.aidl;
interface IDownloadService {
void download(String path);
}

当完成aidl文件创建后,eclipse会自动在项目的gen目录中同步生成IDownloadService.java接口文件。接口文件中生成一个Stub的抽象类,里面包括aidl定义的方法,还包括一些其它辅助方法。值得关注的是asInterface(IBinder iBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换。

编写Aidl文件时,需要注意下面几点:

1.接口名和aidl文件名相同。
2.接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。
3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。
4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。
5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。
6.Java原始类型默认的标记为in,不能为其它标记。

2>

在B应用中实现aidl文件生成的接口(本例是IDownloadService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

3>

在B应用中创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:

4>

把B应用中aidl文件所在package连同aidl文件一起拷贝到客户端A应用,eclipse会自动在A应用的gen目录中为aidl文件同步生成IDownloadService.java接口文件,接下来就可以在A应用中实现与B应用通信,代码如下:

1.5.2.3. 通过Parcelable实现在AIDL间传递自定义类型参数

Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),如果要传递自定义的类型该如何实现呢?

Parcelable接口
要传递自定义类型,首先要让自定义类型支持parcelable协议,实现步骤如下:
1>自定义类型必须实现Parcelable接口,并且实现Parcelable接口的public void writeToParcel(Parcel dest, int flags)方法 。
2>自定义类型中必须含有一个名称为CREATOR的静态成员,该成员对象要求实现Parcelable.Creator接口及其方法。
3> 创建一个aidl文件声明你的自定义类型。
Parcelable接口的作用:实现了Parcelable接口的实例可以将自身的状态信息(状态信息通常指的是各成员变量的值)写入Parcel,也可以从Parcel中恢复其状态。 Parcel用来完成数据的序列化传递。

进程间传递自定义类型的实现过程:

1>

创建自定义类型,并实现Parcelable接口,使其支持parcelable协议。如:在cn.itcast.domain包下创建Person.java:

2>

在自定义类型所在包下创建一个aidl文件对自定义类型进行声明,文件的名称与自定义类型同名。
package cn.itcast.domain;
parcelable Person;

3>

在接口aidl文件中使用自定义类型,需要使用import显式导入,本例在cn.itcast.aidl包下创建IPersonService.aidl文件,内容如下:
package cn.itcast.aidl;
import cn.itcast.domain.Person;
interface IPersonService {
void save(in Person person);
}

4>

在实现aidl文件生成的接口(本例是IPersonService),但并非直接实现接口,而是通过继承接口的Stub来实现(Stub抽象类内部实现了aidl接口),并且实现接口方法的代码。内容如下:

5>

创建一个Service(服务),在服务的onBind(Intent intent)方法中返回实现了aidl接口的对象(本例是ServiceBinder)。内容如下:

其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:

1.5.3. 绑定远程服务和本地服务的区别:
  1. 本地服务 直接定义IService.java的接口
    远程服务 定义一个IService.adil文件 更改扩展名 删除public
  2. 本地服务 extend Binder implement IServcie
    远程服务 extend IService.Stub
  3. 本地服务 绑定成功 直接强制类型转换 IServcie
    远程服务 绑定成功 IService.Stub.asInterface(service)

小讯
上一篇 2025-05-25 15:58
下一篇 2025-05-12 10:05

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/176010.html