服务是一个应用程序组件代表应用程序执行一个长时间操作的行为,虽然不与用户交互或供应功能供其它应用程序使用。它和其他的应用对象一样,在他的宿主进程的主线程中运行。今天我们开始android中普通service服务的学习。本地服务与前台服务,请参见我的另外一篇博客:   android基础---->IntentService的使用

目录导航

  1. service服务的简单说明
  2. service服务测试的准备代码
  3. service服务start的测试
  4. service服务bind的测试
  5. service的生命周期的总结        
  6. 友情链接

service的简单说明

一、 service类型划分:

  • 运行地点划分:
类别区别 优点缺点  应用
本地服务(Local)该服务依附在主进程上, 服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。 主进程被Kill后,服务便会终止。 非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务。
远程服务(Remote)该服务是独立的进程, 服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。 该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。 一些提供系统服务的Service,这种Service是常驻的。
  • 按运行类型分类:
类别区别应用
前台服务会在通知一栏显示 ONGOING 的 Notification,当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。
后台服务默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。
  • 按使用方式分类:
类别区别
startService 启动的服务主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService
bindService 启动的服务该方法启动的服务要进行通信。停止服务使用unbindService
startService 同时也 bindService 启动的服务停止服务应同时使用stepService与unbindService

二、 两种服务的启动流程:

  • context.startService() 启动流程(后台处理工作):

  context.startService()  -> onCreate()  -> onStartCommand()  -> Service running  -> context.stopService()  -> onDestroy()  -> Service stop 所以调用startService的生命周期大致为:onCreate(只在创建的时候调用一次直到被摧毁) --> onStartCommand (服务开启后,可多次调用) --> onDestroy

  • context.bindService()启动流程(在本地同一进程内与Activity交互):

  context.bindService()  -> onCreate()  -> onBind()  -> Service running  -> onUnbind()  -> onDestroy()  -> Service stop,bindService的生命周期简化为为:onCreate --> onBind --> onUnbind --> onDestory。

三、 service的使用细节:

  • 在注册服务的时候,为了将service纳入编译系统,必须在AndroidMainfest.xml中对Service进行显式声明。
  • 计算量较大的又不是UI层的工作的话,可以选择放置在Service中进行工作。
  • 通过开发文档你会发现,Android中的Service与宿主(调用者)在同一线程,而不是专门起一条线程,这意味着,如果你的服务要CPU密集型操作(如:MP3播放)或则阻塞操作(如网络)时,必须产生它自己的线程来完成这个工作,否则会造成线程阻塞。在Service的子类里面,
  • 如果在使用Service的时候又使用了广播接收器配合工作,广播如果是动态注册的话,在服务停止的时候记得调用unregisterReceiver(receiver);这个方法来注销掉接收器

四、 android中服务的启动与停止:

  • 服务的启动:
Intent intent = new Intent();
intent.setClass(MainActivity.this , NormalServices.class);
startService(intent);
  • 服务的停止:
Intent intent = new Intent();
intent.setClass(MainActivity.this , NormalServices.class);
stopService(intent);

service服务测试的准备代码

  我们通过一个具体的案例来说明start与bind方式的service服务的生命周期的介绍。项目结果如下:

一、 在MainActivity.java中做一些初始化工作,如下代码:

private final static String TAG = "NormalServices";
private NormalServices.MyBinder binder; private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (NormalServices.MyBinder) service;
binder.sayHello(name.getClassName());
} @Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "service disconnect: " + name.getClassName());
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "main on create.");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

二、 创建一个简单的服务类:NormalServices

