智慧 + 毅力 = 无所不能

正确性、健壮性、可靠性、效率、易用性、可读性、可复用性、兼容性、可移植性...

导航

android Service 跨进程通信

Posted on 2013-03-22 15:24  Bill Yuan  阅读(9055)  评论(0编辑  收藏  举报

最近做项目一直没能理解清楚Service是如何跨进程通信的,既然是跨进程通信,那么也就意味着多个app可以通过一个Service服务进行数据的交互了。带着这些猜想,花了一天的时间终于把这个猜想实现了。关于Service的生命周期就不说了,网上一大堆。

本地Activity和Service之间的交互demo:

首先定义一个接口,用来进行数据之间的交互。

IService .java

package com.tanlon.localservice;

public interface IService {
  long getCurrentTime();
}

接着完成Service类:

package com.tanlon.localservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class LocalService extends Service{
    //log标记
    private static final String TAG="MyService";
    //获取绑定接口
    private MyBind myBind=new MyBind();
    
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "localService onBind");
        return myBind;
    }

    public void onCreate() {
        // TODO Auto-generated method stub
        Log.d(TAG, "localService onCreate");
        super.onCreate();
    }

    public void onDestroy() {
        // TODO Auto-generated method stub
        Log.d(TAG, "localService onDestroy");
        super.onDestroy();
    }

    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        Log.d(TAG, "localService onStart");
        super.onStart(intent, startId);
    }

    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "localService onUnbind");
        return super.onUnbind(intent);
    }
    //本地服务中的绑定
    public class MyBind extends Binder implements IService{

        public long getCurrentTime() {
            // TODO Auto-generated method stub
            return System.currentTimeMillis();
        }
        
    }

}

本地调用Service:

package com.tanlon.localservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class LocalServiceActivity extends Activity {
    private IService iService=null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button startServiceButton=(Button) findViewById(R.id.startServiceButton);
        Button stopServiceButton=(Button) findViewById(R.id.stopServiceButton);
        Button bindServiceButton=(Button) findViewById(R.id.bindServiceButton);
        Button unbindServiceButton=(Button) findViewById(R.id.unbindServiceButton);
        startServiceButton.setOnClickListener(onClickListener);
        stopServiceButton.setOnClickListener(onClickListener);
        bindServiceButton.setOnClickListener(onClickListener);
        unbindServiceButton.setOnClickListener(onClickListener);
    }
    
    private OnClickListener onClickListener=new OnClickListener() {
        
        public void onClick(View v) {
            // TODO Auto-generated method stub
            int id=v.getId();
            switch (id) {
            case R.id.startServiceButton://启动服务(这里用到getApplicationContext是为了提升应用等级,避免出现“android.app.ServiceConnectionLeaked”这样的错误)
                startService(new Intent(getApplicationContext(), LocalService.class));
                break;
            case R.id.stopServiceButton://停止服务(这里用到getApplicationContext是为了提升应用等级,避免出现“android.app.ServiceConnectionLeaked”这样的错误)
                stopService(new Intent(getApplicationContext(), LocalService.class));
                break;
            case R.id.bindServiceButton://绑定服务
                bindservice();
                break;
            case R.id.unbindServiceButton://解绑定
                unbindService(connection);
                break;
            default:
                break;
            }
        }
    };
    
    //绑定服务
    private void bindservice() {
        // TODO Auto-generated method stub
        //这里用到getApplicationContext是为了提升应用等级,避免出现“android.app.ServiceConnectionLeaked”这样的错误
        Intent intent=new Intent(getApplicationContext(), LocalService.class);
        this.bindService(intent, connection, BIND_AUTO_CREATE);
    }
    
    //连接服务接口
    ServiceConnection connection=new ServiceConnection() {
        
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            iService=null;
        }
        
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //获取连接的服务对象
            iService=(IService) service;
            //调用服务,获取服务中的接口方法
            if(iService!=null)
                Log.d("MyService", "iService bindService getCurrentTime"+iService.getCurrentTime());
        }
    };
    
    protected void onDestroy() {
        // TODO Auto-generated method stub
        Log.d("MyService", "localServiceActivity onDestroy");
        super.onDestroy();
    }
    
    
}

最后在mainfest中注册服务:

<service android:name="com.tanlon.localservice.LocalService"></service>

运行效果:

 

