如题,某场景:使用AS,在Service中进行文件上传,监听上传的各种情况,且上传不能够影响应用。本次就拿FTP吧。
IPC的几种方式:
a. 使用Bundle(putExtras),用于android四大组件间的进程间通信
b. 使用文件共享,如SharePreference(xml实现)
c. 使用Messenger,用于可存放在message中的数据的传递,感觉太麻烦。
d. AIDL,主要用于远程服务通信,可以注册接口。
不影响应用,首先想到远程服务(Remote Service)。而在远程服务中通知activity当前上传的情况,这个却不多见。所以这次来介绍一下远程服务通过AIDL与activity的交互吧。
接下来,直接上代码,步骤:
1、编写AIDL
interface IFileUploadServices {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void initeService(in int interval);
void uploadFiles();
void stop();
}
2、编写Service类
public class FileUploadService extends Service {
boolean ifexitThread = false;
boolean ifSuccess = false;
Thread uploadThread;
int uploadInterval;
public Handler serviceHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
...
}
};
...
Ilisten ilisten = null;
private final IFileUploadServices.Stub mBinder = new IFileUploadServices.Stub() {
public void uploadFiles() {
if (null != serviceHandler)
serviceHandler.sendEmptyMessage(START_SERVICE);
else
Log.e("MainActivity", "serviceHandler null");
}
public void initListen(Ilisten listen) {
ilisten = listen;
}
public void initeService(final int interval) {
uploadInterval = interval;
if (null != serviceHandler)
serviceHandler.sendEmptyMessage(INIT_SERVICE);
else
Log.e("MainActivity", "serviceHandler null");
}
public void stop() {
if (null != serviceHandler)
serviceHandler.sendEmptyMessage(STOP_SERVICE);
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
3、启动Service
private ServiceConnection mConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
fileUploadService = IFileUploadServices.Stub
.asInterface(service);
Log.e(TAG, "UploadService Connected");
try {
fileUploadService.initeService(fileUploadInterval);
fileUploadService.uploadFiles();
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "UploadService Disconnected");
try {
fileUploadService.stop();
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
private void startFileUploadService() {
Log.d(TAG, "启动文件上传服务!");
Intent intent = new Intent(context, FileUploadService.class);
context.bindService(intent, mConn, Service.BIND_AUTO_CREATE);
}
到这里,远程服务已经可以启动了。
4、开始监听,一开始只知道AIDL只支持基础数据类型的数据传递。经google爸爸查询,才知道原来Android早就想到并提供了这些。代码如下:
a.编写远程回调AIDL:
interface Ilisten {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void updateWifiStatus(boolean mobile, boolean wifi);
boolean getWifiStatus();
void handleResult(int ifUploadSuccess);
}
修改远程Service AIDL:
interface IFileUploadServices {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
void initeService(in int interval);
void uploadFiles();
void stop();
/**
* 给service初始化事件回调,记得import Ilisten,
* AS默认无法自动识别和提示,必须手动输入Ilisten正确的“包+接口”路径,然后sync project。
*/
void initListen(in Ilisten listen);
}
b.编写回调listener,注意这里的初始化函数,传进来的是主线程的handler:
public class UploadListener extends Ilisten.Stub {
boolean isWifiOn;
boolean isMobileOn;
Handler handler;
public UploadListener(Handler handler) {
this.handler = handler;
}
/**
* ifUploadSuccess status:
* 2 file not found
* 1 file upload success
* 0 file upload failed
*/
public void handleResult(int ifUploadSuccess) throws RemoteException {
switch (ifUploadSuccess) {
case CallbackConst.FILEUPLOADFAIL:
Log.e("MainActivity", "Upload Fail");
handler.sendEmptyMessage(IMessageContent.HIDECIRLE);
break;
}
}
public void updateWifiStatus(boolean mobile, boolean wifi) {
this.isMobileOn = mobile;
this.isWifiOn = wifi;
}
@Override
public boolean getWifiStatus() throws RemoteException {
return this.isWifiOn;
}
...
}
c.开始监听:
在启动Service的activity、fragment或者业务类中初始化UploadListener对象,将Activity中的handler传给远程服务事件实现UploadListener。
uploadListener = new UploadListener(this.handler);
并在onServiceConnected事件中给远程Service传递该远程listener。
fileUploadService.initListen(uploadListener);
5、现在开始,远程Service中就可以使用
ilisten.handleResult(CallbackConst.STARTUPLOAD); //通知主线程开始上传
等与activity进行交互了。
补充:
有的时候可能需要获取网络状态,而当前已经有BroadcastReceiver进行了监听,这个时候可以将这个uploadListener 对象传给BroadcastReceiver,然后在BroadcastReceiver中进行进行相应操作即可。
例如,更新网络状态:
if (null != uploadListener)
uploadListener.updateWifiStatus(true, false);
然后在Service或者activity等中即可获取到网络状态,如:
isWifiOn = ilisten.getWifiStatus();
至此,便完成了远程service与activity的交互。