我将AndroidAIDL的学习知识总结一下和大家共享

在Android开发中,AIDL主要是用来跨进程訪问。

Android系统中的进程之间不能共享内存,因此,须要提供一些机制在不同进程之间进行数据通信,通常是和Service服务组件一起使用来实现。

1、创建调用AIDL服务

建立AIDL服务的步骤:

第一步:在Eclipse的Androidproject的Java源文件文件夹中建立一个扩展名为aidl的文件。改文件的语法相似于Java代码,但稍有不同。

第二步:假设aidl文件的内容是正确的。ADT会在gen文件夹下自己主动生成一个Java接口文件。

第三步:建立一个服务类(Service的子类)。

第四步:实现有aidl文件生成的Java接口。

第五步:在AndroidManifest.xml文件里配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是client要引用该服务的ID。也就是Intent类构造方法的參数值。

以下实现了一个实例:

IMyService.aidl:(事实上和Java类定义接口文件形式上有些相似)

package mobile.android.aidl;
interface IMyService
{
String getValue();
}

实现的MyService.java类:

package mobile.android.aidl;
import mobile.android.aidl.IMyService;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException; public class MyService extends Service
{
public class MyServiceImpl extends IMyService.Stub
{
@Override
public String getValue() throws RemoteException
{
// TODO Auto-generated method stub
return "《Android深度探索(卷1):HAL与驱动开发》";
}
} @Override
public IBinder onBind(Intent intent)
{
return new MyServiceImpl();
}
}

在AndroidManifest.xml的配置:

<service android:name=".MyService" >
<span style="white-space:pre"> </span><intent-filter>
<action android:name="mobile.android.aidl.IMyService" /> <!--訪问的ID-->
</intent-filter>
</service>

client代码:

package mobile.android.aidlclient;
import mobile.android.aidl.IMyService;
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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast; public class Main extends Activity implements OnClickListener
{
private IMyService myService = null;
private Button btnInvokeAIDLService;
private Button btnBindAIDLService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService = IMyService.Stub.asInterface(service); //获取服务对象
btnInvokeAIDLService.setEnabled(true);
} @Override
public void onServiceDisconnected(ComponentName name)
{
Toast.makeText(Main.this, "无法连接", Toast.LENGTH_SHORT).show();
btnInvokeAIDLService.setEnabled(true);
}
}; @Override
public void onClick(View view)
{
switch (view.getId())
{
case R.id.btnBindAIDLService:
<span style="white-space:pre">				</span>//绑定AIDL服务
if(!bindService(new Intent("mobile.android.aidl.IMyService"),
serviceConnection, Context.BIND_AUTO_CREATE))
Toast.makeText(Main.this, "无法连接", Toast.LENGTH_SHORT).show();
break; case R.id.btnInvokeAIDLService:
try
{
textView.setText(myService.getValue());
}
catch (Exception e)
{
textView.setText(e.getMessage());
}
break;
} } @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService);
btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService);
btnInvokeAIDLService.setEnabled(false);
textView = (TextView) findViewById(R.id.textview);
btnInvokeAIDLService.setOnClickListener(this);
btnBindAIDLService.setOnClickListener(this);
}
}

注意几点:

1、使用bindService方法绑定AIDL服务。当中须要使用Intent对象指定AIDL服务的ID,也就是声明服务时<action>标签中android:name的值。

2、在绑定时须要一个ServiceConnection对象。创建ServiceConnection对象的过程中假设绑定成功,系统会调用ServiceConnection.OnServiceConnected方法,

通过该方法的service參数值可获得AIDL服务对象。

2、传递复杂的数据的AIDL服务(自己定义类型的数据)

首先,了解一下AIDL服务仅仅支持有限的数据类型。因此,假设用AIDL服务传递一些复杂的数据就须要做更一步处理。

AIDL的支持数据类型例如以下:

1、Java的简单类型(int 、char、boolean),不须要Import导入。

2、String和CharSequence。不须要Import导入。

3、List和map。可是要注意。List和Map对象元素类型必须是AIDL服务支持的数据类型。不须要Import导入。

4、AIDL自己主动生成的接口。

须要import导入。

l

5、实现android.os.Parcelable接口的类。

须要import导入。

在传递不须要Import导入的和上面说的一样,传递须要import导入的(实现android.os.Parcelable接口的类)。除了建立一个实现android.os.Parcelable的类

还要为这个类单独建立一个aidl文件,并使用Parcelablekeyword进行定义。

看这个实例:

在AndroidManifest.xml的注冊配置:

<service android:name=".MyService" >
<intent-filter>
<action android:name="mobile.android.complex.type.aidl.IMyService" />
</intent-filter>
</service>

IMyService.aidl:

package mobile.android.complex.type.aidl;
import mobile.android.complex.type.aidl.Product;
interface IMyService
{
Map getMap(in String country, in Product product);
Product getProduct();
}

Product.java类:

