现在的位置: 首页 > 移动开发 > 正文

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

2019年09月18日 移动开发 ⁄ 共 7397字 ⁄ 字号 评论关闭

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>
--------------------------------------------------------------------------

抱歉!评论已关闭.