服务器service系统,关于Service你所需要知道内容(一)

根据下面的目录来介绍和理解Service中的知识点:

一.Service的两种生命周期

service启动有两种方式:启动服务startService,绑定服务bindService。有不同是生命周期,如下所示:

886d795b3343?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

image

1.若一个Service被多次startService启动,onCreate被调用一次,只有onStartCommand被调用多次。

2.onStartCommand必须放回一个整数=描述系统在杀死服务后应该如何继续运行:

a.START_NOT_STICKY;不会重建服务,除非还存在未发送的intent。当服务不再是必需的,并且应用程序能够简单地重启那些未完成的工作时,这是避免服务运行的最安全的选项。

b.START_STICKY;如果系统在onStartCommand()返回后杀死了这个service,会重新创建这个service并且调用onStartCommand(),但是不再重新发送上次最后一个intent,而是使用一个nullintent调用onStartCommand(),除非有一些挂起的intent,在此情况下,这些挂起的intent被派送。(适用媒体播放器类似服务,它们不执行命令,但需要一直运行并随时待命)

c.START_REDELIVER_INTENT;如果系统在onStartCommand()返回后杀死了service,重新创建这个service并且使用上次最后一个intent调用onStartCommand().任何挂起的intent都顺序地被派送。(这适合于活跃地执行一个工作并且应被立即恢复的服务,比如下载一个文件)

3.启动并绑定一个service,如果没有解绑,调用stopService无法杀死服务。

4.unBindService()解除绑定服务,内部调用服务的生命周期方法onUnbind(),然后调用onDestory()销毁服务。服务只能被解除绑定一次,如果unBindService方法被调用多次,就会出错。

5.startService启动服务,调用者退出,service依旧还在;bindService绑定服务,调用者退出,service也就退出。

二.Service的两种启动方式

启动服务startService代码

Intent intent = new Intent(TestActivity.this,TestService.class);

startService(intent);

绑定服务bindService代码

private ServiceConnection mTestServiceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

myBinder = (TestService.MyBinder) iBinder;

}

@Override

public void onServiceDisconnected(ComponentName componentName) {

}

};

Intent intent = new Intent(TestActivity.this,TestService.class);

bindService(intent,mTestServiceConnection,BIND_AUTO_CREATE);

绑定服务,首先要做的事情就是先用Map记录当前绑定服务所需的一些信息。 然后启动服务。

解绑服务,先从早前的Map集合中移除记录,然后停止服务。

如果再次解绑,无非就是再到这个map集合中找找有没有这条记录,没有就抛出服务没有注册的异常,也就是早前根本没有注册过任何服务。

三.远程服务

下图是根据不同方式对服务的分类,这里重点介绍实现远程服务

886d795b3343?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

服务分类.png

实现远程服务的代码:

AIDL代码

// IRemoteService.aidl

package com.example.chenpeng.julyapplication.service;

// Declare any non-default types here with import statements

import com.example.chenpeng.julyapplication.IParticipateCallback;

interface IRemoteService {

int add(int a , int b);

void join(IBinder token,String userName);

void leave(IBinder token);

List getParticipators();

void registerParticipateCallback(IParticipateCallback cb);

void unregisterParticipateCallback(IParticipateCallback cb);

}

创建完AIDL文件以后,点击Build->Rebuild Project,在app\build\generated\source\aidl\debug中会有对应的ADIL的Java接口文件。生成如下代码:

package com.example.chenpeng.julyapplication.service;

public interface IRemoteService extends android.os.IInterface