package mobile.android.complex.type.aidl;
import android.os.Parcel;
import android.os.Parcelable; public class Product implements Parcelable
{
private int id;
private String name;
private float price;
public static final Parcelable.Creator<Product> CREATOR = new Parcelable.Creator<Product>()
{
public Product createFromParcel(Parcel in)
{
return new Product(in);
} public Product[] newArray(int size)
{
return new Product[size];
}
};
public Product()
{
}
private Product(Parcel in)
{
readFromParcel(in);
} @Override
public int describeContents()
{
// TODO Auto-generated method stub
return 0;
} public void readFromParcel(Parcel in)
{
id = in.readInt();
name = in.readString();
price = in.readFloat();
} @Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeInt(id);
dest.writeString(name);
dest.writeFloat(price);
} public int getId()
{
return id;
} public void setId(int id)
{
this.id = id;
} public String getName()
{
return name;
} public void setName(String name)
{
this.name = name;
} public float getPrice()
{
return price;
} public void setPrice(float price)
{
this.price = price;
}
}

Product.aidl:(主要是在aidl中声明上面那个自己定义的类型,才干在IMyService中使用)

parcelable Product;

MyService.java类:

package mobile.android.complex.type.aidl;
import java.util.HashMap;
import java.util.Map;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException; public class MyService extends Service
{
public class MyServiceImpl extends IMyService.Stub
{ @Override
public Product getProduct() throws RemoteException
{
Product product = new Product();
product.setId(1234);
product.setName("汽车");
product.setPrice(31000);
return product;
} @Override
public Map getMap(String country, Product product)
throws RemoteException
{
Map map = new HashMap<String, String>();
map.put("country", country);
map.put("id", product.getId());
map.put("name", product.getName());
map.put("price", product.getPrice());
map.put("product", product);
return map;
}
} @Override
public IBinder onBind(Intent intent)
{
return new MyServiceImpl();
}
}

在client实现AIDL服务:

package mobile.android.complex.type.aidlclient;
import mobile.android.complex.type.aidl.IMyService;
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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView; public class Main extends Activity implements OnClickListener
{
private IMyService myService = null;
private Button btnInvokeAIDLService;
private Button btnBindAIDLService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection()
{ @Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myService = IMyService.Stub.asInterface(service);
btnInvokeAIDLService.setEnabled(true);
} @Override
public void onServiceDisconnected(ComponentName name)
{
// TODO Auto-generated method stub
}
}; @Override
public void onClick(View view)
{
switch (view.getId())
{
case R.id.btnBindAIDLService:
bindService(new Intent("mobile.android.complex.type.aidl.IMyService"),
serviceConnection, Context.BIND_AUTO_CREATE);
break; case R.id.btnInvokeAIDLService:
try
{
String s = "";
s = "Product.id = " + myService.getProduct().getId() + "\n";
s += "Product.name = " + myService.getProduct().getName()
+ "\n";
s += "Product.price = " + myService.getProduct().getPrice()
+ "\n"; s += myService.getMap("China", myService.getProduct()).toString();
textView.setText(s);
}
catch (Exception e)
{
}
break;
}
} @Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService);
btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService);
btnInvokeAIDLService.setEnabled(false);
textView = (TextView) findViewById(R.id.textview);
btnInvokeAIDLService.setOnClickListener(this);
btnBindAIDLService.setOnClickListener(this);
}
}

这边在实现一个扩展的:AIDL与来去电自己主动挂断

虽然能够同Activity Action来拨打电话,可是使用常规的方法无法挂断电话。

只是使用Java反射技术是实现一种通过程序挂断电话的方法。

在Android SDK源生提供了例如以下接口:

com,android.internal,telephony.ITelephony,外部无法直接訪问,这个接口提供了一个ITelephony.endCall的方法:

虽然不能直接訪问ITelephony对象。

只是在TelephonyManager类提供一个getITelepgony的方法能够返回一个ITelephony的对象。只是这种方法是私有的,但

我们能够通过Java的反射技术来调用该方法。在利用getITelephony获得ITelephony对象之前,先将Android SDK 文件夹下找到NeighboringCellInfo.aidl和ITelephony.aidl文件

拷贝到你的project文件夹下。

ADT会依据ITelephony.aidl文件自己主动生成ITelephony.java文件。

以下是一个广播接收来电是先自己主动挂断指定电话的来电:

package mobile.android.call.aidl;
import java.lang.reflect.Method;
import com.android.internal.telephony.ITelephony;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast; public class InCallReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Service.TELEPHONY_SERVICE);
switch (tm.getCallState())
{
case TelephonyManager.CALL_STATE_RINGING: // 响铃
// 获得来电的电话号
String incomingNumber = intent
.getStringExtra("incoming_number");
if ("12345678".equals(incomingNumber))
{
try
{
TelephonyManager telephonyManager = (TelephonyManager) context
.getSystemService(Service.TELEPHONY_SERVICE);
Class<TelephonyManager> telephonyManagerClass = TelephonyManager.class;
Method telephonyMethod = telephonyManagerClass
.getDeclaredMethod("getITelephony",
(Class[]) null);
telephonyMethod.setAccessible(true);
ITelephony telephony = (com.android.internal.telephony.ITelephony) telephonyMethod
.invoke(telephonyManager, (Object[]) null);
telephony.endCall();
}
catch (Exception e)
{
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
break;
}
}
}

 以上是对AIDL服务的理解总结。希望对大家实用,欢迎共同学习和指导。

