您的位置:首页 > 移动开发 > Android开发

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方法是必须实现的,虽然可以在该方法中无任何操作。

阅读以下示例:

/**
*
* 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();
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: