安卓服务Service详解

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

service(服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在清单文件中配置相关信息,本博客将对Service的各个知识点进行详细讲解。



一Service的基本用法:

1使用本地服务

1)服务的启动方式

1通过Context的startService()方法启动服务:以该方法启动的服务,开启该服务的应用组件(如Activity)与该Service不存在关联关系,即使开启该服务的Activity被销毁,Service任能够一直在后台运行。通常,开启的服务执行一个单独的操作且不需向调用者返回一个结果。比如,可能从网络进行下载或者上传一个文件。当任务完成,服务就该自我停止。使用服务于使用Activity非常相似,都是先继承其对应的基类,然后重写其中重要的方法,这些方法就是关于其生命周期回调的方法。代码如下所示:

public class MyService extends Service {

	public static final String TAG = "MyService";

	@Override
	public void onCreate() {
		super.onCreate();
		Log.d(TAG, "onCreate() executed");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(TAG, "onStartCommand() executed");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.d(TAG, "onDestroy() executed");
	}

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

}
然后再Activity中使用

 Intent startIntent = new Intent(this, MyService.class);  
 startService(startIntent); 
即可开启该服务,程序运行结果如下:


从程序的运行结果来看,可以知道当启动一个Service的时候,会调用该Service中的onCreate()和onStartCommand()方法。

当我们在次点击启动服务的按钮,程序运行结果如下:


可以看到,此时只输出onStartCommand() executed。这说明此时只执行了onStartCommand()方法,而未执行onCreate(),这说明onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,则即使多次调用startService()方法,onCreate()方法都不会再执行,这一点非常类似数据库操作中的open一个数据库。

当然上述的例子仅仅只是为了说明上述知识点,因为Service中的代码也仅仅只是打印出log而已,而事实上Service的使用是为了处理一些耗时操作的,如网络请求,文件上传与下载,但都是重写其某个生命周期函数,如onStart(Intent intent, int startId),onDestroy()在这些函数中完成自己的业务逻辑的处理,下面的代码是使用服务来进行网络通信的一个例子。

public class GetMsgService extends Service {
	private Client client;
	private boolean isStart;
	private SharePreferenceUserInfoUtil util;
	private ClientInputThread cit;
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		client=((MyApplication) getApplication()).getClient();
	}

	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
		util = new SharePreferenceUserInfoUtil(getApplicationContext(),
				Constants.SAVE_USER);
	   
		new Thread(){
			   public void run()
			   {
					try {
						isStart=client.create();
					} catch (UnknownHostException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			//在服务中接受来自服务器端的消息,然后通过广播的形式传递给相应的Activity处理。接受服务器端的消息一般在
			//服务中,因为服务可以在后台一直运行
									
				if(isStart)
				{
					cit=client.getClientInputThread();
					if(cit!=null)
					{
						cit.setMessageListener(new MessageListener() {
							
							public void getMessage(TransportObject msg) {
								
								if(msg!=null&&msg instanceof TransportObject)
								{
									//通过广播向Activity传递消息
									Intent intent=new Intent();
									intent.setAction(Constants.ACTION_MSG);
									intent.putExtra(Constants.MSG, msg);
								    sendBroadcast(intent);
								}
							}
						});
					}
					else {
						Log.i("GetMsgService","服务器端连接暂时出错");
					//	Toast.makeText(getApplicationContext(), "服务器端连接暂时出错,请稍后重试!",0).show();
					}
				}
				  
			   }
		   }.start();
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		ClientOutputThread out=client.getClientOutputThread();
		TransportObject<User> msg=new TransportObject<User>(TranObjectType.LOGOUT);
		User user=new User();
		user.setId(Integer.parseInt(util.getId()));
		msg.setObject(user);
		out.setMsg(msg);
		//关闭服务时关闭client
		out.setStart(false);
		client.getClientInputThread().setStart(false);
		
		
		
	}
	
	

}
可以看到,我们在getMsgService的onStart方法中开启了一个线程用来进行客户端从服务器端读取信息的操作,在onDestroy()方法中关闭网络请求的操作。

2通过Context的bindService()方法启动服务:顾名思义,以该方法启动的服务,开启该服务的应用组件(如Activity)与该Service被绑定在一起,通常用这种方式开启的服务是为了与开启该服务的应用组件(如Activity)进行消息通信。

首先我们来看一下bindService的签名:

bindService(Intent service, ServiceConnection conn, int flags)
其中service参数是通过intent指定要启动的Service。

