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
随机推荐
- 编译OpenGL代码时发生 Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed! 错误的解决方案
注:本解决方案适用于使用N卡的PC 出现该错误 , 一般是由于开源的nouveau驱动和Nvidia专有驱动冲突导致的 .在解决该问题时 , 尝试过卸载 N 卡专有驱动 , 仅使用开源nouveau驱 ...
- Emacs阅读chm文档
.title { text-align: center; margin-bottom: .2em } .subtitle { text-align: center; font-size: medium ...
- MFC中组合框CComboBox的使用
假如添加三行数据,其中当选择前两行时,提示自定义提示框信息,选择第三行时,提示当前字符串的内容,实现如下: void Cuse_demo_dllDlg::OnCbnSelchangeCombo1(){ ...
- Unity3d之将terrain转化成mesh
Unity3d中,terrain还是比较耗的,DrawCall数也比较多,为了优化性能,可能需要将terrain转化成mesh. 现提供一工具,思路是根据terrain高度图生成mesh等,可参考: ...
- Edit Individual GridView Cells in ASP.NET
Edit individual GridView cells without putting the entire row into edit mode.Examples using the SqlD ...
- LCA-倍增法(在线)O(nlogn)-O(logn)
1. DFS预处理出所有节点的深度和父节点 inline void dfs(int u) { int i; ;i=next[i]) { if (!deep[to[i]]) { deep[to[i]] ...
- how to use the curses library in unix?
In linux, you can use the ncurses library to use the terminal as a text buffer: move the cursor arou ...
- web前端与后端
Web前端: 1)精通HTML,能够书写语义合理,结构清晰,易维护的HTML结构. 2)精通CSS,能够还原视觉设计,并兼容业界承认的主流浏览器. 3)熟悉JavaScript ...
- sql求日期
2.求以下日期SQL: 昨天 select convert(varchar(10),getdate() - 1,120) 明天 select convert(varchar(10),getdate() ...
- Sublime console installation instructions install Package Control
instructions: import urllib2,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa1548d1 ...