## 第六天.AndroidService ##
### 6.1Service概述 ###
#### 6.1.1 Service概念及用途 ####
服务是运行在后台的一段代码。
不是进程,也不是线程。
可以运行在它自己的进程,也可以运行在其他应用程序进程的上下文(context)里面,这取决于自身的需要。
Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序。
媒体播放器的服务,当用户退出媒体选择用户界面,仍然希望音乐依然可以继续播放,这就是由服务(service)来保证当用户界面关闭时音乐继续播放的。
比如当我们一个应用的数据是通过网络获取的,不同时间的数据是不同的,这时候我们可以用Service在后台定时更新,而不用每打开应用的时候在去获取。
### 6.2 Service生命周期 ####
+ onCreate()
在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
+ onStart()
只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
+ onDestroy()
服务被终止时调用。
+ onBind()
只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
+ onUnbind()
只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。
startService后,即使调用startService的进程结束了Service仍然还存在,直到有进程调用stopService,或者Service自己自杀(stopSelf())。
bindService后,Service就和调用bindService的进程同生共死了,也就是说当调用bindService的进程死了,那么它bind的Service也要跟着被结束,当然期间也可以调用unbindservice让Service结束。
两种方式混合使用时,比如说你startService了,我bindService了,那么只有你stopService了而且我也unbindservice了,这个Service才会被结束。
### 6.3启动与停止Service ###
#### 6.3.1 Service开发步骤 ####
第一步:继承Service类
```
public class MyService extends Service {
}
```
第二步:在AndroidManifest.xml文件中的节点里对服务进行配置:
服务不能自己运行,使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。
#### 6.3.2 采用startService()启动服务 ####
采用Context.startService()方法启动服务的代码如下:
```
public class HelloActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
......
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
startService(intent);
}});
}
}
```
#### 6.3.3 采用bindService()启动服务 ####
采用Context.startService()方法启动服务的代码如下:
```
public class HelloActivity extends Activity {
ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
}
public void onServiceDisconnected(ComponentName name) {
}
};
public void onCreate(Bundle savedInstanceState) {
Button button =(Button) this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent(HelloActivity.this, SMSService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
//unbindService(conn);//解除绑定
}});
}
}
```
#### 6.3.4 Service服务演示 ####
1. 新建一个Android工程ServiceDemo
2. 修改main.xml代码,增加二个按钮
3. 新建一个Service,命名为MyService.java
4. 新建ServiceDemo.java
5. 配置AndroidManifest.xml
6. 执行上述工程, 用Logcat查看日志
7. 按HOME键进入Settings(设置)àApplications(应用)àRunningServices(正在运行的服务)
**main.xml**
```
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
<Button
android:id="@+id/startservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="startService" />
<Button
android:id="@+id/stopservice"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="stopService" />
</LinearLayout>
```
**MyService.java**
````
public class MyService extends Service {
//定义个一个Tag标签
private static final String TAG = "MyService";
//一个Binder类,用在onBind() 方法里,这样Activity那边可以获取到
private MyBinder mBinder = new MyBinder();
public IBinder onBind(Intent intent) {
Log.e(TAG, "start IBinder~~~");
return mBinder;
}
public void onCreate() {
Log.e(TAG, "start onCreate~~~");
super.onCreate();
}
public void onStart(Intent intent, int startId) {
Log.e(TAG, "start onStart~~~");
super.onStart(intent, startId);
}
```
```
public void onDestroy() {
Log.e(TAG, "start onDestroy~~~");
super.onDestroy();
}
public boolean onUnbind(Intent intent) {
Log.e(TAG, "start onUnbind~~~");
return super.onUnbind(intent);
}
public String getSystemTime(){
Time t = new Time();
t.setToNow();
return t.toString();
}
public class MyBinder extends Binder{
MyService getService()
{
return MyService.this;
}
} }
```
**ServiceDemo.java**
```
public class ServiceDemo extends Activity implements OnClickListener {
private MyService mMyService;
private TextView mTextView;
private Button startServiceButton;
private Button stopServiceButton;
private Context mContext;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setupViews();
}
```
```
public void setupViews(){
mContext = ServiceDemo.this;
mTextView = (TextView)findViewById(R.id.text);
startServiceButton = (Button)findViewById(R.id.startservice);
stopServiceButton = (Button)findViewById(R.id.stopservice);
startServiceButton.setOnClickListener(this);
stopServiceButton.setOnClickListener(this);
}
```
```
public void onClick(View v) {
if(v == startServiceButton){
Intent i = new Intent();
i.setClass(ServiceDemo.this, MyService.class);
mContext.startService(i);
}else if(v == stopServiceButton){
Intent i = new Intent();
i.setClass(ServiceDemo.this, MyService.class);
mContext.stopService(i);
}
}
}
```
**AndroidManifest.xml**
```
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lxt008"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ServiceDemo"
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 android:name=".MyService" android:exported="true"></service>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>
```
### 6.4Notification通知 ###
如果需要查看消息,可以拖动状态栏到屏幕下方即可查看消息。
发送消息的代码如下:
```
//获取通知管理器
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int icon = android.R.drawable.stat_notify_chat;
long when = System.currentTimeMillis();
//新建一个通知,指定其图标和标题
//第一个参数为图标,第二个参数为标题,第三个为通知时间
Notification notification = new Notification(icon, null, when);
Intent openintent = new Intent(this, OtherActivity.class);
//当点击消息时就会向系统发送openintent意图
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);
notification.setLatestEventInfo(this, “标题”, “我是内容", contentIntent);
mNotificationManager.notify(0, notification);
```
#### 6.4.1 Android中的通知(Notification) ####
### 6.5案例分析 ###
参考案例:NotificationDemo
[源代码下载](http://www.apkbus.com/forum.php?mod=viewthread&tid=83334)