Android中的Service

本文详细介绍了Android Service的分类及其访问方式,包括本地Service与远程Service的区别,以及如何通过startService和bindService进行调用。同时,阐述了如何利用AIDL实现远程Service,包括服务端和服务客户端的实现步骤,以及如何在AndroidManifest.xml中注册Service。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        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();
		}
	}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值