Android中的Service
2014-12-23 17:04
316 查看
Android中的Service分为两类,一类是本地Service,一类是远程Service,访问方式也有两种,一种是startService,一种是bindService。
startService和bindService的生命周期不同,如下图所示:
LocalService要求实现android.app.Service,可按调用方式实现相关方法,如若用startService调用,则实现onCreate、onStartCommand和onDestroy,若用bindService调用,则实现onCreate、onBind、onUnbind和onDestroy方法,当然,无论用什么方法调用,onBind方法是必须实现的,虽然可以在该方法中无任何操作。
阅读以下示例:
Service定义后,需要在AndroidManifest.xml文件中注册:
接下来则是调用本地Service,在Activity中编写如下代码即可调用:
定义一个Intent,重点是此Intent需要指定Context和Service,Context为当前Activity即可。
定义后startService即可。
也可以bindService方式调用:
与startService大同小异,主要是需要实现conn,conn为:
startService和bindService一个典型的区别,是bindService可以直接在ServiceConnection中获取到Service接口,获取到后即可调用本地Service定义的一些方法执行操作。
远程Service需要借助AIDL实现,下文是引用网友对AIDL的描述:
在Android平台,每个应用程序App都运行在自己的进程空间。通常一个进程不能访问另一个进程的内存空间(一个应用不能访问另一个应用),如果想沟通,需要将对象分解成操作系统可以理解的基本单元,Android提供了AIDL来处理。
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity
与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"。
远程Service分为客户端与服务端,首先看服务端的实现。
第一步是在service包下定义一个aidl文件,后缀名为aidl,如“HelloService.aidl”,内容类似:
此代码内容乍一看,是一个Java的Interface,但其实它与Interface还是有较大区别:
1. Java基本类型如int、long、char、boolean,以及String、CharSequence、List、Map不需要import导入;
2. 其他复杂类型,即使与aidl文件在同一个包下,也必须使用import导入;
3. 不要使用public关键字。
其他区别暂未发布,不过在编写此文件时IDE应有提示。
重点需要注意的是,aidl文件必须位于你想存放Service的包下,例如我的包为com.geloin.baseopera.service,那就必须把HelloService.aidl放在com.geloin.baseopera.service下,你把它当成一个Java文件处理就好了。
该文件编写好后,在gen下会生成com.geloin.baseopera.service.HelloService.java文件,只要它不报错,别管它,反正你也编写不了。
这一步是定义Service接口,接下来需要定义Service实现,如下所示:
跟本地服务其实区别不大,主要在于内部类HelloServerImpl,该类继承aidl生成的HelloService.Stub,并具体实现sayHello方法。
定义实现后,需要在AndroidManifest.xml文件中定义Service:
至此,服务端服务定义完毕。
远程客户端需要调用此服务时,只需要将上文定义的HelloService.aidl复制到客户端即可,同样会在gen中生成HelloService.java。
客户端调用Service的方式与本地Service并无差别,也可以使用startService或bindService,如下所示:
ServiceConnection代码如下所示:
startService和bindService的生命周期不同,如下图所示:
LocalService要求实现android.app.Service,可按调用方式实现相关方法,如若用startService调用,则实现onCreate、onStartCommand和onDestroy,若用bindService调用,则实现onCreate、onBind、onUnbind和onDestroy方法,当然,无论用什么方法调用,onBind方法是必须实现的,虽然可以在该方法中无任何操作。
阅读以下示例:
/** * * Dec 22, 2014 7:18:37 PM * @Geloin * */ package com.geloin.baseopera.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /** * * Dec 22, 2014 7:18:37 PM * * @Geloin * */ public class SyncService extends Service { private IBinder binder; @Override public void onCreate() { super.onCreate(); Intent intent = new Intent(); intent.setAction("SyncService"); intent.putExtra("message", "同步成功!"); sendBroadcast(intent); Log.i("=================", "执行onCreate"); } @Override public IBinder onBind(Intent intent) { return binder; } public String sendMessage() { return "成功清空!"; } public class SyncBinder extends Binder { public SyncService getService() { return SyncService.this; } } }
Service定义后,需要在AndroidManifest.xml文件中注册:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.geloin.baseopera" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".activity.BooksActivity" 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=".service.SyncService" android:exported="false" > <intent-filter> <action android:name="SyncService" /> </intent-filter> </service> </application> </manifest>
接下来则是调用本地Service,在Activity中编写如下代码即可调用:
Intent syncIntent = new Intent(BooksActivity.this, SyncService.class); startService(syncIntent);
定义一个Intent,重点是此Intent需要指定Context和Service,Context为当前Activity即可。
定义后startService即可。
也可以bindService方式调用:
Intent intent = new Intent(BooksActivity.this, SyncService.class); bindService(intent, conn, BIND_AUTO_CREATE);
与startService大同小异,主要是需要实现conn,conn为:
ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "连接断开!"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { SyncService ss = ((SyncService.SyncBinder)service).getService(); String message = ss.sendMessage(); Toast.makeText(BooksActivity.this, message, Toast.LENGTH_LONG).show(); } };
startService和bindService一个典型的区别,是bindService可以直接在ServiceConnection中获取到Service接口,获取到后即可调用本地Service定义的一些方法执行操作。
远程Service需要借助AIDL实现,下文是引用网友对AIDL的描述:
在Android平台,每个应用程序App都运行在自己的进程空间。通常一个进程不能访问另一个进程的内存空间(一个应用不能访问另一个应用),如果想沟通,需要将对象分解成操作系统可以理解的基本单元,Android提供了AIDL来处理。
AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity
与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"。
远程Service分为客户端与服务端,首先看服务端的实现。
第一步是在service包下定义一个aidl文件,后缀名为aidl,如“HelloService.aidl”,内容类似:
package com.geloin.baseopera.service; interface HelloService { /** * 发送Hello给name */ String sayHello(String name); }
此代码内容乍一看,是一个Java的Interface,但其实它与Interface还是有较大区别:
1. Java基本类型如int、long、char、boolean,以及String、CharSequence、List、Map不需要import导入;
2. 其他复杂类型,即使与aidl文件在同一个包下,也必须使用import导入;
3. 不要使用public关键字。
其他区别暂未发布,不过在编写此文件时IDE应有提示。
重点需要注意的是,aidl文件必须位于你想存放Service的包下,例如我的包为com.geloin.baseopera.service,那就必须把HelloService.aidl放在com.geloin.baseopera.service下,你把它当成一个Java文件处理就好了。
该文件编写好后,在gen下会生成com.geloin.baseopera.service.HelloService.java文件,只要它不报错,别管它,反正你也编写不了。
这一步是定义Service接口,接下来需要定义Service实现,如下所示:
/** * * Dec 23, 2014 9:28:43 AM * @Geloin * */ package com.geloin.baseopera.service; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; /** * * Dec 23, 2014 9:28:43 AM * @Geloin * */ public class HelloServer extends Service { private class HelloServerImpl extends HelloService.Stub { @Override public String sayHello(String name) throws RemoteException { return "Hello " + name; } } @Override public IBinder onBind(Intent intent) { return new HelloServerImpl(); } }
跟本地服务其实区别不大,主要在于内部类HelloServerImpl,该类继承aidl生成的HelloService.Stub,并具体实现sayHello方法。
定义实现后,需要在AndroidManifest.xml文件中定义Service:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.geloin.baseopera" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="17" android:targetSdkVersion="21" /> <permission android:name="com.geloin.permission.SayHello" android:protectionLevel="normal" > </permission> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".activity.BooksActivity" 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=".service.HelloServer" android:permission="com.geloin.permission.SayHello" android:process=":remote" > <intent-filter> <action android:name="HelloServer" /> </intent-filter> </service> </application> </manifest>
至此,服务端服务定义完毕。
远程客户端需要调用此服务时,只需要将上文定义的HelloService.aidl复制到客户端即可,同样会在gen中生成HelloService.java。
客户端调用Service的方式与本地Service并无差别,也可以使用startService或bindService,如下所示:
Intent intent = new Intent(BooksActivity.this, HelloService.class); bindService(intent, sayHelloConn, BIND_AUTO_CREATE);
ServiceConnection代码如下所示:
ServiceConnection sayHelloConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "连接断开!"); } @Override public void onServiceConnected(ComponentName name, IBinder service) { HelloService hs = HelloService.Stub.asInterface(service); try { String message = hs.sayHello("张三"); new AlertDialog.Builder(BooksActivity.this) .setTitle("提示") .setMessage(message) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { unbindService(sayHelloConn); } }).show(); } catch (RemoteException e) { e.printStackTrace(); } } };
相关文章推荐
- android activity/service开机后自动运行 (转)
- Android XMPP Service (Google Talk) + Google Map == Follow Me
- communicate with service on android
- 系出名门Android(4) - 活动(Activity), 服务(Service), 广播(Broadcast), 广播接收器(BroadcastReceiver)
- Android service(转)
- 系出名门Android(4) - 活动(Activity), 服务(Service), 广播(Broadcast), 广播接收器(BroadcastReceiver)
- Jollen 的 Android 教学(9): 启动 Service - startService()
- Android中的BatteryService及相关组件
- Android Service Introduce
- android上怎样让一个Service开机自动启动
- [转]Jollen 的 Android 教學,#9: 啟動 Service - startService()
- Android中的BatteryService及相关组件
- communicate with service on android
- [转]Jollen 的 Android 教學,#10: 如何檢查 Service 是否已啟動?使用 Android 除錯器
- Android如何在Activity和Service之间传递数据
- Android Bind Service机制详解
- [转]Jollen 的 Android 教學,#8: 沒有 UI 的 Service
- Jollen 的 Android 教学(10): 如何检查 Service 是否已启动?使用 Android 除错器
- Android基础 : Android Service[转]
- Android基础 : Android Service[转]