您的位置:首页 > 移动开发 > Android开发

android学习笔记---40_建立能与访问者进行相互通信的本地服务,后台运行的service

2013-04-27 21:17 507 查看
40_建立能与访问者进行相互通信的本地服务

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

1.本地服务:如果服务和访问者在一个进程中那么就叫做本地服务。

远程服务:如果服务和访问者不在同一个应用,那么这就叫做远程服务。

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

2.通过startService()和stopService()启动关闭服务。适用于服务和Activity之间没有调用交互的情况。

如果相互之间需要方法调用或者传递参数,需要使用bindService()和unbindService()方法启动关闭服务。

采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法,这个时候调用者和服务绑定在一

起。 如果客户端要与服务进行通信,那么,onBind()方法必须返回Ibinder对象。如果调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用

onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()

方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()--

>onDestroy()方法。

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

Activity与服务进行通信,开发人员通常把通信方法定义在接口里,然后让Ibinder对象实现该接口,而Activity通过该接口引用服务onBind()方法返回的Ibinder

对象,然后调用Ibinder对象里自定义的通信方法。例子如下:

本例是一个本地服务,即服务与Activity在同一个应用内部。

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

接口:

public interface ICountService {

public int getCount();

}

服务类:

public class CountService extends Service {

private boolean quit;

private int count;

private ServiceBinder serviceBinder = new ServiceBinder();

public class ServiceBinder extends Binder implements ICountService {

@Override

public int getCount() {

return count;

}

}

@Override

public IBinder onBind(Intent intent) {

return serviceBinder;

}

@Override

public void onCreate() {

super.onCreate();

new Thread(new Runnable() {

@Override

public void run() {

while (!quit) {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {}

count++;

}

}

}).start();

}

@Override

public void onDestroy() {

super.onDestroy();

this.quit = true;

}

}

客户端Activity:

public class ClientActivity extends Activity {

private ICountService countService;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

this.bindService(new Intent(this, CountService.class), this.serviceConnection, BIND_AUTO_CREATE);

}

@Override

protected void onDestroy() {

super.onDestroy();

this.unbindService(serviceConnection);

}

private ServiceConnection serviceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

countService = (ICountService) service;//对于本地服务,获取的实例和服务onBind()返回的实例是同一个

int i = countService.getCount();

Log.v("CountService", "Count is " + i);

}

@Override

public void onServiceDisconnected(ComponentName name) {

countService = null;

}

};

}

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

2.a.下面是本地服务的例子:

软件界面:有一个

学号:

text框

查询按钮

b.当点击查询按钮后,下面就会显示学生的名字

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

3.这个例子中采用activity作为服务的访问者。

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

1.新建android项目:studentquery

2./studentquery/src/com/credream/stuquery/IStundent.java

package com.credream.stuquery;

public interface IStundent {

public String queryStudent(int no);

}

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

3./studentquery/src/com/credream/stuquery/StudentqueryActivity.java

package com.credream.stuquery;

import android.app.Activity;

import android.content.ComponentName;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.IBinder;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

/**

* 这个是访问者类,那么这个类如何访问服务中的query方法,以实现根据

* 学生的学号得到学生的姓名呢?这里在service服务中的这个方法可以实现。

*

@Override

public IBinder onBind(Intent intent) {

return binder;

}

* 另外当使用方法bindService启动服务的时候,服务会给访问者也就是这个类,返回一个

* IBinder对象给访问者,当访问者接收到IBinder这个对象后,就可以通过这个对象

* 调用服务中的方法。

* -----------------------------------------------

* 具体实现过程是这样的:当访问者(客户端)调用bindService方法启动服务的时候

* 服务就会自动调用onBind方法,取得IBinder对象,然后由操作系统,将IBinder

* 对象传给客户端。客户端得到binder对象后,就可以通过得到的binder对象调用服务中的

* 方法

* @author xiaofeng

*

*/

public class StudentqueryActivity extends Activity {

private EditText studentno;

private ServiceConnection conn = new StudentServiceConnection();

private IStundent iStundent;

private TextView resultView;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

resultView = (TextView) this.findViewById(R.id.resultView);

studentno = (EditText) this.findViewById(R.id.studentno);

Button button = (Button) this.findViewById(R.id.button);

button.setOnClickListener(new ButtonClickListener());

Intent service = new Intent(this, StudentService.class);

bindService(service, conn, BIND_AUTO_CREATE);

//BIND_AUTO_CREATE 值为1,意思是绑定了服务后就自动创建服务

}

private class StudentServiceConnection implements ServiceConnection{

/**

* Interface for monitoring the state of an application service. See Service and Context.bindService() for more information.

Like

many callbacks from the system, the methods on this class are called from the main thread of your process.

*/

/**

* 当客户端绑定到服务后,这个方法会被回调IBinder service

* 会把binder对象返回给客户端.

*/

public void onServiceConnected(ComponentName name, IBinder service) {

iStundent = (IStundent)service;

//将返回的binder对象转换为实现了IStudent接口的对象.IStudent

}

public void onServiceDisconnected(ComponentName name) {

//当客户端不和服务绑定的时候

iStundent = null;

}

}

//当服务被摧毁的时候自动用unbindService,解除和服务的绑定.

@Override

protected void onDestroy() {

unbindService(conn);

super.onDestroy();

}

private final class ButtonClickListener implements View.OnClickListener{

public void onClick(View v) {

String no = studentno.getText().toString();

//得到用户输入的学号

String name = iStundent.queryStudent(Integer.valueOf(no));

//得到学号对应的学生姓名

resultView.setText(name);

}

}

}

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

4./studentquery/src/com/credream/stuquery/StudentService.java

package com.credream.stuquery;

import android.app.Service;

import android.content.Intent;

import android.os.Binder;

import android.os.IBinder;

/**

* 这个是服务类

* @author xiaofeng

*

*/

public class StudentService extends Service{

private String[] names = {"李德伟","李小龙","李连杰"};

private IBinder binder = new StundentBinder();

public String query(int no){

if(no>0 && no<4){

return names[no - 1];

}

return null;

}

//提供这个方法可以让访问者访问服务

@Override

public IBinder onBind(Intent intent) {

return binder;

}

/**

* Binder这个类,已经实现了IBinder这个接口.

* StundentBinder这个类继承Binder就可以实现IBinder接口了.

* 可以看到这个类是私有的那么,客户端是无法直接调用它的,那么这个是用一根接口实现对这个类的调用.

* @author xiaofeng

*这个类用的很巧妙.

*实现接口后IStudent

*当客户端和服务连接好以后,当返回binder对象的时候,会调用这里面的queryStudent方法

*/

private class StundentBinder extends Binder implements IStundent{

public String queryStudent(int no) {

return query(no);//这里就是通过服务中的query方法,来实现在不

}

}

}

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

5./studentquery/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.credream.stuquery"

android:versionCode="1"

android:versionName="1.0" >

<uses-sdk android:minSdkVersion="8" />

<application

android:icon="@drawable/ic_launcher"

android:label="@string/app_name" >

<activity

android:label="@string/app_name"

android:name=".StudentqueryActivity" >

<intent-filter >

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<!-- 配置服务,这样只能使用显示激活服务 -->

<service android:name=".StudentService"/>

</application>

</manifest>

--------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