Android-bindService远程服务(Aidl)-传递对象
之前上一篇讲解到本地服务,本地服务只能在自身APP中Activity访问Service,调用Service里面到方法等操作
如果想A应用访问B应用里面的方法,属于跨进程调用,如果Android不特供这种跨进程间通讯等API,是不能实现的
Google Android 为了解决 A应用--->B应用 跨进程访问通讯,提供了一种机制,就是IBInder,这种IBinder机制是Google工程师加入进去的,以前的Linux里是没有这个机制的
bindService 会返回IBinder接口,IBinder就是Google工程师在为了解决这种跨应用跨进程通讯,IBinder还需要结合Aidl才能实现远程服务(跨进程跨应用通讯)
注意:⚠️以前本地服务是通过显示意图去绑定,现在远程服务由于无法拿到另外应用的字节码,只能隐士意图去绑定
Service2,作为服务端,需要把MyService暴露出去
<!--
代表在应用程序里,当需要该service时,会自动创建新的进程。
android:process=":remote" 是否可以被系统实例化
android:enabled="true" 代表是否能被其他应用隐式调用
android:exported="true"
-->
<service android:name=".service.MyService3"> <intent-filter> <!-- 激活 MyService2 唯一name,不能重名-->
<action android:name="liudeli.service2.service.MyService3" /> </intent-filter> </service>
Service2,传递的对象Student,需要实现 Parcelable 接口
⚠️注意:Student.java Student.aidl 包名必须一致

Service2,传递的对象Student,需要实现 Parcelable 接口
package liudeli.service2; import android.os.Parcel;
import android.os.Parcelable; public class Student implements Parcelable { public int id;
public String name;
public int age;
public String hobby; /**
* 注意:构造方法的读取一定要和writeToParcel(写入)顺序一致
* @param in
*/
protected Student(Parcel in) {
id = in.readInt();
name = in.readString();
age = in.readInt();
hobby = in.readString();
} public Student(){ } public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
} @Override
public Student[] newArray(int size) {
return new Student[size];
}
}; @Override
public int describeContents() {
return 0;
} /**
* 注意:构造方法的读取一定要和writeToParcel(写入)顺序一致
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeInt(age);
dest.writeString(hobby);
} @Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", hobby='" + hobby + '\'' +
'}';
}
}
Service2,传递的对象Student,还需要在.aidl文件中声明是Parcelable

// Student.aidl
package liudeli.service2; // Declare any non-default types here with import statements parcelable Student;
Service2,把逻辑都写在MyService
package liudeli.service2.service; import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException; import liudeli.service2.IQueryStudent;
import liudeli.service2.Student; public class MyService3 extends Service { @Override
public IBinder onBind(Intent intent) {
return new IQueryStudent.Stub() {
@Override
public Student queryStudentByID(int id) throws RemoteException {
Student student = null;
switch (id) {
case 1:
student = new Student();
student.id = 1;
student.name = "张三";
student.age = 20;
student.hobby = "喜欢画画";
break;
case 2:
student = new Student();
student.id = 2;
student.name = "李连杰";
student.age = 46;
student.hobby = "套路扎实,功夫厉害";
break;
default:
student = new Student();
student.id = 3;
student.name = "梁小龙";
student.age = 54;
student.hobby = "腿功厉害";
break;
}
return student;
}
};
}
}
Service2,现在远程服务的AIdl语言接口的定义:

// IQueryStudent.aidl
package liudeli.service2; // Declare any non-default types here with import statements import liudeli.service2.Student; interface IQueryStudent { /**
* ID查询学生详情(学生对象)
*/
Student queryStudentByID(int id); }
注意:要把这些aidl文件,Student.java 文件 全部copy 到 -->Service1应用,要保证这些文件的命名 包名 两个工程 一模一样

----------------------------- 分割线 下面代码是 Service1 访问者相关的了
Service1,⚠️要把Service2 aidl 带包一起copy到Service1,保持aidl相关一模一样
Service1,绑定远程服务相关代码
package liudeli.service1; import android.app.Activity;
import android.content.ComponentName;
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.widget.Toast; import liudeli.service2.IQueryStudent;
import liudeli.service2.Student; public class RemoteActivity2 extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remote); bindServiceAction();
} /**
* Activity初始化的时候绑定服务
*/
private void bindServiceAction() {
Intent intent = new Intent();
intent.setAction("liudeli.service2.service.MyService3");
// android 5.0以后直设置action不能启动相应的服务,需要设置packageName或者Component
intent.setPackage("liudeli.service2");
bindService(intent, connection, BIND_AUTO_CREATE);
} private IQueryStudent iQueryStudent; /**
* 定义服务连接对象,用于连接远程服务
*/
private ServiceConnection connection = new ServiceConnection() {
/**
* 服务连接成功
* @param name 可以获取到服务到完整信息
* @param service 服务那边返回到IBinder接口
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 这里和本地服务不同,本地服务是强制类型转换,远程服务直接使用代理完成
iQueryStudent = IQueryStudent.Stub.asInterface(service);
} /**
* 服务断开连接
* @param name
*/
@Override
public void onServiceDisconnected(ComponentName name) { }
}; /**
* 查询远程服务里面的数据
* @param view
*/
public void queryRemoteService(View view) {
if (null == iQueryStudent) {
Toast.makeText(this, "绑定远程服务失败,无法查询", Toast.LENGTH_LONG).show();
return;
}
try {
Student student = iQueryStudent.queryStudentByID(2);
Toast.makeText(this, "查询成功:" + student.toString(), Toast.LENGTH_LONG).show();
} catch (RemoteException e) {
e.printStackTrace();
Toast.makeText(this, "远程服务失败 远程异常", Toast.LENGTH_LONG).show();
}
} /**
* Activity结束时,记得一定要解绑服务,否则会报连接资源异常
*/
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(connection);
}
}
Layout布局相关:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="queryRemoteService"
android:text="查询远程服务"
/> </LinearLayout>
操作:

