Binder可以提供系统中任何程序都可以访问的全局服务。这个功能当然是任何系统都应该提供的
Android Binder框架分为服务器接口、Binder驱动、以及客户端接口;简单想一下,需要提供一个全局服务,那么全局服务那端即是服务器接口,任何程序即客户端接口,它们之间通过一个Binder驱动访问。
Binder框架原理分析
1、ISettingToServer.aidl文件生成的Java文件
public interface ISettingToServer extends android.os.IInterface
{
/** Default implementation for ISettingToServer. */
public static class Default implements com.wq.qcsettings.ISettingToServer
{
@Override public void setMobileDataEnabled(boolean enabled) throws android.os.RemoteException
{
}
@Override public boolean isMobileDataEnabled() throws android.os.RemoteException
{
return false;
}
@Override public void setGpsEnabled(boolean enabled) throws android.os.RemoteException
{
}
@Override public boolean isGpsEnabled() throws android.os.RemoteException
{
return false;
}
@Override
public android.os.IBinder asBinder() {
return null;
}
}
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.wq.qcsettings.ISettingToServer
{
private static final java.lang.String DESCRIPTOR = "com.zqc.qcsettings.ISettingToServer";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.zqc.qcsettings.ISettingToServer interface,
* generating a proxy if needed.
*/
public static com.wq.qcsettings.ISettingToServer asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.zqc.qcsettings.ISettingToServer))) {
return ((com.wq.qcsettings.ISettingToServer)iin);
}
return new com.wq.qcsettings.ISettingToServer.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_setMobileDataEnabled:
{
data.enforceInterface(descriptor);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setMobileDataEnabled(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_isMobileDataEnabled:
{
data.enforceInterface(descriptor);
boolean _result = this.isMobileDataEnabled();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_setGpsEnabled:
{
data.enforceInterface(descriptor);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setGpsEnabled(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_isGpsEnabled:
{
data.enforceInterface(descriptor);
boolean _result = this.isGpsEnabled();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.wq.qcsettings.ISettingToServer
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void setMobileDataEnabled(boolean enabled) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((enabled)?(1):(0)));
boolean _status = mRemote.transact(Stub.TRANSACTION_setMobileDataEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setMobileDataEnabled(enabled);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public boolean isMobileDataEnabled() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_isMobileDataEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().isMobileDataEnabled();
}
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void setGpsEnabled(boolean enabled) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((enabled)?(1):(0)));
boolean _status = mRemote.transact(Stub.TRANSACTION_setGpsEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setGpsEnabled(enabled);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public boolean isGpsEnabled() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_isGpsEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().isGpsEnabled();
}
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.wq.qcsettings.ISettingToServer sDefaultImpl;
}
static final int TRANSACTION_setMobileDataEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_isMobileDataEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_setGpsEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
static final int TRANSACTION_isGpsEnabled = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
public static boolean setDefaultImpl(com.wq.qcsettings.ISettingToServer impl) {
if (Stub.Proxy.sDefaultImpl == null && impl != null) {
Stub.Proxy.sDefaultImpl = impl;
return true;
}
return false;
}
public static com.wq.qcsettings.ISettingToServer getDefaultImpl() {
return Stub.Proxy.sDefaultImpl;
}
}
public void setMobileDataEnabled(boolean enabled) throws android.os.RemoteException;
public boolean isMobileDataEnabled() throws android.os.RemoteException;
public void setGpsEnabled(boolean enabled) throws android.os.RemoteException;
public boolean isGpsEnabled() throws android.os.RemoteException;
}
ISettingToServer .java文件包含两个静态内部类—Stub和Proxy(其中Proxy是Stub的内部类)
静态内部Stub 类分析
public static abstract class Stub extends android.os.Binder implements com.zqc.qcsettings.ISettingToServer
其中Stub是个抽象类,它继承了Binder,并实现了ISettingToServer接口。Stub提供了几个方法:asInterface、asBinder、onTransact,但并没有实现ISettingToServer接口的方法,所以需要交给Stub的实现类Proxy去实现。
public static com.wq.qcsettings.ISettingToServer asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.wq.qcsettings.ISettingToServer))) {
return ((com.wq.qcsettings.ISettingToServer)iin);
}
return new com.wq.qcsettings.ISettingToServer.Stub.Proxy(obj);
}
静态内部Proxy 类分析
private static class Proxy implements com.zqc.qcsettings.ISettingToServer
Proxy是Stub的内部类,也实现了ISettingToServer 接口。并提供了几个方法:asBinder、getInterfaceDescriptor,并实现了ISettingToServer 接口的方法setMobileDataEnabled()、isMobileDataEnabled()、setGpsEnabled()、isGpsEnabled()。
private static class Proxy implements com.zqc.qcsettings.ISettingToServer
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void setMobileDataEnabled(boolean enabled) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((enabled)?(1):(0)));
boolean _status = mRemote.transact(Stub.TRANSACTION_setMobileDataEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setMobileDataEnabled(enabled);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public boolean isMobileDataEnabled() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_isMobileDataEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().isMobileDataEnabled();
}
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void setGpsEnabled(boolean enabled) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(((enabled)?(1):(0)));
boolean _status = mRemote.transact(Stub.TRANSACTION_setGpsEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().setGpsEnabled(enabled);
return;
}
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public boolean isGpsEnabled() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_isGpsEnabled, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().isGpsEnabled();
}
_reply.readException();
_result = (0!=_reply.readInt());
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.zqc.qcsettings.ISettingToServer sDefaultImpl;
}
可以看到我们服务端提供的服务是由ISettingToServer .Stub来执行的,上面分析过,Stub这个类是Binder的子类,是不是符合我们文章开头所说的服务端其实是一个Binder类的实例。而且mBinder实现了ISettingToServer 接口的方法。
接下来看Stub的onTransact()方法:
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_setMobileDataEnabled:
{
data.enforceInterface(descriptor);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setMobileDataEnabled(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_isMobileDataEnabled:
{
data.enforceInterface(descriptor);
boolean _result = this.isMobileDataEnabled();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
case TRANSACTION_setGpsEnabled:
{
data.enforceInterface(descriptor);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setGpsEnabled(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_isGpsEnabled:
{
data.enforceInterface(descriptor);
boolean _result = this.isGpsEnabled();
reply.writeNoException();
reply.writeInt(((_result)?(1):(0)));
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
服务端的Binder实例会根据客户端依靠Binder驱动发来的消息,执行onTransact方法,然后由其参数决定执行服务端的代码。
可以看到onTransact有四个参数:code , data ,replay , flags
code:是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法
data:客户端传递过来的参数
reply:服务器返回回去的值
flags:标明是否有返回值,0为有(双向),1为没有(单向)
private static final java.lang.String DESCRIPTOR = "com.zqc.qcsettings.ISettingToServer";
java.lang.String descriptor = DESCRIPTOR;
case TRANSACTION_setMobileDataEnabled:
{
data.enforceInterface(descriptor);
boolean _arg0;
_arg0 = (0!=data.readInt());
this.setMobileDataEnabled(_arg0);
reply.writeNoException();
return true;
}
最后读出我们服务端返回的数据,然后return。可以看到Transact和服务端的onTransact基本是一行一行对应的。
当客户端调用transact方法发起RPC(远程过程调用)请求后,当前线程会挂起,等待服务器端的返回结果。所以如果一个远程方法很耗时,那么不能再UI线程中调用此远程方法。
服务端的Binder方法(onTransact)运行在Binder线程池中,所以Binder方法不管是否耗时,都应该采取同步机制,因为它已经运行在一个线程中了。
我们已经通过AIDL生成的代码解释了Android Binder框架的工作原理。Service的作用其实就是为我们创建Binder驱动,即服务端与客户端连接的桥梁。Binder框架原理图如下
代码实例如下
服务端
创建一个SettingsServer.java 类继承Service
ublic class YlfSettingsServer extends Service {
private static final String TAG = "SettingsServer";
private ISettingFunctionIml mISettingFunctionIml;
private Context mContext;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate()");
mContext = this;
mISettingFunctionIml = new ISettingFunctionIml(mContext);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy()");
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind()");
return new YlfSettingsServerIml(mISettingFunctionIml);
}
}
创建一个SettingsServerIml 继承extends ISettingToServer.Stub
public class SettingsServerIml extends ISettingToServer.Stub{
private static String TAG = "SettingsServerIml";
private com.zqc.qcsettings.ISettingFunctionIml mISettingFunctionIml;
public YlfSettingsServerIml(ISettingFunctionIml mISettingFunctionIml){
this.mISettingFunctionIml = mISettingFunctionIml;
}
@Override
public void setMobileDataEnabled(boolean enabled) throws RemoteException {
Log.d(TAG," setMobileDataEnabled " +enabled);
mISettingFunctionIml.setMobileDataEnabled(enabled);
}
@Override
public boolean isMobileDataEnabled() throws RemoteException {
Log.d(TAG," isMobileDataEnabled() " );
return mISettingFunctionIml.isMobileDataEnabled();
}
@Override
public void setGpsEnabled(boolean enabled) throws RemoteException {
Log.d(TAG," setGpsEnabled() enabled " +enabled);
mISettingFunctionIml.setGpsEnabled(enabled);
}
@Override
public boolean isGpsEnabled() throws RemoteException {
Log.d(TAG," isGpsEnabled() " );
return mISettingFunctionIml.isGpsEnabled();
}
@Override
public void setWIFIName(String wifiname) throws RemoteException {
Log.d(TAG," setWIFIName() wifiname " +wifiname);
mISettingFunctionIml.setWIFIName(wifiname);
}
@Override
public String getWIFIName() throws RemoteException {
Log.d(TAG," getWIFIName() " );
return mISettingFunctionIml.getWIFIName();
}
@Override
public void setWIFIPassword(String wifipassword) throws RemoteException {
Log.d(TAG," setWIFIPassword() wifipassword " +wifipassword);
mISettingFunctionIml.setWIFIPassword(wifipassword);
}
@Override
public String getWIFIPassword() throws RemoteException {
Log.d(TAG," getWIFIPassword() " );
return mISettingFunctionIml.getWIFIPassword();
}
@Override
public void setRecordingEnabled(boolean enabled) throws RemoteException {
Log.d(TAG," setRecordingEnabled() enabled " +enabled);
mISettingFunctionIml.setRecordingEnabled(enabled);
}
@Override
public boolean isRecordingEnabled() throws RemoteException {
Log.d(TAG," isRecordingEnabled() " );
return mISettingFunctionIml.isRecordingEnabled();
}
@Override
public void setRecordingTime(int type) throws RemoteException {
Log.d(TAG," setRecordingTime() type " +type);
mISettingFunctionIml.setRecordingTime(type);
}
@Override
public int getRecordingTime() throws RemoteException {
Log.d(TAG," getRecordingTime()" );
return mISettingFunctionIml.getRecordingTime();
}
@Override
public void setCollisionSensitivity(int type) throws RemoteException {
Log.d(TAG," setCollisionSensitivity() type " +type);
mISettingFunctionIml.setCollisionSensitivity(type);
}
@Override
public int getCollisionSensitivity() throws RemoteException {
Log.d(TAG," getCollisionSensitivity()");
return mISettingFunctionIml.getCollisionSensitivity();
}
@Override
public void setVolumeMute(boolean mute) throws RemoteException {
Log.d(TAG," setVolumeMute() mute " +mute);
mISettingFunctionIml.setVolumeMute(mute);
}
@Override
public boolean isVolumeMute() throws RemoteException {
Log.d(TAG," isVolumeMute() ");
return mISettingFunctionIml.isVolumeMute();
}
@Override
public void setVolumeLevel(int level) throws RemoteException {
Log.d(TAG," setVolumeLevel() level "+level);
mISettingFunctionIml.setVolumeLevel(level);
}
@Override
public int getVolumeLevel() throws RemoteException {
Log.d(TAG," getVolumeLevel() ");
return mISettingFunctionIml.getVolumeLevel();
}
@Override
public long getStorageTotalSize() throws RemoteException {
Log.d(TAG," getStorageSize() ");
return mISettingFunctionIml.getStorageTotalSize();
}
@Override
public long getStorageRemainingSize() throws RemoteException {
Log.d(TAG," getStorageRemainingSize() ");
return mISettingFunctionIml.getStorageRemainingSize();
}
@Override
public void setFormatStorage(boolean enabled) throws RemoteException {
Log.d(TAG," setFormatStorage() enabled "+enabled);
mISettingFunctionIml.setFormatStorage(enabled);
}
@Override
public void setSystemUpgrade(boolean enabled) throws RemoteException {
Log.d(TAG," setSystemUpgrade() enabled "+enabled);
mISettingFunctionIml.setSystemUpgrade(enabled);
}
@Override
public void setApplicationUpgrade(boolean enabled) throws RemoteException {
Log.d(TAG," setApplicationUpgrade() enabled "+enabled);
}
}
创建一个ISettingToServer.aidl文件
interface ISettingToServer {
void setMobileDataEnabled(in boolean enabled);
boolean isMobileDataEnabled();
void setGpsEnabled(in boolean enabled);
boolean isGpsEnabled();
void setWIFIName(String wifiname);
String getWIFIName();
void setWIFIPassword(String wifipassword);
String getWIFIPassword();
void setRecordingEnabled(in boolean enabled);
boolean isRecordingEnabled();
void setRecordingTime(int type);
int getRecordingTime();
void setCollisionSensitivity(int type);
int getCollisionSensitivity();
void setVolumeMute(in boolean mute);
boolean isVolumeMute();
void setVolumeLevel(int level);
int getVolumeLevel();
long getStorageTotalSize();
long getStorageRemainingSize();
void setFormatStorage(in boolean enabled);
void setSystemUpgrade(in boolean enabled);
void setApplicationUpgrade(in boolean enabled);
}
然后在AndroidManifest.xml文件中注册服务
<service android:name="com.zqc.qcsettings.SettingsServer">
<intent-filter>
<action android:name="com.zqc.qcsettings.SettingsServer"/>
</intent-filter>
</service>
在mk文件中添加aidl参与编译
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/zqc/qcsettings/ISettingToServer.aidl
客户端
创建MainActivity.java然后绑定服务
public class MainActivity extends AppCompatActivity {
private static final String TAG = "";
private ISettingToServer mISettingToServer;
public static final String BASE_PATH = "/storage/sdcard0";
public static final String VIDEO_DIR = "/DCIM/";
public static final String DIRECTORY_VIDEO = BASE_PATH + VIDEO_DIR;
private ServiceConnection conn = new ServiceConnection() {
//服务连接上的时候调用这个方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected()");
//拿到了远程的服务
mISettingToServer = ISettingToServer.Stub.asInterface(service);
}
//当服务断开的时候调用这个方法
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected()");
//回收资源
mISettingToServer = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定服务
bindServers();
}
//绑定服务
public void onSetOnclick(View view) {
try {
//调用远程aidl服务,这样就可以实现进程间通信了
if(mISettingToServer!=null){
mISettingToServer.setVolumeMute(true);
}
} catch (RemoteException e) {
e.printStackTrace();
}
// Date date = new Date();
// String dataForm = new SimpleDateFormat("yyyy-MM-dd").format(date);
// String path=DIRECTORY_VIDEO+"/"+dataForm;
// Log.d(TAG, "path=" +path);
// File f = new File(path);
// if(!f.exists()){
// f.mkdirs();
// }
}
public void onGetOnclick(View view) {
try {
//调用远程aidl服务,这样就可以实现进程间通信了
if(mISettingToServer!=null) {
mISettingToServer.setVolumeMute(false);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onGetDataclick(View view) {
try {
//调用远程aidl服务,这样就可以实现进程间通信了
if(mISettingToServer!=null) {
Toast.makeText(this," "+mISettingToServer.isVolumeMute(),Toast.LENGTH_LONG).show();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void bindServers() {
//获取到服务端
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.zqc.camera", "com.zqc.qcsettings.YlfSettingsServer"));
boolean isBindService = bindService(intent, conn, Context.BIND_AUTO_CREATE);
Log.d(TAG, " isBindService " +isBindService);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy()");
//解绑服务
if (conn != null) {
unbindService(conn);
conn = null;
}
}
}
把服务中创建的aidl文件也复制到客户端来
interface ISettingToServer {
void setMobileDataEnabled(in boolean enabled);
boolean isMobileDataEnabled();
void setGpsEnabled(in boolean enabled);
boolean isGpsEnabled();
void setWIFIName(String wifiname);
String getWIFIName();
void setWIFIPassword(String wifipassword);
String getWIFIPassword();
void setRecordingEnabled(in boolean enabled);
boolean isRecordingEnabled();
void setRecordingTime(int type);
int getRecordingTime();
void setCollisionSensitivity(int type);
int getCollisionSensitivity();
void setVolumeMute(in boolean mute);
boolean isVolumeMute();
void setVolumeLevel(int level);
int getVolumeLevel();
int getStorageSize(String totalSize,String remainingSize);
void setFormatStorage(in boolean enabled);
void setSystemUpgrade(in boolean enabled);
void setApplicationUpgrade(in boolean enabled);
}
备注说明:
如果有实体类类型,在服务端添加了,在客户端也要添加,这样要保证同步,最好是添加在一个包中便于后面好维护