android Service 跨進程通信


最近做項目一直沒能理解清楚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();
    }
}

運行結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM