热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

ServiceActivity的三种交互方式(详解)

下面小编就为大家带来一篇ServiceActivity的三种交互方式(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

service有两种类型:

本地服务(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中

在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文件:

 
      
        
      
 

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


 
 
 

本地代码:

拷贝远端代码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  CREATOR = new Creator  () {
@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的三种交互方式(详解)的全部内容了,希望对大家有所帮助,多多支持~


推荐阅读
  • 使用MonkeyTalk实现Android自动化测试的Agent配置
    本文详细介绍了在MonkeyTalk框架下设置Android Agent的具体步骤,包括如何将Android项目转换为AspectJ项目,以及如何正确配置和集成MonkeyTalk的Agent库。 ... [详细]
  • Python作为一种广泛使用的高级编程语言,以其简洁的语法、强大的功能和丰富的库支持著称。本文将详细介绍Python的主要特点及其在现代软件开发中的应用。 ... [详细]
  • 本文探讨了在Android应用程序开发过程中动态管理Fragment的方法,包括动态添加和切换Fragment,以及如何实现平滑的过渡动画。文章通过一个具体的案例——订单管理系统,详细介绍了实现步骤和技术细节。 ... [详细]
  • 本文探讨了缓存系统中的两个关键问题——缓存穿透与缓存失效时的雪崩效应,以及这些问题的解决方案。此外,文章还介绍了数据处理、数据库拆分策略、缓存优化、拆分策略、应用架构演进及通信协议的选择等内容。 ... [详细]
  • 本文介绍如何创建一个简单的Android桌面小部件,通过显示两个文本框来展示基本功能。提供代码下载链接及详细步骤。 ... [详细]
  • Hibernate入门指南:单表数据库操作详解
    本文介绍了Hibernate作为全面的ORM框架的基础知识,并详细讲解了在MyEclipse环境中配置Hibernate以及进行基本的数据库单表操作的方法,包括增删改查等常见操作。 ... [详细]
  • 解决fetch上传图片至微信公众号H5页面的问题
    在近期的一个项目需求中,需要在微信公众号内嵌入H5页面,并实现用户通过该页面上传图片的功能,包括拍摄新照片或从已有相册中选择。前端开发中采用了fetch API进行接口调用,但遇到了上传图片时数据无法正确传递的问题。 ... [详细]
  • 本文档详细介绍了Robot Framework的基础知识、安装配置方法及其实用技巧。从环境搭建到编写第一个测试用例,涵盖了一系列实用的操作指南和最佳实践。 ... [详细]
  • 近期参加了一次CSDN线上活动,有幸获得左飞老师的《算法之美——隐匿在数据结构背后的原理(C++版)》一书。为了加深理解并提升编程技能,我决定将书中22个经典算法问题使用Java语言进行重新编写。本文将重点介绍如何使用Java实现Z字形矩阵排列。 ... [详细]
  • Kodi(原名XBMC)是一款由XBMC基金会开发的免费开源媒体播放器应用,支持多种操作系统和硬件平台。该软件以其强大的多媒体处理能力和用户友好的界面受到广泛欢迎。 ... [详细]
  • 本文详细介绍了如何手动编写兼容IE的Ajax函数,以及探讨了跨域请求的实现方法和原理,包括JSONP和服务器端设置HTTP头部等技术。 ... [详细]
  • 本文将详细介绍如何使用ViewPager实现多页面滑动切换,并探讨如何去掉其默认的左右切换动画效果。ViewPager是Android开发中常用的组件之一,用于实现屏幕间的内容切换。 ... [详细]
  • Android实战:使用ProgressBar与AsyncTask实现数据异步加载
    本文介绍如何利用ProgressBar和AsyncTask在Android应用中实现数据的异步加载。包括加载数据的不同状态下的UI展示,如加载中、加载成功及加载失败时的界面处理。 ... [详细]
  • java学习日记对JFrame的操作
    设置背景图片、添加音乐、监控键盘、改变字体风格等等!importjava.applet.Applet;importjava.applet.AudioClip;importjava. ... [详细]
  • 本文详细介绍如何在Android模拟器上安装TaintDroid的过程,包括解决源代码链接失效及服务器文件变动等问题,旨在帮助后续用户避免不必要的麻烦。 ... [详细]
author-avatar
qgone
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有