conn参数是一个ServiceConnection对象,该对象用于监听访问者与service之间的连接情况,当访问者与Service连接成功时会回调该类的onServiceConnected(ComponentName name, IBinder service)方法,然后将服务中创建的Ibinder对象(此时在Service的onBinder方法中需要返回该Ibinder对象)传递给第二个参数service,通过该Ibinder对象就能与Service进行通信。

第三个参数flags指定绑定时是否自动创建Service,一般我们指定为BIND_AUTO_CREATE(自动创建,如果传入0表示不自动创建)示例代码如下:

Service中的代码:

public class MyService extends Service {

	public static final String TAG = "MyService";

	private MyBinder mBinder = new MyBinder();

	@Override
	public void onCreate() {
		super.onCreate();
		Log.d(TAG, "onCreate() executed");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.d(TAG, "onStartCommand() executed");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.d(TAG, "onDestroy() executed");
	}

	@Override
	public IBinder onBind(Intent intent) {//在onBind(Intent intent)中返回IBinder对象
		return mBinder;
	}

	class MyBinder extends Binder {//定义一个类实现IBinder接口( Binder实现了IBinder接口)

		public void doSomething() {
			Log.d("TAG", "doSomething() executed");
			
		}

	}

}
Activity中的代码:

public class MainActivity extends Activity
{
  ...
private ServiceConnection connection = new ServiceConnection() {  
  
        @Override  
        public void onServiceDisconnected(ComponentName name) {  
        }  
  
        @Override  
        public void onServiceConnected(ComponentName name, IBinder service) {  
            myBinder = (MyService.MyBinder) service;  
            myBinder.doSomething();  
        }  
    };  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
	Intent bindIntent = new Intent(this, MyService.class);  
        bindService(bindIntent, connection, BIND_AUTO_CREATE);//此时使用bindService开启服务
    }
  ...

}
即在服务中定义一个IBinder的实例,然后在Service的public IBinder onBind(Intent intent)方法中将其返回,在Activity中定义一个ServiceConnection类的实例,在其onServiceConnected(ComponentName name, IBinder service)方法中获取Service中 返回IBinder对象,利用该对象即可调用Service中的方法进行相互通信。

注意:一个服务在进程中的主线程运行——一个服务不会创建自己的线程,也不会在另外的进程运行(除非另外指定)。这意味着,如果服务需要做一些频繁占用CPU的工作或者会发生阻塞的操作,你需要在服务中另开线程执行任务。避免程序出现ANR。


2使用AIDL跨进程调用服务:

此种情况与上述介绍的使用bindService方法开启的绑定本地的大的框架基本相同,只不过使用AIDL来实现跨进程调用,关于此种情况的介绍,请参看我的博客:安卓中不同APP之间的消息通信中相关的内容。



二Service与线程的关系及IntentService:

事实上Service与线程之间没多大关系,我们之所以把Service与线程放在一起谈论,是为了更清楚的明白在哪些情况下用服务哪些情况下用线程,哪些情况下在服务中开启一个线程,因为Service默认在主线程中运行,不能进行耗时操作,这也是IntentService存在的原因。因为IntentService会创建单独的worker线程来处理intent请求,不需要自己创建一个子线程。

IntentService处理流程
创建默认的一个 worker 线程处理传递给 onStartCommand() 的所有 intent ,不占据应用的主线程
创建一个工作队列一次传递一个 intent 到你实现的 onHandleIntent() 方法,避免了多线程
在所有启动请求被处理后自动关闭服务,不需要调用 stopSelf()
默认提供 onBind() 的实现,且返回 null
默认提供 onStartCommand() 的实现,实现发送intent到工作队列再到onHandleIntent() 方法实现。

正因为如此,所以使用IntentService无需重写onBind(),onStartCommand(),只需重写onHandleIntent() 即可。示例代码如下:

