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

2023-11-14

根据下面的目录来介绍和理解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原理

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

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

随机推荐

  • Python: 装饰器和语法糖

    一 Python 装饰器 Python 装饰器本身就是一个函数 它的作用是装饰一个其他的函数 但是不改变原有的程序功能 还要增添新的功能 调用函数时的接口没有变化 比如 装修一个房子 如果不隔音 我在墙上加一层隔音板 却不能把墙拆了 换成隔
  • C# 关于浏览器——WebBrowser篇

    最近要写一个浏览器包裹一个网站 试了各种浏览器插件 记录一下 第一个就是微软的WebBrowser 这个很容易 直接拖过来 然后写一下注册表调用IE11的内核显示 这个代码是抄的
  • python金融数据分析马伟明_Python金融数据分析

    前言 第1章Python在金融中的应用 1 1Python适合我吗 1 1 1免费 开源 1 1 2高级 强大 灵活的编程语言 1 1 3丰富的标准库 1 2面向对象编程与函数式编程 1 2 1面向对象式方法 1 2 2函数式方法 1 2
  • docker day04

    Dockerfile FORM 1 指定基础镜像 可以起别名 也可以指定多个FROM指令 用于多阶段构建 2 加载触发器 加载ONBUILD指令 3 不指定基础镜像 声明当前镜像不依赖任何镜像 官方保留字 scratch RUN 1 在容器
  • 循序渐进,学会用pyecharts绘制瀑布图

    循序渐进 学会用pyecharts绘制瀑布图 瀑布图简介 瀑布图 Waterfall Plot 是由麦肯锡顾问公司所独创的图表类型 因为形似瀑布流水而称之为瀑布图 瀑布图采用绝对值与相对值结合的方式 适用于表达多个特定数值之间的数量变化关系
  • 串口调试助手与CH340驱动分享

    串口调试助手与CH340驱动分享 分享以下资源给大家 包括CH340与CH341驱动 野火以及正点原子的串口调试助手 网盘链接 链接 https pan baidu com s 1cARKBdzJhDcrQrBSfs2Nlw 提取码 fxv
  • python: PyCharm 2023.1打包项目成执行程序

    IDE 最底部 pyinstaller i heart ico D main py 生成成功
  • d指针在Qt上的应用及实现

    Qt为了使其动态库最大程度上实现二进制兼容 引入了d指针的概念 那么为什么d指针能实现二进制兼容呢 为了回答这个问题 首先弄清楚什么是二进制兼容 所谓二进制兼容动态库 指的是一个在老版本库下运行的程序 在不经过编译的情况下 仍然能够在新的版
  • Unity TimeLine循环播放某个时间段

    1 设置Playable Director的Update Method为GameTime模式 2 API using UnityEngine Playables 我们需要用到PlayableDirector的time属性 3 设置开始和结束
  • USB CDC 4G Module 调试问题总结

    USB CDC 4G Module ESP32S2 自定义开发板 SIM7600C1 其他按照github USB CDC 4G Module 使用说明 确保硬件正确SIM卡正常 编译注意做好在4 4版本下 配置过程注意运营商APN 编译没
  • python的编译器与解释器

    作者介绍 作者 小刘在C站 每天分享课堂笔记 一起努力 共赴美好人生 夕阳下 是最美的绽放 目录 一 为什么会有编译器和解释器 二 编译器和解释器的区别 三 python解释器种类 四 python的运行机制 一 为什么会有编译器和解释器
  • Java集合——Set详解

    前几天简单介绍了一下单列集合中的List 今天就给大家讲一下它的同胞兄弟Set的简介与使用情况 Set存取无序 元素唯一 代码演示 public static void demo1 HashSet
  • 各种排序算法详解集合(时间复杂度、空间复杂度、稳定性分析)

    动图来源 https blog csdn net weixin 41190227 article details 86600821 目录 一 冒泡排序 二 选择排序 三 插入排序 四 希尔排序 五 归并排序 六 快速排序 七 堆排序 八 计
  • Supermarket 【POJ - 1456】【并查集+哈希表思想+贪心】

    题目链接 原来 并查集还有这样的作用 题记 我想用个哈希表的思维来解这道题 但是 显然O N 2 的哈希表去查询并插入显然是不行的 那么既然挂在图论专题 我就得用相应的方式解答咯 要是不挂在图论专题 我可能会自闭了 我们对于每个物品按照价值
  • vue3实现前端导出Excel

    1 安装依赖 npm install xlsx 2 使用
  • 操作系统:进程调度模拟,C语言实现

    作业要求 题目要求 模拟实现进程调度的经典算法 包括FCFS SJF SPF HRRN和RR 时间片大小分别为1和4 输出调度过程 并计算不同调度算法的周转时间 平均周转时间 带权周转时间 平均带权周转时间 等待时间 平均等待时间等信息 实
  • RT-Thread之ENV工具

    快速索引 ENV工具简介 准备工作 1 Git 安装并设置环境变量 2 ENV 前往RT Thread官网下载 3 RTT源码 GitHub OSChina 云盘 ENV工具打开方式 scons 编译项目 1 进入 BSP 目录 选择 st
  • 计算二叉树的第k层中所有叶子结点个数

    计算二叉树的第k层中所有叶子结点个数 Time Limit 1000MS Memory Limit 65535K 题型 编程题 语言 无限制 描述 二叉链表表示的二叉树 按先序次序输入二叉树中结点的值 字符表示空树 构造二叉链表表示的二叉树
  • SpringCloud集成Resilience4j实现熔断器

    前言 在文章 小谈Springcloud中的几个主流熔断器 我们介绍了SpingCloud架构中的几个主流熔断器 其中SpringCloud官方推荐的Resilience4j作为2020 x以后的新秀 远远没有hystrix有名 相关的文档
  • 服务器service系统,关于Service你所需要知道内容(一)

    根据下面的目录来介绍和理解Service中的知识点 一 Service的两种生命周期 service启动有两种方式 启动服务startService 绑定服务bindService 有不同是生命周期 如下所示 image 1 若一个Serv