【Android】安卓学习笔记之服务的基本用法(二)

来源:互联网 发布:地理 知乎 编辑:程序博客网 时间:2024/06/10 01:49

1、使用前台服务

      前台服务和普通服务最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止服务被回收掉才使用前台服务的,有些项目由于特殊的需求会要求必须使用前台服务,比如说墨迹天气,它的服务在后台更新天气数据的同时,还会在系统状态栏一直显示当前的天气信息,如图所示。

那么我们就来看一下如何才能创建一个前台服务吧,其实并不复杂,修改MyService 中的代码,如下所示:
public class MyService extends Service {……@Overridepublic void onCreate() {super.onCreate();Notification notification = new Notification(R.drawable.ic_launcher, "Notification comes",System.currentTimeMillis());Intent notificationIntent = new Intent(this, MainActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);notification.setLatestEventInfo(this, "This is title", "This iscontent", pendingIntent);startForeground(1, notification);Log.d("MyService", "onCreate executed");}……}
       可以看到,这里只是修改了onCreate()方法中的代码,相信这部分的代码你会非常眼熟。没错!这就是我们学习的创建通知的方法。只不过这次在构建出Notification 对
象后并没有使用NotificationManager 来将通知显示出来,而是调用了startForeground()方法。这个方法接收两个参数,第一个参数是通知的id,类似于notify()方法的第一个参数,第二个参数则是构建出的Notification 对象。调用startForeground()方法后就会让MyService 变成一个前台服务,并在系统状态栏显示出来。

2、使用IntentService

      服务中的代码都是默认运行在主线程当中的,如果直接在服务里去处理一些耗时的逻辑,就很容易出现ANR(Application NotResponding)的情况。所以这个时候就需要用到Android 多线程编程的技术了,我们应该在服务的每个具体的方法里开启一个子线程,然后在这里去处理那些耗时的逻辑。因此,一个比较标准的服务就可以写成如下形式:
public class MyService extends Service {@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {// 处理具体的逻辑}}).start();return super.onStartCommand(intent, flags, startId);}}

      但是,这种服务一旦启动之后,就会一直处于运行状态,必须调用stopService()或者stopSelf()方法才能让服务停止下来。所以,如果想要实现让一个服务在执行完毕后自动停止的功能,就可以这样写:
public class MyService extends Service {@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {// 处理具体的逻辑stopSelf();}}).start();return super.onStartCommand(intent, flags, startId);}}

      虽说这种写法并不复杂,但是总会有一些程序员忘记开启线程,或者忘记调用stopSelf()方法。为了可以简单地创建一个异步的、会自动停止的服务,Android 专门提供了一个IntentService 类,这个类就很好地解决了前面所提到的两种尴尬,下面我们就来看一下它的用法。
      新建一个MyIntentService 类继承自IntentService,代码如下所示:
public class MyIntentService extends IntentService {public MyIntentService() {super("MyIntentService"); // 调用父类的有参构造函数}@Overrideprotected void onHandleIntent(Intent intent) {// 打印当前线程的idLog.d("MyIntentService", "Thread id is " + Thread.currentThread().getId());}@Overridepublic void onDestroy() {super.onDestroy();Log.d("MyIntentService", "onDestroy executed");}}

      这里首先是要提供一个无参的构造函数,并且必须在其内部调用父类的有参构造函数。然后要在子类中去实现onHandleIntent()这个抽象方法,在这个方法中可以去处理一些具体的逻辑,而且不用担心ANR 的问题,因为这个方法已经是在子线程中运行的了。这里为了证实一下,我们在onHandleIntent()方法中打印了当前线程的id。另外根据IntentService 的特性,这个服务在运行结束后应该是会自动停止的,所以我们又重写了onDestroy()方法,在这里也打印了一行日志,以证实服务是不是停止掉了。
      最后仍然不要忘记,服务都是需要在AndroidManifest.xml 里注册的,如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.servicetest"    android:versionCode="1"    android:versionName="1.0" >……    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >……        <service android:name=".MyIntentService" >        </service>    </application></manifest>


0 0