Android-bindService远程服务(Aidl)-传递对象的更多相关文章
- Android之Activity之间传递对象
在非常多时候,我们须要在Activity之间传递对象,比方当你点击了某列表的item,须要传递给下一个Activity该对象,那我们须要该怎么做呢? Android支持两种传递对象的方式.一种是bun ...
- [Android学习]Activity之间传递对象和对象集合
开发过程中,Activity之间传递数据是必不可少的,android中使用Intent和Bundle作为数据载体,在Activity之间传递,对于基础数据类型,Bundle已经提供相关的put,get ...
- Android开发——使用intent传递对象
intent传递对象有两种方法: 方式一:Serializable 方式 方式二:Parcelable方式 在这里不多介绍了,这一篇就是快速上手使用教程,至于详细原理介绍的,请看这一篇http://w ...
- Android 如何进行页面传递对象
当我们从一个页面调到另一个页面的时候,需要把该页面的一些设定值也传递给下一个页面.当要传递的值很多时,我们可以传递一个对象. 页面1: Intent intent = new Intent(PageO ...
- Android--Service之AIDL传递复杂对象
前言 Android的AIDL不仅可以在绑定服务中传递一些Android规定的数据类型的数据,还可以传递一些复杂类型的数据.但是与传递系统允许的数据类型相比,复杂类型数据的传递要做更多的工作,本篇博客 ...
- Android 中的AIDL,Parcelable和远程服务
Android 中的AIDL,Parcelable和远程服务 早期在学习期间便接触到AIDL,当时对此的运用也是一撇而过.只到近日在项目中接触到AIDL,才开始仔细深入.AIDL的作用 ...
- Android 全局获取 Context 与使用 Intent 传递对象
=====================全局获取 Context======================== Android 开发中很多地方需要用到 Context,比如弹出 Toast.启动活 ...
- Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]
http://blog.csdn.net/cjjky/article/details/6441104 在Android中的不同Activity之间传递对象,我们可以考虑采用Bundle.putSeri ...
- Android中Intent传递对象的两种方法(Serializable,Parcelable)
今天要给大家讲一下Android中 Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是 Bundle.putP ...
随机推荐
- rsyslog传输type
Rsyslog远程传输的几种方式 基本介绍 Rsyslog是一个syslogd的多线程增强版,rsyslog vs. syslog-ng 链接是rsyslog官方和syslog特性和性能上的一些对比, ...
- spring security的原理及教程
spring security使用分类: 如何使用spring security,相信百度过的都知道,总共有四种用法,从简到深为:1.不用数据库,全部数据写在配置文件,这个也是官方文档里面的demo: ...
- mybatis mysql 批量insert 返回主键
Mybatis在插入单条数据的时候有两种方式返回自增主键: mybatis3.3.1支持批量插入后返回主键ID, 首先对于支持自增主键的数据库:useGenerateKeys和keyProper ...
- C# 调用动态代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- MYSQL 存储过程、函数、临时表、游标
创建函数 因为我们平时经常需要创建不同日期的数据,以模拟的场景,覆盖更多的用例,所以这里写了一个返回随机日期的demo.大家可以自行扩展. DROP FUNCTION IF EXISTS milan_ ...
- java-tip-各种Map的区别及如何选择
这里主要讨论这三种:HashMap.LinkedHashMap.TreeMap 1. HashMap是常规的哈希表,查询以及插入的性能最好,如果没有特殊要求,应该使用这个 2. LinkedHashM ...
- XIb中使用tableview报错UIViewAlertForUnsatisfiableConstraints
1.使用断点工具并不能找出错误,最后仔细看了下报错信息 2.报错信息 [LayoutConstraints] Unable to simultaneously satisfy constraints. ...
- sql查询exist替换in
很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b) 用下面的语句替换: select num f ...
- btrfs的介绍与使用
源文献:http://www.ibm.com/developerworks/cn/linux/l-cn-btrfs/index.html#ibm-pcon 简单看了一下这篇文章,对其中一些机制的实现还 ...
- sql分组获取第一条记录(sql+oracle)
sql版本 select * from (select t.CloseDate,t.ExpiryDate,t.DataTypeLookupID,ROW_NUMBER() over(partition ...