【远程Service】AIDL进程间通信实例

本文介绍如何使用AIDL实现Android应用程序间的远程Service通信。包括创建远程Service的步骤和客户端如何绑定及调用Service的方法。

对于Service的定义及使用场合等请详见官方定义:http://developer.android.com/guide/components/services.html

Service有两种类型:

1. 本地服务(Local Service):用于应用程序内部

2. 远程服务(Remote Service):用于android系统内部的应用程序之间

本文讲解远程Service服务的使用。

 远程Service通常用于Android内部应用程序之间通信,既然是两个应用程序,所以可以将其理解为一个是服务器提供Service服务,一个是客户端使用Service服务。通常远程Service使用AIDL(Android Interface Define Language)接口定义语言进行进程间通信。

下面编写服务器Service应用的实例代码(三步即可完成):

1)创建一个应用之后,新建一个接口文件,后缀*.adil结尾。如图:

       

文件中的使用Java语言编写一个接口:

package com.example.aidl;
interface CountInterface {
 int getCount();
 //可以继续定义更多方法提供给客户端使用
}

该文件定义好之后,系统会自动生成其对应的*.java 文件。如图:



2)创建一个服务器端提供的Service服务类,继承Service。实例代码如下:

package com.example.a_bindservice_a;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.example.aidl.CountInterface;
import com.example.aidl.CountInterface.Stub;

public class MyBindService extends Service {
	Thread t;
	int i = 0;
	/**
	 * 创建一个CountInterface.Stub类型的binder,binder将返回给客户端作为客户端的代理,从而可以调用当前服务的方<span style="white-space:pre">	</span> *法。
	 * Stub是CountInterface接口的一个静态内部类
	 * */
	CountInterface.Stub binder = new Stub() {
		@Override
		public int getCount() throws RemoteException {
			return i;//在这里实现CountInterface计数的方法
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		// 如果使用远程Service 必须返回一个binder对象。
		return binder;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		System.out.println("bind Oncreate");
		// 通过启动线程在Service中实现一个计数的功能。
		t = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println("Thread run");
				while (true) {
					i++;
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});
		t.start();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public void onDestroy() {
		System.out.println("onDestroy");
		t.interrupt();// 当远程调用unbindService()方法时,当前Service一起被销毁,同时终止子线程。
		super.onDestroy();
	}

	@Override
	public boolean onUnbind(Intent intent) {
		System.out.println("onUnbind");
		return super.onUnbind(intent);
	}
}
需要注意的是:远程Service的onBind()方法中必须返回一个binder对象。binder对象使用CountInterface的内部类Stub 创建。

3)在AndroidManifest.xml文件中注册当前Service并添加Action(不然其他应用找不到这个Service)

注册代码如下:

 <service android:name="MyBindService">
            <intent-filter >
                <action android:name="com.example.a_bindservice_a.MyBindService"/>
            </intent-filter>
        </service>




下面创建客户端使用Service服务的实例代码(两步即可完成):
1)首先将服务器Service创建的接口文件连同报名一同拷贝到客户端应用中。如图:

2)编写客户端使用远程Service的实例代码:

package com.example.a_bindservice_b;

import com.example.aidl.CountInterface;

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.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

/**
 * 远程服务在客户端:首先将服务器端的AIDL包及文件拷贝到当前项目中。
 * 在客户端创建AIDL接口类型的引用对象cInterface,用来作为服务器再本地的代理。
 * 在本地创建ServiceConnection类型的对象sConnection,
 * 并且重写onServiceConnected和onServiceDisconnected两个方法。
 * onServiceConnected方法会在bindService时被回调。
 * 在onServiceConnected方法里面对AIDL接口对象赋值,cInterface =
 * CountInterface.Stub.asInterface(binder);。 在unbindService时清空cInterface对象的引用。
 * bindService(intent, sConnection, BIND_AUTO_CREATE);
 * unbindService(sConnection); Intent对象通过new Intent("Action")方法创建。
 * sConnection对象就是ServiceConnection的对象。
 * 
 * */
public class MainActivity extends Activity implements OnClickListener {
	Intent intent; //通过Intent找到服务器端的Service 
	CountInterface cInterface; // 创建一个接口对象,实现本地代理?
	private Button bind;//绑定Service的按钮
	private Button unbind;//解绑的按钮
	private Button getNum;//调用远程Service中接口方法的按钮

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		intent = new Intent("com.example.a_bindservice_a.MyBindService");
		bind = (Button) findViewById(R.id.btnbind);
		unbind = (Button) findViewById(R.id.btnUnbind);
		getNum = (Button) findViewById(R.id.btngetCount);
		getNum.setOnClickListener(this);
		bind.setOnClickListener(this);
		unbind.setOnClickListener(this);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (cInterface != null) {
			unbindService(sConnection);
			cInterface = null;
		}
	};

	ServiceConnection sConnection = new ServiceConnection() {

		/**
		 * onServiceDisconnected() 在连接正常关闭的情况下是不会被调用的, 该方法只在Service
		 * 被破坏了或者被杀死的时候调用. 例如, 系统资源不足, 要关闭一些Services, 刚好连接绑定的 Service 是<span style="white-space:pre">		</span> *被关闭者之一,
		 * 这个时候onServiceDisconnected() 就会被调用。
		 * */
		@Override
		public void onServiceDisconnected(ComponentName name) {
			System.out.println("onServiceDisconnected");
			cInterface = null;
		}
		
		/**
		 * 在调用bindService方法时会回调此方法。
		 * 远程Service在onBind()方法必须返回一个binder对象,否则当前方法不会被调用。
		 * */
		@Override
		public void onServiceConnected(ComponentName name, IBinder binder) {
			System.out.println("onServiceConnected");
			// 通过asInterface()方法获得接口CountInterface对象的引用实例。binder就是服务器Service返回的<span style="white-space:pre">			</span>//binder对象。
			cInterface = CountInterface.Stub.asInterface(binder);
		}
	};

	// 为按钮添加监听
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btnbind:
			bindService(intent, sConnection, BIND_AUTO_CREATE);
			break;
		case R.id.btnUnbind:
			if (cInterface != null) {
				unbindService(sConnection);
				cInterface = null;
			}
			break;
		case R.id.btngetCount:
			try {
				if (cInterface != null) {
					int i =cInterface.getCount();// 通过cInterface对象调用应用A的getCount()方法
					System.out.println("--------------->" + i);
				}
			} catch (RemoteException e) {
				System.out.println("RemoteException");
				e.printStackTrace();
			}
			break;

		default:
			break;
		}
	}
}

需要注意的是:1.客户端使用服务器Service的接口方法时通过CountInterface接口的变量cInterface来实现的。

  2.客户端在bindService时需要使用ServiceConnection类型的变量,创建sConnection变量时使用匿名     内部类,并实现其中的两个方法。


到此运行程序。然后就可以在客户端程序B中使用服务器A中定义的接口方法了。

真正纯自己写的第一个Blog,参考了许多其他大神的博客。如有错误,欢迎探讨~~好开森~大笑大笑




下载前可以先看下教程 https://pan.quark.cn/s/a426667488ae 标题“仿淘宝jquery图片左右切换带数字”揭示了这是一个关于运用jQuery技术完成的图片轮播机制,其特色在于具备淘宝在线平台普遍存在的图片切换表现,并且在整个切换环节中会展示当前图片的序列号。 此类功能一般应用于电子商务平台的产品呈现环节,使用户可以便捷地查看多张商品的照片。 说明中的“NULL”表示未提供进一步的信息,但我们可以借助标题来揣摩若干核心的技术要点。 在构建此类功能时,开发者通常会借助以下技术手段:1. **jQuery库**:jQuery是一个应用广泛的JavaScript框架,它简化了HTML文档的遍历、事件管理、动画效果以及Ajax通信。 在此项目中,jQuery将负责处理用户的点击动作(实现左右切换),并且制造流畅的过渡效果。 2. **图片轮播扩展工具**:开发者或许会采用现成的jQuery扩展,例如Slick、Bootstrap Carousel或个性化的轮播函数,以达成图片切换的功能。 这些扩展能够辅助迅速构建功能完善的轮播模块。 3. **即时数字呈现**:展示当前图片的序列号,这需要通过JavaScript或jQuery来追踪并调整。 每当图片切换时,相应的数字也会同步更新。 4. **CSS美化**:为了达成淘宝图片切换的视觉效果,可能需要设计特定的CSS样式,涵盖图片的排列方式、过渡效果、点状指示器等。 CSS3的动画和过渡特性(如`transition`和`animation`)在此过程中扮演关键角色。 5. **事件监测**:运用jQuery的`.on()`方法来监测用户的操作,比如点击左右控制按钮或自动按时间间隔切换。 根据用户的交互,触发相应的函数来执行...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值