package com.example.linux.serviceslifetest;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log; public class NormalServices extends Service {
private final static String TAG = "NormalServices";
private MyBinder myBinder = new MyBinder(); class MyBinder extends Binder {
public void sayHello(String name) {
Log.i(TAG, "say hello method: " + name);
}
public void sayWorld(String name) {
Log.i(TAG, "say world method: " + name);
}
} public NormalServices() {
Log.i(TAG, "NormalServices constructor.");
} @Override
public IBinder onBind(Intent intent) {
String username = intent.getStringExtra("username");
Log.i(TAG, "on bind" + ": username: " + username);
return myBinder;
} @Override
public void onCreate() {
Log.i(TAG, "on create.");
super.onCreate();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "on start command.");
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
Log.i(TAG, "on destory.");
super.onDestroy();
} @Override
public boolean onUnbind(Intent intent) {
//默认返回false
String username = intent.getStringExtra("username");
Log.i(TAG, "on unbind: " + super.onUnbind(intent) + ", username: " + username);
return true;
} @Override
public void onRebind(Intent intent) {
Log.i(TAG, "on rebind");
super.onRebind(intent);
}
}

三、 创建另外一个活动,用于测试活动切换时,service的生命周期的变化:OtherActivity

package com.example.linux.serviceslifetest;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View; public class OtherActivity extends AppCompatActivity {
private final static String TAG = "NormalServices";
private NormalServices.MyBinder binder; private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (NormalServices.MyBinder) service;
binder.sayHello(name.getClassName());
} @Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "OtherActivity service disconnect: " + name.getClassName());
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
} public void startService(View view) {
Intent intent = new Intent();
intent.setClass(OtherActivity.this, NormalServices.class);
startService(intent);
} public void stopService(View view) {
Intent intent = new Intent();
intent.setClass(OtherActivity.this, NormalServices.class);
stopService(intent);
} // 绑定服务
public void bindService(View view) {
Intent intent = new Intent();
intent.setClass(OtherActivity.this, NormalServices.class);
boolean isBind = bindService(intent, connection, Context.BIND_AUTO_CREATE);
Log.i(TAG, "bind service: " + isBind);
} // 解绑服务
public void unbindService(View view) {
Intent intent = new Intent();
intent.setClass(OtherActivity.this, NormalServices.class);
unbindService(connection);
}
}

四、 在AndroidManifest.xml中注册服务与活动:

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <service
android:name=".NormalServices"
android:enabled="true"
android:exported="true" /> <activity android:name=".OtherActivity"/

五、 在MainActivity中加入方法,启动另外一个活动:

//启动另外一个Activity
public void otherActivity(View view) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, OtherActivity.class);
startActivity(intent);
}

service服务start的测试

一、 在MainActivity中创建方法startService,启动服务:

public void startService(View view) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, NormalServices.class);
startService(intent);
}

二、 在MainActivity中创建方法stopService,停止服务:

public void stopService(View view) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, NormalServices.class);
stopService(intent);
}

三、 运行的结果如下:

  • 点击start:
03-24 19:28:40.130 9986-9986/com.example.linux.serviceslifetest I/NormalServices: NormalServices constructor.
03-24 19:28:40.130 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on create.
03-24 19:28:40.130 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击stop:
03-24 19:31:18.730 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on destory.
  • 点击start:
03-24 19:32:23.660 9986-9986/com.example.linux.serviceslifetest I/NormalServices: NormalServices constructor.
03-24 19:32:23.660 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on create.
03-24 19:32:23.660 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击start:
03-24 19:33:06.350 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击stop:
03-24 19:33:30.240 9986-9986/com.example.linux.serviceslifetest I/NormalServices: on destory.

四、 对于上述结果的分析:

  • 当service第一次创建启动(start方法触发):

  service的构造方法:

  oncreate方法

  onStartCommand方法

  • stop方法触发时,关闭服务:

  on destory

  • 如果service没有被destory,那么随后点击start,只会执行onStartCommand方法

service服务bind的测试

一、 在MainActivity中创建方法bindService,绑定服务:

// 绑定服务
public void bindService(View view) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, NormalServices.class);
intent.putExtra("username", "linux");
boolean isBind = bindService(intent, connection, Context.BIND_AUTO_CREATE);
Log.i(TAG, "bind service: " + isBind);
}