public class HelloIntentService extends IntentService {
  /**
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
  public HelloIntentService() {
    super("HelloIntentService");
  }
  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
    // Normally we would do some work here, like download a file.
    // For our sample, we just sleep for 5 seconds.
    long endTime = System.currentTimeMillis() + 5*1000;
    while (System.currentTimeMillis() < endTime) {
      synchronized (this) {
        try {
          wait(endTime - System.currentTimeMillis());
        } catch (Exception e) {
        }
      }
    }
  }
}


三Service的生命周期

我们先来看一下谷歌官方图片:


从上述图片可以看到两种不同的启动方式其生命周期也不同:

启动的服务: 
startService()->onCreate()->onStartCommand()->running->stopService()/stopSelf()->onDestroy()->stopped 
其中,服务未运行时会调用一次onCreate(),运行时不调用。
绑定的服务: 
bindService()->onCreate()->onBind()->running->onUnbind()->onDestroy()->stopped
服务起始于 onCreate() ,终止于 onDestory()

服务的开关过程,只有 onStartCommand() 可多次调用,其他在一个生命周期只调用一次。

这两个过程不是完全独立,也可以绑定一个由 startService() 启动过的服务



四如何创建不被系统杀死的服务

服务不被杀死包括三种情况

1.系统根据资源分配情况杀死服务

2.用户通过 settings -> Apps -> Running -> Stop 方式杀死服务
3.用户通过 settings -> Apps -> Downloaded -> Force Stop 方式杀死服务
第一种情况:

用户不干预,完全靠系统来控制,办法有很多。比如 onStartCommand() 方法的返回值设为 START_STICKY ,服务就会在资源紧张的时候被杀掉,然后在资源足够的时候再恢复。当然也可设置为前台服务,使其有高的优先级,在资源紧张的时候也不会被杀掉。

关于 onStartCommand() 方法的返回值做一下简单的介绍:

START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

第二种情况:
用户干预,主动杀掉运行中的服务。这个过程杀死服务会通过服务的生命周期,也就是会调用 onDestory() 方法,这时候一个方案就是在 onDestory() 中发送广播开启自己。这样杀死服务后会立即启动。如下:

在onCreate中注册广播,用来开启服务,在服务的onDestroy()中发送广播通知服务开启自己,代码如下:

public void onCreate() {
  // TODO Auto-generated method stub
  super.onCreate();
  mBroadcast = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
      // TODO Auto-generated method stub
      Intent a = new Intent(ServiceA.this, ServiceA.class);
      startService(a);
    }
  };
  mIF = new IntentFilter();
  mIF.addAction("listener");
  registerReceiver(mBroadcast, mIF);
}
@Override
public void onDestroy() {
  // TODO Auto-generated method stub
  super.onDestroy();
  Intent intent = new Intent();
  intent.setAction("listener");
  sendBroadcast(intent);
  unregisterReceiver(mBroadcast);
}

第三种情况:
强制关闭就不好解决。这个好像是从包的level去关的,不是走的Service的完整的生命周期。所以在服务里加代码是无法被调用的。处理这个情况的唯一方法是屏蔽掉 force stop 和 uninstall 按钮,让其不可用。

好了,以上就是本人理解的关于Service的相关知识,看官如果觉得不错请不要吝啬点击一下下方的“顶”按钮给我一点鼓励哦! 微笑


Android 四大组件Service详解 ** 一、Service的简介 ** Service是Android中实现程序后台运行的解决方案,适用于去执行那些不需要和用户交互而且还要求长期运行的任务。Service是android 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。 作用:提供 需在后台长期运行的服务 特点:无用户界面、在后台运行、生命周期长 1、Service的生命周期 阅读详情

相关推荐

Android之 Service服务详解

Service服务详解

qq_29848853的博客 5107

关于Android Service真正的完全详解,你需要知道的一切

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52709857 出自【zejian的博客】   Service全部内容基本会在本篇涉及到,我们将围绕以下主要知识点进行分析: Service简单概述 Service在清单文件中的声明 Service启动服务实现方式及其详解 Service绑定服务的三种实现方式 关于启动服务与绑定服务间的转换问题 前台服务以及通知发送 服务Service与线程Thread的区别 管理服务生命周

Gabriel的专栏 896

前台service的使用

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Ma...

mb061的博客 623

【Android】安卓四大组件服务Service详解:从基础到进阶

Service作为安卓应用后台任务处理的核心组件,在保障应用功能完整性和提升用户体验方面起着不可或缺的作用。通过掌握Service的生命周期、分类及使用场景,开发者能够合理设计应用架构,实现高效、稳定的后台任务处理。随着安卓系统的不断升级,Service的使用也需与时俱进,结合新特性和替代方案,让应用在后台运行中发挥更大价值。希望本文能帮助大家深入理解Service,在安卓开发中灵活运用这一强大工具

m0_59734531的博客 1499

Service组件详解:IoT-Firstep安卓后台服务开发实战教程

IoT-Firstep是一个全面的物联网开发入门教程项目,涵盖单片机、上位机、移动应用及服务器后台开发等知识。其中安卓后台服务Service)开发是构建稳定物联网应用的核心环节,本文将通过实战案例详解Service组件在物联网场景中的应用。 ## 一、Service组件核心价值:物联网应用的后台引擎 🚀 在物联网应用开发中,设备连接管理、数据同步、传感器数据采集等功能需要长期在后台运行,这

gitblog_00729的博客 749

Android Service服务详解

原文转载自:https://blog.csdn.net/javazejian/article/details/52709857  Service全部内容基本会在本篇涉及到,我们将围绕以下主要知识点进行分析: Service简单概述 Service在清单文件中的声明 Service启动服务实现方式及其详解 Service绑定服务的三种实现方式 关于启动服务与绑定服务间的转换问题 前台服务以及通知...

蜗牛慢爬的李成广 512

android四大组件——服务(Service)详解

四大组件——服务(Service) @author lisiwen @createTime 2021/08/08 1.认识服务服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。 2.多线程编程 ​ java多线程如果不太熟悉的话可以看看我之前的文章:----先熟悉一下java的多线程编程 2.1 使用多线程进

无忧少年的博客 3326

安卓服务Service详解

四大组件之一:服务Service 一,定义 服务是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够开启Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个Service与之交互,例如,一个Service可能会处理网络操作,播放音乐,操作文件或者与内容提供者交互,所有这些操作都是在后台进行。 二,服务的两种状态 服务

smile0528的博客 667

[Android] Service服务详解以及怎么使service服务不被杀死

android内核剖析学习笔记:AMS(ActivityManagerService)内部原理和工作机制一、ActivityManagerService提供的主要功能: (1)统一调度各应用程序的Activity (2)内存管理 (3)进程管理 二、启动一个Activity的方式有以下几种: (1)在应用程序中调用startActivity启动指定的Act

kenjili的博客 562

Android 服务(Service)详解

总结学习类文章 service服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在AndroidManifest.xml配置相关信息。 服务Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。 不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖

weixin_40862356的博客 1万+

Android中Service(服务)详解

Service是Android中四大组件之一,在Android开发中起到非常重要的作用,先来看一下官方对Service的定义: A Service is an application component that can perform long-running operations in the background and does not provide a user interfac

Ryan's zone 12万+

[Android] Service服务详解以及如何使service服务不被杀死

[Android] Service服务详解以及如何使service服务不被杀死 转自http://www.cnblogs.com/rossoneri/p/4530216.html 阅读目录Services 创建“启动的”服务 创建“绑定的”服务 关于怎样让服务不被杀死Services   服务是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。一个应用程序组件可以启动一个

-琥珀-的专栏 811

Android service服务详解

为什么要写服务这篇文章 1.被老员工喷了 2.自己犯贱,捡西瓜丢芝麻,该打,555 服务是啥 服务是一个应用程序组件,可以在后台执行长时间运行,不提供用户界面。一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切换到另一个应用程序。此外,一个组件可以绑定到一个服务与它交互,多个主键也可以绑定同一个服务,甚至执行进程间通信(IPC)。例如,一个服务可能处理网络通信、播放音乐、计时操作或与...

齐码闯天涯 1万+

android 服务 按键,Android中Service服务详解(二)

本文详细分析了Android中Service服务。分享给大家供大家参考,具体如下:在前面文章《Android中Service服务详解(一)》中,我们介绍了服务的启动和停止,是调用Context的startService和stopService方法。还有另外一种启动方式和停止方式,即绑定服务和解绑服务,这种方式使服务与启动服务的活动之间的关系更为紧密,可以在活动中告诉服务去做什么事情。为了说明这种情...

weixin_35143514的博客 429

android service 什么时候停止服务,Android Service服务不被停止详解及实现

service服务在开发中一直是很重要的,它要在后台执行很长的时间,这个不需要界面操作,下面爱站技术频道小编给大家分享Android Service服务不被停止详解及实现,一起和小编来看看吧。Android Service服务一直运行:最近有个项目需求是后台一直运行Service,但是一般都是可以手动停止的,这里就提供一个方法让Android Service服务一直运行,大家看下。1.设置-&gt...

weixin_39532352的博客 1105

Android 服务详解-Service(本地服务)

一、服务简介 Service四大组件之一(Android四大组件:Activity、Service、Content Provider和BroadcastReceiver),其地位和Activity一样重要,在开发中用的不多,但是又缺少不了,在求职面试也是必出的题目。 什么是ServiceService是一种可以在后台长时间运行的且不提供用户交互界面的应用组件。Service可由其他组件启动,启...

ISmartWang的博客 1137
上一篇: 安卓中的内存泄漏
下一篇: 安卓AsyncTack详解
这个家伙很懒~
这个家伙很懒~ 领域专家: 算法与数据结构技术领域 领域专家: 算法与数据结构技术领域
博客等级 码龄11年 411粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值