代码描述的Android AIDL示例 - IPC
2017-02-10 16:50
281 查看
在我们了解Android接口定义语言(AIDL)之前,让我们知道为什么需要它?答案很简单。每个Android应用程序都在其自己的进程中运行。所以一个应用程序不能直接访问另一个应用程序的内存空间如果你想从一个应用程序访问一些数据到另一个应用程序,那么我们需要像其他平台一样使用进程间通信(IPC)。所以在Android IPC中也称为AIDL。为此,Android提供了一种称为Android接口定义语言(AIDL)的技术。它是一种轻量级的IPC实现,就像C / C ++语言一样。
所以要在进程之间进行通信或者说在应用程序之间,我们需要在我们的Android应用程序中实现AIDL。换句话说,您可以说AIDL技术是一种轻量级的客户端服务器架构,以服务的形式,这有助于多个应用程序之间的通信。为此,我们需要以下步骤。
1. AIDL接口 - 定义AIDL接口,它将是应用程序之间的接口。
2.实现远程服务 - 远程服务保存您的数据/方法以公开给其他应用程序访问数据。
3.将远程服务暴露给其他本地客户端 - 我们需要与其他应用程序共享的数据/方法需要公开,以便其他应用程序可以访问和共享来自远程服务的数据。
为了使示例简单,让我们举一个简单的例子。我们将开发一个用于添加两个数字的远程服务。这意味着我们将从客户端应用程序获取用户输入,然后将数据发送到远程服务,并从远程服务获取结果。我的东西它是足够好的学习基本的远程服务器使用AIDL。
创建AIDL接口 - 定义AIDL接口,它将是应用程序之间的接口
这里我们只定义方法签名(原型),我们需要暴露给其他客户端(应用程序)。 请注意,AIDL中支持所有Java基元数据类型。 您还可以在AIDL中使用您自己的用户定义数据类型。 也可以在这里使用Parcelable类。 但在这里我们将讨论基本的原始数据类型,使示例更简单。 下面是代码片段。
将以下文件放在源文件夹中,如下所示:\ src \ com \ sergeycao\ aidlexample \ IAddService.aidl
接口文件:IAddService.aidl
注意:在上面的代码中,方法add()将暴露给本地客户端。
实现我们的远程服务 -
在我们创建了我们的AIDL文件并将其放置在正确的位置之后,Eclipse中内置的AIDL工具将生成一个新的文件,扩展名为.java,与AIDL文件的名称相同,您可以在项目的jen '文件夹。所以现在我们在位置\ gen \ com \ sergeycao\ aidlexample中有一个名为'IAddService.java'的新文件。这是一个自动生成的文件,所以不要编辑它。这个调用的邮件目的是它包含一个Stub类,我们需要为我们的远程服务实现。
要实现我们的远程服务,我们需要通过扩展Android服务类(在我们的情况下为AddService)来创建一个新的服务类。然后我们将从服务类中的onBind()方法返回IBinder,它代表我们的远程服务的实现。要实现IBinder,我们需要从自动生成的Java代码中继承子类IAddService.Stub类。然后,我们需要在我们的例子中实现我们公开的方法add()的代码逻辑,我们只是在AIDL接口文件中声明。然后他的方法add()将从客户端代码调用。看看下面的代码片段。
将以下文件放在源文件夹中,如下所示:\ src \ com \ sergeycao\ aidlexample \ AddService.Java
远程服务文件:AddService.Java
将我们的远程服务暴露给本地客户端
在我们在我们的服务类中正确实现onBind()之后,现在我们准备从本地客户端连接到我们的服务。为此,我们将有一个简单的Activity类,从中我们将连接到我们的远程服务,并从服务调用暴露的add()函数。要建立服务和本地客户端之间的连接,我们需要通过在我们的活动类(在我们的例子中是AIDLActivity)的一侧实现Android ServiceConnection类来创建一个新的内部类。所以我们的AIDLActivity类通过实现onServiceConnected()和onServiceDiconnected()方法实现了AddServiceConnection内部类。这些方法是回调,它将在连接时获得远程服务的存根实现。然后我们只需要将它们从Stubs转换到我们的AIDL服务实现。所以要这样做,我们需要使用IAddService.Stub.asInterface((IBinder)boundService)辅助方法。从这里,我们将有一个本地服务指针来访问数据和方法。所以initService()是我们的方法,它从Activity的onCreate()方法中调用来建立连接。然后当我们点击“Result”按钮时,onClickButtonResult()方法将被调用,我们已经调用了我们的远程服务的add()方法。
将以下文件放在源文件夹中,如下所示:\ src \ com \
sergeycao\ aidlexample \ AIDLActivity.Java
本地客户端活动文件:AIDLActivity.Java
XML Layout (activity_aidl.xml)我们的UI包含简单的元素。 我们使用2 EditText获取用户输入和一个按钮获得结果。 结果字段也是具有可编辑false的EditText。 您可以使用任何其他控件。 此外,我们使用Textview显示一些信息广告提示。
Manifest
文件
在最后一步中,我们将我们的服务类条目(在我们的案例中的AddService)放在我们项目的Manifest文件中,如下所示。
而已。 构建并运行应用程序。 输入2位数字,然后单击结果按钮,您可以从AIDL服务获得结果。
所以要在进程之间进行通信或者说在应用程序之间,我们需要在我们的Android应用程序中实现AIDL。换句话说,您可以说AIDL技术是一种轻量级的客户端服务器架构,以服务的形式,这有助于多个应用程序之间的通信。为此,我们需要以下步骤。
1. AIDL接口 - 定义AIDL接口,它将是应用程序之间的接口。
2.实现远程服务 - 远程服务保存您的数据/方法以公开给其他应用程序访问数据。
3.将远程服务暴露给其他本地客户端 - 我们需要与其他应用程序共享的数据/方法需要公开,以便其他应用程序可以访问和共享来自远程服务的数据。
为了使示例简单,让我们举一个简单的例子。我们将开发一个用于添加两个数字的远程服务。这意味着我们将从客户端应用程序获取用户输入,然后将数据发送到远程服务,并从远程服务获取结果。我的东西它是足够好的学习基本的远程服务器使用AIDL。
创建AIDL接口 - 定义AIDL接口,它将是应用程序之间的接口
这里我们只定义方法签名(原型),我们需要暴露给其他客户端(应用程序)。 请注意,AIDL中支持所有Java基元数据类型。 您还可以在AIDL中使用您自己的用户定义数据类型。 也可以在这里使用Parcelable类。 但在这里我们将讨论基本的原始数据类型,使示例更简单。 下面是代码片段。
将以下文件放在源文件夹中,如下所示:\ src \ com \ sergeycao\ aidlexample \ IAddService.aidl
接口文件:IAddService.aidl
12345678 | package com.sergeycao.aidlexample; // Declare the communication interface which holds all of our exposed functions.interface IAddService { // WE can pass values along with in, out, or inout parameters. // Android Java Primitive datatypes (such as int,, string, boolean, etc.) can only be passed in. int add(in int ValueFirst, in int valueSecond);} |
实现我们的远程服务 -
在我们创建了我们的AIDL文件并将其放置在正确的位置之后,Eclipse中内置的AIDL工具将生成一个新的文件,扩展名为.java,与AIDL文件的名称相同,您可以在项目的jen '文件夹。所以现在我们在位置\ gen \ com \ sergeycao\ aidlexample中有一个名为'IAddService.java'的新文件。这是一个自动生成的文件,所以不要编辑它。这个调用的邮件目的是它包含一个Stub类,我们需要为我们的远程服务实现。
要实现我们的远程服务,我们需要通过扩展Android服务类(在我们的情况下为AddService)来创建一个新的服务类。然后我们将从服务类中的onBind()方法返回IBinder,它代表我们的远程服务的实现。要实现IBinder,我们需要从自动生成的Java代码中继承子类IAddService.Stub类。然后,我们需要在我们的例子中实现我们公开的方法add()的代码逻辑,我们只是在AIDL接口文件中声明。然后他的方法add()将从客户端代码调用。看看下面的代码片段。
将以下文件放在源文件夹中,如下所示:\ src \ com \ sergeycao\ aidlexample \ AddService.Java
远程服务文件:AddService.Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | package com.sergeycao.aidlexample; import com.sergeycao.aidlexample.IAddService; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; /** * This AddService class exposes the remote service (functions in AIDL file, which we need to expose to other apps) to the client */ public class AddService extends Service { private static final String TAG = "AddService"; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate()"); } @Override public IBinder onBind(Intent intent) { return new IAddService.Stub() { /** * In the AIDL file we just add the declaration of the function * here is the real implementation of the add() function below */ public int add(int ValueFirst, int valueSecond) throws RemoteException { Log.i(TAG, String.format("AddService.add(%d, %d)",ValueFirst, valueSecond)); return (ValueFirst + valueSecond); } }; } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy()"); } } |
在我们在我们的服务类中正确实现onBind()之后,现在我们准备从本地客户端连接到我们的服务。为此,我们将有一个简单的Activity类,从中我们将连接到我们的远程服务,并从服务调用暴露的add()函数。要建立服务和本地客户端之间的连接,我们需要通过在我们的活动类(在我们的例子中是AIDLActivity)的一侧实现Android ServiceConnection类来创建一个新的内部类。所以我们的AIDLActivity类通过实现onServiceConnected()和onServiceDiconnected()方法实现了AddServiceConnection内部类。这些方法是回调,它将在连接时获得远程服务的存根实现。然后我们只需要将它们从Stubs转换到我们的AIDL服务实现。所以要这样做,我们需要使用IAddService.Stub.asInterface((IBinder)boundService)辅助方法。从这里,我们将有一个本地服务指针来访问数据和方法。所以initService()是我们的方法,它从Activity的onCreate()方法中调用来建立连接。然后当我们点击“Result”按钮时,onClickButtonResult()方法将被调用,我们已经调用了我们的远程服务的add()方法。
将以下文件放在源文件夹中,如下所示:\ src \ com \
sergeycao\ aidlexample \ AIDLActivity.Java
本地客户端活动文件:AIDLActivity.Java
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 | package com.sergeycao.aidlexample; import com.sergeycao.aidlexample.IAddService;import com.sergeycao.aidlexample.R; import android.os.Bundle;import android.os.IBinder;import android.os.RemoteException;import android.app.Activity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.util.Log;import android.view.Menu;import android.view.View;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast; public class AIDLActivity extends Activity { private static final String TAG = "AIDLExample"; IAddService service; AddServiceConnection connection; /** * This is the class which represents the actual service-connection. * It type casts the bound-stub implementation of the service class to our AIDL interface. */ class AddServiceConnection implements ServiceConnection { public void onServiceConnected(ComponentName name, IBinder boundService) { service = IAddService.Stub.asInterface((IBinder) boundService); Log.i(TAG, "onServiceConnected(): Connected"); Toast.makeText(AIDLActivity.this, "AIDLExample Service connected", Toast.LENGTH_LONG).show(); } public void onServiceDisconnected(ComponentName name) { service = null; Log.i(TAG, "onServiceDisconnected(): Disconnected"); Toast.makeText(AIDLActivity.this, "AIDLExample Service Connected", Toast.LENGTH_LONG).show(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_aidl); initService(); } public void onClickButtonResult(View v) { TextView value1 = (TextView) findViewById(R.id.editTextValue1); EditText value2 = (EditText) findViewById(R.id.editTextValue2); EditText result = (EditText) findViewById(R.id.editTextResult); int n1 =0, n2 =0, res = -1; n1 = Integer.parseInt(value1.getText().toString()); n2 = Integer.parseInt(value2.getText().toString()); try { res = service.add(n1, n2); } catch (RemoteException e) { Log.i(TAG, "Data fetch failed with: " + e); e.printStackTrace(); } result.setText(new Integer(res).toString()); } /** This is our function which binds our activity(MainActivity) to our service(AddService). */ private void initService() { Log.i(TAG, "initService()" ); connection = new AddServiceConnection(); Intent i = new Intent(); i.setClassName("com.techblogon.aidlexample", com.techblogon.aidlexample.AddService.class.getName()); boolean ret = bindService(i, connection, Context.BIND_AUTO_CREATE); Log.i(TAG, "initService() bound value: " + ret); } /** This is our function to un-binds this activity from our service. */ private void releaseService() { unbindService(connection); connection = null; Log.d(TAG, "releaseService(): unbound."); } @Override protected void onDestroy() { super.onDestroy(); releaseService(); } @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; }} |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textViewTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="Enter 2 digits for addition, then click result button for getting the result form the service using AIDL." /> <EditText android:id="@+id/editTextValue1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textViewTitle" android:layout_centerHorizontal="true" android:layout_marginTop="35dp" android:hint="Enter a number" android:ems="10" android:inputType="number" /> <EditText android:id="@+id/editTextValue2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/editTextValue1" android:layout_centerHorizontal="true" android:layout_marginTop="33dp" android:hint="Enter a number" android:ems="10" android:inputType="number"/> <EditText android:id="@+id/editTextResult" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/editTextValue2" android:layout_centerHorizontal="true" android:layout_marginTop="18dp" android:editable="false" android:ems="10" /> <Button android:id="@+id/buttonResult" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/editTextResult" android:layout_centerHorizontal="true" android:layout_marginTop="26dp" android:onClick="onClickButtonResult" android:text="Result" /> </RelativeLayout> |
文件
在最后一步中,我们将我们的服务类条目(在我们的案例中的AddService)放在我们项目的Manifest文件中,如下所示。
1 | <service android:name="com.techblogon.aidlexample.AddService" /> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sergeycao.aidlexample" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.techblogon.aidlexample.AIDLActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="com.techblogon.aidlexample.AddService" /> </application> </manifest> |