二、  在MainActivity中创建方法unbindService,解绑服务:

// 解绑服务
public void unbindService(View view) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, NormalServices.class);
unbindService(connection);
}

三、 运行结果如下:

  • 点击bind服务:
03-24 19:37:26.340 18803-18803/com.example.linux.serviceslifetest I/NormalServices: bind service: true
03-24 19:37:26.350 18803-18803/com.example.linux.serviceslifetest I/NormalServices: NormalServices constructor.
03-24 19:37:26.350 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on create.
03-24 19:37:26.350 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on bind: username: linux
03-24 19:37:26.370 18803-18803/com.example.linux.serviceslifetest I/NormalServices: say hello method: com.example.linux.serviceslifetest.NormalServices
  • 点击start开启服务:
03-24 19:38:12.020 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on start command.
  • 点击stop:无输出
  • 点击unbind解绑服务:
03-24 19:39:05.200 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on unbind: false, username: linux
03-24 19:39:05.200 18803-18803/com.example.linux.serviceslifetest I/NormalServices: on destory.

四、 对于上述结果的分析:

服务的绑定:
  • 在绑定服务之前,首先要有服务存在才行。如果指定了BIND_AUTO_CREATE,而且此时没有服务。则会创建服务,但onStartCommand方法此时没有执行。
  • 执行onbind方法,返回Ibind是onServiceConnected方法中的service参数,这样就可以执行Ibinder的方法了
  • 一个Activity同时绑定同一服务再次,那么服务的onbind方法就不会得到执行
服务的解绑:
  • onbind方法,如果没有之前的startService,那么onDestory方法也会得到执行
其它说明:
  • 类ServiceConnection中的onServiceDisconnected()方法在正常情况下是不被调用的,它的调用时机是当Service服务被异外销毁时,例如内存的资源不足时.
  • This typically happens when the process hosting the service has crashed or been killed.
活动与服务:
  • 在bind服务时,不需要服务启动。启动服务也不需要有Activity绑定服务
  • Activity销毁之后,对应的服务也被销毁。

service的生命周期的总结

  前面我们使用到的onCreate()、onStartCommand()、onBind()和onDestroy()等方法都是在服务的生命周期内可能回调的方法。

一、 启动与停下服务:

  一旦在项目的任何位置调用了Context 的startService()方法,相应的服务就会启动起来,并回调onStartCommand()方法。如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand()方法执行。服务启动了之后会一直保持运行状态,直到stopService()或stopSelf()方法被调用。注意虽然每调用一次startService()方法,onStartCommand()就会执行一次,但实际上每个服务都只会存在一个实例。所以不管你调用了多少次startService()方法,只需调用一次stopService()或stopSelf()方法,服务就会停止下来了。

二、 绑定与解绑服务:

  另外,还可以调用Context 的bindService()来获取一个服务的持久连接,这时就会回调服务中的onBind()方法。类似地,如果这个服务之前还没有创建过,onCreate()方法会先于onBind()方法执行。之后,调用方可以获取到onBind()方法里返回的IBinder 对象的实例,这样就能自由地和服务进行通信了。只要调用方和服务之间的连接没有断开,服务就会一直保持运行状态。

三、 启动与绑定服务:

  当调用了startService()方法后,又去调用stopService()方法,这时服务中的onDestroy()方法就会执行,表示服务已经销毁了。类似地,当调用了bindService()方法后,又去调用unbindService()方法,onDestroy()方法也会执行,这两种情况都很好理解。但是需要注意,我们是完全有可能对一个服务既调用了startService()方法,又调用了bindService()方法的,这种情况下该如何才能让服务销毁掉呢?根据Android 系统的机制,一个服务只要被启动或者被绑定了之后,就会一直处于运行状态,必须要让以上两种条件同时不满足,服务才能被销毁。所以,这种情况下要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行。

友情链接

05-11 17:27