写点什么

android AIDL 服务,移动客户端开发面经

作者:嘟嘟侠客
  • 2021 年 11 月 27 日
  • 本文字数:3891 字

    阅读完需:约 13 分钟

67.return mRemote;


68.}


69.public java.lang.String getInterfaceDescriptor()


70.{


71.return DESCRIPTOR;


72.}


73.public double getQuote(java.lang.String ticker) throws android.os.RemoteException


74.{


75.android.os.Parcel _data = android.os.Parcel.obtain();


76.android.os.Parcel _reply = android.os.Parcel.obtain();


77.double _resul


《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享


t;


78.try {


79._data.writeInterfaceToken(DESCRIPTOR);


80._data.writeString(ticker);


81.mRemote.transact(Stub.TRANSACTION_getQuote, _data, _reply, 0);


82._reply.readException();


83._result = _reply.readDouble();


84.}


85.finally {


86._reply.recycle();


87._data.recycle();


88.}


89.return _result;


90.}


91.}


92.static final int TRANSACTION_getQuote = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);


93.}


94.public double getQuote(java.lang.String ticker) throws android.os.RemoteException;


95.}


对于所生成的类,请注意以下几点。


在 AIDL 文件中定义的接口在生成的代码中实现为接口 (也就是说,有一个名为 IStockQuoteService 的接口)。


名为 Stub 的 static final 抽象类扩展了 android.os.Binder 并实现了 IStockQuoteService。请注意该类是一个抽象类。


名为 Proxy 的内部类实现了 IStockQuoteService, 后者是 Stub 类的代理。


AIDL 文件必须位于应该包含所生成文件的包中(在 AIDL 文件的包声明中指定)。


在服务类中实现 AIDL 接口


上边我们为股票报价服务定义了 AIDL 文件并生成了绑定文件。现在我们将提供该服务的实现。要实现服务的接口,需要编写一个类来扩展 android.app.Service 并实现 IStockQuoteService 接口。我们将编写的类 命名为 StockQuoteService。为了将服务向客户端公开,StockQuoteService 需要提供 onBind()方法 的实现,我们还需要将一些配置信息添加到 AndroidManifest.xml 文件中。? 下面给出 我们服务类得实现。


IStockQuoteService 服务实现。


package com.androidbook.stockquoteservice;


import android.app.Service;


import android.content.Intent;


import android.os.IBinder;


import android.os.RemoteException;


import android.util.Log;


public class StockQuoteService extends Service {


private static final String TAG = "StockQuoteService";


public class StockQuoteServiceImpl extends IStockQuoteService.Stub {


@Override


public double getQuote(String ticker) throws RemoteException {


Log.v(TAG, "getQuote() called for " + ticker);


return 20.0;


}


}


@Override


public void onCreate() {


super.onCreate();


Log.v(TAG, "onCreate called");


}


@Override


public void onDestroy() {


super.onDestroy();


Log.v(TAG, "onDestory() called");


}


@Override


public void onStart(Intent intent, int startId) {


super.onStart(intent, startId);


Log.v(TAG, "onStart() called");


}


@Override


public IBinder onBind(Intent intent) {


Log.v(TAG, "onBind() called");


return new StockQuoteServiceImpl();


}


}


在这个服务类中大家可以看到我们实现了 onBind() 方法。从 AIDL 文件生成的 Stub 类是抽象类并且它实现了 IStockQuoteService 接口。在我们的服务实现中,有一个扩展了 Stub 类得内部类,名为 StockQuoteServiceImpl。此类充当着远程服务实现,而且 onBind()方法会返回此类的实例。到此,我们有了一个有效的 ADIL 服务,但是外部的客户端还无法连接到它。


要将服务向客户端公开,需要在 AndroidManifest.xml 文件中添加服务声明,而这一次我们需要一个 Intent 过滤器来公开服务,如下。


点击查看原始大小图片


从客户端应用程序调用服务


当客户端与服务通信时,它们之间必须有一个协议或契约。在 Android 中,这个契约就是 AIDL。所以,使用服务的第一步是,获取服务的 AIDL 文件并将其复制到客户端项目中。当将 AIDL 文件复制到客户端项目时,AIDL 编译器将创建一个接口定义文件,这个文件与我们在服务端定义的文件相同。这会向客户端公开所有的方法、参数并返回服务的类型。我们创建一个新项目并复制 AIDL 文件。


(1)创建一个新的 Android 项目, 将其命名为 StockQuoteClient。使用不同的包名称比如 com.androidbook.stockquoteclient。在 Create Activity 字段中使用 MainActivity 注意不要把 IStockQuoteService.aidl 文件放到这包中,这个包只有一个 MainActivity 类。


