Android专题8——本地服务和远程服务通信

关于远程服务

  • 远程服务指的是服务和访问者不在同一个应用程序中,即不在同一个进程中。

  • 访问远程服务类似进程间通信。

  • 访问者和远程服务需要遵守能够被操作系统理解的协议,AIDL。

1. 在服务端和客户端配置AIDL

  • aidl文件最好都放在aidl目录下,aidl文件用于接口描述

  • 会自动生成一个同名的JAVA文件

  • 在自动生成的JAVA文件中,系统会自动定义一个Stub类,继承Binder类,实现aidl文件中描述的接口

技术分享

技术分享

 

2. 编写service业务代码

  • 在清单文件中注册

  • 实现自定义的IBinder

技术分享
        <service android:name=".StudentService">
            <intent-filter >
                <action android:name="com.njulya.REMOTESERVICE"/>
            </intent-filter>
        </service>
View Code
技术分享
import com.njulya.aidl.StudentQuery;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class StudentService extends Service {
    IBinder iBinder;
    String[] names = {"张阳","李永安","潘杰"};
    @Override
    public IBinder onBind(Intent intent) {
        iBinder = new StudentBinder();
        return iBinder;
    }
/**
 * 实现IBinder接口,用于通信
 * @author Andy
 */
    private class StudentBinder extends StudentQuery.Stub{
        @Override
        //aidl文件中描述的接口
        public String query(int no) throws RemoteException {
            return names[no-1];//业务代码
        }
        
    }
}
View Code

 

 

3.编写客户端应用

技术分享
package com.njulya.remoteserviceclient;

import com.njulya.aidl.StudentQuery;

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.os.RemoteException;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {
    
    private EditText studentId;
    private TextView content;
    private StudentQuery studentQuery;
    private ServiceConnection conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        studentId = (EditText)this.findViewById(R.id.student_id);
        content = (TextView)this.findViewById(R.id.content);
        conn = new StudentConnetion();
        Intent service = new Intent("com.njulya.REMOTESERVICE");
        this.bindService(service, conn, BIND_AUTO_CREATE);
    }
    /**
     * 按键触发业务代码
     * @param v
     */
    public void queryOnClick(View v){
        int no = Integer.valueOf(studentId.getText().toString());
        try {
            String studentName = studentQuery.query(no);
            content.setText(studentName);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    private class StudentConnetion implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //将IBinder代理对象转换为接口类型
            studentQuery = StudentQuery.Stub.asInterface(service);
        }
        
        @Override
        public void onServiceDisconnected(ComponentName name) {
            studentQuery = null;
        }
    }
    
    
    @Override
    protected void onDestroy() {
        unbindService(conn);
        super.onDestroy();
    }
    @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;
    }
    


}
View Code

 

关于本地服务

  • 启动的service是运行在主线程中的,所以耗时的操作还是要新建工作线程

  • 用bindService时需要实现ServiceConnection,flags用BIND_AUTO_CREATE

  • service中关键要返回IBinder的实现类对象,该对象中会使用服务中的一些API

  • 一般在自定义的ServiceConnection实现类中得到和关闭IBinder对象

  • 通过得到的IBinder对象实现调用服务中的API

业务界面

技术分享

客户端代码

技术分享
package com.njulya.intsum;

import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    private EditText num1;
    private EditText num2;
    private TextView sum;
    private ServiceConnection conn;
    
    //自定义的公共接口,用于求两数之和
    private SumOfTwo sumOfTwo;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        num1 = (EditText)this.findViewById(R.id.num1);
        num2 = (EditText)this.findViewById(R.id.num2);
        sum = (TextView)this.findViewById(R.id.sum);
        Button button = (Button)this.findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sum();
            }
        });
        conn = new SumConnetion();
        Intent service = new Intent(this, SumService.class);
        this.bindService(service, conn, BIND_AUTO_CREATE);
    }

    protected void sum() {
        int number1 = Integer.valueOf(num1.getText().toString());
        int number2 = Integer.valueOf(num2.getText().toString());
        int result = sumOfTwo.sum(number1, number2);
        sum.setText(String.valueOf(result));
        
    }
    private class SumConnetion implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            sumOfTwo = (SumOfTwo)service;
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            sumOfTwo = null;
        }
    }
    
    @Override
    protected void onDestroy() {
        unbindService(conn);
        super.onDestroy();
    }

    @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;
    }

}
View Code

服务端代码

技术分享
package com.njulya.intsum;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class SumService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return new SumBinder();
    }
    public class SumBinder extends Binder implements SumOfTwo{
        @Override
        public int sum(int number1, int number2) {
            return number1 + number2;
        }
        
    }
}
View Code

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。