`
心雨心
  • 浏览: 351700 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android 使用【AIDL】调用外部服务

阅读更多

在Android 中有一种服务说是服务其实倒不如说是一个接口,这个接口名为:Android Interface Definition Language ,这个接口可提供跨进程访问服务,英文缩写为:AIDL。

  此种服务的好处在于,多个应用程序之间建立共同的服务机制,通过AIDL在不同应用程序之间达到数据的共享和数据相互操作,下面将通过一个DEMO 演示AIDL 是如何为应用程序之间提供服务的。

本文大纲为:

  • 1、创建AIDL 服务端。
  • 2、创建AIDL 客户端。
  • 3、客户端调用服务端提供的服务接口。
  • 4、小结。

本文要实现的功能大致如下:创建AIDL服务端,此服务端将提供一个Student 的javabean 提供客户端取得数据,因为aidl 支持的数据类型比较简单,故这里建议把常用的数据类型的数据写入服务。

1、创建AIDL 服务端

在Android 的src 文件夹下的任意包里面新建文件,后缀名为*.aidl,如下图

输入如下代码:

 

package com.aidl.test;
import com.aidl.test.Student;

interface IMyService
{
        Map getMap(in String test_class,in Student student);
         Student getStudent();
}

 

Student 类是一个序列化的类,这里使用Parcelable 接口来序列化是Google 提供的一个比Serializable 效率更高的序列化类。Student  类代码如下:

 

<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> -->package com.aidl.test;

import android.os.Parcel;
import android.os.Parcelable;

public class Student implements Parcelable {

    
private int age;
    
private String name;

    
public int getAge() {
        
return age;
    }

    
public void setAge(int age) {
        
this.age = age;
    }

    
public String getName() {
        
return name;
    }

    
public void setName(String name) {
        
this.name = name;
    }

    
public static final Parcelable.Creator<Student> CREATOR = new Creator<Student>() {

        @Override
        
public Student[] newArray(int size) {
            
// TODO Auto-generated method stub
            return new Student[size];
        }

        @Override
        
public Student createFromParcel(Parcel source) {
            
// TODO Auto-generated method stub
            return new Student(source);
        }
    };

    
public Student() {
    }

    
public Student(Parcel pl) {
        age 
= pl.readInt();
        name 
= pl.readString();
    }

    @Override
    
public int describeContents() {
        
// TODO Auto-generated method stub
        return 0;
    }

    @Override
    
public void writeToParcel(Parcel dest, int flags) {
        
// TODO Auto-generated method stub
        dest.writeInt(age);
        dest.writeString(name);
    }

}

 

 

在这里必须注意,编写javabean时必须注意如下三点:

  • 在Student 类中必须有一个静态常量,常量名必须是CREATOR,而且CREATOR 常量的数据类型必须是 Parcelable.Creator
  • 在writeToParcel 方法中需要将要序列化的值写入到 Parcel对象中。
  • 编写完Student 为时,必须再新建一个Student.aidl 文件,此文件输入以下内容:
    parcelable Student; 这里的书写是供上面我们说过的接口   *.aidl 文件导包时可以找到,并通过此文件找到Student类对象。

如果上面的步骤顺利通过的话,Android 将会自动在gen 目录下R文件的相同目录生成一个以*.aidl 文件命名的*.java 文件,如下图:

顺利生成成功后,我们再来编写一个AIDL 服务类,代码如下:

 

<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> -->package com.aidl.test;

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 {

    @Override
    
public IBinder onBind(Intent intent) {
        
// TODO Auto-generated method stub
        return new MyServiceimpl();
    }

    
public class MyServiceimpl extends IMyService.Stub {

        @Override
        
public Student getStudent() throws RemoteException {
            
// TODO Auto-generated method stub
            Student st = new Student();
            st.setAge(
18);
            st.setName(
"terry");

            
return st;
        }

        @Override
        
public Map getMap(String testClass, Student student)
                
throws RemoteException {
            
// TODO Auto-generated method stub
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(
"class""五年级");
            map.put(
"age", student.getAge());
            map.put(
"name", student.getName());
            
return map;
        }

    }

}

 

 

如上代码,MyService 服务类有一个子类并继承自我们上面生成的*.java 文件重写其中我们在*.aidl 中声明的两个接口方法,实现了其功能。上面IBinder 必须返回此服务类的子类对象,否则客户端将无法获得服务对象。

最后,即然有服务的操作,那么就得在manifest文件中注册服务类,代码如下:

 

<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --><service android:name=".MyService">
    
<intent-filter>
        
<action android:name="com.aidl.test.IMyService"></action>
    
</intent-filter>
</service>

 

 

至此,服务端就己经开发完成了,下面接着开发客启端。

2、创建AIDL 客户端

同样是新建一个项目,这里要注意,需要将服务端生成成功后的gen 目录下的包复制过来,放到我们新建项目的src 文件夹下,如下图:

因为IMyService 这个生成类,引用到了Student 这个javabean 所以这里一并将javabean也复制过来。

至此,客户端的创建己经完毕,下面我们就要利用创建的客户端去调用服务端的方法。

 

3、客户端调用服务端提供的服务接口

先看一下运行效果:

细心的朋友会发现,上面的数据不是我们在上面客户端为Student 设置的数据吗?怎么在这个程序 里面也同样得到了?没错。这就是aidl 的魅力,下面来看看如何调用 吧,图中有两个按钮,一个按钮为绑定AIDL 服务,即通过Activity 的 bindService 绑定 AIDL 外部服务,全部代码如下:

 

<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> -->package com.aidl.client;

import com.aidl.test.IMyService;

import android.app.Activity;
import android.app.AlertDialog;
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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class aidlActivity extends Activity implements OnClickListener {
    Button btn1, btn2;

    
private IMyService myService = null;
    
private ServiceConnection serviceConnection = new ServiceConnection() {

        @Override
        
public void onServiceDisconnected(ComponentName name) {
            
// TODO Auto-generated method stub

        }

        @Override
        
public void onServiceConnected(ComponentName name, IBinder service) {
            
// TODO Auto-generated method stub
            myService = IMyService.Stub.asInterface(service);
            btn2.setEnabled(
true);

        }
    };

    
/** Called when the activity is first created. */
    @Override
    
public void onCreate(Bundle savedInstanceState) {
        
super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn1 
= (Button) findViewById(R.id.Button01);
        btn2 
= (Button) findViewById(R.id.Button02);
        btn2.setEnabled(
false);

        btn1.setOnClickListener(
this);
        btn2.setOnClickListener(
this);
    }

    @Override
    
public void onClick(View v) {
        
// TODO Auto-generated method stub
        switch (v.getId()) {
        
case R.id.Button01:
            bindService(
new Intent("com.aidl.test.IMyService"),
                    serviceConnection, Context.BIND_AUTO_CREATE);
            
break;
        
case R.id.Button02:
            StringBuilder sb 
= new StringBuilder();
            
try {
                sb.append(
"学生名称为:" + myService.getStudent().getName() + "\n");
                sb.append(
"年龄为:" + myService.getStudent().getAge() + "\n");
                sb.append(
"map 对象内容为如下:"
                        
+ myService.getMap("中国", myService.getStudent())
                                .toString());
            } 
catch (RemoteException e) {
                
// TODO Auto-generated catch block
                e.printStackTrace();
            }

            
new AlertDialog.Builder(aidlActivity.this).setTitle("调用外部服务")
                    .setMessage(sb.toString()).setPositiveButton(
                            android.R.string.ok, 
null).show();
            
break;
        
default:
            
break;
        }
    }
}

 

 

在ServiceConnetction里面对IMyService 进行初始化,即可操作该对象 ,该对象就可以得到我们所有要处理的数据。

 

4、小结

  • aidl 文件调用javabean 的aidl文件必须导包;
  • javabean 必须序列化,如果没有用javabean可以用简单的变量代替,如返回一个整型,返回一个字符串等。
  • 使用aidl 必须同时存在客户端和服务端,即客户端在本机上,服务端也在本机上,要使用客户端必须服务端事先在本机上注册过服务。

本文出自 “Terry_龙” 博客,请务必保留此出处http://terryblog.blog.51cto.com/1764499/382457

分享到:
评论

相关推荐

    android 进程之间通信--Android 使用【AIDL】调用外部服务

    NULL 博文链接:https://venus585625.iteye.com/blog/855874

    Android 使用【AIDL】调用外部服务的解决方法

    本篇文章是对Android中使用AIDL调用外部服务的方法进行了详细的分析介绍,需要的朋友参考下

    AIDL监听器回调

    自己写的一个通过AIDL进行注册的小实例 ...register_service_aidl 外部API与service的AIDL接口 register_service_api 外部API(即暴露给UI的接口) register_ui 注册UI 调用关系为 ui-&gt;service_api----&gt;service

    精通ANDROID 3(中文版)1/2

    11.3 使用服务的真实示例  11.3.1 Google翻译API  11.3.2 使用Google翻译API  11.4 参考资料  11.5 小结  第12章 包  12.1 包和进程  12.1.1 包规范的细节  12.1.2 将包名称转换为进程名称  ...

    疯狂Android讲义源码

     13.5.3 使用Android应用调用  Web Service 512  13.6 本章小结 524  第14章 管理Android手机桌面 525  14.1 管理手机桌面 526  14.1.1 删除桌面组件 526  14.1.2 添加桌面组件 526  14.2 改变手机壁纸 527 ...

    精通Android 3 (中文版)2/2

    11.3 使用服务的真实示例  11.3.1 Google翻译API  11.3.2 使用Google翻译API  11.4 参考资料  11.5 小结  第12章 包  12.1 包和进程  12.1.1 包规范的细节  12.1.2 将包名称转换为进程名称  ...

    疯狂Android讲义.part2

    13.5.3 使用Android应用调用 Web Service 512 13.6 本章小结 524 第14章 管理Android手机桌面 525 14.1 管理手机桌面 526 14.1.1 删除桌面组件 526 14.1.2 添加桌面组件 526 14.2 改变手机壁纸 527 14.2.1 开发实时...

    疯狂Android讲义.part1

    13.5.3 使用Android应用调用 Web Service 512 13.6 本章小结 524 第14章 管理Android手机桌面 525 14.1 管理手机桌面 526 14.1.1 删除桌面组件 526 14.1.2 添加桌面组件 526 14.2 改变手机壁纸 527 14.2.1 开发实时...

    深入理解Android:卷I--详细书签版

     第9章分析了Vold和Rild,其中Vold负责Android平台中外部存储设备的管理,而Rild负责与射频通信有关的工作。本章的拓展思考部分介绍了嵌入式系统中与存储有关的知识,还探讨了 Rild和Phone设计优化方面的问题。 ...

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--aidl调用系统service未公开的方法挂电话 |--aidl调用系统未公开的方法代码示例2 |--android dp和px之间转换 |--android INSTALL_PARSE_FAILED_MANIFEST_MALFORMED |--android root下禁用组件 |--android 判断网络...

Global site tag (gtag.js) - Google Analytics