`
jishublog
  • 浏览: 898827 次
文章分类
社区版块
存档分类
最新评论

【代码】android软件开发 Service Binder交互通信实例

 
阅读更多
Android SDK提供了Service,用于类似*nix守护进程或者windows的服务。
Service有两种类型:
1、本地服务(Local Service):用于应用程序内部
2、远程服务(Remote Sercie):用于android系统内部的应用程序之间
前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。
后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
编写不需和Activity交互的本地服务示例
本地服务编写比较简单。首先,要创建一个Service类,该类继承android的Service类。这里写了一个计数服务的类,每秒钟为计数器加一。在服务类的内部,还创建了一个线程,用于实现后台执行上述业务逻辑。

package com.easymorse;
 
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
 
public class CountService extends Service {
 
private boolean threadDisable;
 
private int count;
 
@Override
public IBinder onBind(Intent intent) {
return null;
}
 
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
 
@Override
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
Log.v("CountService", "Count is " + count);
}
}
}).start();
}
 
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v("CountService", "on destroy");
}
 
public int getCount() {
return count;
}
 
}

需要将该服务注册到配置文件AndroidManifest.xml中,否则无法找到:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easymorse" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".LocalServiceDemoActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="CountService" />
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest/>

在Activity中启动和关闭本地服务。

package com.easymorse;
 
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
 
public class LocalServiceDemoActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
 
this.startService(new Intent(this, CountService.class));
}
 
@Override
protected void onDestroy() {
super.onDestroy();
this.stopService(new Intent(this, CountService.class));
}
}

可通过日志查看到后台线程打印的计数内容。
编写本地服务和Activity交互的示例
上面的示例是通过startService和stopService启动关闭服务的。适用于服务和activity之间没有调用交互的情况。如果之间需要传递参数或者方法调用。需要使用bind和unbind方法。
具体做法是,服务类需要增加接口,比如ICountService,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承Binder类并实现ICountService接口。还有,就是要实现Service的onBind方法,不能只传回一个null了。
这是新建立的接口代码:

package com.easymorse;
 
public interface ICountService {
public abstract int getCount();
}

修改后的CountService代码:

package com.easymorse;
 
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
 
public class CountService extends Service implements ICountService {
 
private boolean threadDisable;
 
private int count;
 
private ServiceBinder serviceBinder = new ServiceBinder();
 
public class ServiceBinder extends Binder implements ICountService {
@Override
public int getCount() {
return count;
 
}
 
}
 
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
 
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
 
@Override
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
Log.v("CountService", "Count is " + count);
}
}
}).start();
}
 
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v("CountService", "on destroy");
}
 
/*
* (non-Javadoc)
*
* @see com.easymorse.ICountService#getCount()
*/
public int getCount() {
return count;
}
 
}

服务的注册也要做改动,AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easymorse" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".LocalServiceDemoActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="CountService">
<intent-filter>
<action android:name="com.easymorse.CountService"/>
</intent-filter>
</service>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>

Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。

package com.easymorse;
 
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.util.Log;
 
public class LocalServiceDemoActivity extends Activity {
 
private ServiceConnection serviceConnection = new ServiceConnection() {
 
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
Log.v("CountService", "on serivce connected, count is "
+ countService.getCount());
}
 
@Override
public void onServiceDisconnected(ComponentName name) {
countService = null;
}
 
};
 
private ICountService countService;
 
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.bindService(new Intent("com.easymorse.CountService"),
this.serviceConnection, BIND_AUTO_CREATE);
}
 
@Override
protected void onDestroy() {
 
this.unbindService(serviceConnection);
super.onDestroy(); // 注意先后
}
}

编写传递基本型数据的远程服务
上面的示例,可以扩展为,让其他应用程序复用该服务。这样的服务叫远程(remote)服务,实际上是进程间通信(RPC)。
这时需要使用android接口描述语言(AIDL)来定义远程服务的接口,而不是上述那样简单的java接口。扩展名为aidl而不是java。可用上面的ICountService改动而成ICountSerivde.aidl,eclipse会自动生成相关的java文件。
package com.easymorse;
 
interface ICountService {
int getCount();
}

编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。桩对象是远程对象的本地代理。

package com.easymorse;
 
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
 
public class CountService extends Service {
 
private boolean threadDisable;
 
private int count;
 
private ICountService.Stub serviceBinder = new ICountService.Stub() {
 
@Override
public int getCount() throws RemoteException {
return count;
}
};
 
@Override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
 
@Override
public void onCreate() {
super.onCreate();
new Thread(new Runnable() {
 
@Override
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
Log.v("CountService", "Count is " + count);
}
}
}).start();
}
 
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v("CountService", "on destroy");
}
}


配置文件AndroidManifest.xml和上面的类似,没有区别。
在Activity中使用服务的差别不大,只需要对ServiceConnection中的调用远程服务的方法时,要捕获异常。

private ServiceConnection serviceConnection = new ServiceConnection() {
 
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
try {
Log.v("CountService", "on serivce connected, count is "
+ countService.getCount());
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
 
@Override
public void onServiceDisconnected(ComponentName name) {
countService = null;
}
 
};

这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。
如果是另外的应用程序使用远程服务,需要做的是复制上面的aidl文件和相应的包构到应用程序中,其他调用等都一样。
编写传递复杂数据类型的远程服务
远程服务往往不只是传递java基本数据类型。这时需要注意android的一些限制和规定:
1、android支持String和CharSequence
2、如果需要在aidl中使用其他aidl接口类型,需要import,即使是在相同包结构下;
3、android允许传递实现Parcelable接口的类,需要import;
4、android支持集合接口类型List和Map,但是有一些限制,元素必须是基本型或者上述三种情况,不需要import集合接口类,但是需要对元素涉及到的类型import;
5、非基本数据类型,也不是String和CharSequence类型的,需要有方向指示,包括in、out和inout,in表示由客户端设置,out表示由服务端设置,inout是两者均可设置。
这里将前面的例子中返回的int数据改为复杂数据类型:

package com.easymorse;
 
import android.os.Parcel;
import android.os.Parcelable;
 
public class CountBean implements Parcelable {
 
public static final Parcelable.Creator<COUNTBEAN> CREATOR = new Creator<COUNTBEAN>() {
 
@Override
public CountBean createFromParcel(Parcel source) {
CountBean bean = new CountBean();
bean.count = source.readInt();
return bean;
}
 
@Override
public CountBean[] newArray(int size) {
return new CountBean[size];
}
 
};
 
public int count;
 
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.count);
}
 
@Override
public int describeContents() {
return 0;
}
 
}


然后,需要在相同包下建一个同名的aidl文件,用于android生成相应的辅助文件:

package com.easymorse;

parcelable CountBean;
这一步是android 1.5后的变化,无法通过adt生成aidl,也不能用一个比如全局的project.aidl文件,具体见:
http://www.anddev.org/viewtopic.php?p=20991
然后,需要在服务的aidl文件中修改如下:

package com.easymorse;
 
import com.easymorse.CountBean;
 
interface ICountService {
CountBean getCount();
}

其他的改动很小,只需将CountService和调用CountService的部分修改为使用CountBean即可。


本文讲述了android软件开发 Service Binder交互通信实例,希望本文能给读者带来灵感,帮助读者解决疑问,感谢阅读本文。更多安卓技术问题欢迎加群探讨:314230976,验证码:csl,不写验证不予通过哟~

分享到:
评论

相关推荐

    android编程 android编程入门 android开发 android软件

    3. **远程过程调用(RPC)**:Android提供了Binder机制实现跨进程通信,使得在不同进程间调用方法成为可能。 4. **线程安全方法**:在多线程环境下,确保多个线程同时访问同一数据时不会产生错误,需要使用线程安全的...

    Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析[归纳].pdf

    在Android系统中,Binder机制是实现进程间通信(IPC,Inter-Process Communication)的核心组件。它允许不同进程之间的对象和数据共享,使得Android组件如服务(Service)、活动(Activity)等能够跨越进程边界进行...

    Android Binder入门学习笔记

    1. **Binder机制**:是Android系统实现进程间通信的基础,允许不同进程的对象交互。 2. **代理模式**:在Binder机制中,客户端通过代理对象间接调用服务端的方法,实现跨进程通信。 3. **AIDL**:定义进程间通信的...

    android开发技巧 教程 安卓软件开发

    在Android软件开发中,掌握关键的开发技巧和理解其核心概念是至关重要的。这篇教程将围绕"Android开发技巧 教程 安卓软件开发"的主题,深入讲解Android应用程序的基础和框架,帮助开发者更好地理解和构建安卓应用。 ...

    《Android开发艺术探索》书中源代码.rar

    在Android开发中,你需要了解Android SDK(软件开发工具包),它包含了开发Android应用所需的所有工具,如ADT(Android Developer Tools)、Android Studio IDE以及各种版本的Android平台库。 Android应用程序通常...

    AndroidService生命周期及用法[收集].pdf

    在Android开发中,Service是一个非常重要的组件,它主要用于在后台执行长时间运行的操作,而不与用户直接交互。Service的特性使得它在处理如音乐播放、定时任务、后台数据同步等场景中发挥关键作用。 Service的基本...

    Android 开发技巧:音乐播放器的后台处理【Service、Handler、MediaPlayer】完整代码

    `Service`是Android系统的一个组件,它在后台执行长时间运行的操作而不会与用户界面交互。在音乐播放器应用中,`Service`通常用于在后台持续播放音乐,即使用户已经离开应用界面,音乐仍然可以继续播放。 `Handler`...

    Android应用开发

    1. **Android SDK**: Android软件开发工具包(SDK)是进行Android应用开发的基础,包含了开发、调试和发布Android应用所需的工具和库。它包括了Java开发工具(JDK)、Android Studio集成开发环境(IDE)、模拟器、...

    hellobinder

    5. **AIDL(Android Interface Definition Language)**:AIDL是Android系统用来生成Binder通信所需的代码工具。通过AIDL,开发者可以定义接口,使不同进程之间的组件能够互相调用方法。在`hellobinder`项目中,可能...

    王家林的Android软硬整合框架精髓实战

    2. **Android Service 架构与Binder**:Service在Android系统中扮演着重要角色,课程将介绍Zygote与SystemServer,ServiceManager,以及Binder作为Android进程间通信(IPC)的基础。学员将学习AIDL(Android ...

    android代码案例,Android中的aidl接口及案例说明博客中的源码整理,服务端

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于实现跨进程通信(IPC, Inter-Process Communication)的工具,它允许不同的Android组件之间进行数据交换和服务调用,即使这些组件运行在...

    Android aidl 实现进程间通信

    在Android系统中,进程间通信(IPC,Inter-Process Communication)是实现不同应用程序组件之间交互的关键技术。Android的AIDL(Android Interface Definition Language)就是专为处理IPC而设计的一种接口定义语言,...

    Android 底层驱动原理

    此外,Android对Linux内核进行了定制,添加了如Binder IPC驱动、WiFi驱动和蓝牙驱动等专有驱动,以满足其对设备交互和通信的需求。 1.1 Android系统架构 Android系统构建在Linux内核之上,通过一系列的中间层提供...

    android代码整理,Android中的aidl接口及案例说明中的源码整理,客户端代码

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于跨进程通信(IPC,Inter-Process Communication)的重要工具。AIDL允许我们定义服务接口,使得一个应用能够暴露其功能给其他应用,即使...

    DownService

    在Android应用开发中,`Service` 是一个非常重要的组件,它允许应用程序在后台长时间运行,即使没有用户界面。`Service` 通常用于执行耗时的操作,如音乐播放、网络通信等。`DownService` 可能是作者为特定下载功能...

    Android4.0.3照相机源码

    Android系统的照相机服务主要由`system/core/services/camera`目录下的代码实现,它作为系统服务运行在SystemServer进程中,提供给应用程序通过 Binder 通信接口进行调用。这个服务处理来自多个应用的相机请求,确保...

    Android底层驱动原理

    在Android系统中,底层驱动是连接硬件与操作系统之间的重要桥梁,它是实现软件功能与硬件设备交互的关键组件。本文将深入探讨Android底层驱动的工作原理、重要性以及如何进行开发。 一、底层驱动概述 1. 定义:...

    android整体架构ppt

    Android添加了IPC Binder机制,通过Service Manager管理服务和数据交换,使得进程间通信更加高效和便捷。 3. **内存管理**: 与标准Linux的OOM(Out of Memory)机制不同,Android采用LMK(Low Memory Killer)...

Global site tag (gtag.js) - Google Analytics