`
wayfarer
  • 浏览: 297660 次
  • 性别: 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方法。

相关推荐

    不被杀死 service

    在安卓开发中,Service是一种用于在后台长时间运行的组件,它可以独立于用户界面执行任务,例如播放音乐、网络通信等。"不被杀死的 Service"指的是通过特定技术手段实现的Service,它能够在设备清理内存或者用户关闭...

    android service 简单实例源代码

    在Android开发中,Service是四大组件之一,它在后台运行,不与用户界面直接交互,常用于执行长时间的任务,如播放音乐、网络通信等。本篇文章将深入解析"android service 简单实例源代码",帮助你理解如何在Android...

    Service 启动与停止

    Service是Android系统中的一个重要组件,它负责在后台执行长时间运行的操作,不依赖于用户界面。在Android应用开发中,理解Service的启动与停止机制对于创建高效、稳定的后台服务至关重要。 一、Service概述 ...

    oracle service_name参数

    ### Oracle Service_Name 参数详解 #### 一、概述 在Oracle数据库管理中,`service_name`是一个重要的参数,它用于标识数据库实例所提供的服务名称。通过设置正确的`service_name`,可以确保客户端应用程序能够...

    Activity绑定Service(Kotlin)

    在Android应用开发中,Service是用于执行长时间运行操作的一个组件,而Activity是用户与应用交互的界面。将Activity与Service绑定是一种常见的通信方式,尤其在需要在后台运行任务且需要与用户界面保持交互时。本...

    通过Service播放音频的代码

    在Android开发中,Service是一种可以在后台长时间运行的组件,它不具有用户界面,但可以执行各种后台任务,如播放音乐。本示例的"通过Service播放音频的代码"旨在教你如何利用Service组件来实现音乐播放功能,使得...

    Java Service Wrapper使用总结

    Java Service Wrapper 使用总结 Java Service Wrapper 是一种可以将 Java 应用程序发布为可安装的服务的解决方案,它提供了一种简单的方式来将 Java 应用程序打包成一个独立的服务。下面是 Java Service Wrapper ...

    Android防止service多次执行startCommand

    在Android应用开发中,Service是四大组件之一,用于在后台长时间运行操作,比如播放音乐、网络通信等。然而,如果不加以控制,用户或者系统可能会多次启动同一个Service,导致不必要的资源消耗和服务的异常行为。本...

    android 录音机 service 例子

    在这个"android 录音机 service 例子"中,我们将深入探讨如何结合Service和MediaRecorder来创建一个能够后台录制音频的应用。 1. **Service基础** Service组件是Android应用开发中的关键部分,它可以在没有用户...

    Service向Activity传值(kotlin)

    在Android应用开发中,Service和Activity是两个非常重要的组件。Service用于在后台执行长时间运行的任务,而Activity则负责用户界面交互。在某些场景下,我们可能需要Service与Activity之间进行数据传递,例如本例中...

    ServiceNow 基础手册

    ServiceNow是当今流行的企业服务管理平台,它提供了一个集成的系统,允许用户在一个统一的界面中管理和自动化企业内部的各种工作流程。ServiceNow平台的基础手册涵盖了该平台的基本使用方法,包括如何导航、管理记录...

    Android-Service与Activity传值

    在Android应用开发中,`Service`和`Activity`是两个重要的组件。`Service`用于在后台执行长时间运行的任务,而`Activity`则负责用户界面交互。在某些场景下,我们可能需要在`Service`和`Activity`之间传递数据,比如...

    android多个activity和一个service通信

    在Android应用开发中,Activity和Service是两个关键组件。Activity代表用户界面,而Service则用于在后台执行长时间运行的任务,不直接与用户交互。在实际项目中,常常需要多个Activity与一个Service进行通信,比如本...

    【Android】开机自启动Service

    在Android系统中,Service是一种可以在后台长时间运行的组件,它不提供用户界面,但可以执行各种任务,如播放音乐、网络通信等。当设备启动时,我们有时希望某些Service能够自动启动,以便立即开始执行预定的任务,...

    用SQL语句解决Service Broker未启动的问题

    "解决 Service Broker 未启动的问题" Service Broker 是 SQL Server 中的一个组件,用于实现异步消息传递。它允许数据库管理员创建可靠的、可扩展的消息应用程序。但是,有时可能会遇到 Service Broker 未启动的...

    Android 多个service的action 相同冲突 验证demo

    在Android开发中,Service是应用程序组件之一,用于在后台执行长时间运行的操作,即使用户与应用程序交互界面不直接关联。在某些情况下,我们可能需要启动多个Service来执行不同的任务,但问题在于,如果这些Service...

    JavaService-2.0.10 32位,64位

    JavaService-2.0.10 是一个针对Java应用程序的服务包装工具,它允许开发者将Java应用程序作为Windows服务来运行。这个版本提供了32位和64位两种版本,以适应不同操作系统环境的需求。 在Windows系统中,服务是一种...

    Android之Service实现比较大小

    在Android开发中,Service是应用程序组件之一,用于在后台执行长时间运行的操作,即使用户与应用程序交互的界面已关闭。本篇文章将深入探讨Android中的Service,分析不同类型的Service及其特性,并对比它们之间的...

    Android系统在新进程中启动自定义服务过程(startService)的原理

    "Android系统在新进程中启动自定义服务过程(startService)的原理" 在 Android 系统中,startService 函数是一个非常重要的函数,它允许开发者在新进程中启动自定义服务。这项技术可以将一些计算型逻辑从主进程中...

    基于Service的简易音乐播放器

    在Android开发中,创建一个基于Service的简易音乐播放器是一个常见的练习,可以帮助开发者理解服务(Service)的概念以及如何处理多媒体播放。在这个项目中,我们关注的是Android 4.1.2版本,它提供了对基本多媒体...

Global site tag (gtag.js) - Google Analytics