您的位置:首页 > 移动开发 > Android开发

Android AIDL使用详解

2016-10-17 17:12 477 查看
  在Android中, 每个应用程序都可以有自己的进程。在写UI应用的时候,经常要用到Service。在不同的进程中,怎样传递对象呢? 显然,Java中不允许跨进程内存共享,因此传递对象,只能把对象拆分成操作系统能理解的简单形式,以达到跨界对象访问的目的。在J2EE中,采用RMI的方式,可以通过序列化传递对象。在Android中,则采用AIDL的方式。理论上AIDL可以传递Bundle,但实际上做起来却比较麻烦.
  Android跨进程通信方式具体做法就是在多个应用程序之间建立共同的服务机制,通过AIDL在不同应用程序之间达到数据共享和数据相互操作。
  具体实现过程为:
1、创建AIDL 服务端。
1)创建.aidl文件,声明接口(IDvbService.aidl);
package com.dvb.service;

interface IDvbService
{
void startInitDvbModule();
int doSystemCmd(String cmd);
int getCurstomerID();
boolean isFactorySW();
String getSerialNumber();
byte[] getFullSN();
String getEncryptSN();
void setPowerAction(int action);
String[] getTimeZones();
int getCurZoneIndex();
void saveTimeZone(int index);
Rect getOutRange();
void setOSDArea(int l, int t, int r, int b);
int getHdmiIndex();
void setHdmiIndex(int index);
}
2)在Service中建个子类实现接口的存根(stub)对象,并在onBind()方法中返回该对象(DvbService.java);
package com.dvb.service;

import android.app.Service;
import android.content.Intent;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.dvb.dbase.BOX_INFO_STRUCT;
import com.dvb.dbase.dbaseManager;
import com.dvb.fpanel.FpanelManager;
import com.dvb.init.InitDVBModule;
import com.dvb.init.InitDVBModule.InitStatus;
import com.dvb.security.SecurityManager;
import com.dvb.settingmodule.SettingManager;
import com.dvb.specialcmd.SpecialCmd;
import com.dvb.systemtime.SystemTimerService;

public class DvbService extends Service
{
private String TAG = DvbService.class.getSimpleName();

private final IDvbService.Stub mBinder = new IDvbService.Stub()
{
@Override
public void startInitDvbModule() throws RemoteException
{
InitStatus status = InitDVBModule.getInstance(getApplication()).getInitStatus();
if(status == InitStatus.UNINITIALIZED)
InitDVBModule.getInstance(getApplication()).startInit();
}

@Override
public int doSystemCmd(String cmd) throws RemoteException
{
return SpecialCmd.getInstance(getApplication()).execSystemCmd(cmd);
}

@Override
public int getCurstomerID() throws RemoteException
{

return InitDVBModule.getInstance(getApplication()).getInitBackMsg().iCustomID;
}

@Override
public boolean isFactorySW() throws RemoteException
{
return InitDVBModule.getInstance(getApplication()).getInitBackMsg().iFactory_sw;
}

@Override
public String getSerialNumber() throws RemoteException
{
return SecurityManager.getInstance(getApplication()).getSNNumber();
}

@Override
public byte[] getFullSN() throws RemoteException
{
return SecurityManager.getInstance(getApplication()).getSerialNumber();
}

@Override
public String getEncryptSN() throws RemoteException
{
return SecurityManager.getInstance(getApplication()).getEncryptSN().SNNumber;
}

@Override
public void setPowerAction(int action) throws RemoteException
{
switch(action)
{
case 0:
FpanelManager.getInstance(DvbService.this).setPowerReboot();
break;
case 1:
FpanelManager.getInstance(DvbService.this).setPowerStandby();
break;
case 2:
FpanelManager.getInstance(DvbService.this).setPowerShutUp();
break;
}
}

@Override
public String[] getTimeZones() throws RemoteException
{
if(SystemTimerService.getInstance(DvbService.this).getTimeZoneMaps() == null)
{
SystemTimerService.getInstance(DvbService.this).initTimeZoneList();
}
return SystemTimerService.getInstance(DvbService.this).getTimeZoneNameArray();
}

@Override
public int getCurZoneIndex() throws RemoteException
{
return SystemTimerService.getInstance(DvbService.this).getZoneDefaultIndex();
}

@Override
public void saveTimeZone(int index) throws RemoteException
{
SystemTimerService.getInstance(DvbService.this).setTimeZone(index);
SystemTimerService.getInstance(DvbService.this).saveZoneSelected(index);
}

@Override
public Rect getOutRange() throws RemoteException
{
BOX_INFO_STRUCT boxInfo = dbaseManager.getInstance(getApplication()).getBoxInfo();
Rect rect = new Rect(boxInfo.screen_area_xpos, boxInfo.screen_area_ypos, boxInfo.screen_area_width, boxInfo.screen_area_height);
return rect;
}

@Override
public void setOSDArea(int l, int t, int r, int b) throws RemoteException
{
SettingManager.getInstance(getApplication()).setOSDArea(l, t, r, b);
BOX_INFO_STRUCT boxInfo = dbaseManager.getInstance(getApplication()).getBoxInfo();
boxInfo.screen_area_xpos = l;
boxInfo.screen_area_ypos = t;
boxInfo.screen_area_width = r;
boxInfo.screen_area_height = b;
dbaseManager.getInstance(getApplication()).updateBoxInfo(boxInfo);
}

@Override
public int getHdmiIndex() throws RemoteException
{
SettingManager settingManager = SettingManager.getInstance(getApplication());
BOX_INFO_STRUCT boxInfo = dbaseManager.getInstance(getApplication()).getBoxInfo();
return settingManager.getHDModeIndex(boxInfo.hdmi_mode);
}

@Override
public void setHdmiIndex(int index) throws RemoteException
{
SettingManager settingManager = SettingManager.getInstance(getApplication());
BOX_INFO_STRUCT boxInfo = dbaseManager.getInstance(getApplication()).getBoxInfo();
int iHDValue = settingManager.getHDValueUnderSpecifiedTVSys(boxInfo.tv_type, index);
settingManager.setHdmiMode(iHDValue);
}
};

public void onCreate()
{
super.onCreate();
InitStatus status = InitDVBModule.getInstance(getApplication()).getInitStatus();
if(status == InitStatus.UNINITIALIZED)
InitDVBModule.getInstance(getApplication()).startInit();
};

@Override
public IBinder onBind(Intent intent)
{
Log.d(TAG, "bind action "+intent.getAction());
if (IDvbService.class.getName().equals(intent.getAction()))
{
Log.d(TAG, "return mBinder");
return mBinder;
}
else
{
return null;
}
}
}
3)将Service添加进服务端或引用服务端的应用程序配置文件清单中(AndroidManifest.xml)。
<service
android:name="com.dvb.service.DvbService"
android:exported="true"
android:process=":remote" >
<intent-filter>
<action android:name="com.dvb.service.IDvbService" />
</intent-filter>
</service>

