Android应用内跨进程通信AIDL实例与源码
来源:互联网 发布:vga矩阵切换器标准进出 编辑:程序博客网 时间:2024/06/17 13:16
1. 跨进程通信
2. 应用内多进程
3. Android跨进程通信接口
4. 实例解析
(1) Android工程结构
在android应用中不同进程是不能共享内存的,所以在不同进程间传递对象就需要用到跨进程通信。
2. 应用内多进程
一般一个应用一个进程就足够了,但如果像一些大型的应用经常会看到不止一个进程,比如微信、QQ之类的。一个进程的内存是定死的,如果有耗内存的动作就容易OOM,这时候就可以考虑多进程,提高内存的限制,还有就是不同进程间可以相互监听达到互相守护的功能,提高应用后台保持运行几率。
比如本人所在公司开发的软件是关于VoIP通信类,一个进程是那些通讯录、消息、历史记录、用户等等相关的Activity,而另一个进程是PJSIP通信相关的Service。这个service就相当于远程服务,独立运行,而Activity经常需要跟这个Service交互比如打VoIP电话,这就需要用到跨进程通信。
3. Android跨进程通信接口
Android跨进程通信可以采用AIDL来公开服务的接口,采用远程过程调用和代理模式来实现跨进程通信。AIDL英文全称Android Interface Definition Language 即 Android接口描述语言,ADT会根据AIDL在gen下生成相应的JAVA接口文件。
4. 实例解析
这个实例本来是我给来公司面试的人员出的一道面试题,后来闲着没事就自己写了个demo,题目大体如下:展示天气的demo,Activity负责展示,Service负责获取天气,Acitivty和Service在不同的进程,之间必须通过AIDL来传递对象。过程是Activity点击获取天气的BUTTON后Service开始获取天气,并封装成一个对象以回调的形式回传给Activity,Activity展示该天气信息。
(1) Android工程结构
以前用Eclipse,现在改用Android Studio,感觉效率提高了不少。结构如下图包括MainActivity 展示天气,WeatherBean 天气对象,WeatherService 获取天气的服务。 AIDL 包括 IWeatherInterface 天气服务的接口,IWeatherServiceCallback 天气服务回调的接口, WeatherBean 天气对象接口。
(2) AIDL文件
IWeatherInterface.aidl
IWeatherServiceCallback.aidl
WeatherBean.aidl
(3) 主程序
运行后界面大致如下:
IWeatherInterface.aidl
这个AIDL主要是Activity绑定Service后注册和解注册回调接口以及通知Service开始获取天气的接口方法。源码如下:
// IWeatherInterface.aidlpackage com.easiio.test.weather;import com.easiio.test.weather.IWeatherServiceCallback;interface IWeatherInterface { void registerCallback(int hash, IWeatherServiceCallback callback); void unregisterCallback(int hash); void startGetWeather(String citypinyin);}
这个是Service将天气回传给Activity的接口文件,源码如下:
// IWeatherServiceCallback.aidlpackage com.easiio.test.weather;import com.easiio.test.weather.WeatherBean;interface IWeatherServiceCallback { void showWeather(in WeatherBean weather);}
AIDL支持传递实现了android.os.Parcelable接口的复杂类型,这里的天气对象就是implements Parcelable 的复杂类型对象
// IWeatherServiceCallback.aidlpackage com.easiio.test.weather;parcelable WeatherBean;
(3) 主程序
MainActivity.java
package com.easiio.test.weather;import android.app.ProgressDialog;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import android.os.Bundle;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.RemoteException;import android.support.design.widget.Snackbar;import android.support.v4.util.LogWriter;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.text.TextUtils;import android.util.Log;import android.view.View;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends AppCompatActivity { private static final String TAG = "[EASIIO]MainActivity"; private static final int MSG_WHAT_GET_SUCCESS = 0; private TextView mShowWeatherView; private EditText mCityPinyinET; private ProgressDialog mProgressDialog; private IWeatherInterface mIWeatherInterface; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i(TAG, "onCreate..."); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); mShowWeatherView = (TextView) this.findViewById(R.id.weather_text_view); mCityPinyinET = (EditText) this.findViewById(R.id.city_pinyin_edittext); mProgressDialog = new ProgressDialog(this); mProgressDialog.setMessage("Loading..."); this.findViewById(R.id.button_get_weather).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String pinyin = mCityPinyinET.getEditableText().toString(); if (TextUtils.isEmpty(pinyin)){ Toast.makeText(MainActivity.this, "Not empty", Toast.LENGTH_SHORT).show(); return; } mProgressDialog.show(); try { if (mIWeatherInterface != null){ mIWeatherInterface.startGetWeather(pinyin); } } catch (RemoteException ex){ Log.e(TAG, "Start get weather failed, ex : " + ex.getLocalizedMessage()); } } }); if(!bindService(new Intent(this, WeatherService.class), mServiceConnection, Context.BIND_AUTO_CREATE)){ Toast.makeText(this, "Bind service failed.", Toast.LENGTH_SHORT); finish(); return; } } @Override protected void onDestroy() { super.onDestroy(); if (mServiceConnection != null){ this.unbindService(mServiceConnection); } } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { try { mIWeatherInterface = IWeatherInterface.Stub.asInterface(iBinder); mIWeatherInterface.registerCallback(mIWeatherServiceCallback.hashCode(), mIWeatherServiceCallback); } catch (Exception ex){ Log.e(TAG, "onServiceConnected failed : " + ex.getLocalizedMessage()); } } @Override public void onServiceDisconnected(ComponentName componentName) { try { mIWeatherInterface.unregisterCallback(mIWeatherServiceCallback.hashCode()); } catch (Exception ex){ Log.e(TAG, "onServiceConnected failed : " + ex.getLocalizedMessage()); } } }; private IWeatherServiceCallback mIWeatherServiceCallback = new IWeatherServiceCallback.Stub () { @Override public void showWeather(WeatherBean weather) throws RemoteException { Log.i(TAG, "shoWeather : " + weather.toString()); Message msg = mHandler.obtainMessage(); msg.what = MSG_WHAT_GET_SUCCESS; msg.obj = weather; mHandler.sendMessage(msg); } }; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg.what == MSG_WHAT_GET_SUCCESS){ mProgressDialog.dismiss(); if (msg.obj == null){ mShowWeatherView.setText("Weather is null."); return; } WeatherBean weather = (WeatherBean) msg.obj; if (weather == null){ mShowWeatherView.setText("Weather is null."); return; } mShowWeatherView.setText(weather.toString()); } } };}<span style="color:#4169e1;font-weight: bold;"></span>
WeatherService.java
WeatherBean.java
package com.easiio.test.weather;import android.app.Service;import android.content.Intent;import android.os.DeadObjectException;import android.os.IBinder;import android.os.RemoteException;import android.support.annotation.Nullable;import android.text.TextUtils;import android.util.Log;import org.json.JSONException;import org.json.JSONObject;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.net.URL;import java.net.URLConnection;import java.util.HashMap;import java.util.Iterator;import java.util.Set;/** * Created by gavin on 10/30/15. */public class WeatherService extends Service{ private static final String TAG = "[EASIIO]WeatherService"; private HashMap<Integer, IWeatherServiceCallback> m_callback = new HashMap<Integer, IWeatherServiceCallback>(); @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); } @Override public IBinder onBind(Intent intent) { return new WeatherBinder(); } private class WeatherBinder extends IWeatherInterface.Stub{ @Override public void registerCallback(int hash, IWeatherServiceCallback callback) throws RemoteException { if (m_callback != null && !m_callback.containsKey(hash)){ m_callback.put(hash, callback); Log.w(TAG, "Add callback hash = " + hash); } } @Override public void unregisterCallback(int hash) throws RemoteException { if (m_callback != null) { Iterator<Integer> it = m_callback.keySet().iterator(); while (it.hasNext()) { Integer i_hash = it.next(); if (i_hash.equals(hash)) { it.remove(); break; } } Log.i(TAG, "Removed callback: " + hash + " callbacks: " + m_callback.size()); } } @Override public void startGetWeather(final String citypinyin) throws RemoteException { Log.w(TAG, "startGetWeather"); Thread thread = new Thread(new Runnable() { @Override public void run() { WeatherBean weather = null; String urlStr = "http://apistore.baidu.com/microservice/weather?citypinyin=" + citypinyin; try{ URL url = new URL(urlStr); URLConnection connection = url.openConnection(); connection.connect(); InputStream inputStream = connection.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); StringBuffer sb = new StringBuffer(); String str = ""; while ((str = reader.readLine()) != null) { sb.append(str).append("\n"); } str = sb.toString(); Log.w(TAG, "Get weather result = " + str); weather = parseJsonForWeather(str); } catch (Exception ex){ Log.e(TAG, "Open url failed, ex : " + ex.getLocalizedMessage()); } if (weather == null){ weather = new WeatherBean(); weather.errMsg = "Weather is Null."; } callbackShowWeather(weather); } }); thread.start(); } } private void callbackShowWeather(WeatherBean weather){ Set<Integer> clientsHash = null; if (m_callback != null) { clientsHash = m_callback.keySet(); } if (clientsHash == null) { return; } for (Integer hash : clientsHash) { IWeatherServiceCallback callback = m_callback.get(hash); if (callback != null){ try { callback.showWeather(weather); } catch (DeadObjectException e_do) { Log.w(TAG, "Callback removed. DeadObjectException: hash " + hash); m_callback.remove(hash); } catch (RemoteException re) { Log.w(TAG, "RemoteException:", re); } } } } private WeatherBean parseJsonForWeather(String str){ if (TextUtils.isEmpty(str)){ return null; } try{ WeatherBean weather = new WeatherBean(); JSONObject json = new JSONObject(str); weather.errNum = json.getInt("errNum"); weather.errMsg = json.getString("errMsg"); if (weather.errNum == 0){ JSONObject dataJson = json.getJSONObject("retData"); weather.city = dataJson.getString("city"); weather.weather = dataJson.getString("weather"); weather.temp = dataJson.getString("temp"); weather.l_tmp = dataJson.getString("l_tmp"); weather.h_tmp = dataJson.getString("h_tmp"); weather.wd = dataJson.getString("WD"); weather.ws = dataJson.getString("WS"); } return weather; } catch (JSONException ex){ Log.e(TAG, "parseJson failed : " + ex.getLocalizedMessage()); return null; } }}
WeatherBean.java
package com.easiio.test.weather;import android.os.Parcel;import android.os.Parcelable;/** * Created by gavin on 10/30/15. */public class WeatherBean implements Parcelable { public String city; public String weather; public String temp; public String l_tmp; public String h_tmp; public String wd; public String ws; public int errNum; public String errMsg; public WeatherBean(){ } @Override public String toString(){ StringBuilder builder = new StringBuilder(); builder.append("Result:").append(errMsg).append("\n") .append("City = ").append(city).append("\n") .append("Weather = ").append(weather).append("\n") .append("Temp = ").append(temp).append("\n") .append("Low Temp = ").append(l_tmp).append("\n") .append("High Temp = ").append(h_tmp).append("\n") .append("WD = ").append(wd).append("\n") .append("WS = ").append(ws).append("\n"); return builder.toString(); } private Object mLock = new Object(); private WeatherBean(Parcel in){ readFromParcel( in ); } public void readFromParcel( Parcel in ){ synchronized (mLock) { errNum = in.readInt(); errMsg = in.readString(); city = in.readString(); weather = in.readString(); temp = in.readString(); l_tmp = in.readString(); h_tmp = in.readString(); wd = in.readString(); ws = in.readString(); } } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { synchronized (mLock) { dest.writeInt(errNum); dest.writeString(errMsg); dest.writeString(city); dest.writeString(weather); dest.writeString(temp); dest.writeString(l_tmp); dest.writeString(h_tmp); dest.writeString(wd); dest.writeString(ws); } } public static final Creator<WeatherBean> CREATOR = new Creator<WeatherBean>() { public WeatherBean createFromParcel( Parcel in ){ return new WeatherBean(in); } public WeatherBean[] newArray( int size){ return new WeatherBean[size]; } };}
运行后界面大致如下:
基本上是这样子的了,欢迎交流,工程源码可到github下载
https://github.com/zjc3909/TestWeather.git
0 0
- Android应用内跨进程通信AIDL实例与源码
- AIDL Android跨进程通信调用实例
- Android跨进程通信-AIDL
- Android跨进程通信-AIDL
- Android AIDL跨进程通信
- Android AIDL跨进程通信
- Android 跨进程通信: AIDL
- Android:AIDL跨进程通信
- Android中的跨进程通信AIDL、Binder源码详解
- AIDL跨进程通信在Android的应用
- Android 中的Binder跨进程通信机制与AIDL
- AIDL与Messenger跨进程通信
- Andorid AIDL与跨进程通信
- android 跨进程间通信AIDL
- Android跨进程通信 AIDL方式
- Android跨进程通信----AIDL使用方法
- android studio AIDL跨进程通信
- Android AIDL跨进程通信基础
- MFC获取系统当前时间
- 封装一个类搞定90%安卓客户端与服务器端交互
- 服务器上安装PL\sql工具-(整理)
- request.getParameter中文乱码分析
- MVC应用程序中管理(更新)上传的文件
- Android应用内跨进程通信AIDL实例与源码
- 流程控制(计算器编程1)
- move resource files like logback.xml for packaging an executable jar
- Android子线程中直接回到UI线程执行
- Python 碎片
- Android第三方开源数据库Litepal学习
- 最小生成树算法(引自《算法导论》)
- VirtualBox 创建com对象失败
- 流程控制(计算器编程2)