`
wayfarer
  • 浏览: 298281 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Service

阅读更多

1. Service生命周期
(1)Service生命周期只有onCreate, onStart和onDestroy,没有onResume, onPause和onStop 。如果你在onCreate或onStart做一些很耗时间的事情,最好启动一个线程来完成,因为如果Service是跑在主线程中的,会影响到你的UI操作或者阻塞主线程中的其他事情。
(2)Android系统会尽量保持使用Service的进程尽可能长(Service被启动或者有客户端绑定到Service)。当系统内存变低,系统需要kill现存的进程时,Service的hosting进程的优先级将会在下列的可能中保持更高:
If the service is currently executing code in its onCreate(), onStart(), or onDestroy() methods, then the hosting process will be a foreground process to ensure this code can execute without being killed.
If the service has been started, then its hosting process is considered to be less important than any processes that are currently visible to the user on-screen, but more important than any process not visible. Because only a few processes are generally visible to the user, this means that the service should not be killed except in extreme low memory conditions.
If there are clients bound to the service, then the service's hosting process is never less important than the most important client. That is, if one of its clients is visible to the user, then the service itself is considered to be visible.
(3)大多数时间你的Service是运行的,但在严重的内存压力下它也可能被系统kill。如果是这样,系统会在稍后尝试重新启动这个Service 。 An important consequence of this is that if you implement onStart()  to schedule work to be done asynchronously or in another thread, then you may want to write information about that work into persistent storage during the onStart() call so that it does not get lost if the service later gets killed.
Other application components running in the same process as the service (such as an Activity) can, of course, increase the importance of the overall process beyond just the importance of the service itself.

2. Service的调用
(1)Context.startService():Service会经历onCreate -> onStart(如果Service还没有运行,则android先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次 );stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。 注意,多次调用Context.startservice()不会嵌套(即使会有相应的onStart()方法被调用),所以无论同一个服务被启动了多少次,一旦调用Context.stopService()或者stopSelf(),他都会被停止。补充说明:传递给startService()的Intent对象会传递给onStart()方法。调用顺序为:onCreate --> onStart(可多次调用) --> onDestroy。
(2)Context.bindService():Service会经历onCreate() -> onBind(),onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind -> onDestroyed相应退出,所谓绑定在一起就共存亡了
补充说明:传递给bindService()的Intent对象会传递给onBind(),传递给unbindService()的Intent对象会传递给onUnbind()方法 调用顺序为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。
(3)注意事项:在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。还有一点,目前我没有遇到过需要startService和bindService交互使用的情况(我认为不会有这种需求),所以不必去考虑交互的问题,待遇到时再考虑不迟。
(4)BroadcastReceiver只能通过startService启动Service ,因为广播本身生命周期很短,bind的话没有意义:Method bindService can not be called from an BroadcastReceiver component. A pattern you can use to communicate from an BroadcastReceiver to a Service is to call startService(Intent) with the arguments containing the command to be sent, with the service calling its stopSelf(int) method when done executing that command. See the API demo App/Service/Service Start Arguments Controller for an illustration of this. It is okay, however, to use this method from an BroadcastReceiver that has been registered with registerReceiver(BroadcastReceiver, IntentFilter), since the lifetime of this BroadcastReceiver is tied to another object (the one that registered it).

 

3. 示例代码

(1)调用者Activity

public class TServiceHolder extends Activity {
	private boolean isBound;
	private TService tService;
	private int statusCode;
	
	private ServiceConnection conn = new ServiceConnection() {
		// Called when a connection to the Service has been established, with the IBinder of the communication channel to the Service.
		public void onServiceConnected(ComponentName name, IBinder service) {
			tService = ( (TService.LocalBinder) service ).getService();
			statusCode = ( (TService.LocalBinder) service ).getStatusCode();
			Toast.makeText(TServiceHolder.this, "Service Connected", Toast.LENGTH_SHORT).show();
		}
		
		//无法被触发,原因未能找到
		public void onServiceDisconnected(ComponentName name) {
			tService = null;
			Toast.makeText(TServiceHolder.this, "Service DisConnected", Toast.LENGTH_SHORT).show();
		}
    };
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        initButtons();
    }
	
	private void initButtons() {
		Button startButton = (Button) findViewById(R.id.startService);
		Button bindButton = (Button) findViewById(R.id.bindService);
		Button unbindButton = (Button) findViewById(R.id.unbindService);
		Button stopButton = (Button) findViewById(R.id.stopService);
		
		startButton.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				Intent i = new Intent(TServiceHolder.this, TService.class);
				TServiceHolder.this.startService(i);
			}
		});
		bindButton.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				Intent i = new Intent(TServiceHolder.this, TService.class);
				TServiceHolder.this.bindService(i, conn, Context.BIND_AUTO_CREATE);
				isBound = true;
			}
		});
		unbindButton.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				if (isBound) {
					TServiceHolder.this.unbindService(conn);
					isBound = false;
				}
			}
		});
		stopButton.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				Intent i = new Intent(TServiceHolder.this, TService.class);
				TServiceHolder.this.stopService(i);
			}
		});
	}
	
}

 (2)Service

public class TService extends android.app.Service {
	private final String TAG = "Service";
	private final int NOTIFICATION_ID = 1;
	private NotificationManager nManager;
	
	private LocalBinder localBinder = new LocalBinder();
	private int statusCode;
	
	public void onCreate() {
		Log.i(TAG, "Service.onCreate");
		nManager = (NotificationManager) getSystemService(android.content.Context.NOTIFICATION_SERVICE);
		showNotification();
	}
	private void showNotification() {
		Notification n = new Notification(R.drawable.face_1, "Service启动", System.currentTimeMillis());
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, TServiceHolder.class), 0);
		n.setLatestEventInfo(this, "任务标题", "任务内容", contentIntent);
		nManager.notify(NOTIFICATION_ID, n); // 任务栏启动
	}
	public void onStart(Intent intent, int startId) {
		Log.i(TAG, "Service.onStart");
	}
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "Service.onBind");
		/*
		 * 调用者和Service间是依靠IBinder对象进行通信的,Service的onBind()返回的IBinder对象传递给调用者中ServiceConnection对象的onServiceConnected()方法(以参数形式接收);
		 * TService的调用者就可以利用这个IBinder获得TService对象,进而对TService进行操作控制;
		 * TService的调用者也可以利用这个IBinder获得其他信息,比如TService的状态statusCode。
		 */ 
		return localBinder; 
	}
	/*
	 * 当应用程序bind一个Service后,该应用程序和Service之间就能进行互相通信,通常,这种通信的完成依靠于我们定义的一些接口,例如下面的LocalBinder。
	 */
	class LocalBinder extends Binder {
		public TService getService() {
			return TService.this; // Service本身
		}
		public int getStatusCode() {
			return statusCode;
		}
	}
	public void onRebind(Intent i) {
		Log.i(TAG, "Service.onRebind");
	}
	public boolean onUnbind(Intent i) {
		Log.i(TAG, "Service.onUnbind");
		return false;
	}
	public void onDestroy() {
		nManager.cancel(NOTIFICATION_ID); // 任务栏关闭
		Log.i(TAG, "Service.onDestroy");
	}
}
 

4. 与远程Service通信(进程间Service通信)

如何两个进程间的Service需要进行通信,则需要把对象序列化后进行互相发送。
Android提供了一个 AIDL (Android接口定义语言)工具来处理序列化和通信。这种情况下Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个 stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:
先创建一个IMyRemoteService.aidl文件,内容如下:

package com.wissen.testApp;

interface IMyRemoteService {
    int getStatusCode();
}

如果你正在使用eclipse的 Android插件,则它会根据这个aidl文件生成一个Java接口类。生成的接口类中会有一个内部类Stub类,你要做的事就是去继承该Stub类:

package com.wissen.testApp;

class RemoteService implements Service {
    int statusCode;
  
    @Override
    public IBinder onBind(Intent arg0) {
        return myRemoteServiceStub;
    }

    private IMyRemoteService.Stub myRemoteServiceStub = new IMyRemoteService.Stub() {
        public int getStatusCode() throws RemoteException {
            return 0;
        }
    };
  
    …
}

当客户端应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:


ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        IMyRemoteService myRemoteService = IMyRemoteService.Stub.asInterface(service);
        try {
            statusCode = myRemoteService.getStatusCode();
       } catch(RemoteException e) {
           // handle exception
       }
        Log.i(”INFO”, “Service bound “);
    }
  
    …
};

分享到:
评论
1 楼 carywei 2010-06-10  
不过bindService 和startService混合使用时一定有的了。比如你做个map3播放器的时候,会用到,呵呵~~~,bindService是可以多次绑定的,但是前提你unBindService,这样你注册的接口什么的就不会重复注册了。还有如果你想多次绑定的话,你要将你的onUnbind的返回值设置成true他就会再次绑定,但是向你说一样,他不会调用onBind了,而是调用OnReBind方法。

相关推荐

    基于智能温度监测系统设计.doc

    基于智能温度监测系统设计.doc

    搜广推推荐系统中传统推荐系统方法思维导图整理-完整版

    包括userCF,itemCF,MF,LR,POLY2,FM,FFM,GBDT+LR,阿里LS-PLM 基于深度学习推荐系统(王喆)

    2023-04-06-项目笔记 - 第三百五十五阶段 - 4.4.2.353全局变量的作用域-353 -2025.12.22

    2023-04-06-项目笔记-第三百五十五阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.353局变量的作用域_353- 2024-12-22

    和美乡村城乡融合发展数字化解决方案.docx

    和美乡村城乡融合发展数字化解决方案.docx

    CNN基于Python的深度学习图像识别系统

    基于Python的深度学习图像识别系统是一个利用卷积神经网络(CNN)对图像进行分类的先进项目。该项目使用Python的深度学习库,如TensorFlow,构建和训练一个模型,能够自动识别和分类图像中的对象。系统特别适合于图像处理领域的研究和实践,如计算机视觉、自动驾驶、医疗影像分析等。 项目的核心功能包括数据预处理、模型构建、训练、评估和预测。用户可以上传自己的图像或使用预定义的数据集进行训练。系统提供了一个直观的界面,允许用户监控训练进度,并可视化模型的性能。此外,系统还包括了一个模型优化模块,通过调整超参数和网络结构来提高识别准确率。 技术层面上,该项目使用了Python编程语言,并集成了多个流行的机器学习库,如NumPy、Pandas、Matplotlib等,用于数据处理和可视化。模型训练过程中,系统会保存训练好的权重,以便后续进行模型评估和预测。用户可以通过简单的API调用,将新的图像输入到训练好的模型中,获取预测结果。

    拳皇97.exe拳皇972.exe拳皇973.exe

    拳皇97.exe拳皇972.exe拳皇973.exe

    基于python和协同过滤算法的电影推荐系统

    基于python和协同过滤算法的电影推荐系统 基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法的电影推荐系统基于python和协同过滤算法

    DEV-CPP-RED-PANDA

    DEV-CPP-RED-PANDA

    Python语言求解旅行商(TSP)问题,算法包括禁忌搜索、蚁群算法、模拟退火算法等

    Python语言求解旅行商问题,算法包括禁忌搜索、蚁群算法、模拟退火算法等。

    pdfjs2.5.207和4.9.155

    pdfjs 用于在浏览器中查看/预览/打印pdf。 pdfjs 2.5.207 支持firefox/chrome/edge/ie11以上版本。 如果需要支持旧版本浏览器,可以使用这个,是未修改过的原版,支持打印和下载按钮。亲测有效。 pdf 4.9.155分两个包: pdfjs-4.9.155-dist.zip pdfjs-4.9.155-legacy-dist.zip

    建设项目现场高温人员中暑事故应急预案.docx

    建设项目现场高温人员中暑事故应急预案

    数据结构上机实验大作业-线性表选题.zip

    数据结构上机实验大作业-线性表选题.zip

    基于高德地图的校园导航全部资料+详细文档+高分项目.zip

    【资源说明】 基于高德地图的校园导航全部资料+详细文档+高分项目.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    全自动批量建站快速养权重站系统【纯静态html站群版】:(GPT4.0自动根据关键词写文章+自动发布+自定义友链+自动文章内链+20%页面加提权词)

    【静态站群程序视频演示,只有视频,不含程序,下载须知】【静态站群程序视频演示,只有视频,不含程序,下载须知】全自动批量建站快速养权重站系统【纯静态html站群版】:(GPT4.0自动根据关键词写文章+自动发布+自定义友链+自动文章内链+20%页面加提权词)

    9.30 SWKJ 男头7张+女头2张.zip

    9.30 SWKJ 男头7张+女头2张.zip

    基于java+springboot+vue+mysql的技术交流和分享平台 源码+数据库+论文(高分毕业设计).zip

    项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea、vscode 数据库:MySql5.7以上 部署环境:maven 数据库工具:navicat

    一个通过单片机在各种屏幕上显示中文的解决方案.7z

    一个通过单片机在各种屏幕上显示中文的解决方案.7z

    Halcon模板匹配图像包

    图像

    线上辅导班系统-JAVA-基于springboot的线上辅导班系统的开发与设计(毕业论文)

    一、用户管理功能 用户注册与登录 学生注册:学生可以通过手机号、邮箱、社交账号等方式注册,填写个人信息(如姓名、年龄、学校等)。 家长/监护人账户:支持家长/监护人注册并管理学生账户,查看学习进度和成绩。 教师账户:教师可以注册并设置个人资料,上传资质认证文件。 管理员账户:管理员负责整个系统的管理,包括用户管理、课程管理、平台设置等。 用户权限管理 角色权限:系统根据用户类型(学生、家长、教师、管理员)分配不同权限,确保信息安全。 家长监督:家长可以查看子女的学习进度、成绩和教师反馈,参与学习监督。 个人资料管理 用户可以在个人中心更新基本信息,设置个人头像、联系方式、密码等。 支持学籍信息的维护,例如学生的年级、班级、课程历史等。 二、课程管理功能 课程设置 课程创建与编辑:教师或管理员可以创建和编辑课程内容,上传课件、视频、文档等教学材料。 课程分类:根据学科、年级、难度等维度进行课程分类,方便学生浏览和选择。 课程排课:管理员可以设置课程的时间表、教学内容和授课教师,并调整上课时间和频率。 课程安排与通知 课程预约:学生可以在线选择并预约感兴趣的课程,系统根据学生的时

    英特尔2021-2024年网络连接性和IPU路线图

    内容概要:本文档介绍了英特尔2021年至2024年的网络连接性产品和智能处理单元(IPU)的战略和技术路线图。涵盖了从10GbE到200GbE的不同系列以太网适配器的特性、性能和发布时间。详细列出了各个产品的关键功能,如PCIe接口、安全特性、RDMA支持等。同时,介绍了IPU的发展计划,包括200G、400G和800G的不同代次产品的性能提升和新的功能特点。 适合人群:从事网络工程、数据中心管理、IT架构设计的专业技术人员。 使用场景及目标:本文档主要用于了解英特尔未来几年在以太网适配器和IPU领域的技术和产品规划,帮助企业在采购和部署网络设备时做出决策。同时,为研究人员提供最新技术发展趋势的参考。 其他说明:文档内容涉及的技术细节和时间表可能会有变动,请以英特尔官方发布的最新信息为准。

Global site tag (gtag.js) - Google Analytics