2012-09-09 22:52 4013人阅读 评论(2) 收藏 举报
    service有两种类型:
       本地服务(Local Service):用于应用程序内部 
       远程服务(Remote Sercie):用于android系统内部的应用程序之间

前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。

后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

编写不需和Activity交互的本地服务示例
本地服务编写比较简单。首先,要创建一个Service类,该类继承androidService类。这里写了一个计数服务的类,每秒钟为计数器加一。在服务类的内部,还创建了一个线程,用于实现后台执行上述业务逻辑。

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代码不再通过startSerivcestopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接ServiceActivity

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.aidleclipse会自动生成相关的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三种交互方式的更多相关文章

  1. android Service Activity三种交互方式(付源码)(转)

    android Service Activity三种交互方式(付源码) Android应用服务器OSBeanthread  android Service Binder交互通信实例 最下边有源代码: ...

  2. android Service Activity三种交互方式(付源码)

    android SDK提供了Service,用于类似Linix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Rem ...

  3. 大数据--Hive的安装以及三种交互方式

    1.3 Hive的安装(前提是:mysql和hadoop必须已经成功启动了) 在之前博客中我有记录安装JDK和Hadoop和Mysql的过程,如果还没有安装,请先进行安装配置好,对应的随笔我也提供了百 ...

  4. [转] Bound Service的三种方式(Binder、 Messenger、 AIDL)

    首先要明白需要的情景,然后对三种方式进行选择: (一)可以接收Service的信息(获取Service中的方法),但不可以给Service发送信息 (二) 使用Messenger既可以接受Servic ...

  5. (转)JAVA 调用Web Service的三种方法

    1.使用HttpClient用到的jar文件:commons-httpclient-3.1.jar方法:预先定义好Soap请求数据,可以借助于XMLSpy Professional软件来做这一步生成. ...

  6. 转-Web Service中三种发送接受协议SOAP、http get、http post

    原文链接:web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 一.web服务中三种发送接受协议SOAP/HTTP GET/HTTP POST 在web服务中,有三种可供选择的发 ...

  7. Open Interface Service WCF三种通信模式

    WCF三种通信模式 一.请求响应模式: 概念:客户端发送请求,一直等待服务端响应,在此期间处于等待(假死)状态:直到服务器响应,才能继续执行其他的操作: 即使返回值是void 也属于请求与答复模式. ...

  8. Android service ( 一 ) 三种开启服务方法

    一. Service简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟 Activ ...

  9. Ext.net中常用的三种交互方式

    http://www.ext.net.cn/forum.php?mod=viewthread&tid=10433

随机推荐

  1. ZUFE OJ 2289 God Wang II

    Description 这个世界太无聊了,于是God Wang想出了新的运算符号$,对于两个数x,y来说x$y的值等于x和y各个位置上的数字乘积之和,没有的位按0来算 比如说123$321=1*3+2 ...

  2. @Value 注解获取properties值

    转自:使用Spring 3的@value简化配置文件的读取 Spring 3支持@value注解的方式获取properties文件中的配置值,大简化了读取配置文件的代码. 1.在application ...

  3. hdu_5683_zxa and xor(非正解的暴力)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5683 题意: 问题描述 zxa最近对按位异或(exclusive disjunction)产生了极大的 ...

  4. LeetCode OJ 220.Contains Duplicate 3

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  5. Python实战:爬虫的基础

    网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕 ...

  6. CentOS7 PostgreSQL 安装

    PostgreSQL安装 安装使用yum安装 (找源 http://yum.postgresql.org/) yum install https://download.postgresql.org/p ...

  7. Windows下的ls的命令

    习惯了linux下的ls命令,windows的dir用的很不习惯,又不想装cygwin, bash,就想把dir重命名为ls,发现dos下有个命令doskey可以完成该功能.在命令提示符下敲: > ...

  8. 109.110.100.56 samba用户名 PAS, 密码 111111

    如果修改文件夹名字, 需要更改 cd /etc/samba/smb.conf 然后重启samba service smb restart 如果要修改文件夹权限 chmod -R 777 folder ...

  9. linux下mysql root密码忘记修改方法

    一.MySQL密码的恢复方法之一 如果忘记了MySQL的root密码,可以用以下方法重新设置:1.切换到root下su root 2. KILL掉系统里的MySQL进程: killall -TERM ...

  10. C++设计模式-Singleton单例模式

    template <typename T> class Singleton { public: template <typename... Args> static T* In ...