Service绑定模式

使用绑定的Service可以实现组件与Service的通信。

组件与被绑定的Service可以不归属于同一个应用程序,因此通过绑定Service可以实现进程间通信。

调用bindService(Intent service,ServiceConnectionconn,int flags)方法即可实现当前组件与Service的绑定。

参数说明

Intent service:配置被激活的Service组件,该Intent可以是显式的,也可以是隐式的;

ServiceConnection conn:当前组件与被激活的Service的连接对象,当成功的以绑定模式激活Service后,该

Service的onBlind()方法的返回值(非null)对象被回传到当前组件,即当前组件与被激活的Service存在相同的IBinder对象;

关于Service的onBind()方法

在绑定Service时,定义的Service类中,onBind()方法应该返回一个非null的值。

onBind()方法的返回值类型是IBinder类型,IBinder是接口,开发人员可以自己定义类实现该接口

Google官方并不推荐开发人员直接定义类实现IBinder接口,而是通过继承Binder类即可,Binder类是

IBinder接口的实现类

如果onBind()方法的返回值是null,则该绑定过程是失败的,尽管Service也会执行onCreate()方法开始工作,

但其他的组件无法与Service通信。

实现Activity绑定Service的开发步骤如下:

创建Activity类继承android.app.Service类,并在AndroidMainfest.xml中注册该Service;

在自定义的Service类中创建IBinder的对象,作为onBind()方法的返回值;

在Activity中创建ServiceConnection的对象;

在Activity中调用bindService()方法实现与Service的绑定;

重写Activity的onDestroy()方法,调用unbindService()方法取消与Service的绑定,以避免

当Activity被销毁时绑定仍然存在而导致的异常。

取消绑定

当与Service绑定的组件被销毁时,应该及时取消与Service的绑定,否则会导致异常。

在组件中,调用unbindService(ServiceConnection conn)方法则可以取消与Service的绑定。

Service的生命周期

ServiceConnection的onServiceDisconnected()方法并不会随着组件取消与Service的绑定而

回调,该方法仅在Service在意外情况下崩溃时被调用。

一般情况下,onRebind()方法并不会被回调,被回调的情景通常为:

与该Service的所有组件都已经取消与它的绑定,导致该Service的onUnbind()方法被回调,

且重写了onUnbind()方法返回值为true;

该Service没有被销毁且再次被绑定时,则被回调onRebind()方法;

注意:以绑定模式激活的Service租价那并不是粘性的,且与Service绑定的组件在退出之前必须取消绑定

,即无法保证Service依然存在,所以,为了保证其它组件可以销毁,但Service依然存在,可以:

1、先调用startService()激活Service组件;

2、再调用bindService()实现绑定。

实现Activity与Service的通信

已知:在Service中,onBind()方法的返回值可以被Activity获得,即Activity与Service共有一个IBinder类型的对象;

结论:开发人员可以在Service中自定义IBinder的实现类,并在该类中定义若干个方法,当Activity获得该实现类

的对象时,即可调用这些方法。

矛盾:IBinder的实现类的相关业务可能与Activity发送的Intent、service的生命周期等存在密切关系,

使用Service的内部类则无法让Activity知晓该实现类的数据库类型。

解决方法:使用接口定义Activity需要让Service完成的方法。

绑定Service时,接口的作用为:

约定一种数据类型,让组件与Service均可使用这种类型的数据;

约定组件与Service通信的标准,以使得组件可以调用相关的方法;

绑定Service的音乐播放器

在Activity中添加2个按钮,分别表示“播放”与“暂停”;

歌曲的播放与暂停功能由Service实现;

关于MediaPlayer暂停

通过MediaPlayer的isPlaying()方法的布尔类型返回值可知晓是否正在播放(如果没有在播放,则不许需要暂停);

通过MediaPlayer的getCurrentPositon()方法可知晓当前的播放进度;

通过MediaPlayer的seekTo()方法可快进到指定位置在播放。

案例:

布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     >

    <ImageButton
        android:id="@+id/pause"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/play"
        android:layout_marginLeft="58dp"
        android:onClick="pause"
        android:layout_toRightOf="@+id/play"
        android:src="@android:drawable/ic_media_pause" />

    <ImageButton
        android:id="@+id/play"
        android:onClick="play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="61dp"
        android:layout_marginTop="68dp"
        android:src="@android:drawable/ic_media_play" />

</RelativeLayout>

MainActivity,

package com.example.music_service;

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.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends Activity {
	private ServiceConnection conn;
	private Player player;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		conn = new InnerServiceConnection();
		int flags = BIND_AUTO_CREATE;
		Intent service = new Intent(this,PlayService.class);
		bindService(service, conn, flags);
	}
	public void pause(View view){
		player.playMusic();
	}
	public void play(View view){
		player.pauseMusic();
	}
	private class InnerServiceConnection implements ServiceConnection{

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			player = (Player) service;
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub

		}

	}
	protected void onDestroy(){
		unbindService(conn);
		super.onDestroy();
	}

}

Service:

package com.example.music_service;

import java.io.IOException;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;

