Android Activity与远程Service的通信学习总结
当一个Service在androidManifest中被声明为 process=":remote", 或者是还有一个应用程序中的Service时,即为远程Service, 远程的意思是和当前程序不在同一个进程中执行。
Activity和远程Service的跨进程通信(IPC)通过Binder机制,使用AIDL服务实现。
一. 定义远程服务端
1.新建一个project,project文件夹例如以下
2. 文件内容
aidl传递复杂对象时,须要该对象实现Parcelable或Serializable接口,并在aidl文件里声明
Student.java
package com.example.aidl; import java.util.Locale; import android.R.integer;
import android.os.Parcel;
import android.os.Parcelable; public class Student implements Parcelable { public static final int SEX_MALE = 1;
public static final int SEX_FEMALE = 2; public int sno;
public String name;
public int sex;
public int age; public Student() {
} private Student(Parcel in) {
readFromParcel(in);
} public void readFromParcel(Parcel in) {
sno = in.readInt();
name = in.readString();
sex = in.readInt();
age = in.readInt();
} @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sno);
dest.writeString(name);
dest.writeInt(sex);
dest.writeInt(age);
} public static final Parcelable.Creator<Student> CREATOR = new Parcelable.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;
} @Override
public String toString() {
return String.format(Locale.ENGLISH, "Student[ %d, %s, %d, %d ]", sno, name, sex, age);
} }
Student.aidl
package com.example.aidl; parcelable Student;
IService.aidl
package com.example.aidl; import com.example.aidl.Student; interface IMyService{ List<Student> getStudent();
void addStudent(in Student student); //in标记为输入类型
}
然后再写远程服务类StudentService.java
package com.example.remote_service; import java.util.LinkedList;
import java.util.List; import com.example.aidl.IMyService;
import com.example.aidl.Student; import android.R.integer;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log; public class StudentService extends Service { private static final String TAG = "StudentService"; private static final String PACKAGE_PEMISSION = "com.yjq.service"; private LinkedList<Student> studentList = new LinkedList<Student>(); @Override
public IBinder onBind(Intent intent) {
Log.d(TAG, String.format("on bind,intent = %s", intent.toString()));
return mBinder;
} //继承由AIDL生成的抽象类
// 实现aidl里的接口的方法 ,以供调用
//这里实现了aidl中的抽象函数
private final IMyService.Stub mBinder = new IMyService.Stub() { @Override
public List<Student> getStudent() throws RemoteException {
return studentList;
} @Override
public void addStudent(Student student) throws RemoteException {
if (student != null) {
synchronized (studentList) {
studentList.add(student);
}
}
} //在这里能够做权限认证。return false意味着client的调用就会失败,比方以下。仅仅同意包名为 PACKAGE_PEMISSION 的client通过,
//其它apk将无法完毕调用过程
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
String packageName = null;
String[] packages = StudentService.this.getPackageManager().
getPackagesForUid(getCallingUid());
if (packages != null && packages.length > 0) {
packageName = packages[0];
}
Log.d(TAG, "onTransact: " + packageName);
if (!PACKAGE_PEMISSION.equals(packageName)) {
return false;
}
return super.onTransact(code, data, reply, flags);
} }; @Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "student服务创建"); synchronized (studentList) {
for (int i = 1; i < 6; i++) {
Student student = new Student();
student.name = "student#" + i;
student.age = i * 5;
studentList.add(student);
}
} } @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "student服务启动");
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
Log.d(TAG, "student服务结束");
super.onDestroy();
} }
Stub这个内部类是一个实现了IMyService接口的Binder抽象类
onTransact()是通过应用程序的包名来限制权限的,通过验证的程序才干绑定。 同意绑定的client程序 的包名。可在client的androidManifist中查看。
并注意在androidManifest中声明
<service
android:name="com.example.remote_service.StudentService"
android:process=":remote"
>
<intent-filter >
<!-- 这里的action是隐式bindService时用到的 -->
<action android:name="com.example.remoteservice" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter> </service>
要声明action以供隐式bindService
二. 本地Activity怎样绑定远程Service
新建一个项目作为绑定远程Service的client,将上面的aidl所在包拷贝到src中,注意整个包名和文件名称都要全然一样,否则无法远程绑定。
再写MainActivity.java来进行绑定操作
package com.yjq.local_service; import java.util.List; import com.example.aidl.IMyService;
import com.example.aidl.Student;
import com.yjq.local_service.MyService.MyBinder;
import com.yjq.service.R;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection; public class MainActivity extends Activity { private static final String TAG = "MainActivity_local"; //绑定远程Service的action
public static final String BIND_REMOTE_SERVICE_ACTION = "com.example.remoteservice"; // 远程服务 , 服务的类是在aidl中定义的
private IMyService mRemoteService; private Button bindRemoteServiceButton; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); bindRemoteServiceButton =(Button)findViewById(R.id.bind_remote_service); bindRemoteServiceButton.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
bindRemoteService();
}
});
} /**
* 创建并绑定远程Service
* */
private void bindRemoteService() {
Intent intentService = new Intent(BIND_REMOTE_SERVICE_ACTION);
intentService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
bindService(intentService, remoteServiceConnection, BIND_AUTO_CREATE);
} /**
* 绑定远程服务的ServiceConnection类
*/
ServiceConnection remoteServiceConnection = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) {
mRemoteService = null;
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
mRemoteService = IMyService.Stub.asInterface(service); new Thread(new Runnable() {
@Override
public void run() {
try {
List<Student> students = mRemoteService.getStudent();
for (Student s : students) {
System.out.println("远程调用: " + s.toString());
}
} catch (Exception e) {
// TODO: handle exception
}
}
}).start(); }
}; @Override
protected void onDestroy() {
unbindService(remoteServiceConnection);
super.onDestroy();
} }
activity中通过
bindService(intentService, remoteServiceConnection, BIND_AUTO_CREATE);
来绑定远程Service
实现接口的几条说明:
*不会有返回给调用方的异常
*默认IPC调用是同步的。假设已知IPC服务端会花费非常多毫秒才干完毕,那就不要在Activity或View线程中调用,否则会引起应用程序挂起(Android可能会显示“应用程序未响应”对话框),所以上面创建了一个Thread来运行
*AIDL接口中仅仅支持方法,不能声明静态成员。
并且。当调用结束时,应该使用
unbindService(remoteServiceConnection);
来解除绑定,否则会造成内存泄漏
三. 执行測试
先安装服务端的程序,再执行client程序。点击绑定button,即看到结果
08-20 22:49:48.447: I/System.out(1319): 远程调用: Student[ 0, student#1, 0, 5 ]
08-20 22:49:48.457: I/System.out(1319): 远程调用: Student[ 0, student#2, 0, 10 ]
08-20 22:49:48.457: I/System.out(1319): 远程调用: Student[ 0, student#3, 0, 15 ]
08-20 22:49:48.457: I/System.out(1319): 远程调用: Student[ 0, student#4, 0, 20 ]
08-20 22:49:48.457: I/System.out(1319): 远程调用: Student[ 0, student#5, 0, 25 ]
Demo下载: http://download.csdn.net/detail/guige_csdn/9032089
四. 在android中的应用
摘自:http://blog.csdn.net/u011485531/article/details/12073647
以下我们就讲一个挂断电话的样例,我们知道。Android的api里面是没有挂断电话的操作的
那假设我们的应用就有这样一个需求呢,那怎么办
能够通过java的反射来实现。也能够通过aidl来实现,以下介绍aidl的方法
首先,我们先把两个aidl文件拷贝到src文件夹以下
你肯定会问,这些aidl文件是在那里找到的,那么我能够告诉你,这些是Android的源代码里面找到的,就是在base这个以下的
大家能够下载下来看看。假设有不会的,请看点击这里
既然把aidl文件拷贝过去之后。我们就能够写代码啦
com.xiaobin.endcall.MainActivity
- package com.xiaobin.endcall;
- import java.lang.reflect.Method;
- import com.android.internal.telephony.ITelephony;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.IBinder;
- import android.view.View;
- public class MainActivity extends Activity
- {
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- this.setContentView(R.layout.main);
- }
- public void click(View v)
- {
- endCall();
- }
- //挂断电话
- private void endCall()
- {
- try
- {
- //通过反射拿到android.os.ServiceManager里面的getService这种方法的对象
- Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
- //通过反射调用这个getService方法,然后拿到IBinder对象,然后就能够进行aidl啦
- IBinder iBinder = (IBinder) method.invoke(null, new Object[] {TELEPHONY_SERVICE});
- ITelephony telephony = ITelephony.Stub.asInterface(iBinder);
- telephony.endCall();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
由于那个服务没有公开的,所以我们就要用到反射来调用这个服务,来拿到Binder对象
还有重要的一点喔,要加上对应的权限。不然挂不断的喔
- <uses-permission android:name="android.permission.CALL_PHONE"/>
好啦,到这里。挂断电话的操作就完毕的啦,能够測试一下啦,然后我们手机卫士的这个项目的黑名单那里也有挂断电话的操作的喔
挂断电话的样例下载:http://download.csdn.net/detail/guige_csdn/9032239
Android Activity与远程Service的通信学习总结的更多相关文章
- android 中activity调用远程service中的方法之 aidl的使用
服务端:只有服务,没有界面 1.编写interface文件,复制到 .aidl 文件中,并去掉其中的public 等修饰符.系统会自动在gen目录下生成对应的java文件 (对应本地调用中的接口文件 ...
- Android成长日记-Android四大组件之Service组件的学习
1.什么是Service? Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它 ...
- android 远程Service以及AIDL的跨进程通信
在Android中,Service是运行在主线程中的,如果在Service中处理一些耗时的操作,就会导致程序出现ANR. 但如果将本地的Service转换成一个远程的Service,就不会出现这样的问 ...
- Android四大组件之一 -- Service详解
相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的Android程序员如果连Service都没听说过的话,那确实也太逊了.Service作为Android四大组件之一,在每一个应用程序 ...
- Android学习总结(四)—— Activity和 Service进行通信
一.Activity 和 Service进行通信的基本概念 前面我们学习我生命周期里面包含了启动和停止服务的方法,虽然服务器在活动里启动,但在启动了服务之后,活动与服务基本就没有什么关系了.我们在活动 ...
- Android:(本地、可通信的、前台、远程)Service使用全面介绍
2.具体使用解析 2.1 本地Service 这是最普通.最常用的后台服务Service. 2.1.1 使用步骤 步骤1:新建子类继承Service类 需重写父类的onCreate().onStart ...
- 一个简单的demo学习Android远程Service(AIDL的使用)
这是milo很早之前写在论坛上的一个帖子,现在整理出来,milo也复习一下一般来说Android 的四大组件都是运行在同一个进程中的,但远程Service运行在不同的进程里.这进程间的通信是使用了An ...
- Android 服务类Service 的详细学习
http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建 目录(?)[+] 什么是服务 服务有 ...
- Android应用程序的Activity启动过程简要介绍和学习计划
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...
随机推荐
- PHP05 PHP语言基础
学习要点 初识PHP 基础语法 变量 常量 运算符 表达式 学习目标 掌握PHP基础语法 掌握PHP变量 掌握PHP常量 掌握PHP表达式 掌握PHP运算符 初识PHP 第一个PHP程序 编写代码 1 ...
- Swift中的init方法
摘要:Swift有着超级严格的初始化方法,不仅强化了designated初始化方法的地位,所有不加修饰的init方法都需要在方法中确保非Optional的实例变量被赋值初始化,而在子类中,也强制调用s ...
- C++知识点总结(纯C++!!)
1.重载函数是否能够通过函数返回值的类型不同来区分? 不可以.因为在C++编程中,函数的返回值可以忽略(不使用其返回值),程序中调用此时函数名相同和参数相同的两个函数对编译器和程序员来说是没有办法区分 ...
- 文本三剑客之awk
awk和流编辑器sed在工作原理和用法上有很多类似之处,它们都是检查输入数据中的行是否匹配指定的模式,如果匹配成功就对匹配的行执行相应的操作,重复这个过程直到所有的输入数据都被处理完,因此awk和se ...
- ps----像素与分辨率
1.为了用于印刷,所以调整文档尺寸也很重要. 2.像素的多少决定了文件的大小,像素越多图像越清晰越逼真. 3.文档的尺寸改变需要结合分辨率. 4.像素固定的情况下修改分辨率高度宽度也会变化. 5.画面 ...
- Linux使用yum命令安装软件时,连接不了网路报错:ERROR 6 - "Couldn't resolve host 'mirrorlist.centos.org'"
错误: 解决方案: 在/etc/sysconfig/network-scripts/ifcfg-eth0文件中配置DNS信息: vim /etc/sysconfig/network-scripts/i ...
- java环境配置——配置tomcat用户
Tomcat Manager是Tomcat自带的.用于对Tomcat自身以及部署在Tomcat上的应用进行管理的web应用.Tomcat是Java领域使用最广泛的服务器之一,因此Tomcat Mana ...
- 简单的发红包的PHP算法
假设有有10元钱 ,发给10个人.保证每个人都有钱拿,最少分得0.01.我们最先想到的肯定就是随机.0.01-10随机.但是会出现第一个人就分得9.99的情况.下面就没人可分了.然后就是我的错误思路 ...
- 搜狗大数据总监、Polarr 联合创始人关于深度学习的分享交流 | 架构师小组交流会
架构师小组交流会是由国内知名公司技术专家参与的技术交流会,每期选择一个时下最热门的技术话题进行实践经验分享.第一期:来自沪江.滴滴.蘑菇街.扇贝架构师的 Docker 实践分享 第二期:来自滴滴.微博 ...
- 洛谷 P3800 Power收集
题目背景 据说在红雾异变时,博丽灵梦单身前往红魔馆,用十分强硬的手段将事件解决了. 然而当时灵梦在Power达到MAX之前,不具有“上线收点”的能力,所以她想要知道她能收集多少P点,然而这个问题她答不 ...