Service

启动service

有了 Service 类我们如何启动他呢,有两种方法:
      • Context.startService()

           单独调用则生命周期:  【onCreate()-  >onStartCommand()->startService()->onDestroy()】
      • Context.bindService()

           单独调用则生命周期: 【onCreate()->onBind()->onUnbind()->onDestroy()】   (bindService是不会调用StartCommand()的)
     1.  在同一个应用任何地方调用 startService() 方法就能启动 Service 了,然后系统会回调 Service 类的 onCreate() 以及 onStart() 方法。这样启动的 Service 会一直运行在后台,直到 Context.stopService() 或者 selfStop() 方法被调用。另外如果一个 Service 已经被启动,其他代码再试图调用 startService() 方法,是不会执行 onCreate() 的,但会重新执行一次 onStart() 。
      2. 另外一种 bindService() 方法的意思是,把这个 Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方发,你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 onStart()。    

      总结:
      1. startService()的目的是回调onStart()方法,onCreate() 方法是在Service不存在的时候调用的,如果Service存在(例如之前调用了bindService,那么Service的onCreate方法已经调用了)那么startService()将跳过onCreate() 方法。
      2.  bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过StartService启动的服务)。
      由于Service 的onStart()方法只有在startService()启动Service的情况下才调用,故使用onStart()的时候要注意这点。

参考http://www.cnblogs.com/gzgg/archive/2012/02/20/2359485.html

onStartCommand()取代了onStart()方法。

//frameworks/base/core/java/android/app/Service.java
package android.app;

public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
    public int onStartCommand(Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
    }

}

onStart()是否被调用取决于onStartCommand()重写后是否调用onStart()

下面给第一种方式调用Service

public class FirstService extends Service
{
    public static final String TAG = "11111";

    /**
     * 通过startService(intent);方式调用服务时,该方法不会被调用
     */
    @Override
    public IBinder onBind(Intent arg0)
    {
        Log.d(TAG, "Service onBind");
        return null;
    }

    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.d(TAG, "Service is Created");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.d(TAG, "Service is Started");
        return START_STICKY;
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        Log.d(TAG, "Service is Destroyed");
    }
}
public class MainActivity extends Activity {
    private Button start, stop;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        start = (Button) findViewById(R.id.start);
        stop = (Button) findViewById(R.id.stop);

        final Intent intent = new Intent();
        intent.setAction("org.crazyit.service.FIRST_SERVICE");

        start.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                Log.d("11111", "startService()"); startService(intent); } }); stop.setOnClickListener(
new OnClickListener() { @Override public void onClick(View arg0) {
Log.d("11111", "stopService()"); stopService(intent); } }); } }
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.service"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 配置一个Service组件 -->
        <service android:name=".FirstService">
            <intent-filter>
                <!-- 为该Service组件的intent-filter配置action -->
                <action android:name="org.crazyit.service.FIRST_SERVICE" />
            </intent-filter>        
        </service>
    </application>
</manifest> 

从log上看Activity和Service是同一个线程里面
------------------------------------------------------

第二种方式bindService()调用服务

public class BindService extends Service {
    private static final String TAG = "CM-BindService";
    private int count;
    private boolean quit;
    private MyBinder binder = new MyBinder();

    //通过binder来向外提供对应的接口
public class MyBinder extends Binder { public int getCount() { return count; } } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "Service is Binded"); return binder; } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "Service is Created"); new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { } count++; } } }.start(); } @Override public boolean onUnbind(Intent intent) { Log.d(TAG, "Service is Unbinded"); return true; } @Override public void onDestroy() { super.onDestroy(); this.quit = true; Log.d(TAG, "Service is Destroyed"); } @Override public void onRebind(Intent intent) { super.onRebind(intent); this.quit = true; Log.d(TAG, "Service is ReBinded"); } }
public class MainActivity extends Activity {
    protected static final String TAG = "CM-MainActivity";
    Button bind, unbind, getServiceStatus;
    BindService.MyBinder binder;
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected");
            binder = (BindService.MyBinder) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected");
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        bind = (Button) findViewById(R.id.bind);
        unbind = (Button) findViewById(R.id.unbind);
        getServiceStatus = (Button) findViewById(R.id.getServiceStatus);

        final Intent intent = new Intent();
        intent.setAction("org.crazyit.service.BIND_SERVICE");

        bind.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View source) {
                Log.d(TAG, "onClick() bindService");
                bindService(intent, conn, Service.BIND_AUTO_CREATE);
            }
        });

        unbind.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View source) {
                Log.d(TAG, "onClick() unbindService");
                unbindService(conn);
            }
        });

        getServiceStatus.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View source) {
                Log.d(TAG, "onClick() get Serivce count");
                Toast.makeText(MainActivity.this,
                        "Serivce count " + binder.getCount(), 4000).show();
            }
        });
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.example.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 配置一个Service组件 -->
        <service android:name=".BindService">
            <intent-filter>
                <!-- 为该Service组件的intent-filter配置action -->
                <action android:name="org.crazyit.service.BIND_SERVICE" />
            </intent-filter>    
        </service>
    </application>
</manifest> 

Service的生命周期
onCreate  onStart  onDestroy  onBind
1). 被启动的服务的生命周期:如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。

2). 被绑定的服务的生命周期:如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。

3). 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。

4). 当服务被停止时清除服务:当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

特别注意:
1、你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自      动解除,并且Service会自动停止);
2、你应当注意 使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
3、同时使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。
5、在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。

 只要还有Activity bind 这个服务(始终只有一个实例),或者startService()后没有调用stopService(), 那么该服务会一直存活(也就是OnDestroy()一直没有被调用)。

-------------------------------------------------------------------------------------

 

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected()");
            catService = ICat.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected()");
            catService = null;
        }
    };

 

bindService()和onServiceConnected()不是在同一个线程里面。
当bindService()调用返回绑定成功时,onServiceConnected()还没有执行.此时catService = null.
只有当onServiceConnected()被另外一个线程回调运行结束,那么catService才会有赋值。

 

posted @ 2015-03-16 09:46  牧 天  阅读(177)  评论(0)    收藏  举报