{

/** 内部类Stub,继承Binder */

public static abstract class Stub extends android.os.Binder implements com.example.chenpeng.julyapplication.service.IRemoteService

{

/**Binder的唯一标识,一般用当前的类名表示*/

private static final java.lang.String DESCRIPTOR = "com.example.chenpeng.julyapplication.service.IRemoteService";

public Stub()

{

this.attachInterface(this, DESCRIPTOR);

}

/**

* 用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程区分进程

* 如果客户端和服务端位于同一个进程,返回服务端的Stub对象本身;否则返回系统封装后的Stub.proxy对象

*/

public static com.example.chenpeng.julyapplication.service.IRemoteService asInterface(android.os.IBinder obj)

{

if ((obj==null)) {

return null;

}

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

if (((iin!=null)&&(iin instanceof com.example.chenpeng.julyapplication.service.IRemoteService))) {

return ((com.example.chenpeng.julyapplication.service.IRemoteService)iin);

}

return new com.example.chenpeng.julyapplication.service.IRemoteService.Stub.Proxy(obj);

}

/**返回当前Binder对象*/

@Override public android.os.IBinder asBinder()

{

return this;

}

/**

* 这个方法运行在服务端中的Binder线程池中,当客户端发起跨进程请求时,远程请求会通过系统底层封装后交由此方法处理。

* 通过code可以确定调用哪个方法,如有入参,从data中获取,方法完成后,如需要返回参数,将参数存入result中。

* 若果,onTransact返回false,则客户端的请求失败,因此可以利用这个特征来做权限验证。

* */

@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException

{

switch (code)

{

case INTERFACE_TRANSACTION:

{

reply.writeString(DESCRIPTOR);

return true;

}

case TRANSACTION_add:

{

data.enforceInterface(DESCRIPTOR);

int _arg0;

_arg0 = data.readInt();

int _arg1;

_arg1 = data.readInt();

int _result = this.add(_arg0, _arg1);

reply.writeNoException();

reply.writeInt(_result);

return true;

}

case TRANSACTION_join:

{

data.enforceInterface(DESCRIPTOR);

android.os.IBinder _arg0;

_arg0 = data.readStrongBinder();

java.lang.String _arg1;

_arg1 = data.readString();

this.join(_arg0, _arg1);

reply.writeNoException();

return true;

}

case TRANSACTION_leave:

{

data.enforceInterface(DESCRIPTOR);

android.os.IBinder _arg0;

_arg0 = data.readStrongBinder();

this.leave(_arg0);

reply.writeNoException();

return true;

}

case TRANSACTION_getParticipators:

{

data.enforceInterface(DESCRIPTOR);

java.util.List _result = this.getParticipators();

reply.writeNoException();

reply.writeStringList(_result);

return true;

}

case TRANSACTION_registerParticipateCallback:

{

data.enforceInterface(DESCRIPTOR);

com.example.chenpeng.julyapplication.IParticipateCallback _arg0;

_arg0 = com.example.chenpeng.julyapplication.IParticipateCallback.Stub.asInterface(data.readStrongBinder());

this.registerParticipateCallback(_arg0);

reply.writeNoException();

return true;

}

case TRANSACTION_unregisterParticipateCallback:

{

data.enforceInterface(DESCRIPTOR);

com.example.chenpeng.julyapplication.IParticipateCallback _arg0;

_arg0 = com.example.chenpeng.julyapplication.IParticipateCallback.Stub.asInterface(data.readStrongBinder());

this.unregisterParticipateCallback(_arg0);

reply.writeNoException();

return true;

}

}

return super.onTransact(code, data, reply, flags);

}

/**

* 这个方法运行在客户端

* 先把参数写入_data中,接着调用transact方法发起RPC(远程过程调用)请求,同时当前线程挂起;然后服务端的onTransact方法被调用,

* 直到RPC过程返回后,当前线程继续执行,并从_reply中取出RPC过程的返回结果,最后返回_reply中的数据

* */

private static class Proxy implements com.example.chenpeng.julyapplication.service.IRemoteService

{

private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote)

{

mRemote = remote;

}

@Override public android.os.IBinder asBinder()

{

return mRemote;

}

public java.lang.String getInterfaceDescriptor()

{

return DESCRIPTOR;

}

@Override public int add(int a, int b) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

int _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeInt(a);

_data.writeInt(b);

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

_reply.readException();

_result = _reply.readInt();

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

@Override public void join(android.os.IBinder token, java.lang.String userName) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeStrongBinder(token);

_data.writeString(userName);

mRemote.transact(Stub.TRANSACTION_join, _data, _reply, 0);

_reply.readException();

}

finally {

_reply.recycle();

_data.recycle();

}

}

@Override public void leave(android.os.IBinder token) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeStrongBinder(token);

mRemote.transact(Stub.TRANSACTION_leave, _data, _reply, 0);

_reply.readException();

}

finally {

_reply.recycle();

_data.recycle();

}

}

@Override public java.util.List getParticipators() throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

java.util.List _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

mRemote.transact(Stub.TRANSACTION_getParticipators, _data, _reply, 0);

_reply.readException();

_result = _reply.createStringArrayList();

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

@Override public void registerParticipateCallback(com.example.chenpeng.julyapplication.IParticipateCallback cb) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));

mRemote.transact(Stub.TRANSACTION_registerParticipateCallback, _data, _reply, 0);

_reply.readException();

}

finally {

_reply.recycle();

_data.recycle();

}

}

@Override public void unregisterParticipateCallback(com.example.chenpeng.julyapplication.IParticipateCallback cb) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeStrongBinder((((cb!=null))?(cb.asBinder()):(null)));

mRemote.transact(Stub.TRANSACTION_unregisterParticipateCallback, _data, _reply, 0);

_reply.readException();

}

finally {

_reply.recycle();

_data.recycle();

}

}

}

static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

static final int TRANSACTION_join = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

static final int TRANSACTION_leave = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

static final int TRANSACTION_getParticipators = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);

static final int TRANSACTION_registerParticipateCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);

static final int TRANSACTION_unregisterParticipateCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);

}

public int add(int a, int b) throws android.os.RemoteException;

public void join(android.os.IBinder token, java.lang.String userName) throws android.os.RemoteException;

public void leave(android.os.IBinder token) throws android.os.RemoteException;

public java.util.List getParticipators() throws android.os.RemoteException;

