最近项目有用到Service,在网上参考了相关的资料(http://android.blog.51cto.com/268543/527314)和Android自带的ApiDemos,下面做些总结。

一、Service是在一段不定的时间运行在后台,不和用户交互应用组件。当我们不用界面交互时可以考虑使用service,service的使用和广播一样必须在配置文件中声明:

        <!-- Service Samples -->        <service android:name=".app.LocalService" />二、service的两种模式,本地模式(Local Service)和远程服务(Remote Service)

本地模式(Loacal Service) :可以参考ApiDemos中的LocalService.java和 LocalServiceBinding.java两个文件。本地模式有两种使用方法,使用startService()方法启用服务和使用bindService()方法启用服务。

远程服务(Remote Service) 用于android系统内部的应用程序之间。
它可以通过自己定义并暴露出来的接口进行程序操作。客户端建立一个到服务对象的连接,并通过那个连接来调用服务。连接以调用Context.bindService()方法建立,以调用 Context.unbindService()关闭。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

三、生命周期(本部分转载)

生命周期 Service的生命周期并不像Activity那么复杂,它只继承了onCreate(),onStart(),onDestroy()三个方法,当我们第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。
而启动service,根据onStartCommand的返回值不同,有两个附加的模式: 1. START_STICKY 用于显示启动和停止service。 2. START_NOT_STICKY或START_REDELIVER_INTENT用于有命令需要处理时才运行的模式。
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。
1. 使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。
如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。
采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
2. 使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
采用Context.bindService()方法启动服务时只能调用onUnbind()方法解除调用者与服务解除,服务结束时会调用onDestroy()方法。
看看官方给出的比较流程示意图:


官方文档告诉我们,一个service可以同时start并且bind,在这样的情况,系统会一直保持service的运行状态如果service已经start了或者BIND_AUTO_CREATE标志被设置。如果没有一个条件满足,那么系统将会调用onDestory方法来终止service.所有的清理工作(终止线程,反注册接收器)都在onDestory中完成。

四、构建Service类

(1)不需和Activity交互的本地服务,可以使用startService/stopService启动和关闭service。

运行时可以发现第一次startService时,会调用onCreate和onStart,在没有stopService前,无论点击多少次startService,都只会调用onStart。而stopService时调用onDestroy。再次点击stopService,会发现不会进入service的生命周期的,即不会再调用onCreate,onStart和onDestroy。

service类分别实现onstart (),oncreate(),onStop方法即可。

Java代码:

public class LocalService extends Service {         private static final String TAG = "LocalService";         @Override         public IBinder onBind(Intent intent) {                 Log.i(TAG, "onBind");                 return null;         }         @Override         public void onCreate() {                 Log.i(TAG, "onCreate");                 super.onCreate();         }         @Override         public void onDestroy() {                 Log.i(TAG, "onDestroy");                 super.onDestroy();         }         @Override         public void onStart(Intent intent, int startId) {                 Log.i(TAG, "onStart");                 super.onStart(intent, startId);         } }

这里的onBind()可以不是实现。

Activity代码:

public class ServiceActivity extends Activity {         @Override         protected void onCreate(Bundle savedInstanceState) {                 super.onCreate(savedInstanceState);                 setContentView(R.layout.servicedemo);                 ((Button) findViewById(R.id.startLocalService)).setOnClickListener(                                 new View.OnClickListener(){                                         @Override                                         public void onClick(View view) {                                                 // TODO Auto-generated method stub                                                startService(new Intent("com.demo.SERVICE_DEMO"));                                         }                                  });                 ((Button) findViewById(R.id.stopLocalService)).setOnClickListener(                                 new View.OnClickListener(){                                         @Override                                         public void onClick(View view) {                                                 // TODO Auto-generated method stub                                                 stopService(new Intent("com.demo.SERVICE_DEMO"));                                         }                                 });         } }

2.有本地服务和Activity交互必须用bind方式使用service

使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。大家可以参考ApiDemos的代码。

LoacalService.java

/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.apis.app;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.os.Parcel;import android.util.Log;import android.widget.Toast;// Need the following import to get access to the app resources, since this// class is in a sub-package.import com.example.android.apis.R;/** * This is an example of implementing an application service that runs locally * in the same process as the application.  The {@link LocalServiceController} * and {@link LocalServiceBinding} classes show how to interact with the * service. * * <p>Notice the use of the {@link NotificationManager} when interesting things * happen in the service.  This is generally how background services should * interact with the user, rather than doing something more disruptive such as * calling startActivity(). */public class LocalService extends Service {    private NotificationManager mNM;    /**     * Class for clients to access.  Because we know this service always     * runs in the same process as its clients, we don't need to deal with     * IPC.     */    public class LocalBinder extends Binder {        LocalService getService() {            return LocalService.this;        }    }        @Override    public void onCreate() {        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);        // Display a notification about us starting.  We put an icon in the status bar.        showNotification();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.i("LocalService", "Received start id " + startId + ": " + intent);        // We want this service to continue running until it is explicitly        // stopped, so return sticky.        return START_STICKY;    }    @Override    public void onDestroy() {        // Cancel the persistent notification.        mNM.cancel(R.string.local_service_started);        // Tell the user we stopped.        Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();    }    @Override    public IBinder onBind(Intent intent) {        return mBinder;    }    // This is the object that receives interactions from clients.  See    // RemoteService for a more complete example.    private final IBinder mBinder = new LocalBinder();    /**     * Show a notification while this service is running.     */    private void showNotification() {        // In this sample, we'll use the same text for the ticker and the expanded notification        CharSequence text = getText(R.string.local_service_started);        // Set the icon, scrolling text and timestamp        Notification notification = new Notification(R.drawable.stat_sample, text,                System.currentTimeMillis());        // The PendingIntent to launch our activity if the user selects this notification        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,                new Intent(this, LocalServiceController.class), 0);        // Set the info for the views that show in the notification panel.        notification.setLatestEventInfo(this, getText(R.string.local_service_label),                       text, contentIntent);        // Send the notification.        // We use a layout id because it is a unique number.  We use it later to cancel.        mNM.notify(R.string.local_service_started, notification);    }}

说明:1、实现了OnBind()方法,当绑定时返回IBinder类,getService方法来返回当前的Service对象。

Acitviy上面的操作,可以参考LocalServiceBinding.java :

/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.example.android.apis.app;import com.example.android.apis.R;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.IBinder;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;/** * <p>Example of binding and unbinding to the {@link LocalService}. * This demonstrates the implementation of a service which the client will * bind to, receiving an object through which it can communicate with the service.</p> */public class LocalServiceBinding extends Activity {    private boolean mIsBound;    private LocalService mBoundService;    @Overrideprotected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.local_service_binding);        // Watch for button clicks.        Button button = (Button)findViewById(R.id.bind);        button.setOnClickListener(mBindListener);        button = (Button)findViewById(R.id.unbind);        button.setOnClickListener(mUnbindListener);    }    private ServiceConnection mConnection = new ServiceConnection() {        public void onServiceConnected(ComponentName className, IBinder service) {            // This is called when the connection with the service has been            // established, giving us the service object we can use to            // interact with the service.  Because we have bound to a explicit            // service that we know is running in our own process, we can            // cast its IBinder to a concrete class and directly access it.            mBoundService = ((LocalService.LocalBinder)service).getService();                        // Tell the user about this for our demo.            Toast.makeText(LocalServiceBinding.this, R.string.local_service_connected,                    Toast.LENGTH_SHORT).show();        }        public void onServiceDisconnected(ComponentName className) {            // This is called when the connection with the service has been            // unexpectedly disconnected -- that is, its process crashed.            // Because it is running in our same process, we should never            // see this happen.            mBoundService = null;            Toast.makeText(LocalServiceBinding.this, R.string.local_service_disconnected,                    Toast.LENGTH_SHORT).show();        }    };    private OnClickListener mBindListener = new OnClickListener() {        public void onClick(View v) {            // Establish a connection with the service.  We use an explicit            // class name because we want a specific service implementation that            // we know will be running in our own process (and thus won't be            // supporting component replacement by other applications).            bindService(new Intent(LocalServiceBinding.this,                     LocalService.class), mConnection, Context.BIND_AUTO_CREATE);            mIsBound = true;        }    };    private OnClickListener mUnbindListener = new OnClickListener() {        public void onClick(View v) {            if (mIsBound) {                // Detach our existing connection.                unbindService(mConnection);                mIsBound = false;            }        }    };}


说明: 1、实现ServiceConnection类,分别实现对绑定和解除绑定的处理。

2、bindService(Intent service, ServiceConnection conn, int flags) ,Context.BIND_AUTO_CREATE 表示服务和在绑定的时候开启。

文档对于flags的说明:

Flag for bindService(Intent, ServiceConnection, int): automatically create the service as long as the binding exists. Note that while this will create the service, itsonStartCommand(Intent, int, int) method will still only be called due to an explicit call tostartService(Intent). Even without that, though, this still provides you with access to the service object while the service is created.

Specifying this flag also tells the system to treat the service as being as important as your own process -- that is, when deciding which process should be killed to free memory, the service will only be considered a candidate as long as the processes of any such bindings is also a candidate to be killed. This is to avoid situations where the service is being continually created and killed due to low memory.

3、unbindService(ServiceConnection conn) ,解除绑定。

(2)远程服务(Remote Service)

大家可以参考ApiDemos app/

1、RemoteService.java 2、RemoteServiceBinding.java 3、RemoteServiceController

本文参考资料:

1、《Android Service学习之本地服务》(http://android.blog.51cto.com/268543/527314)。

更多相关文章

  1. tcping测试服务器TCP端口
  2. Android(安卓)四大组件(Activity、Service、BroadCastReceiver、
  3. Android的Animation之LayoutAnimation使用方法(控件设置动画)
  4. Android(安卓)Fragment 体系 源码追踪笔记(4)
  5. 【ALearning】第五章 Android相关组件介绍(一)Activity
  6. Android(安卓)Service完全解析(下)
  7. Gradle Build速度加快终极方法
  8. android中path的arcTo方法的使用
  9. Android(安卓)JNI编程—JNI基础

随机推荐

  1. android自定义title
  2. Android(安卓)ndk-stack tool
  3. Android(安卓)网络链接,不要忘记添加网络
  4. Android动画
  5. 使用SlidingDrawer的隐藏/显示搜索框
  6. android基础知识点复习之短信发送
  7. 不停地切换两张图片ViewFlipper
  8. ListPreference
  9. 手工下载android sdk或者system images等
  10. 2.5.2 使用alertdialog 创建列表对话框