`
wsqwsq000
  • 浏览: 675493 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android service入门

 
阅读更多

android SDK提供了Service,用于类似*nix守护进程或者windows的服务。

Service有两种类型:

1. 本地服务(Local Service):用于应用程序内部

2. 远程服务(Remote Sercie):用于android系统内部的应用程序之间

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

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

编写不需和Activity交互的本地服务示例

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

package com.easymorse;
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() {
@Override
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
Log.v("CountService", "Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v("CountService", "on destroy");
}
public int getCount() {
return count;
}
}

需要将该服务注册到配置文件AndroidManifest.xml中,否则无法找到:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easymorse" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".LocalServiceDemoActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="CountService" />
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>

在Activity中启动和关闭本地服务。
package com.easymorse;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class LocalServiceDemoActivity extends Activity {
/** Called when the activity is first created. */
@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了。

这是新建立的接口代码:

 
package com.easymorse;
public interface ICountService {
public abstract int getCount();
}

修改后的CountService代码:
package com.easymorse;
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++;
Log.v("CountService", "Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v("CountService", "on destroy");
}
/* (non-Javadoc)
* @see com.easymorse.ICountService#getCount()
*/
public int getCount() {
return count;
}
}
服务的注册也要做改动,AndroidManifest.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.easymorse" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".LocalServiceDemoActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="CountService">
<intent-filter>
<action android:name="com.easymorse.CountService"/>
</intent-filter>
</service>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>

Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。

package com.easymorse;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
public class LocalServiceDemoActivity extends Activity {
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
Log.v("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.easymorse.CountService"),
this.serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
this.unbindService(serviceConnection);
}
}
编写传递基本型数据的远程服务

上面的示例,可以扩展为,让其他应用程序复用该服务。这样的服务叫远程(remote)服务,实际上是进程间通信(RPC)。

这时需要使用android接口描述语言(AIDL)来定义远程服务的接口,而不是上述那样简单的java接口。扩展名为aidl而不是java。可用上面的ICountService改动而成ICountSerivde.aidl,eclipse会自动生成相关的java文件。

package com.easymorse;
interface ICountService {
int getCount();
}

编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。桩对象是远程对象的本地代理。

package com.easymorse;
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.v("CountService", "Count is " + count);
}
}
}).start();
}
@Override
public void onDestroy() {
super.onDestroy();
this.threadDisable = true;
Log.v("CountService", "on destroy");
}
}

配置文件AndroidManifest.xml和上面的类似,没有区别。

在Activity中使用服务的差别不大,只需要对ServiceConnection中的调用远程服务的方法时,要捕获异常。

private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
countService = (ICountService) service;
try {
Log.v("CountService", "on serivce connected, count is "
+ countService.getCount());
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
countService = null;
}
};
这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。

如果是另外的应用程序使用远程服务,需要做的是复制上面的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数据改为复杂数据类型:

package com.easymorse;
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;
}
}
然后,需要在相同包下建一个同名的aidl文件,用于android生成相应的辅助文件:
package com.easymorse;
parcelable CountBean;

这一步是android 1.5后的变化,无法通过adt生成aidl,也不能用一个比如全局的project.aidl文件,具体见:http://www.anddev.org/viewtopic.php?p=20991

然后,需要在服务的aidl文件中修改如下:

package com.easymorse;
import com.easymorse.CountBean;
interface ICountService {
CountBean getCount();
}
其他的改动很小,只需将CountService和调用CountService的部分修改为使用CountBean即可。
分享到:
评论

相关推荐

    android开发入门与实战(下)

    14.1.4 豆瓣网API快速入门 14.1.5 豆瓣网APIJava库介绍 14.2 豆瓣网(Web2.0)客户端设计 14.2.1 客户端功能规划设计 14.2.2 UI和交互流程设计 14.2.3 数据存储设计 14.3 豆瓣网(Web2.0)客户端实现 14.3.1 申请APIKey ...

    Android开发入门经典

    第一部份 Android的入门基础 第二部份 Android应用核心基础知识 第三部份 理解Activity 第四部份 用户界面 第五部份 Service 第六部份 BroadCast Receiver 第七部份 数据存储 第八部份 数据库操作

    android编写Service入门_本地和远程调用参照.pdf

    android编写Service入门_本地和远程调用参照.pdf

    Android从入门到精通(明日科技著)5、6章源代码

    内容包括Android快速入门、Android模拟器与常用命令、用户界面设计、高级用户界面设计、基本程序单元Activity、Android应用核心Intent、Android事件处理、资源访问、图形图像处理技术、多媒体应用开发、Content ...

    Android从入门到精通(明日科技著)第十五章源代码家庭理财通

    内容包括Android快速入门、Android模拟器与常用命令、用户界面设计、高级用户界面设计、基本程序单元Activity、Android应用核心Intent、Android事件处理、资源访问、图形图像处理技术、多媒体应用开发、Content ...

    《Google Android开发入门与实战》.pdf

    14.1.4 豆瓣网api快速入门 264 14.1.5 豆瓣网api java库介绍 265 14.2 豆瓣网(web 2.0)客户端设计 268 14.2.1 客户端功能规划设计 268 14.2.2 ui和交互流程设计 268 14.2.3 数据存储设计 270 14.3...

    android开发入门与实战(上)

    14.1.4 豆瓣网API快速入门 14.1.5 豆瓣网APIJava库介绍 14.2 豆瓣网(Web2.0)客户端设计 14.2.1 客户端功能规划设计 14.2.2 UI和交互流程设计 14.2.3 数据存储设计 14.3 豆瓣网(Web2.0)客户端实现 14.3.1 申请APIKey ...

    《Google Android开发入门与实战》

    第10章 一切为用户服务——Service应用实例 第12章 Android综合案例一——RSS阅读器实例 第14章 Android综合案例三——基于Android的豆瓣网(Web2.0)移动客户端开发 第15章 Android综合案例四——在线音乐播放器 第16...

    《ANDROID从入门到精通》PDF

    内容包括Android快速入门、Android模拟器与常用命令、用户界面设计、高级用户界面设计、基本程序单元Activity、Android应用核心Intent、Android事件处理、资源访问、图形图像处理技术、多媒体应用开发、Content ...

    Android从入门到精通(明日科技著)3、4章源代码

    内容包括Android快速入门、Android模拟器与常用命令、用户界面设计、高级用户界面设计、基本程序单元Activity、Android应用核心Intent、Android事件处理、资源访问、图形图像处理技术、多媒体应用开发、Content ...

    Android Studio从入门到实战.txt

    包含Android Studio入门及使用技巧,UI界面介绍,数据库存储,音乐播放,Service等组件的介绍和使用......

    android开发入门教程

    14.1.4 豆瓣网API快速入门 14.1.5 豆瓣网APIJava库介绍 14.2 豆瓣网(Web2.0)客户端设计 14.2.1 客户端功能规划设计 14.2.2 UI和交互流程设计 14.2.3 数据存储设计 14.3 豆瓣网(Web2.0)客户端实现 14.3.1 申请APIKey ...

    Google.Android开发入门与实战

     《Android开发入门与实战》内容上涵盖了用Android开发的大部分场景,从Android基础介绍、环境搭建、SDK介绍、Market使用,到应用剖析、组件介绍、实例演示等方面。从技术实现上,讲解了5个Android平台下的完整综合...

    Android入门到精通源代码.

    《Android从入门到精通》 第1章 初识Android 1.1 什么是Android 1.1.1 移动信息设备分类 1.1.2 Open Handset Alliance和 Android 1.2 Android简介 1.2.1 Andriod的历史 1.2.2 Andriod的未来 1.2.3 Andriod平台的技术...

    android编程 android编程入门 android开发 android软件

    2. Service元素 3 3. Broadcast receivers元素 3 4. Content providers元素 3 (一) 元素的激活 3 (二) 元素的去激活 4 (三) Manifest文件 4 (四) Intent 筛选 5 三、 Activity和Task 6 (一) Affinities和新Task 7 ...

    Android从入门到精通(明日科技著)第7章源代码

    内容包括Android快速入门、Android模拟器与常用命令、用户界面设计、高级用户界面设计、基本程序单元Activity、Android应用核心Intent、Android事件处理、资源访问、图形图像处理技术、多媒体应用开发、Content ...

    android初学者入门项目

    41、AIDL Service android中的跨进程调用 客户端,服务端见AidlService 42、BroadcastReceiver 接收广播消息 43、非UI线程中不能操作UI线程中的View测试 44、ImageSwitcher animation gesture实现可以滑动的跑马灯...

    android初学者入门教程ppt

    android初学者入门教程 ppt Android系统简介 建立Android开发环境 第一个Android应用 Android程序基础 Intent与Activity Activity生命周期 使用Service Content Provider

    Google Android开发入门与实战的代码

    Google Android开发入门与实战的代码 1章 掀起你的盖头来——初识Android. 1 1.1 认识Android 1 1.2 Android的背景 2 1.2.1 Android的历史 2 1.2.2 Android的发展 2 1.3 我的Android我做主 2 ...

    Android框架揭秘.pdf

    《Android框架揭秘》通过对Android系统源代码的分析,主要介绍Android框架的初始...《Android框架揭秘》不仅可以供具备一定开发经验的Android开发人员参考阅读,也可作为Android开发初学者的Android框架入门教材使用。

Global site tag (gtag.js) - Google Analytics