实验四 远程服务.docx
《实验四 远程服务.docx》由会员分享,可在线阅读,更多相关《实验四 远程服务.docx(22页珍藏版)》请在冰豆网上搜索。
实验四远程服务
天津理工大学
计算机与通讯工程学院
实验报告
2012至2013学年第二学期
实验四远程服务
课程名称
软件主流开发平台与工具
学号
学生姓名
年级
专业
教学班号
实验地点
实验时间
主讲教师
辅导教师
实验(四)
实验名称
远程Service
软件环境
Windows
Ecllipse&AndroidSDK
硬件环境
PC
实验目的:
完成Android远程服务建立及绑定,以及进程间数据传递
完成Android应用程序建立及界面处理技术,包括以下内容:
●Android应用层程序建立
●远程服务定义及实现(AIDL语言定义接口)
●远程服务绑定及调用
●进程间数据传递(AIDL语言定义数据结构,Parcelable接口实现)
实验内容(应包括实验题目、实验要求、实验任务等)
实验要求:
完善“Calcultor”功能,实现远程调用与进程间数据传递
在已有本地服务调用程序基础上,分步骤实现下述功能:
步骤一、
AIDL定义远程服务接口。
定义远程服务,并将已有本地服务移植到远程服务中。
实现远程服务调用
步骤二、
AIDL语言定义AllResult数据结构(数据元素为两个整数的和、差、积、商的计算结果)
实现AllResult.java类,利用该类实现Parcelable接口,用于远程数据传递
远程服务中定义新方法Compute,输入值为两个整数,返回值为AllResult
Activity显示调用结果(如下图)
实验过程与实验结果(可包括实验实施的步骤、算法描述、流程、结论等)
实验步骤:
主要实验步骤是
(1)使用AIDL语言定义跨进程服务的接口。
(2)通过继承Service类实现跨进程服务。
(3)绑定和使用跨进程服务。
参照书中P137页RemoteMathServiceDemo示例。
用到的比较大小,Compare()方法如下:
publicintCompare(inta,intb)throwsRemoteException{
if(a>b)returna;
elsereturnb;
}
用到的求和,求差,求积,求商Compute()方法如下:
publicAllResultCompute(inta,intb)throwsRemoteException{
intaddResult=a+b;
intsubResult=a-b;
intmulResult=a*b;
doubledivResult=(double)a/(double)b;
AllResultresult=newAllResult(addResult,subResult,mulResult,divResult);
returnresult;
}
步骤一、
AIDL定义远程服务接口。
用AIDL语言定义RemoteCalculatorService的服务接口,文件名为IRemoteCalculatorService.aidl。
packageedu.tjut.cs.RemoteCalculatorService;
importedu.tjut.cs.RemoteCalculatorService.AllResult;
interfaceIRemoteCalculatorService{
intCompare(inta,intb);
AllResultCompute(inta,intb);}
从上面代码中知,IRemoteCalculatorService接口含有两个方法,传入的参数是两个int型整数。
第一个方法Compare()用于实现两个整数的比较,返回较大者,具体实现见上面该方法代码。
第二个方法Computer()实现了两个整数的求和,求差,求积,求商。
使用Eclipse编辑IRemoteCalculatorService.aidl文件,当用户保存文件后,ADT会自动在/gen目录下生成IRemoteCalculatorService.java文件,文件结构如下:
IRemoteCalculatorService.java文件根据IRemoteCalculatorService.aidl的定义,生成一个内部静态抽象类Stub继承了Binder类,并实现IRemoteCalculatorService接口。
在Stub类中,还包含一个重要的静态类Proxy,类Proxy用来实现跨进程服务调用,而Stub类是实现进程内服务调用。
步骤二
通过继承Service类实现跨进程服务。
实现跨进程服务需要建立一个继承android.app.Service的类,并在该类中通过onBind()方法返回IBinder对象,调用者使用返回的IBinder对象就可访问跨进程服务。
onBind对象的建立通过使用IRemoteCalculatorService.java内部的Stub类实现,并逐一实现在IRemoteCalculatorService.aidl接口文件定义的函数。
具体代码如下:
packageedu.tjut.cs.calculator;
importandroid.app.Service;
importandroid.content.Intent;
importandroid.os.Binder;
importandroid.os.IBinder;
importandroid.util.Log;
publicclassCalculatorServiceextendsService{
privatefinalIBindermBinder=newLocalBinder();
privateThreadworkThread;
privatebooleanmultiThreadFlag=false;
@Override
publicvoidonCreate(){
//TODOAuto-generatedmethodstub
workThread=newThread(null,backgroundWork,"WorkThread");
super.onCreate();
}
publicclassLocalBinderextendsBinder{
CalculatorServicegetService(){
returnCalculatorService.this;
}
}
@Override
publicbooleanonUnbind(Intentintent){
//TODOAuto-generatedmethodstub
if(multiThreadFlag==true)
{
workThread.interrupt();
Log.v("XXXX","interrupted");
multiThreadFlag=false;
}
returnsuper.onUnbind(intent);
}
@Override
publicIBinderonBind(Intentarg0){
//TODOAuto-generatedmethodstub
if(arg0.getBooleanExtra("MultiThread",false)==true)
{
workThread.start();
multiThreadFlag=true;
returnnull;
}
returnmBinder;
}
publicintcompare(inta,intb)
{
if(a>b)returna;
elsereturnb;
}
privateRunnablebackgroundWork=newRunnable(){
@Override
publicvoidrun()
{
while(!
Thread.interrupted()){
intinput1=(int)(100*Math.random());
intinput2=(int)(100*Math.random());
intresult=(input1>input2)?
input1:
input2;
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
CalculatorActivity.UpdateGUI(input1,input2,result);
}
}
};
}
步骤二
绑定和使用跨进程服务。
该实验用户可以绑定进程服务,也可以取消服务绑定。
应用程序在调用跨进程服务时,应用程序与跨进程服务应具有相同的Proxy类和签名函数,这样才能使数据在调用者处打包后,可以在远程访问端正确拆包。
比较重要的是“比较”按钮的监听事件:
compareButton.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
Stringmsg="";
if(calculatorService==null)
{
msg="服务尚未启动";
resultTextView.setText(msg);
}
else
{
//intresult=calculatorSpare(Integer.parseInt(inputEditText1.getText().toString()),Integer.parseInt(inputEditText2.getText().toString()));
intresult=0;
AllResultallResult=null;
try{
result=calculatorService.Compare(Integer.parseInt(inputEditText1.getText().toString()),Integer.parseInt(inputEditText2.getText().toString()));
allResult=calculatorService.Compute(Integer.parseInt(inputEditText1.getText().toString()),Integer.parseInt(inputEditText2.getText().toString()));
}catch(NumberFormatExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(RemoteExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
msg="最大值为:
"+String.valueOf(result)+"\n";
msg+="和为:
"+String.valueOf(allResult.AddResult)+"\n";
msg+="差为:
"+String.valueOf(allResult.SubResult)+"\n";
msg+="积为:
"+String.valueOf(allResult.MulResult)+"\n";
msg+="商为:
"+String.valueOf(allResult.DivResult)+"\n";
resultTextView.setText(msg);
}
}
源代码如下:
CalculatorActivity中代码如下:
packageedu.tjut.cs.calculator;
importedu.tjut.cs.RemoteCalculatorService.IRemoteCalculatorService;
importedu.tjut.cs.RemoteCalculatorService.AllResult;
importandroid.app.Activity;
importandroid.content.ComponentName;
importandroid.content.Context;
importandroid.content.Intent;
importandroid.content.ServiceConnection;
import.Uri;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.IBinder;
importandroid.os.RemoteException;
importandroid.util.Log;
importandroid.view.View;
importandroid.widget.*;
publicclassCalculatorActivityextendsActivity{
/**Calledwhentheactivityisfirstcreated.*/
privatestaticTextViewresultTextView=null;
privatestaticintinput1,input2,result;
//privateCalculatorServicecalculatorService=null;
privateIRemoteCalculatorServicecalculatorService=null;
privatestaticHandlerhandler=newHandler();
publicstaticvoidUpdateGUI(intfirstValue,intsecondValue,intres)
{
input1=firstValue;
input2=secondValue;
result=res;
handler.post(Refresh);
}
privatestaticRunnableRefresh=newRunnable(){
@Override
publicvoidrun(){
if(input1==result)
resultTextView.setText(String.valueOf(input1)+">"+String.valueOf(input2));
else
resultTextView.setText(String.valueOf(input1)+"<"+String.valueOf(input2));
}
};
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
finalEditTextinputEditText1=(EditText)findViewById(R.id.inputEditText01);
finalEditTextinputEditText2=(EditText)findViewById(R.id.inputEditText02);
resultTextView=(TextView)findViewById(R.id.resultTextView);
ButtonstartServiceButton=(Button)findViewById(R.id.startServiceButton);
ButtonstopServiceButton=(Button)findViewById(R.id.stopServiceButton);
ButtoncompareButton=(Button)findViewById(RpareButton);
finalCheckBoxmodeCheckBox=(CheckBox)findViewById(R.id.modeCheckbox01);
modeCheckBox.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
if(calculatorService!
=null)
{
unbindService(mConnection);
calculatorService=null;
}
}
});
startServiceButton.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
Intentintent=newIntent();
intent.setAction("edu.tjut.cs.RemoteCalculatorService");
/*intent.setAction("edu.tjut.cs.CalculatorService");
if(modeCheckBox.isChecked())
intent.putExtra("MultiThread",true);
else
intent.putExtra("MultiThread",false);*/
Log.v("Test","---------------bindServiceiscalled\n");
bindService(intent,mConnection,Context.BIND_AUTO_CREATE);
}
});
stopServiceButton.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
unbindService(mConnection);
calculatorService=null;
}
});
compareButton.setOnClickListener(newView.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
Stringmsg="";
if(calculatorService==null)
{
msg="服务尚未启动";
resultTextView.setText(msg);
}
else
{
//intresult=calculatorSpare(Integer.parseInt(inputEditText1.getText().toString()),Integer.parseInt(inputEditText2.getText().toString()));
intresult=0;
AllResultallResult=null;
try{
result=calculatorService.Compare(Integer.parseInt(inputEditText1.getText().toString()),Integer.parseInt(inputEditText2.getText().toString()));
allResult=calculatorService.Compute(Integer.parseInt(inputEditText1.getText().toString()),Integer.parseInt(inputEditText2.getText().toString()));
}catch(NumberFormatExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(RemoteExceptione){
//TODOAu