Service是Android四大组件之一。
 1. Android提供service类来专门创建处理长生命周期的应用程序组件以及不需要用户界面的功能。
 2. Android赋予service比处于非活动状态的Activity更高的优先级。和Activity BroadcastReceiver一样,运行在主线程

 3. Service主要用于执行Intent查找 处理数据 更新ContentProvider 激活Intent以及触发Notication等。

 4. Service的优先级比较高,通常情况下不会自动停止,因此自终止可以显著的改善应用程序中的资源占用情况。

 5. 有两种方式可以启动Service,分别为startService和bindService

下面先分别描述一下两种方式的异同及各自的生命周期。

A、startService

    1.启动和停止方式:


<span >	</span>//显示启动停止service
        Intent startServiceIntent = new Intent(this, MyService.class);
        startService(startServiceIntent);
        stopService(startServiceIntent);

<span >	</span>//隐士启动停止service
        startServiceIntent = new Intent(MyService.START_SERVICE_ACTION);
        startService(startServiceIntent);
        stopService(startServiceIntent);
<span >	</span>//service 自杀<pre name="code" class="java"><span >	</span>stopSelr();




    2.生命周期:


<span >	</span>11-09 11:43:45.243 23785-23785/com.happy.test.service I/MyService: ---onCreate---
 <span >	</span>11-09 11:43:45.243 23785-23785/com.happy.test.service I/MyService: ---onStartCommand---
 <span >	</span>11-09 11:43:45.243 23785-23785/com.happy.test.service I/MyService: ---onStart---
 
 <span >	</span>11-09 11:44:12.043 23785-23785/com.happy.test.service I/MyService: ---onStartCommand---
 <span >	</span>11-09 11:44:12.043 23785-23785/com.happy.test.service I/MyService: ---onStart---
 
 <span >	</span>11-09 11:44:15.233 23785-23785/com.happy.test.service I/MyService: ---onDestroy---



    onCreateService只会调用一次,如果启动后再次调用startService,会走onStartCommand和onStart方法.

    3.简述onStart和onStartCommand的区别:


/**
     * 废弃,被onStartCommand取代
     *
     * @param intent
     * @param startId
     */
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i(TAG, "---onStart---");
    }

    /**
     * 1.android 2.0 API以后引入,提供了和onStart一样的功能,并且还允许你告诉系统,如果系统在显示调用stopService或stopSelf之前终止了service,那么应该如何启动service。
     * 2.实现service的标准模式是从此方法中创建和运行一个新线程,用来在后台执行处理,并在该线程完成后终止这个service
     *
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "---onStartCommand---");
        return Service.START_STICKY;
    }



    4.优缺点:

优:一旦开启,除非我们显示的调用stopService和stopSelf,正常情况下是不会停止的,会一直在后台运行

缺:虽然在Activity中开启的,但是activity缺无法调用service中的方法

B、bindService

    1.简介:

      要让一个Service支持绑定,需要实现onBind方法,并返回当前被绑定service的实例
      Service与Activity绑定,后者拥有对前者的实例实例引用,可以对service中的方法进行调用
      Service与其它组件的连接表示为一个ServiceConnection,通过重写onServiceConnected和onServiceDisconnected获得对service的引用

    2.生命周期:


11-09 16:48:02.310 12231-12231/com.happy.test.service I/MyService: ---onCreate---
   11-09 16:48:02.310 12231-12231/com.happy.test.service I/MyService: ---onBind---

   11-09 16:48:03.130 12231-12231/com.happy.test.service I/MyService: ---onUnbind---
   11-09 16:48:03.130 12231-12231/com.happy.test.service I/MyService: ---onDestroy---

    3.允许service和activity绑定,这样能够获得更加详细的接口。要让一个service支持绑定,需要实现onBind方法,并返回被绑定service的当前实例。

service代码:


@Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "---onBind---");
        return myBind;
    }

    private MyBind myBind = new MyBind();

    public class MyBind extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "---onUnbind---");
        return super.onUnbind(intent);
    }


Activity代码

private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //当建立连接时调用
            mService = ((MyService.MyBind) service).getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // 当service意外断开时接收
            mService = null;
        }
    };



     4.下面就可以在activity中调用service中的方法了


case R.id.bindService:
                bindService(startServiceIntent,serviceConnection, Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbindService:
                unbindService(serviceConnection);
                break;
            case R.id.playMusic:
                mService.playMusic("月亮之上");
                break;
            case R.id.stopMusic:
                mService.stopMusic("月亮之上");
                break;

     5.特点

该Service与Activity不同生,但共死,也就是说只要bindService后,该activity finish的时候,即使不显示的调用unBindService,系统也会帮我们完成此操作。

C、两种方式相结合

     当我们既想让service长期在后台运行,又想让我们的activity可以调用service的方法的时候,可以才取这两种方式相结合的形势。具体流程为:

     startService-->bindService,这样即使我们activity finish掉,只会调用service的onUnbind方法,而我们的service会继续在后台运行。这个时候,想停止service只能通过stopService或者stopSelf来实现了。

D、创建前台service

     在service需要和用户直接交互的情况下,防止在内存不足时被kill掉,最合适的方法是把service的优先级提高到和前台activity一样高,可以通过调用service的startForeground的方法实现。

     比如,在播放音乐的过程中,前台service会直接和用户进行交互,因此可以调用startForeground方法,在调用此方法时还需要传入一个持续工作的notification,只要service在前台运行,这个notification就会显示。


/**
     * 不完整代码,尤其是notification
     */
    public void startPlayBack() {
        // 当通知栏被点击时打开的activity
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, 0);
        //设置notification
        Notification notification = new Notification();
        //设置notification持续展示
        notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
        startForeground(0, notification);
    }

    如果有这样多个同时运行在前台并且不可停止的service,系统可能会变的比较卡顿。理想情况下,应该为用户提供一种禁用前台service的方法,比如当用户点击通知栏的时候,启动一个activity,调用stopForeground(true)来把service移到后台,并且可以决定是否移除通知栏。