- 浏览: 352281 次
- 性别:
- 来自: 北京
最新评论
-
sxchao2008:
心雨心 写道你说的不好用是?你好,在静默卸载系统级别app的时 ...
静默卸载系统软件和第三方软件 -
zhao1111:
请问楼主哪里提供地震的xml文件啊
android解析xml文件 Android DOM解析XML之全球实时地震信息列表 -
yuanmouren1hao:
java字节流(读写文件) -
haiyangzhy:
很好。
ScrollView中嵌入ListView办法 -
gisdaniel:
[/url][url][fla ...
Android中的XML解析-DOM的使用与开发技巧
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的一些限制和规定:
- android支持String和CharSequence
- 如果需要在aidl中使用其他aidl接口类型,需要import,即使是在相同包结构下;
- android允许传递实现Parcelable接口的类,需要import;
- android支持集合接口类型List和Map,但是有一些限制,元素必须是基本型或者上述三种情况,不需要import集合接口类,但是需要对元素涉及到的类型import;
- 非基本数据类型,也不是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文件中修改如下:
其他的改动很小,只需将CountService和调用CountService的部分修改为使用CountBean即可。package com.easymorse; import com.easymorse.CountBean; interface ICountService { CountBean getCount(); }
原文出自:http://marshal.easymorse.com/archives/1564
评论
"编写传递复杂数据类型的远程服务"这部分可以写的更详细些么?!
CountService.java具体应该怎么修改?
int count;
需要修改为CountBean count;么?
count++;需要修改么?
发表评论
-
查看Android应用包名package和入口activity名称
2014-08-05 16:20 2189使用android自动化测试工具monkeyrunner启动 ... -
设置默认应用
2014-05-15 11:46 1729setDefaultLauncher(); ... -
Android之APK文件签名——keytool和jarsigner
2012-10-10 14:06 1867一、生成密钥库将位置定位在jdk的bin文件中,输入以下命名行 ... -
Android中应用程序如何获得系统签名权限
2012-08-21 14:18 0有些库的使用条件比较苛刻,要求同一签名的程序才可以获得访问权。 ... -
Android中应用程序如何获得系统签名权限
2012-08-21 14:18 0有些库的使用条件比较苛刻,要求同一签名的程序才可以获得访问权。 ... -
Android权限共享UID和签名(转)
2012-08-21 14:17 1768共享UID 安装在设备中的每一个Android包文件(.ap ... -
android小结
2012-04-17 10:21 16361.获取屏幕的分辨率 在 Activity 里使 ... -
TextView实现电话、网址链接
2012-03-22 17:39 1655TextView是android中一个组件,具有autolin ... -
Android Eclipse JNI 调用 .so文件加载
2012-03-01 18:41 5975http://blog.sina.com.cn/s/blo ... -
Gallery加小点效果实现
2012-02-15 16:15 1696大家好: 心雨心今天又跟大家见面了 今天发布的是Gal ... -
如何解决:Android中 Error generating final archive: Debug Certificate expired on 10/09
2011-12-21 13:39 1626问题概述: 在导入一个app后提示如下错误(出现该问题, ... -
Android Google Map API 开发基础知识
2011-12-16 17:25 1779开发基于谷歌地图的应用和普通的android应用差不多都要 ... -
使一段字符串显示不同的颜色
2011-12-12 15:09 2679一种:字体颜色改变 String appna ... -
droid系统中使用TelephonyManager类来获取imei号和其他手机信息
2011-11-22 11:15 14831在AndroidManifest.xml文件中增加& ... -
CategoryAdapter控件
2011-11-17 10:50 1554使用方法: private Cate ... -
(转)Android开发:在EditText中关闭软键盘
2011-11-04 13:45 151851、EditText有焦点(focusable为true)阻止 ... -
获取未安装的APK图标
2011-09-01 10:38 1440网上关于"获取未安装的APK图 ... -
android ListView的美化涉及到的一些属性
2011-08-26 10:44 2376用心的朋友应该会发现,listview中在设置了背景之后。会有 ... -
ScrollView中嵌入ListView办法
2011-08-11 17:13 2276①layout布局代码: <ScrollView an ... -
android 混淆 去除第三方jar
2011-06-10 19:05 12521编译与反编译,一对相辅相成的 ...
相关推荐
android编写Service入门_本地和远程调用参照.pdf
Android应用开发入门教程(经典版)&android;快速入门 Android应用开发入门教程(经典版)&android;快速入门
作为Android Studiod 的入门级教程 能对安卓的开发工具有一个初识
AndroidAPP开发入门教程.pdf
里面包括了《Java语言基础从入门到熟悉》、《Kotlin语言基础从入门到熟悉》、《Android 技术栈从入门到熟悉》、《Android Jetpack 全家桶全面学习》
【android开发】Android APP开发入门教程Android APP开发入门教程 说明:Android APP开发入门教程Android APP开发入门教程 (Android APP Development tutorialAndroid APP Development tutorial) 文件列表: Android ...
android基础教程,里边包括新版Android开发教程&笔记1--基础入门,Android开发教程&笔记2--基础入门二,Android开发教程&笔记3--环境搭建与解析,Android开发教程&笔记4--Dalvik ADB Android开发教程+笔记5--模拟器...
Android APP开发入门教程,从SDK下载、开发环境搭建、代码编写、APP打包等步骤
Android基础入门教程,网上教程,打包成chm,看得时候方便一些 教程于2015年7月开始撰写,耗时半年,总共148节,涵盖了Android基础入门的大部分知识。
Android开发入门实战教程
Android平台Qt开发入门教程.pdf
android初学者入门教程 ppt Android系统简介 建立Android开发环境 第一个Android应用 Android程序基础 Intent与Activity Activity生命周期 使用Service Content Provider
android 及 linux 入门 视频教程2 android 及 linux 入门 视频教程2android 及 linux 入门 视频教程2android 及 linux 入门 视频教程2android 及 linux 入门 视频教程2
Android ORMLite框架入门用法教程二(两张表关联外键)实例Demo,详情请看博客教程
Android 教程 入门 ,是我总结的欢迎大家下载学习。
Android渗透测试入门教程
android,启动service,并且service把值传给Activity显示
Android快速入门教程Android快速入门教程Android快速入门教程Android快速入门教程Android快速入门教程Android快速入门教程
Android编程入门教程andbook与Android开发教程笔记完全版打包发送~~
Android从入门到精通+经典教程