之前上一篇讲解到本地服务,本地服务只能在自身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)-传递对象的更多相关文章

  1. Android之Activity之间传递对象

    在非常多时候,我们须要在Activity之间传递对象,比方当你点击了某列表的item,须要传递给下一个Activity该对象,那我们须要该怎么做呢? Android支持两种传递对象的方式.一种是bun ...

  2. [Android学习]Activity之间传递对象和对象集合

    开发过程中,Activity之间传递数据是必不可少的,android中使用Intent和Bundle作为数据载体,在Activity之间传递,对于基础数据类型,Bundle已经提供相关的put,get ...

  3. Android开发——使用intent传递对象

    intent传递对象有两种方法: 方式一:Serializable 方式 方式二:Parcelable方式 在这里不多介绍了,这一篇就是快速上手使用教程,至于详细原理介绍的,请看这一篇http://w ...

  4. Android 如何进行页面传递对象

    当我们从一个页面调到另一个页面的时候,需要把该页面的一些设定值也传递给下一个页面.当要传递的值很多时,我们可以传递一个对象. 页面1: Intent intent = new Intent(PageO ...

  5. Android--Service之AIDL传递复杂对象

    前言 Android的AIDL不仅可以在绑定服务中传递一些Android规定的数据类型的数据,还可以传递一些复杂类型的数据.但是与传递系统允许的数据类型相比,复杂类型数据的传递要做更多的工作,本篇博客 ...

  6. Android 中的AIDL,Parcelable和远程服务

    Android 中的AIDL,Parcelable和远程服务      早期在学习期间便接触到AIDL,当时对此的运用也是一撇而过.只到近日在项目中接触到AIDL,才开始仔细深入.AIDL的作用    ...

  7. Android 全局获取 Context 与使用 Intent 传递对象

    =====================全局获取 Context======================== Android 开发中很多地方需要用到 Context,比如弹出 Toast.启动活 ...

  8. Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]

    http://blog.csdn.net/cjjky/article/details/6441104 在Android中的不同Activity之间传递对象,我们可以考虑采用Bundle.putSeri ...

  9. Android中Intent传递对象的两种方法(Serializable,Parcelable)

    今天要给大家讲一下Android中 Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是 Bundle.putP ...

随机推荐

  1. linux tcp调优

    Linux TCP Performance Tuning News Linux Performance Tuning Recommended Books Recommended Links Linux ...

  2. 关于where和having的直观理解

    一,查询区别 where是对前面select的字段没有要求,直接查询库表的 having是对前面的select的字段有要求,字段已经select出来的 可以用having进行处理 select id, ...

  3. awk 数据处理小技巧

    进行数据分析或统计时,如果数据量较小,我们可以用awk快速处理,以下是一些小技巧   一.时间戳转换 日期转时间戳: date -d "20150315"  "+%s&q ...

  4. CBCentralManagerDelegate Protocol 委托协议相关分析

    总体概述 CBCentralManagerDelegate 协议中定义了一系列方法列表,这些方法是委托对象必须要实现的方法(也有可选择的),当中央管理器的相应变化就会调用委托对象中实现的相应方法. M ...

  5. JDBC模板对象是多例的

  6. 在SharePoint解决方案中使用JavaScript (2) – 模块化

    本文是在SharePoint中使用JavaScript的第二篇文章,前面的文章包括: 在SharePoint解决方案中使用JavaScript (0) 在SharePoint解决方案中使用JavaSc ...

  7. Linux下Mysql数据库互为主从的配置过程

    配置准备: 两台机器:A(193.168.10.101)  B(193.168.10.102) mysql大版本需要一致,小版本可忽略 配置过程: A(193.168.10.101) 机器配置: 执行 ...

  8. Bash CookBook(一)--基础

    Bash 是brian Fox在1988年1月10号出于Richard Stallman的建议而写的.   一. 运行模板: 交互登陆的shell,登陆后bash会读取和执行/etc/profile. ...

  9. vpp命令总结

    create sub BondEthernet0 834 创建子接口,tag是834 set interface ip table BondEthernet0.834 1 将此接口设置在fib 1里 ...

  10. [C++] Virtual Destructor(虚析构函数)

    Without Virtual Destructor(虚析构函数) class A{ public: ; A() { cout <<"A()..."<< e ...