首页 > 代码库 > Service和Activity之间的通信

Service和Activity之间的通信

Service的启动方式有两种,一种是通过start方式,一种是通过bind方式,通过start方式启动服务后,启动服务的组件和服务便没有多大联系了。所以为了能和Service通信,只能通过bind的方式。下面分几步介绍下:(demo里面的Service提供一个下载的功能,然后在Activity中决定何时开始下载,以及随时查看下载进度)

第一步:

在Service类中创建一个内部类继承自Binder(onBind方法返回IBinder接口,Binder类是IBinder接口的实现类)(看到这里还实现了一个接口,并实现了接口里的方法,还提供了一个额外的方法,这个额外的方法不希望Activity访问到,所以这里我们通过接口的方式):

//1.
	private class DownloadBinder extends Binder implements DownloadBinderImpl{

		@Override
		public void startDownload() {
			Log.i(TAG, "startDownload");
		}

		@Override
		public int getProgress() {
			Log.i(TAG, "getProgress");
			return 0;
		}
		
		
		public void Inner(){
			Log.i(TAG, "我不希望Activity使用我");
		}
		
	}
	
第二步:上面提到的接口:

package com.dystu.servicedemo;

public interface DownloadBinderImpl {

	public void startDownload();

	public int getProgress();

}

第三步:在Service的onBind()方法里面返回DownloadBinder实例:

@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "onBind");
		return new DownloadBinder();
	}

第四步:在Activity中绑定服务:

	public void bind(View view) {

		Intent intent = new Intent(this, MyService.class);

		bindService(intent, conn, BIND_AUTO_CREATE);
	}
第五步:创建ServiceConnection 匿名内部类,实现了onServiceConnected和onServiceDisconnected方法,这两个方法会在服务成功绑定和解除绑定的时候调用。

private class MyConn implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			dbi = (DownloadBinderImpl) service;
			Log.i(TAG, "成功绑定服务----onServiceConnected执行了");
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			Log.i(TAG, "解除绑定服务----onServiceDisconnected执行了");
		}

	}

第六步:

调用服务的方法:

public void call(View view) {

		if (dbi != null) {
			dbi.startDownload();
			dbi.getProgress();
		} else {
			Toast.makeText(this, "请先绑定服务", 0).show();
		}

	}

也可在onServiceConnected中执行。

实现的效果:

技术分享

点击bind:

技术分享


点击call:

技术分享


点击unbind:

技术分享



完整的代码:

接口:

package com.dystu.servicedemo;

public interface DownloadBinderImpl {

	public void startDownload();

	public int getProgress();

}

服务:

package com.dystu.servicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {

	private static final String TAG = "MyService";

	// 2.
	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "onBind");
		return new DownloadBinder();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		Log.i(TAG, "onUnbind");
		return super.onUnbind(intent);
	}

	@Override
	public void onCreate() {
		super.onCreate();
		Log.i(TAG, "onCreate");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(TAG, "onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.i(TAG, "onDestroy");
	}
	
	
	//1.
	private class DownloadBinder extends Binder implements DownloadBinderImpl{

		@Override
		public void startDownload() {
			Log.i(TAG, "startDownload");
		}

		@Override
		public int getProgress() {
			Log.i(TAG, "getProgress");
			return 0;
		}
		
		
		public void Inner(){
			Log.i(TAG, "我不希望Activity使用我");
		}
		
	}
	
	
}

主界面布局:

<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"
    tools:context="${relativePackage}.${activityClass}" >

    <Button
        android:id="@+id/btn1"
        android:onClick="bind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="bind" />
    
     <Button
         android:id="@+id/btn2"
         android:layout_below="@id/btn1"
        android:onClick="unbind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="unbind" />
     <Button
         android:layout_below="@id/btn2"
        android:onClick="call"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="call" />

</RelativeLayout>


MainActivity:

package com.dystu.servicedemo;

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;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

	public static final String TAG = "MainActivity";

	private MyConn conn;

	DownloadBinderImpl dbi;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		conn = new MyConn();
	}

	// 3.
	public void bind(View view) {

		Intent intent = new Intent(this, MyService.class);

		bindService(intent, conn, BIND_AUTO_CREATE);
	}

	public void unbind(View view) {
		unbindService(conn);
		dbi = null;
	}

	public void call(View view) {

		if (dbi != null) {
			dbi.startDownload();
			dbi.getProgress();
		} else {
			Toast.makeText(this, "请先绑定服务", 0).show();
		}

	}

	// 4.
	private class MyConn implements ServiceConnection {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			dbi = (DownloadBinderImpl) service;
			Log.i(TAG, "成功绑定服务----onServiceConnected执行了");
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			Log.i(TAG, "解除绑定服务----onServiceDisconnected执行了");
		}

	}

}


PS:

类ServiceConnection中的onServiceDisconnected()方法在正常情况下是不被调用的,它的调用时机是当Service服务被异外销毁时,例如内存的资源不足时这个方法才被自动调用。



Service和Activity之间的通信