安卓Service服务
一 Service简介
Service是运行在后台的,没有界面的,用来处理耗时比较长的。Service不是一个单独的进程,也不是一个单独的线程。
Service有两种类型:
本地服务(Local Service):用于应用程序内部
远程服务(Remote Sercie):用于android系统内部的应用程序之间
前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。
后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
二 Service的生命周期以及启动方式
Service有startService()和bindService()两种启动Service方法,每种方法Service的生命周期是不一样的。
1 通过startService()启动服务
Service会经历 onCreate() --> onStartCommand()
stopService()的时候直接onDestroy()
如果是调用者直接退出而没有调用stopService的话,Service会一直在后台运行, 下次调用者再起来仍然可以stopService()。
2 通过bindService() 启动服务
Service会运行onCreate()-->onBind() ,此时调用者和Service绑定在一起
unbindService()的时候 运行 onUnbind()-->onDestroyed()
调用者退出了,Srevice就会调用onUnbind()-->onDestroyed()
所谓绑定在一起就共存亡了。
注意:Service的onCreate()的方法只会被调用一次,也就是说无论你多少次的调用startService()或bindService(),Service只被创建一次。
Android中的服务和Windows中的服务是类似的,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用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()方法。
三 具体运用
1、开始服务,开始服务一般都是界面和服务简单数据交互。示例为从主界面传递一个值给服务,服务接收。
流程:
示例:
项目工程目录结构:
package com.example.service;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity
extends Activity
{
Button button1;
@Override
protected void onCreate ( Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1
= (Button)
this.findViewById(R.id.button1);
button1.setOnClickListener(
new OnClickListener()
{
@Override
public void onClick ( View v)
{
startMyService();
}
});
}
// 服务开启方法 protected void startMyService ()
{
Intent intent
= new Intent(
"com.example.service.MyService");
// 利用Intent向服务传递数据,数据通过界面输入 intent.putExtra(
"myMessage",
"MainActivity--lhyService123456【这是活动前台传递过来的数据】!");
this.startService(intent);//开始服务
}
@Override
public boolean onCreateOptionsMenu ( Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService
extends Service
{
@Override
public IBinder onBind ( Intent arg0)
{
// TODO Auto-generated method stub return null;
}
@Override
public void onCreate ()
{
Log.i(
"lhy",
"服务创建onCreate ()-----------");
super.onCreate();
}
// 启动服务,目前该方法不用 // @Override // public void onStart ( Intent intent, int startId) // { // // TODO Auto-generated method stub // super.onStart(intent, startId); // } @Override
public int onStartCommand ( Intent intent,
int flags,
int startId)
{
Log.i(
"lhy",
"服务开启,在后台运行,正在做事情当中。。。。。。。。。。。。。");
// 接收activity传递过来的数据 String message
= intent.getStringExtra(
"myMessage");
Log.i(
"lhy",
"MyService--服务后台接收前台活动输入的数据:" + message);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy ()
{
// TODO Auto-generated method stub super.onDestroy();
}
}
<RelativeLayout xmlns
:android
= "http://schemas.android.com/apk/res/android" xmlns
:tools
= "http://schemas.android.com/tools" android
:layout_width
= "match_parent" android
:layout_height
= "match_parent" android
:paddingBottom
= "@dimen/activity_vertical_margin" android
:paddingLeft
= "@dimen/activity_horizontal_margin" android
:paddingRight
= "@dimen/activity_horizontal_margin" android
:paddingTop
= "@dimen/activity_vertical_margin" tools
:context
= ".MainActivity" > <TextView
android
:id
= "@+id/textView1" android
:layout_width
= "wrap_content" android
:layout_height
= "wrap_content" android
:layout_marginBottom
= "10dp" android
:text
= "开始服务示例演示" / > <Button
android
:id
= "@+id/button1" android
:layout_width
= "wrap_content" android
:layout_height
= "wrap_content" android
:layout_marginTop
= "38dp" android
:text
= "开始服务" / > <EditText
android
:id
= "@+id/editText1" android
:layout_width
= "match_parent" android
:layout_height
= "wrap_content" android
:layout_alignLeft
= "@+id/button1" android
:layout_below
= "@+id/button1" android
:layout_marginTop
= "38dp" android
:ems
= "10" > <requestFocus
/ > < /EditText
> < /RelativeLayout
> AndroidMainfest.xml文件中注册服务 <service android
:name
= "com.example.service.MyService" > <intent
-filter
> <action android
:name
= "com.example.service.MyService" / > < /intent
-filter
> < /service
> 控制台输出信息:MainActivity--lhyService123456 是活动界面传递过来,在服务端接收的数据
2、绑定服务,一般都是界面与服务深层次数据交互,进程之间数据传递,绑定服务需要连接对象,连接对象中可以获得服务类的内部类对象,这样活动前台可以利用服务类内部类对象操作服务里面的任何方法和属性。
具体流程:
示例:
项目工程目录结构:
package com.example.servicebind;import com.example.servicebind.MyServices.MyBind;import android.os.Bundle;import android.os.IBinder;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.util.Log;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;public class MainActivity extends Activity{ Button button1; Button button2; MyBind myBind; @Override protected void onCreate ( Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button1 = (Button) this.findViewById(R.id.button1); button1.setOnClickListener(onClickListener); button2 = (Button) this.findViewById(R.id.button2); button2.setOnClickListener(onClickListener); } // 按钮事件监听 OnClickListener onClickListener = new OnClickListener() { @Override public void onClick ( View v) { switch (v.getId()) { case R.id.button1: startMyServiceBind(); break; case R.id.button2: stopMyServiceBind(); break; default: break; } } }; // 按钮点击事件监听方法,也就是绑定服务 protected void startMyServiceBind () { // 如果部内部类对象不为空,那么就直接调用内部类方法,否则重新绑定服务,建立连接 if (myBind != null) { // 利用服务内部对象,调用服务内部类方法,相当于调用了服务类的的数据 myBind.myBindFun(); Log.i("lhy", myBind.getStr()); } else { // 绑定服务方法******************************* Intent intent = new Intent("com.example.servicebind.MyServices"); // intent意图,serviceConnection连接, Context.BIND_AUTO_CREATE绑定自动创建 this.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } } protected void stopMyServiceBind () { if (serviceConnection == null) { return; } else { this.unbindService(serviceConnection); Log.i("lhy", "服务解除!!"); serviceConnection = null; } } // 绑定服务开始,类似于事件监听,一个服务连接 ServiceConnection serviceConnection = new ServiceConnection() { // 绑定失败之后 @Override public void onServiceDisconnected ( ComponentName name) { // TODO Auto-generated method stub } // 绑定成功之后,也就是服务建立了连接 @Override public void onServiceConnected ( ComponentName name, IBinder service) { // 获取服务类内部对象,IBinder service,该参数就是服务类回调方法OnBind()返回的数据,也就是服务内部对象 myBind = (MyBind) service; } };} package com.example.servicebind;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;import android.util.Log;public class MyServices extends Service{ // 服务类成员变量 String str = "MyServiceMessage"; // 服务类成员方法 public void fun1 () { Log.i("lhy", "服务内部方法fun1()"); } // 服务类内部类 public class MyBind extends Binder { // 内部类调用外部类方法 public void myBindFun () { fun1(); } // 内部类调用外部类成员变量 public void setStr ( String str) { MyServices.this.str = str; } public String getStr () { return MyServices.this.str; } } @Override public void onCreate () { Log.i("lhy", "服务创建onCreate()"); super.onCreate(); } @Override public IBinder onBind ( Intent intent) { Log.i("lhy", "服务绑定onBind()"); // 实例化内部类对象,该对象可以无条件调用其外部类(本服务类)的一切方法和成员变量 return new MyBind(); } @Override public boolean onUnbind ( Intent intent) { Log.i("lhy", "服务解除onUnbind()"); return super.onUnbind(intent); }} <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="绑定服务演示" /><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/textView1"android:layout_below="@+id/textView1"android:layout_marginTop="23dp"android:text="绑定服务" /><Buttonandroid:id="@+id/button2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@+id/button1"android:layout_below="@+id/button1"android:layout_marginTop="14dp"android:text="解除服务" /></RelativeLayout> 最后在AndroidMainfest.xml文件中注册服务: <service android
:name
= "com.example.servicebind.MyServices" > <intent
-filter
> <action android
:name
= "com.example.servicebind.MyServices" / > < /intent
-filter
> < /service
>