在这篇文章中,我们想谈谈Android Service 。 这是开发Android应用程序的关键组件。 与Activity不同,Android中的Service在后台运行,它们没有界面,并且生命周期与Activity完全不同。 使用Service我们可以实现一些后台操作,例如,我们可以假设我们想从远程服务器加载网页。 使用服务,我们可以在Android中实现多任务。
服务总览
我们已经知道,如果系统资源太少甚至可以重新创建,则可以启动,停止,销毁Android Activity,因此Service的使用寿命更长。 Android中的服务可以从活动,广播接收器和其他服务启动。
我们必须注意到,使用Service不会自动创建新线程,因此,如果我们在Service内部实现简单的逻辑,则不需要很长时间的处理,就不需要在单独的线程上运行它,但是如果我们必须实施复杂的逻辑并需要长时间的处理,我们必须注意创建新线程,否则服务将在主线程上运行,这可能会导致ANR问题。
在Android中,使用Service的主要原因有两个:
- 实施多任务
- 启用进程间通信(IPC)
第一种情况的典型示例是需要从远程服务器下载数据的应用程序,在这种情况下,我们可以拥有与用户交互并启动一项在后台完成工作的服务的活动,而用户可以使用该应用程序和也许当服务完成时会向用户发送一条消息。
在第二种情况下,我们要“共享”一些常用功能,以便不同的应用程序可以重复使用它们。 例如,假设我们有一个发送电子邮件的服务,并且希望在多个应用程序之间共享该服务,这样就不必重写相同的代码。 在这种情况下,我们可以使用IPC,以便该服务公开一个“远程”接口,其他应用程序可以调用该接口。
在本文中,我们讨论第一种情况,在这种情况下,我们有本地服务,local意味着可以在我们的apk内看到该服务。
基本服务
现在我们对服务有了更多的了解,我们想创建它。 在Android中创建服务,我们必须扩展Service类。
public class TestService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
如我们所见,我们仅需实现一种称为onBind的方法。 在我们的例子中,我们正在使用本地服务,因此此方法应返回null。 如前所述,服务具有生命周期,我们可以重写一些回调方法,以便处理其不同的状态:
public class TestService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}
在必须创建服务时,仅调用一次第一个方法onCreate。 如果服务已经在运行,则不会调用此方法。 我们不直接调用它,而是由操作系统来调用它。
OnStartCommand是最重要的方法,因为在我们需要启动服务时会调用它。 在这种方法中,我们在运行服务时会传递Intent,这样我们就可以与Service交换一些信息。 在这种方法中,我们实现了可以在该方法内部直接执行的逻辑(如果它不是很费时的话),否则我们可以创建一个线程。 如您所见,此方法要求我们返回一个Integer作为结果。 此整数表示操作系统应如何处理服务:
- START_STICKY :使用此返回值,如果OS终止了我们的服务,它将重新创建它,但没有重新发送发送给该服务的Intent。 通过这种方式,服务始终处于运行状态
- START_NOT_STICKY :如果SO终止了服务,则在客户端明确调用onStart命令之前,它不会重新创建服务
- START_REDELIVER_INTENT :与START_STICKY类似,在这种情况下,Intent将重新交付给服务。
OnDestroy是操作系统将在服务被销毁时调用的方法。
一旦有了服务类,就必须在Manifest.xml中对其进行声明,以便可以使用它:
<service android:name=".TestService"
android:enabled="true"/>
启动和停止服务
众所周知,服务必须启动并最终停止,才能完成其任务。 我们可以假设从一个活动开始,可以使用Intent将一些信息传递给服务。 我们可以假设我们的“活动”有两个按钮,一个可以启动,一个可以停止服务:
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, TestService.class);
i.putExtra("name", "SurvivingwithAndroid");
MainActivity.this.startService(i);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this, TestService.class);
MainActivity.this.stopService(i);
}
});
在上面的第5行的代码中,我们创建了一个传递处理我们的Service的类名称的Intent,此外,我们设置了一些类似于name的参数,然后在第7行启动了Service。以同样的方式,在第17行我们停止了该服务。 。
单击开始按钮,我们进入日志:
我们可以注意到onCreate方法被调用是因为这是我们第一次启动该服务,如果再次单击开始按钮,则操作系统不会调用onCreate方法。 当我们单击停止按钮时,操作系统将破坏服务。
意图服务
正如我们在服务在主线程上运行之前所提到的那样,因此在此服务中实现某些逻辑时必须非常小心。 我们必须考虑,如果此逻辑是阻塞操作或需要很长时间才能完成ANR问题,则可能会发生。 在这种情况下,我们必须将逻辑移至单独的线程,这意味着我们必须在onStartCommand方法中创建一个线程并运行它。
从Service派生的另一个名为IntentService的类简化了我们的生活。 当我们不需要同时处理多个请求时,此类非常有用。 此类创建一个工作线程来处理不同的请求。 此类执行以下操作:
- 创建一个单独的线程来处理请求
- 创建一个请求队列并一次传递一个Intent
- 创建onStartCommand的默认实现
- 处理所有请求后停止服务
如果要创建IntentService,则必须扩展IntentService类而不是Service:
public class TestIntentService extends IntentService {
public TestIntentService() {
super("TestIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
}
}
在这种情况下,我们只有一种方法称为onHandleIntent 。 在这里,我们无需执行任何操作即可实现逻辑,因为操作是否需要很长时间,因为此方法是在单独的线程中调用的。
自动启动服务
很多时候,我们想自动启动服务,例如在启动时。 我们知道要启动服务,我们需要一个组件来启动它。 我们该怎么做? 好吧,我们可以使用启动服务的广播接收器。 例如,如果我们想在智能手机启动时启动它,我们首先创建一个广播接收器来侦听此事件,然后启动该服务。
public class BootBroadcast extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent intent) {
ctx.startService(new Intent(ctx, TestService.class));
}
}
并在Manifest.xml中
<receiver android:name=".BootBroadcast">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
参考:来自我们的JCG合作伙伴 Francesco Azzola的《 Android服务教程》 ,位于Surviving w / Android博客上。
翻译自: https://www.javacodegeeks.com/2014/01/android-service-tutorial.html