Service Activity三种交互方式
本地服务(Local Service):用于应用程序内部
远程服务(Remote Sercie):用于android系统内部的应用程序之间
前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。
后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。
编写不需和Activity交互的本地服务示例
本地服务编写比较简单。首先,要创建一个Service类,该类继承android的Service类。这里写了一个计数服务的类,每秒钟为计数器加一。在服务类的内部,还创建了一个线程,用于实现后台执行上述业务逻辑。
Service代码:
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() {
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
System.out.println(" CountService Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v(" CountService ", " on destroy ");
}
}
将该服务注册到配置文件AndroidManifest.xml中
<service android:name="CountService" />
在Activity中启动和关闭本地服务
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class LocalServiceDemoActivity extends Activity {
@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了。
新建立的接口代码:
public interface ICountService {
public abstract int getCount();
}
CountService代码:
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++;
System.out.println("CountService Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v(" CountService ", " on destroy ");
}
// @Override
public int getCount() {
return count;
}
}
服务的注册也要做改动,AndroidManifest.xml文件:
<service android:name="CountService" >
<intent-filter>
<action android:name="com.phone.jiaohuservice.CountService" />
</intent-filter>
</service>
Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
public class LocalServiceDemoActivity extends Activity {
private ServiceConnection serviceConnection = new ServiceConnection() {
// @Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
System.out.println(" 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.phone.jiaohuservice.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文件。
远端代码:
ICountService.aidl
package com.phone.remoteservice.aidl;
interface ICountService {
int getCount();
}
CountService.java
import com.phone.remoteservice.aidl.ICountService;
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.i("aa", "---" + count + "---");
}
}
}).start();
}
// @Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v(" CountService ", " on destroy ");
}
}
配置文件AndroidManifest.xml
<service android:name=".CountService" >
<intent-filter>
<action android:name="com.phone.remoteservice.CountService" />
</intent-filter>
</service>
本地代码:
拷贝远端代码gen:com.phone.remoteservice.aidl包名及内部生成的ICountService.java文件到本地,注意包名不要变,java文件名也不要变。
测试代码
import com.phone.remoteservice.aidl.ICountService;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
public class RemoteServiceTest extends Activity {
private ICountService countService;
private boolean SreviceDisable;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bindService(new Intent("com.phone.remoteservice.CountService"),
this.serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
this.unbindService(serviceConnection);
SreviceDisable = true;
super.onDestroy(); // 注意先后
}
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
countService = ICountService.Stub.asInterface(service);
new Thread(new Runnable() {
// @Override
public void run() {
while (!SreviceDisable) {
try {
System.out
.println(" CountService on serivce connected, count is "
+ countService.getCount());
} catch (RemoteException e) {
e.printStackTrace();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}).start();
}
public void onServiceDisconnected(ComponentName name) {
countService = null;
}
};
}
在Activity中使用服务的差别不大,只需要对ServiceConnection中的调用远程服务的方法时,要捕获RemoteException 异常。
这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。 如果是另外的应用程序使用远程服务,需要做的是复制上面的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数据改为复杂数据类型:
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 ;
}
}
Service Activity三种交互方式的更多相关文章
- android Service Activity三种交互方式(付源码)(转)
android Service Activity三种交互方式(付源码) Android应用服务器OSBeanthread android Service Binder交互通信实例 最下边有源代码: ...
- android Service Activity三种交互方式(付源码)
android SDK提供了Service,用于类似Linix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Rem ...
- 大数据--Hive的安装以及三种交互方式
1.3 Hive的安装(前提是:mysql和hadoop必须已经成功启动了) 在之前博客中我有记录安装JDK和Hadoop和Mysql的过程,如果还没有安装,请先进行安装配置好,对应的随笔我也提供了百 ...
- [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)
首先要明白需要的情景,然后对三种方式进行选择: (一)可以接收Service的信息(获取Service中的方法),但不可以给Service发送信息 (二) 使用Messenger既可以接受Servic ...
- (转)JAVA 调用Web Service的三种方法
1.使用HttpClient用到的jar文件:commons-httpclient-3.1.jar方法:预先定义好Soap请求数据,可以借助于XMLSpy Professional软件来做这一步生成. ...
- 转-Web Service中三种发送接受协议SOAP、http get、http post
原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...
- Open Interface Service WCF三种通信模式
WCF三种通信模式 一.请求响应模式: 概念:客户端发送请求,一直等待服务端响应,在此期间处于等待(假死)状态:直到服务器响应,才能继续执行其他的操作: 即使返回值是void 也属于请求与答复模式. ...
- Android service ( 一 ) 三种开启服务方法
一. Service简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟 Activ ...
- Ext.net中常用的三种交互方式
http://www.ext.net.cn/forum.php?mod=viewthread&tid=10433
随机推荐
- ios设置textField只能输入数字用于电话号码
首先在.xib中将UITextField的Keyboard设置为Number Pad,但是使用时键盘会切回别的键盘无法对内容进行校验.通过神奇的百度我知道了通过以下方法可以解决这样的问题: 首先让.x ...
- 笔记整理--Linux_Socket
揭开Socket编程的面纱 - 博客 - 伯乐在线 - Google Chrome (2013/9/22 19:28:24) 揭开Socket编程的面纱 2013/09/21 | 分类: IT技术 | ...
- 《剑指Offer》算法题——“旋转数组”的最小数字
题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减序列的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数 ...
- VBS基础篇 - 对象(6) - Folder对象
VBS基础篇 - 对象(6) - Folder对象 描述:提供对文件所有属性的访问,从FSO对象的GetFile方法获得 使用Folder对象 要用Folder对象模型来编程必须先用FSO对象的G ...
- VMware 虚拟机(linux)增加根目录磁盘空间
今天查看学校的监控报修系统,不能访问了!!!系统运行很慢,用top命令查看发现内存使用率90%,用"df -h ”查看“/”目录使用率已达到80%,导致系统运行很慢.我用以下方法扩大根目录磁 ...
- mysql常用命令使用技巧
一.连接Mysql格式: mysql -h主机地址 -u用户名 -p用户密码 1.连接到本机上的MYSQL.首先打开DOS窗口,然后进入目录mysql\bin,再键入命令mysql -u root - ...
- The List ADT
1.Definiation A list is a sequence. a0, a1,a2,..., aN (N>0) 2.Character For any list except the ...
- Storm官方帮助手册翻译(下)
使用其他语言编写Bolt Bolt可以使用任意语言编写.用另外一种语言编写Bolt来作为子进程运行.Storm会在标准输入输出的基础上使用Json来与子进程通信.通信协议之需要一个100行的适配器库, ...
- R语言笔记3--实例1
综合性例子: 模拟产生统计专业同学的名单(学号区分),记录数学分析,线性代数.概率统计三科成绩,然后进行一些统计分析 1.首先产生一个向量(100个元素,代表100位学生) 2.模拟成绩 runif: ...
- 17 个 tar 命令实用示例【转】
Tar(Tape ARchive,磁带归档的缩写,LCTT 译注:最初设计用于将文件打包到磁带上,现在我们大都使用它来实现备份某个分区或者某些重要的目录)是类 Unix 系统中使用最广泛的命令,用于归 ...