zoukankan      html  css  js  c++  java
  • 安卓中AIDL的使用方法快速入门

    1.AIDL是什么?

    AIDL全称是Android Interface Definition Language,即安卓接口定义语言。

    2.AIDL是用来做什么的?(为什么要有AIDL)

    AIDL是用来进行进程间通信(IPC全称interprocess communication )的。

    3.如何使用AIDL?

    对于AIDL的使用,

    服务端需要完成的任务是:

    ①.写一个xxxx.aidl文件

    ②.写一个Service并在AndroidManifest.xml中声明它。(注意:这个service里面有一个引用了实现xxxx.Stub抽象类的IBinder对象,这个对象将在service的onBind方法里面返回给调用者)

    客户端的任务:

    ①.使用和服务端相同的那个aidl文件

    ②.在实现了ServiceConnection接口的onServiceConnected(ComponentName name, IBinder service)方法中调用myvar = testidl.Stub.asInterface(service)保存得到的对象,其中myvar是xxxx的类型

    这么说还是不够清楚,下面直接上代码。

    首先是服务端的

    //testidl.idl文件的内容
    package com.example.xxnote;
    
    interface testidl {
    	void TestFunction(int anInt, long aLong, boolean aBoolean, float aFloat,
                double aDouble, String aString);
    }
    

     

    //myaidlservice.java文件的内容
    package com.example.xxnote;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class myaidlservice extends Service {
    
    	private final IBinder myStub = new testidl.Stub() {
    
    		@Override
    		public void TestFunction(int anInt, long aLong, boolean aBoolean,
    				float aFloat, double aDouble, String aString)
    				throws RemoteException {
    			// TODO Auto-generated method stub
    			System.out.println("basicTypes()");
    			System.err.println("Service"+anInt + "," + aLong + "," + aBoolean + ","
    					+ aFloat + "," + aDouble + "," + aString);
    		}
    	};
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		// TODO Auto-generated method stub
    		System.out.println("AIDL Service  onBind, and return IBinder");
    		return myStub;
    	}
    
    	@Override
    	public void onCreate() {
    		// TODO Auto-generated method stub
    		System.out.println("AIDL Service onCreate");
    		super.onCreate();
    	}
    
    	@Override
    	public boolean onUnbind(Intent intent) {
    		// TODO Auto-generated method stub
    		System.out.println("AIDL Service onUnbind");
    		return super.onUnbind(intent);
    	}
    
    	@Override
    	public void onDestroy() {
    		// TODO Auto-generated method stub
    		System.out.println("AIDL Service onDestroy");
    		super.onDestroy();
    	}
    
    	@Override
    	public int onStartCommand(Intent intent, int flags, int startId) {
    		// TODO Auto-generated method stub
    		System.out.println("AIDL Service onStartCommand");
    		return super.onStartCommand(intent, flags, startId);
    	}
    }
    

     

    1 <!--  AndroidManifest.xml 的 application 标签的内容-->
    2 <service android:name="myaidlservice">
    3             <intent-filter >
    4                 <action android:name="zhenshi.mafan.qisia.aidl"/>
    5             </intent-filter>
    6  </service>

     对于客户端,首先需要把aidl文件复制到相应的目录本例中是src/com/example/xxnote/testidl.aidl

    package com.example.xxnote.callaidl;
    
    import com.example.xxnote.testidl;
    
    import android.R.bool;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    public class MainActivity extends Activity {
    
    	private testidl mytTestidl;
    	private ServiceConnection connection;
    	private boolean isServiceConnected;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		connection = new ServiceConnection() {
    			
    
    			@Override
    			public void onServiceDisconnected(ComponentName name) {
    				// TODO Auto-generated method stub
    				System.out.println("Client onServiceDisconnected");
    			}
    			
    			@Override
    			public void onServiceConnected(ComponentName name, IBinder service) {
    				// TODO Auto-generated method stub
    				System.out.println("Client onServiceConnected");
    				mytTestidl = testidl.Stub.asInterface(service);
    				isServiceConnected = true;
    			}
    		};
    	}
    
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		// Inflate the menu; this adds items to the action bar if it is present.
    		getMenuInflater().inflate(R.menu.main, menu);
    		return true;
    	}
    
    	
    	@Override
    	public boolean onOptionsItemSelected(MenuItem item) {
    		// Handle action bar item clicks here. The action bar will
    		// automatically handle clicks on the Home/Up button, so long
    		// as you specify a parent activity in AndroidManifest.xml.
    		int id = item.getItemId();
    		if (id == R.id.action_settings) {
    			return true;
    		}
    		return super.onOptionsItemSelected(item);
    	}
         
            //关闭服务按钮的事件
    	public void StopMyService(View v) {
    		System.out.println("StopMyService");
    		isServiceConnected = false;
    		unbindService(connection);
    		mytTestidl = null;
    	}
         //开启服务按钮的事件
    	public void StartMyService(View v) {
    		System.out.println("before bindService()");
    		bindService(
    				new Intent().setAction("zhenshi.mafan.qisia.aidl"), 
    				connection,
    				Context.BIND_AUTO_CREATE);
    		/**
    		 * bindService是异步的所以执行bindService方法的同时也开始执行下面的方法了,
    		 * Debug跟踪了一下程序发现貌似Activity里面所有的方法都是在主线程的loop()方法
    		 * 循环里面以消息队列里面的一个消息的样子执行的,也就是此处的StartMyService方
    		 * 法对应的消息处理完(此函数返回)后,才能处理下一个消息,即执行onServiceConnected回调方法
    		 * 
    		 * 试验了一下,StopMyService里面把mytTestidl赋值为null,即每次解除服务绑定后都重置mytTestidl为null
    		 * 果然每次下面的语句:
    		 * mytTestidl.basicTypes(1, 1, true, 100.0f, 200.0, "ssss");
    		 * 都报空指针异常
    		 */
    		
    		try {
    			mytTestidl.TestFunction(1, 1, true, 100.0f, 200.0, "ssss");
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    

      

    这里还有一个需要注意的地方,就是bindService方法 的时候用到的intent,通过setAction可以成功启动服务,用setClassName就不能,不知道什么原因,暂时留待以后解决。

    找到原因了,用setClassName的时候必须使用全限定类名,如:new Intent().setClassName("com.example.client.callaidl", "com.example.client.callaidl.testact")

     

     

  • 相关阅读:
    [2020.8.3]联想 ZUK Z2 Pro(Z2121) Magisk ROOT 纯净无推广 一键刷机 ZUI_4.0.247
    [2020.8.3]联想 K5 Note(L38012) Magisk ROOT 纯净无推广 一键刷机 ZUI_3.9.218
    [2020.8.3]联想 A5(L18011) Magisk ROOT 纯净无推广 一键刷机 ZUI_3.9.068
    [2020.8.3]联想 ZUK Edge(Z2151) Magisk ROOT 纯净无推广 一键刷机 ZUI_4.0.282
    [2020.8.3]Moto P30(XT1943-1) Magisk ROOT 纯净无推广 一键刷机 ZUI_4.0.374
    [2020.8.3]联想 Z6 青春版(L38111) Magisk ROOT 纯净无推广 一键刷机 ZUI_11.5.160
    [2020.8.3]联想 Z6(L78121) Magisk ROOT 纯净无推广 一键刷机 ZUI_11.1.262
    [2020.8.3]联想 Z5S(L78071) Magisk ROOT 纯净无推广 一键刷机 ZUI_11.5.132
    《将博客搬至CSDN》
    eclipse菜单栏隐藏
  • 原文地址:https://www.cnblogs.com/xxNote/p/5496156.html
Copyright © 2011-2022 走看看