public class PlayService extends Service{
    private MediaPlayer player;
    private int Current;
    @Override
    public void onCreate() {
    	// TODO Auto-generated method stub
    	player = new MediaPlayer();
    	player.setOnPreparedListener(new InnerPreparedListener());
        player.setOnCompletionListener(new InnerCompletionListener());
    }
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return new InnerBinder();
	}
	public class InnerBinder extends Binder implements Player{

		@Override
		public void playMusic() {
			// TODO Auto-generated method stub
			play();
		}

		@Override
		public void pauseMusic() {
			pause();
			// TODO Auto-generated method stub
		}

	}
	private void play(){

		try {
			 player.reset();
			 player.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Music/Groove Coverage - She.mp3");
			 player.prepareAsync();
//			 player.start();
		} catch (IllegalArgumentException e) {
			// TODO: handle exception
			e.printStackTrace();
		}catch(SecurityException e){
			e.printStackTrace();
		}
        catch(IllegalStateException  e){
			e.printStackTrace();
		}
        catch(IOException  e){
				e.printStackTrace();
			}
	}
	private void pause(){
		if(player.isPlaying()){
			Current = player.getCurrentPosition();
			player.pause();
		}
	}

	private class InnerPreparedListener implements MediaPlayer.OnPreparedListener{

		@Override
		public void onPrepared(MediaPlayer mp) {
			// TODO Auto-generated method stub
			mp.seekTo(Current);
			mp.start();
			Current = 0;
		}

	}
	private class InnerCompletionListener implements MediaPlayer.OnCompletionListener{

		@Override
		public void onCompletion(MediaPlayer mp) {
			// TODO Auto-generated method stub
			play();
		}

	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		player.release();
		player = null;
		super.onDestroy();
	}

}

接口:

package com.example.music_service;

public interface Player {
       void playMusic();
       void pauseMusic();
}

OK,对了,service不要忘了在AndroidMainfest.xml中配置一下

时间: 2024-10-27 09:15:43

Service绑定模式的相关文章

绑定模式下ifcfg-eth0的配置

场景描述:今天整一个下午都是在部署CentOS绑定模式,我不知道为什么开发者非得要同学们手动加载绑定驱动或者桥接驱动,这是一个坑啊!!当然,开源的卫士们辛苦啦!!献上我最真挚的祝福,好人一生平安.本身配置不是很复杂,我已经编写网络配置的脚本,但是在合并代码的过程中,发现绑定模式无法启动,以下是详细报道. 环境描述:CentOS绑定模式ifcfg-bond0 配置如下: DEVICE=bond0 TYPE=bonding IPADDR=12.12.12.12 GATEWAY=12.12.12.1

Android -- Service绑定解绑和aidl

Service是安卓四大组件之一,先前讲到了Service的生命周期,以及非绑定类型的生命周期的例子,这次来分享一下绑定形式的. 应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder. 绑定是异步的,bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传给b

android 将Service绑定到Activity

Service可以和Activity绑定,后者会维持对Service实例的引用,此引用允许你像对待其他实例化的那样,对正在运行的Service进行方法调用. 允许Service和Activity绑定,这样能够获得更加详细的接口.要让一个Service支持绑定,需要实现onBind方法,并返回被绑定Service的当前实例. package com.example.androidtest.service; import android.app.Service; import android.con

Service Locator 模式

什么是Service Locator 模式? 服务定位模式(Service Locator Pattern)是一种软件开发中的设计模式,通过应用强大的抽象层,可对涉及尝试获取一个服务的过程进行封装.该模式使用一个称为"Service Locator"的中心注册表来处理请求并返回处理特定任务所需的必要信息. 场景描述 某类ClassA依赖于服务ServiceA和服务ServiceB,服务的具体类型需在编译时指定. 这种条件下有以下缺点: 尝试替换或更新依赖项,必须更改类的源代码并且重新编

cxGrid 增加序号 (非数据库绑定模式) (测试通过)

cxGrid 增加序号 (非数据库绑定模式) ----------------------------------- 1. 选在 adoQuery 控件 , 鼠标右键菜单中 选择 Fields Editor 2. 在  adoQuery 控件 Fields Editor 中 鼠标右键菜单  (1)  Add all fields (2)  New field  --->  Name ==>     curRowNo                         Type    ==>

Activity和Service绑定

Activity和Service绑定后,可以方便Activity随时调用对应的Service里面的方法 绑定代码如下 Activity类代码: [java] view plaincopy <span style="font-size:16px;">package com.fox.Activity; import com.fox.Activity.service.Service1; import android.app.Activity; import android.con

七种网卡绑定模式详解

概览: 目前网卡绑定mode共有七种(0~6)bond0.bond1.bond2.bond3.bond4.bond5.bond6 常用的有三种: mode=0:平衡负载模式,有自动备援,但需要"Switch"支援及设定. mode=1:自动备援模式,其中一条线若断线,其他线路将会自动备援. mode=6:平衡负载模式,有自动备援,不必"Switch"支援及设定. 说明: 需要说明的是如果想做成mode 0的负载均衡,仅仅设置这里optionsbond0 miimon

Linux中bond的七种网卡绑定模式详解

概览: 目前网卡绑定mode共有七种(0~6)bond0.bond1.bond2.bond3.bond4.bond5.bond6 常用的有三种: mode=0:平衡负载模式,有自动备援,但需要”Switch”支援及设定. mode=1:自动备援模式,其中一条线若断线,其他线路将会自动备援. mode=6:平衡负载模式,有自动备援,不必”Switch”支援及设定. 说明: 需要说明的是如果想做成mode 0的负载均衡,仅仅设置这里optionsbond0 miimon=100 mode=0是不够的

bond绑定模式与操作(centos7)

一.简介 二.模式 注*建议学之前先看这个文章 http://blog.csdn.net/galdys/article/details/7506495 1.balance-rr 轮转策略:按照顺序轮流使用每个接口来发送和接收数据包,提高了负载均衡的能力,但是需要交换机的支持,因为该模式所有端口的mac地址相同,交换机不能识别多个一个Mac地址对应多个端口,所以需要做链路聚合 ----Ethernet Channel mode=0 2.active-backup 主备策略:只使用其中一个网卡,当网