运行结果:

 

跨进程通信:

第一步:建立服务端(ServiceServer) :配置aidl接口

package com.tanlon.server;

interface IService {
  long getCurrentTime();
  void setValue(in String from,in int value);
  String getValue();
}

配置服务类

package com.tanlon.server;

import com.tanlon.server.IService.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service{
    //log标记
    private static final String TAG="MyService";
    
    private String str;
    
    private IService.Stub bind=new Stub() {
        
        public long getCurrentTime() throws RemoteException {
            // TODO Auto-generated method stub
            return System.currentTimeMillis();
        }

        public void setValue(String from, int value) throws RemoteException {
            // TODO Auto-generated method stub
            str="value from-------"+from+" and value is-------"+value;
            Log.d(TAG, "ServiceServer setValue from-------"+from+" value is-------"+value);
        }

        public String getValue() throws RemoteException {
            // TODO Auto-generated method stub
            return str;
        }
    };
    
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "ServiceServer onBind");
        return bind;
    }

    public void onCreate() {
        // TODO Auto-generated method stub
        Log.d(TAG, "ServiceServer onCreate");
        super.onCreate();
    }

    public void onDestroy() {
        // TODO Auto-generated method stub
        Log.d(TAG, "ServiceServer onDestroy");
        super.onDestroy();
    }

    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        Log.d(TAG, "ServiceServer onStart");
        super.onStart(intent, startId);
    }

    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "ServiceServer onUnbind");
        return super.onUnbind(intent);
    }

}

第二步:配置客户端1(ServiceClientOne):用来和服务端、其他的客户端交互数据(此处主要通过Service来设置值,其他的进程则通过Service来取这里设置的值)。

先将服务端的com.tanlon.server包以及其下的IService.aidl一起拷到客户端下面来。

接着就是客户端连接Service的代码:

package com.tanlon.client;

import java.text.SimpleDateFormat;
import com.tanlon.server.IService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class ServiceClientActivity extends Activity {
    private IService iService=null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //绑定服务,获取远程服务
        bindService(new Intent(IService.class.getName()), connection, BIND_AUTO_CREATE);
    }
    //连接服务
    private ServiceConnection connection=new ServiceConnection() {
        
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            iService=null;
        }
        
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //获取绑定的接口
            iService=IService.Stub.asInterface(service);
            try {
                if(iService!=null){
                    //调用远程服务中的方法
                    long date=iService.getCurrentTime();
                    Log.d("MyService", "IService getCurrentTime------"+getDate(date));
                    //为交互进程间的交互设置值
                    iService.setValue(ServiceClientActivity.class.getName(), 10);
                }
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    };
    //将long型系统时间转换成当前时间
    private String getDate(long date){
        SimpleDateFormat formatter;  
        formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");  
        String ctime = formatter.format(date);
        return ctime; 
    }

    protected void onDestroy() {
        // TODO Auto-generated method stub
        unbindService(connection);
        super.onDestroy();
    }
    
    
}

第三步:配置客户端2(ClientDemo):通过Service来获取客户端1设置的值。

先将服务端的com.tanlon.server包以及其下的IService.aidl一起拷到客户端下面来。

接着就是客户端连接Service的代码:

package com.tanlon.clientdemo;

import java.text.SimpleDateFormat;

import com.tanlon.server.IService;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class ClientDemoActivity extends Activity {
    private IService iService=null;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        bindService(new Intent(IService.class.getName()), connection, BIND_AUTO_CREATE);
    }
    //连接服务
    private ServiceConnection connection=new ServiceConnection() {
        
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            iService=null;
        }
        
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //获取绑定的接口
            iService=IService.Stub.asInterface(service);
            try {
                if(iService!=null){
                    //调用远程服务中的方法
                    long date=iService.getCurrentTime();
                    Log.d("MyService", "IService getCurrentTime------"+getDate(date));
                    //获取进程间的交互值
                    String str=iService.getValue();
                    Log.d("MyService", "IService getValue------"+str);
                }
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    };
    //将long型系统时间转换成当前时间
    private String getDate(long date){
        SimpleDateFormat formatter;  
        formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");  
        String ctime = formatter.format(date);
        return ctime; 
    }

    protected void onDestroy() {
        // TODO Auto-generated method stub
        unbindService(connection);
        super.onDestroy();
    }
}

运行结果: