zoukankan      html  css  js  c++  java
  • Android初级教程进程间的通信AIDL

    在介绍跨程序进程间通信AIDL前,先看一下本程序activity与某个服务是怎么绑定在一起进行交互的。

    需求:服务有两个方法。分别是播放音乐与停止播放音乐。该程序的活动要访问这两个方法,在activity中控制服务的这两个方法,通过点击按钮的方式实现停止与播放音乐。

    对同一个程序服务与活动交互的方式,先给出一张图片:


    给出代码(案例为模拟音乐播放器):

    一、定义一个服务类MusicService:

    package com.ydl.music;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    
    public class MusicService extends Service {
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		return new MusicController();// 把中间人对象返回给绑定服务方法。
    	}
    
    	class MusicController extends Binder implements MusicInterface {// 实现接口是为了让绑定的而活动仅仅调用相应的方法
    		// 比如本服务还有一个打麻将方法,不想被活动调用。则抽取接口指定访问的方法。
    		// 中间人里面有两个方法可以访问到本服务中的停止和播放方法
    		public void play() {
    			MusicService.this.play();
    		}
    
    		public void pause() {
    			MusicService.this.pause();
    		}
    
    		public void daMaJiang() {
    			System.out.println("陪领导打麻将");
    		}
    	}
    
    	// 本程序有两个方法
    	public void play() {
    		System.out.println("播放音乐");
    	}
    
    	public void pause() {
    		System.out.println("停止播放音乐");
    	}
    }
    

    二、抽取interface接口:

    package com.ydl.music;
    
    public interface MusicInterface {
    	void play();
    
    	void pause();
    }
    

    三、主活动界面:

    package com.ydl.music;
    
    import android.os.Bundle;
    import android.os.IBinder;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.view.Menu;
    import android.view.View;
    
    public class MainActivity extends Activity {
    	
    	MusicInterface mi;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		Intent intent = new Intent(this, MusicService.class);
    		//注意:这里需要混合调用
    		/**
    		 * 混合调用:既要调用startservice有需要bindService。因为只调用bindService服务与活动绑定在一起的,当用户返回键使得activity进入后台
    		 * 此时服务也会进入后台模式,很容易被杀死进程。从而没法播放音乐。
    		 */
    		startService(intent);
    		bindService(intent, new MusicServiceConn(), BIND_AUTO_CREATE);//第二个参数是一个服务连接对象,活动与服务的关联起着很重要的作用
    	}
    	
    	class MusicServiceConn implements ServiceConnection{//服务连接方法
    
    		@Override//与服务绑定的时候调用
    		public void onServiceConnected(ComponentName name, IBinder service) {
    			mi = (MusicInterface) service;
    			
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			// TODO Auto-generated method stub
    			
    		}
    		
    	}
    	
    	
    
    	public void start(View v) {
    		mi.play();
    	}
    
    	public void stop(View v) {
    		mi.pause();
    	}
    }
    

    四、去清单文件配置我们自定义的服务

    <service android:name="com.ydl.music.MusicService"></service>

    运行后可以实现活动调用服务的方法,实现音乐播放器的播放与暂停,同时及时在后台时,服务进程也很难被杀掉。(当然这里播放音乐的逻辑仅仅是打印一行log)


    好了。有了上边的基础,就来开始探讨AIDL通信了。

    还是给出一张图。大致看一下意思:


    场景:两个项目,01和02.其中01项目是一个服务类,有一些方法;02项目是一个activity类。02项目想去使用01项目服务中的方法,就需要跨进程进行通信。

    使用传统的bindservice()方法已经没办法,因此使用AIDL技术——


    AIDL技术使用步骤:(注意:此时必须隐式方式绑定服务)

    • Android interface definition language
    • 进程间通信
    • 把远程服务的方法抽取成一个单独的接口java文件
    • 把接口java文件的后缀名改成aidl
    • 在自动生成gen文件中的PublicBusiness.java文件中,有一个静态抽象类Stub,它已经继承了Binder类,实现了publicBusiness接口,这个抽象类就是新的中间人
    • 把aidl文件复制粘贴到06项目,粘贴的时候注意,aidl文件所在的包名必须跟05项目中aidl所在的包名一致。此时06项目中也拥有了与05一模一样的Stub类
    • 在06项目中,强转中间人对象时,直接使用Stub.asInterface()。它直接做了强制转
    一、定义远程服务程序:(这里模拟支付宝支付功能,远程服务定义名称为PayService,中间人类定义为小胖子PayPangzhi)

    1、把上边接口的文件修改后缀名为aidl

    改远程服务端的代码:

    package com.ydl.remoteservice;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    import com.ydl.remoteservice.PayInterface.Stub;
    
    public class PayService extends Service {
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		return new PayPangZhi();
    	}
    
    	class PayPangZhi extends Stub {//胖纸作为中间人,注意继承的是Stub类
    
    		@Override
    		public void pay() throws RemoteException {
    			PayService.this.pay();
    			
    		}
    	}
    
    	public void pay() {//虚假的支付功能,以log方式模拟
    		System.out.println("加测运行环境");
    		System.out.println("加密用户名和密码");
    		System.out.println("建立连接");
    		System.out.println("完成支付");
    	}
    
    }
    

    活动中的方法:

    package com.example.startpayservice;
    
    import com.ydl.remoteservice.PayInterface;
    import com.ydl.remoteservice.PayInterface.Stub;
    
    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;
    
    public class MainActivity extends Activity {
    	
    	PayInterface pi;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            Intent intent = new Intent();//隐式绑定服务
            intent.setAction("com.ydl.pangzhi");
            bindService(intent, new ServiceConnection() {//第二个链接对象采用匿名内部类方式
    			
    			@Override
    			public void onServiceDisconnected(ComponentName name) {
    				
    				
    			}
    			
    			@Override
    			public void onServiceConnected(ComponentName name, IBinder service) {
    				pi = Stub.asInterface(service);//这里自动做了强制类型转换
    				
    			}
    		}, BIND_AUTO_CREATE);
        }
        
        public void click(View v){
        	try {
    			pi.pay();
    		} catch (RemoteException e) {//请求远程服务支付异常
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
        }
        
    }
    

    清单文件中配置方式改为隐式:

    <service android:name="com.ydl.remoteservice.PayService">
                <intent-filter >
                    <action android:name="com.ydl.pangzhi"/>
                </intent-filter>
            </service>

    终于完成,本篇写了好久才完成~~~~(>_<)~~~~赶快留下您的而脚印吧!




  • 相关阅读:
    [转]Worksheet.Change Event (Excel)
    [转]EXCEL如何使用动态公式
    [转]用NPOI操作EXCEL--数据有效性
    [转]How to insert a row between two rows in an existing excel with HSSF (Apache POI)
    [转]Excel
    [转]asp.net解决高并发的方案.
    [转]ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调
    Programming ActionScript 3.0 for Flash
    页游 《大皇帝》
    [转]Flash ActionScript2.0面向对象游戏开发-推箱子
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299666.html
Copyright © 2011-2022 走看看