1.使用Intent进行异步通讯

在Service任务一旦完成后,就发送广播。开发者只需要实现一个BroadcastReceiver来监听响应既可。

Activity.startService启动intentService,intentService完成任务后sendBroadcast()发送广播,BroadcastReceiver.startActivity()通知Activity操作结果。

在任务结束后调用sendBroadcast(new Intent(Action));

然后在广播中通知Activity执行的结果。这种方法的优点是,Android提供了现成的机制,而不需要开发者自己构建复杂的组件间消息处理系统。

缺点是通知的结果受限于Intent,该方法也不适合在IntentService和Activity之间进行大规模快速更新操作,比如进度条,因为这会阻塞系统。

具体的代码就不多讲,和基本的Service一样使用,只是多实现了个广播.

2.本地绑定Service

本地绑定Service可以在Service中给Activity提供更复杂的回调,因为那些耗时的操作必须放到Service的后台线程中,所以Service大部分回调应该是异步的。实际的调用触发后台操作立即返回,一旦操作完成,Service使用回调接口来通知Activity相应的执行结果.

下面的例子添加了一个回调接口和一个实现AsyncTask的类,该类用来模拟后台操作。Service的onBind()方法返回一个localBinder对象,通过该对象客户端可以获取Service引用,并能执行doLongRunningOperation()方法。此方法创建了一个新的AsyncTask,并用客户端传递进来的参数执行execute()函数,在执行的过程中,回调函数会通知客户端新进度,当执行完毕会回调执行结果.

这个例子以下载图片讲解其详细的实现步骤

public class MyLocalService extends Service {
private static final int
NOTIFICATION_ID = 1001;//通知的ID
private LocalBinder mLocalBinder = new
LocalBinder();//用于返回的localBinder对象
private Callback mCallback;

@Override
public IBinder
onBind(Intent intent) {
// TODO Auto-generated method stub
return
this.mLocalBinder;
}

public class LocalBinder extends Binder
{
public
MyLocalService getService() {
return MyLocalService.this;
}
}

public void
setCallback(Callback callback) {
this.mCallback = callback;
}

//回调接口,便于Activity与Service进行通信
public interface Callback
{
void
onOperationProgress(int progress);

void onOperationCompleted(String
result);
}

public void doLongRunningOperation(String
urlString) {
new
MyAsyncTask().execute(urlString);
}

private class MyAsyncTask extends
AsyncTask<String, Integer, String> {

//处理任务之中
@Override
protected String doInBackground(String...
params) {
publishProgress(0);//更新进度条
String result =
downloadPhoto(params[0]);
publishProgress(10);
return result;
}

//执行任务之前
@Override
protected void
onPreExecute() {
super.onPreExecute();
startForeground(NOTIFICATION_ID,
buildNotification());//保持服务一直处于活跃状态。并创建通知
}

//返回任务执行结果
@Override
protected void onPostExecute(String result)
{
if (mCallback !=
null) {
mCallback.onOperationCompleted(result);
}
mCallback.onOperationProgress(10);
stopForeground(true);
}

//进度条更新
@Override
protected void
onProgressUpdate(Integer... values) {
if (mCallback != null && values.length
> 0) {
for
(Integer value : values) {
mCallback.onOperationProgress(value);
}
}
}

//任务(结束)调用取消后
@Override
protected void
onCancelled(String result) {
// TODO Auto-generated method stub
super.onCancelled(result);
stopForeground(true);
}

}

//创建通知
private Notification
buildNotification() {
Builder builder = new Builder(this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("正在下载");
builder.setContentText("图片还在下载中");
Notification notification =
builder.getNotification();
return notification;
}

//下载图片
private String
downloadPhoto(String uriString) {
HttpURLConnection conn = null;
try {
Thread.sleep(8000);
URL url = new
URL(uriString);
conn = (HttpURLConnection)
url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(8000);
conn.setConnectTimeout(8000);
InputStream is =
conn.getInputStream();
File file = new
File(Environment.getExternalStorageDirectory()
.toString() + "/" +
"book.jpg");

FileOutputStream fos = new
FileOutputStream(file);
byte[] buf = new byte[8196];
int line = 0;
while ((line =
is.read(buf)) != -1) {
fos.write(buf, 0, line);
}
fos.close();
return "下载完成";
} catch (Exception e)
{
e.printStackTrace();
} finally {
if (conn != null)
{
conn.disconnect();
}
}
return "下载失败";
}
}

下面的代码显示了更新后的Activity,值得注意的变化是Activity实现了MyLocalService.Callback接口,当在onServiceConnected()方法中获取到对Service的引用后,调用setCallback(this)方法,以便于Activity能在操作执行期间收到回调通知。还有一点非常重要,当用户离开Activity或者调用onPause()时,不要忘记移除回调监听,否则可能导致内存泄漏。

public class MainActivity extends Activity implements
ServiceConnection,
MyLocalService.Callback {
private Button
start;
private
TextView content;
private MyLocalService mService;
private ProgressDialog
dialog;

@Override
protected void onCreate(Bundle
savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.start = (Button)
findViewById(R.id.start);
this.content = (TextView)
findViewById(R.id.content);

}

//启动Service里的AsyncTask线程

public void onTriggerLongRunningOperation(View view) {
if (this.mService != null)
{
this.mService
.doLongRunningOperation("http://image.baidu.com/i?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fwenwen.soso.com%2Fp%2F20090901%2F20090901120123-329341688.jpg&thumburl=http%3A%2F%2Fimg5.imgtn.bdimg.com%2Fit%2Fu%3D390263343%2C2695552076%26fm%3D21%26gp%3D0.jpg");
}
}

//进度条更新操作
@Override
public void
onOperationProgress(int progress) {
if (dialog == null) {
dialog = new
ProgressDialog(this);
dialog.setMessage("正在下载");
dialog.setMax(10);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
} else {
dialog.setProgress(progress);
}
if (progress == 10
&& dialog != null) {
dialog.dismiss();
}
}

@Override
public void onOperationCompleted(String result)
{
this.content.setText(result);//设置下载图片的返回结果
}

//绑定服务后的初始化操作都写在该方法内
@Override
public void
onServiceConnected(ComponentName name, IBinder service) {
this.mService =
((MyLocalService.LocalBinder) service).getService();
this.mService.setCallback(this);
this.start.setOnClickListener(new
OnClickListener() {

@Override
public void onClick(View v) {
onTriggerLongRunningOperation(v);//执行Service下载线程
start.setEnabled(false);//设置启动按钮为不可用
}
});
}

//注销之前结束后的收尾操作
@Override
public void
onServiceDisconnected(ComponentName name) {
this.mService = null;
}

@Override
protected void onResume()
{
super.onResume();
Intent bindIntent = new Intent(this,
MyLocalService.class);
bindService(bindIntent, this,
BIND_AUTO_CREATE);//绑定Service
}

@Override
protected void onPause() {
super.onPause();
if (this.mService != null)
{
this.mService.setCallback(null);
unbindService(this);//解绑Service
}
}
}

如果用户在操作执行完前离开了Activity,Service还会继续执行,因为显式调用了StartForeground()方法。如果Activity在操作结束前又重新恢复,它会在成功绑定到Service后继续调用继续接受回调。这种行为很容易把耗时的操作和用户界面分开。并且允许Activity恢复后还能继续获取运行的状态。

如果Service内部维护了一些状态,允许客户端获取这些状态以及订阅这些状态的变化是个很好的做法。因为当Activity重新恢复并绑定到Service后,这些状态可能已经发生了变化.

Service通信详解的更多相关文章

  1. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  2. SSL握手通信详解及linux下c/c++ SSL Socket代码举例

    SSL握手通信详解及linux下c/c++ SSL Socket代码举例 摘自:http://www.169it.com/article/3215130236.html   分享到:8     发布时 ...

  3. 【转载】Android Studio Service AIDL 详解

    公司产品之前IM这块存在很多问题,消息到达率低,加上协议上有些问题,丢消息频繁,所以需要重构IM,AIDL不能解决以上问题.好吧!那AIDL可以解决什么问题?什么是AIDL? 什么是AIDL? AID ...

  4. Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解

    Android中实现java与PHP服务器(基于新浪云免费云平台)http通信详解 (本文转自: http://blog.csdn.net/yinhaide/article/details/44756 ...

  5. Android Socket通信详解

    一.Socket通信简介  Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客 ...

  6. SSL握手通信详解及linux下c/c++ SSL Socket代码举例(另附SSL双向认证客户端代码)

    SSL握手通信详解及linux下c/c++ SSL Socket代码举例(另附SSL双向认证客户端代码) 摘自: https://blog.csdn.net/sjin_1314/article/det ...

  7. 开源项目SMSS发开指南(五)——SSL/TLS加密通信详解(下)

    继上一篇介绍如何在多种语言之间使用SSL加密通信,今天我们关注Java端的证书创建以及支持SSL的NioSocket服务端开发.完整源码 一.创建keystore文件 网上大多数是通过jdk命令创建秘 ...

  8. Kubernetes K8S之Service服务详解与示例

    K8S之Service概述与代理说明,并详解所有的service服务类型与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-master Cent ...

  9. java网络编程Socket通信详解

    Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket.像大家熟悉的QQ.MSN都使用了Socket相关的技术. ...

随机推荐

  1. 介绍50个 WordPress 动作挂钩

    WordPress 之所以能成为世界上最受欢迎的网页内容管理系统,原因就在于它的高度灵活性和可塑性,而这种灵活性和可塑性正是由“挂钩”(Hooks)简洁宜用的结构所决定的.可以说,没有过滤挂钩(Fil ...

  2. C#多线程(上) 分类: C# 线程 2015-03-09 10:35 174人阅读 评论(0) 收藏

    一.多线程的相关概念 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源. 而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行 ...

  3. Codeforces Gym 100418J Lucky tickets 数位DP

    Lucky ticketsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view ...

  4. IOS 手绘地图导航

    手绘地图导航 第三方库 NAMapKit, 1)支持在手绘图上标记.缩放 2)支持在单张图片 3)支持瓦片小图片 思路 前提:美工已经切好手绘图,并告知我们当前的缩放级别. 1)确定好手绘图左上角点在 ...

  5. ResolveClientUrl("~/Styles/Site.cs")%>

    区别: <%=ResolveClientUrl("~/Styles/Site.cs")%> 和 <%=ResolveUrl("~/Styles/Site ...

  6. WEB服务器、应用程序服务器、HTTP服务器区别(转)

    WEB服务器.应用程序服务器.HTTP服务器有何区别?IIS.Apache.Tomcat.Weblogic.WebSphere都各属于哪种服务器,这些问题困惑了很久,今天终于梳理清楚了: Web服务器 ...

  7. MS509Team----------------Cknife

    http://www.ms509.com/ http://www.freebuf.com/sectool/98681.html 中国蚁剑

  8. php版DES

    class DES { var $key; var $iv; //偏移量 function DES( $key, $iv=0 ) { //key长度8例如:1234abcd $this->key ...

  9. focuskye 学习及下载

    学习:http://www.focusky.com.cn/tutorials/ 下载:http://www.focusky.com.cn/download/

  10. SSIS 学习(6):包配置(上)【转】

    Integrartion Services 包实际上就是一个对象属性的集合,在前面我们开发的所有 Integration Services包,其中的变量.属性,比如:数据库链接.同步文件目录等,我们都 ...