Service与Activity交互之IPC

  如题,某场景:使用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的交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值