Android跨进程訪问(AIDL服务)的更多相关文章

  1. android跨进程通信(IPC)——AIDL

    转载请标明出处: http://blog.csdn.net/sinat_15877283/article/details/51026711: 本文出自: [温利东的博客] 近期在看 @任玉刚 大神编写 ...

  2. 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

    前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...

  3. jsonp突破同源策略,实现跨域訪问请求

    版权声明:本文为博主原创文章,未经博主同意不得转载.如需转载请声明:[转自 http://blog.csdn.net/xiaoxian8023 ] https://blog.csdn.net/xiao ...

  4. 让Apache 和nginx支持跨域訪问

    1,怎样让Apache支持跨域訪问呢? 步骤: 改动httpd.conf,windows中相应的文件夹是:C:\wamp\bin\apache\Apache2.4.4\conf\httpd.conf ...

  5. Android 跨进程启动Activity黑屏(白屏)的三种解决方案

    原文链接:http://www.cnblogs.com/feidu/p/8057012.html 当Android跨进程启动Activity时,过程界面很黑屏(白屏)短暂时间(几百毫秒?).当然从桌面 ...

  6. 使用FREDATED引擎实现跨实例訪问

    跨数据库server.跨实例訪问是比較常见的一种訪问方式,在Oracle中能够通过DB LINK的方式来实现. 对于MySQL而言,有一个FEDERATED存储引擎与之相相应.相同也是通过创建一个链接 ...

  7. jquery ajax CORS 跨域訪问 WebService

    JS代码: var word = document.getElementById("word").value; $.ajax({ type: "POST", c ...

  8. CentOs虚拟机能够互相ping通,但无法訪问虚拟机服务

    CentOs虚拟机能够互相ping通,但无法訪问虚拟机服务 虚拟机ip:192.168.0.57 主机 ip:192.168.0.80 在虚拟机上搭建了php环境.虚拟机CentOs,主机win7 虚 ...

  9. Android跨进程通信AIDL服务

    服务(Service)是android系统中非常重要的组件.Service可以脱离应用程序运行.也就是说,应用程序只起到一个启动Service的作用.一但Service被启动,就算应用程序关闭,Ser ...

随机推荐

  1. 我爱学 Python 之文件

    读取文件 假设你已经在某个文件夹下创建了 "test.txt" 文件,且里面有一些内容,那你在当前位置输入 Python3,进入到交互模式,然后执行下面的操作: >>& ...

  2. [超级基础]Web安全之SQL注入由浅入深(?)

    前言 断断续续看Web安全到现在了,感觉对很多基础知识还是一知半解,停留在模糊的层次.所以准备系统总结一下. Sql注入我以前一直不以为然,一是现在能sql的站确实很少,二是有像sqlmap的工具可以 ...

  3. C# Winform打包部署时添加注册表信息实现开机启动(转载)

    使用VS自带的打包模块可以很方便的对项目进行打包部署,同时我们也可以在安装部署时操作注册表实现开机启动软件.具体实现如下:    1.添加安装部署项目后,鼠标右键安装项目->视图->注册表 ...

  4. leetcode NO.349 两个数组的交集 (python实现)

    来源 https://leetcode-cn.com/problems/intersection-of-two-arrays/ 题目描述 给定两个数组,写一个函数来计算它们的交集. 例子: 给定 nu ...

  5. PAT1017

    本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数.你需要输出商数Q和余数R,使得A = B * Q + R成立. 输入格式: 输入在1行中依次给出A和B,中间以1空格分隔. 输出格 ...

  6. poj2002 hash+邻接表优化Squares

    Squares Time Limit: 3500MS   Memory Limit: 65536K Total Submissions: 17487   Accepted: 6643 Descript ...

  7. 计算两个日期之间的天数差C++/java

    1--Java 分析:调用java中Calendar类 int days(Date date1,Date date2){ Calendar cal = new Calendar.getInstance ...

  8. Generator与async/await与Generator的模拟

    Generator 函数有多种理解角度.语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态. 执行 Generator 函数会返回一个遍历器对象,也就是说,Gener ...

  9. 小w的喜糖(candy)

    小w的喜糖(candy) 题目描述 废话不多说,反正小w要发喜糖啦!! 小w一共买了n块喜糖,发给了n个人,每个喜糖有一个种类.这时,小w突发奇想,如果这n个人相互交换手中的糖,那会有多少种方案使得每 ...

  10. 城市改造 (city)

    城市改造 (city) 题目描述 为了节约当前社会巨大的能源消耗,A 城市发起了新能源改造计划,也就是用太阳能代替旧能源.为了简化题意,可以假设 A 城市在一个二维平面上,平面上从11到nn每一个地方 ...