public void registerParticipateCallback(com.example.chenpeng.julyapplication.IParticipateCallback cb) throws android.os.RemoteException;

public void unregisterParticipateCallback(com.example.chenpeng.julyapplication.IParticipateCallback cb) throws android.os.RemoteException;

}

创建在服务端的Service代码

public class RemoteService extends Service {

private static final String TAG = "RemoteService";

private List mClient = new ArrayList<>();

private List mList = new ArrayList<>();

//RemoteCallbackList,帮我自动处理了Link-To-Death的问题

private RemoteCallbackList mRemoteCallbackList = new RemoteCallbackList<>();

private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {

@Override

public int add(int a, int b) throws RemoteException {

return a+b;

}

@Override

public void join(IBinder token, String userName) throws RemoteException {

if(findClient(token) < 0){

Client client = new Client(token,userName);

//注册客户端死掉的通知

mClient.add(client);

client.mToken.linkToDeath( client,0);

Log.i(TAG, "join: client token = " + token + " 加入client队列");

notifyParticipate(client.mName,true);

}else{

Log.i(TAG, "join: client成员已存在");

}

}

@Override

public void leave(IBinder token) throws RemoteException {

int index = findClient(token);

if(index >= 0 ){

Client client = mClient.get(index);

//取消注册

client.mToken.unlinkToDeath( client,0);

mClient.remove(client);

Log.i(TAG, "leave: 删除token = " + token);

notifyParticipate(client.mName,false);

}

}

@Override

public List getParticipators() throws RemoteException {

int size = mClient.size();

for(int i = 0 ; i < size ; i++){

mList.add(mClient.get(i).mName);

}

return mList;

}

@Override

public void registerParticipateCallback(IParticipateCallback cb) throws RemoteException {

mRemoteCallbackList.register(cb);

}

@Override

public void unregisterParticipateCallback(IParticipateCallback cb) throws RemoteException {

mRemoteCallbackList.unregister(cb);

}

};

//更新通知

private void notifyParticipate(String mName, boolean joinOrLeave) {

int length = mRemoteCallbackList.beginBroadcast();

for(int i = 0 ; i < length ; i++){

try {

//通知回调

mRemoteCallbackList.getBroadcastItem(i).onParticipate(mName,joinOrLeave);

} catch (RemoteException e) {

e.printStackTrace();

}

}

mRemoteCallbackList.finishBroadcast();

}

private int findClient(IBinder token){

int index = -1;

int size = mClient.size();

for(int i = 0 ; i < size ; i++){

if(mClient.get(i).mToken == token){

index = i;

}

}

return index;

}

@Nullable

@Override

public IBinder onBind(Intent intent) {

Log.i(TAG, "onBind: 绑定服务" );

return mBinder;

}

@Override

public void onDestroy() {

super.onDestroy();

mRemoteCallbackList.kill();

}

private class Client implements Binder.DeathRecipient{

IBinder mToken;

String mName;

public Client(IBinder token , String name){

mToken = token;

mName = name;

}

@Override

public void binderDied() {

//客户端的异常退出

int index = mClient.indexOf(this);

if(index < 0){

return;

}

Log.i(TAG, "binderDied: 异常退出的客户端名字 = " + mName);

mClient.remove(index);

}

}

}

在服务端的AndroidMinfest.xml中做一下配置

android:name=".service.RemoteService"

android:process=":remote"

android:exported="true"

>

//此处Intent的action最好写成“服务器端包名.aidl文件名”的形式

创建客户端,一个不同的应用,首先将aidl文件复制到工程中,位置内容必须原封不动,下面就是client的代码

public class MainActivity extends AppCompatActivity {

private Button mBindServiceBtn,mMethodBtn;

private IRemoteService mRemoteService;

private ServiceConnection mServiceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

mRemoteService = IRemoteService.Stub.asInterface(iBinder);

}

@Override

public void onServiceDisconnected(ComponentName componentName) {

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mBindServiceBtn = findViewById(R.id.bindServiceBtn);

mMethodBtn = findViewById(R.id.methodBtn);

mBindServiceBtn.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

//通过Intent指定服务端的服务名称和所在包,与远程Service进行绑定

//参数与服务器端的action要一致,即"服务器包名.aidl接口文件名"

Intent intent = new Intent("com.example.chenpeng.julyapplication.service.IRemoteService");

//Android5.0后无法只通过隐式Intent绑定远程Service

//需要通过setPackage()方法指定包名,否则启动失败

intent.setPackage("com.example.chenpeng.julyapplication");

bindService(intent,mServiceConnection,BIND_AUTO_CREATE);

}

});

mMethodBtn.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

if(mRemoteService != null){

try {

int sum = mRemoteService.add(2,4);

Toast.makeText(getApplicationContext(),String.valueOf(sum),Toast.LENGTH_SHORT).show();

} catch (RemoteException e) {

e.printStackTrace();

}

}

}

});

}

}

四.IntentService原理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值