(2)在此项目中新建一个包 com.androidbook.stockquoteservice,放在 src 目录下。


(3)将 IStockQuoteService.aidl 文件从 StockQuoteService 项目也就是我们服务端得项目复制到新建的包中。复制过来之后,AIDL 编译器会自动生成关联的 java 文件。


重新生成的服务接口充当着客户端与服务之间的契约。下一步是获取服务的引用,以便调用 getQuote()方法。对于远程服务,必须调用 bindService()方法,而不是 startService()方法。


客户端布局文件


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


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


android:orientation="vertical"


android:layout_width="fill_parent"


android:layout_height="fill_parent"



<Button


android:id="@+id/bindBtn"


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:text="Bind"/>


<Button


android:id="@+id/callBtn"


android:layout_height="wrap_content"


android:layout_width="wrap_content"


android:text="Call Again"/>


<Button


android:id="@+id/unbindBtn"


android:layout_width="wrap_content"


android:layout_height="wrap_content"


android:text="UnBind"/>


</LinearLayout>


MainActivity 类


package com.androidbook.stockquoteclient;


import com.androidbook.stockquoteservice.IStockQuoteService;


import android.app.Activity;


import android.content.ComponentName;


import android.content.Context;


import android.content.Intent;


import android.content.ServiceConnection;


import android.os.Bundle;


import android.os.IBinder;


import android.os.RemoteException;


import android.util.Log;


import android.view.View;


import android.view.View.OnClickListener;


import android.widget.Button;


import android.widget.Toast;


public class MainActivity extends Activity {


protected static final String TAG = "StockQuoteClient";


private IStockQuoteService stockService = null;


private Button bindBtn;


private Button callBtn;


private Button unbindBtn;


@Override


public void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.main);


bindBtn = (Button) findViewById(R.id.bindBtn);


bindBtn.setOnClickListener(new OnClickListener() {


@Override


public void onClick(View v) {


bindService(new Intent(IStockQuoteService.class.getName()),


serConn, Context.BIND_AUTO_CREATE);


bindBtn.setEnabled(false);


callBtn.setEnabled(true);


unbindBtn.setEnabled(true);


}


});


callBtn = (Button) findViewById(R.id.callBtn);


callBtn.setOnClickListener(new OnClickListener() {


@Override


public void onClick(View v) {


callService();


}


});


callBtn.setEnabled(false);


unbindBtn = (Button) findViewById(R.id.unbindBtn);


unbindBtn.setOnClickListener(new OnClickListener() {


@Override


public void onClick(View v) {


unbindService(serConn);


bindBtn.setEnabled(true);


callBtn.setEnabled(false);


unbindBtn.setEnabled(false);


}


});


}


private void callService() {


try {


double val = stockService.getQuote("SYH");


Toast.makeText(this, "Value from service is " + val,


Toast.LENGTH_LONG).show();


} catch (RemoteException e) {


Log.e("MainActivity", e.getMessage(), e);


}


}


private ServiceConnection serConn = new ServiceConnection() {


// 此方法在系统建立服务连接时调用


@Override


public void onServiceConnected(ComponentName name, IBinder service) {


Log.v(TAG, "onServiceConnected() called");


stockService = IStockQuoteService.Stub.asInterface(service);


callService();


}


// 此方法在销毁服务连接时调用


@Override


public void onServiceDisconnected(ComponentName name) {


Log.v(TAG, "onServiceDisconnected()");


stockService = null;


}


};


}


MainActivity 里边我们定义了三个按钮 分别是 Bind、Call Again 和 UnBind。当用户单击 Bind 按钮时,活动调用 bindService()方法。类似地,当用户点击 UnBind 时,活动调用 unbindService()方法。请注意传递给 bindService()方法 的 3 个参数:AIDL 服务的名称、ServiceConnection 实例和自动创建服务的标志。


我们在程序了打印了日志,我们可以看到当我们点击 Bind 按钮的时候 服务端 方法的一个执行顺序。


点击查看原始大小图片


程序的运行效果如下


最后

在这里我和身边一些朋友特意整理了一份快速进阶为 Android 高级工程师的系统且全面的学习资料。涵盖了 Android 初级——Android 高级架构师进阶必备的一些学习技能。


附上:我们之前因为秋招收集的二十套一二线互联网公司 Android 面试真题(含 BAT、小米、华为、美团、滴滴)和我自己整理 Android 复习笔记(包含 Android 基础知识点、Android 扩展知识点、Android 源码解析、设计模式汇总、Gradle 知识点、常见算法题汇总。)



本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

用户头像

嘟嘟侠客

关注

还未添加个人签名 2021.03.19 加入

还未添加个人简介

评论

发布
暂无评论
android AIDL服务,移动客户端开发面经