2、创建AIDL 客户端。

1)把之前编写的aidl文件(注意不是生成的java文件)和它的包目录拷贝到客户端的src目录中;
2)客户端调用服务端提供的服务接口(DvbServiceImpl.java);
package com.starview.tv.service;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;

import com.dvb.service.IDvbService;
import com.starview.tv.util.LogTool;

public class DvbServiceImpl
{
private static IDvbService instance;

private static final Object obj = new Object();
private static ServiceConnection mRemoteConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service)
{
LogTool.d("benson", "ComponentName = " + className.getClassName());
instance = IDvbService.Stub.asInterface(service);
synchronized (obj)
{
obj.notifyAll();
}
}

public void onServiceDisconnected(ComponentName className)
{
instance = null;
}
};

public static synchronized boolean isInit()
{
return instance != null;
}

public static synchronized boolean init(Context context)
{
if (instance == null)
{
Intent service = new Intent(IDvbService.class.getName());
boolean bBindOk = context.getApplicationContext().bindService(service, mRemoteConnection, Context.BIND_AUTO_CREATE);
Log.d("benson", "bBindOk = " + bBindOk);
return bBindOk;
}
return true;
}

public static synchronized boolean init(Context ctx, final InitListener listener)
{
if (instance == null)
{
if (listener != null)
{
new Thread()
{
@Override
public void run()
{
synchronized (obj)
{
if (instance == null)
{
try
{
obj.wait(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
listener.onInitEnd(instance);
}
}
}.start();
}
Intent service = new Intent(IDvbService.class.getName());
try
{
boolean bBindOk = ctx.getApplicationContext().bindService(service, mRemoteConnection, Context.BIND_AUTO_CREATE);
Log.d("benson", "bBindOk = " + bBindOk);
return bBindOk;
}
catch (SecurityException e)
{
e.printStackTrace();
return false;
}

}
else
{
if (listener != null)
{
listener.onInitEnd(instance);
}
return true;
}

}

public static synchronized void deInit(Context context)
{
if (instance != null)
{
Log.i("benson", "deInit...");
context.unbindService(mRemoteConnection);
instance = null;
}
}

public static synchronized IDvbService getDvbService(final Context context) throws UnInitException
{
if (instance == null)
{
throw new UnInitException("Please Call init First");
}
return instance;
}

public static class UnInitException extends Exception
{
private static final long serialVersionUID = 1L;

public UnInitException()
{
super();
}

public UnInitException(String detailMessage, Throwable throwable)
{
super(detailMessage, throwable);
}

public UnInitException(String detailMessage)
{
super(detailMessage);
}

public UnInitException(Throwable throwable)
{
super(throwable);
}

}

public static interface InitListener
{
public void onInitEnd(IDvbService instance);
}
}
3)在需要调用该服务的地方实例化该对象;
IDvbService dvbService = null;
try
{
dvbService = DvbServiceImpl.getDvbService(mContext);
}
catch (UnInitException e)
{
e.printStackTrace();
return;
}

4)调用该对象方法。
dvbService.setPowerAction(0);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: