zoukankan      html  css  js  c++  java
  • 调用远程服务里的方法service,进程间通信adil的学习

    1当一个进程需要调用另外一个进程的方法时候,进程可以通过aidl文件以接口的方式将方法抛出。比如android没有对外提供挂电话的方法,若用户想要调用这个方法就必须与电话管理这个应用程序通信,调用挂电话的方法。

    2、下面我就举例一个demo调用远程服务里的方法。为了验证service能否单独启动,这个demo启动了2个远程服务,一个有activity的一个只有service的。并且他们抛出的接口名字相同,正好学习一下同名的引用,发现一个java文件里只能import  1个同同名的类,若想调用另外一个同名类则只有引用他的全路径名:包名+类名。

    (1)、含activity远程服务和接口:(注意:清单文件里需要配置service)

    //服务
    package com.example.androidservice;
    
    import com.example.androidservice.Iservicemethod.Stub;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class IService extends Service {
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		System.out.println("onbind");
    		
    		return new Mybindle();
    	}
    	
    	@Override
    	public void onCreate() {
    		System.out.println("oncreate");
    		super.onCreate();
    	}
    
    	private class Mybindle extends Stub                      
    //一旦修改接口的扩展名为aidl,就会在gen文件下与接口所在包名同名,里面自动生成一个接口名的java文件,通过查看该接口,
    发现里面自动实现了一个内部类Stub,它实现Ibundle和抛出的接
    口public static abstract class Stub extends android.os.Binder implements com.example.demoonlyservice.Iservicemethod,
    因此我们实现返回的Ibundle的时候写的类可以直接继承Stub即可,后面调用Stub里的方法可以返回接口,即将返回去的bundle service实例化接口,通过接口来调用服务里的方法。
    { @Override public void sayhello() throws RemoteException { // TODO Auto-generated method stub // sayhello();                            // (1)接口抛出的方法名字不能和服务的名字相同,否则覆写的时候不能调用,我先开始直接调用发现和覆写名相同出现                                                 // 无限循环
    //			System.out.println("hello service!!!");            //  (2)一旦在接口定义了该方法,生成了aidl文件后,就不能修改覆写方法里的内容,内里实现的方法是调用service里                                                 //    的方法,因此可以修改service里的方法来修改接口抛出的方法。
    			sayhello2();
    		}
    		
    	}
    	
    	public void sayhello2()
    	{
    		System.out.println("hello service!!!");
    		System.out.println("hello service2!!!");
    	}
    
    }
    
    
    //抛出的接口
    package com.example.androidservice;
    
     interface Iservicemethod {
    	
    	 void sayhello();
    
    }
    

      第二个只含service的服务和接口:(注意:清单文件里也需要配置service)

    package com.example.demoonlyservice;
    
    import com.example.demoonlyservice.Iservicemethod.Stub;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class IService extends Service {
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		System.out.println("onbind");
    		
    		return new Mybindle();
    	}
    	
    	@Override
    	public void onCreate() {
    		System.out.println("oncreate");
    		super.onCreate();
    	}
    
    	private class Mybindle extends Stub
    	{
    
    		@Override
    		public void sayhello() throws RemoteException {
    			// TODO Auto-generated method stub
    //			sayhello();
    //			System.out.println("hello service!!!");
    			sayhello2();
    		}
    		
    	}
    	
    	public void sayhello2()
    	{
    		System.out.println("hello service!!!");
    	}
    
    }
    
    
    //接口
    package com.example.demoonlyservice;
    
     interface Iservicemethod {
    	
    	 void sayhello();
    
    }
    

      3在这个应用里通过点击2个按钮调用上面的2个服务,通过返回的Ibundle实现了接口方法来调用服务的方法sayhello

    package com.example.getothermehod;
    
    import com.example.androidservice.Iservicemethod;
    
    //import com.example.demoonlyservice.Iservicemethod;
    import android.support.v7.app.ActionBarActivity;
    import android.support.v7.app.ActionBar;
    import android.support.v4.app.Fragment;
    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.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.os.Build;
    
    public class MainActivity extends ActionBarActivity {
    
    	private Iservicemethod is;
    	private com.example.demoonlyservice.Iservicemethod  is2;
    	
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    //        Intent intent=new Intent("onlyservice");
    //    	bindService(intent, new Myconnect2(),  BIND_AUTO_CREATE);
        }
        
        public void  startonlyservice(View v) throws InterruptedException
        {
        	Intent intent=new Intent("onlyservice");
        	bindService(intent, new Myconnect2(),  BIND_AUTO_CREATE);
    //    	try {
    //			is2.sayhello();
    //		} catch (RemoteException e) {
    //			// TODO Auto-generated catch block
    //			e.printStackTrace();
    //		}
    //    	Thread.sleep(2000);
        	System.out.println(is2==null);
        	
        }
        
    
        public void startservice(View v) 
      {
      	Intent intent=new Intent("providerservice");
      	bindService(intent, new Myconnect(),  BIND_AUTO_CREATE);
    //		try {
    //			is.sayhello();
    //		} catch (RemoteException e) {
    //			// TODO Auto-generated catch block
    //			e.printStackTrace();
    //		}
      }
        
        
        class Myconnect implements ServiceConnection
        {
    
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    					System.out.println("fuck");
    					 is=Iservicemethod.Stub.asInterface(service);
    						try {
    							is.sayhello();
    						} catch (RemoteException e) {
    							// TODO Auto-generated catch block
    							e.printStackTrace();
    						}
    					
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			// TODO Auto-generated method stub
    			
    		}
        	
        }
        class Myconnect2 implements ServiceConnection
        {
    		@Override
    		public void onServiceConnected(ComponentName name, IBinder service) {
    					System.out.println("fuck");
    					 is2=com.example.demoonlyservice.Iservicemethod.Stub.asInterface(service);
    						try {
    							is2.sayhello();
    						} catch (RemoteException e) {
    							// TODO Auto-generated catch block
    							e.printStackTrace();
    						}
    					
    		}
    
    		@Override
    		public void onServiceDisconnected(ComponentName name) {
    			// TODO Auto-generated method stub
    			
    		}
        	
        }
    
    
    }
    

      下面总结一下完成的步骤和注意的问题:

    1 、首先创建一个远程服务,demo里创建了2个,并且服务的名字相同,在清单文件里注册的action不同而已。服务里有个方法需要被其他的应用程序访问,即sayhello。

    2、定义一个接口,接口里有需要被调用的方法,名字不要与服务里需要的方法同名(具体说明见第一个服务里mybundle类实现的代码解释部分),去掉接口和方法前面的访问权限,即public,private等,并到相应文件目录下将接口扩展名修改为aidl,保存刷新项目,会发现在gen文件下的和接口同包名的目录下产生一个接口同名的java文件,点击进去发现里面的是我们写的接口,它里面有个Stub的子类,它继承了Bunle类并实现了我们的抱出去的接口里的方法,因此在服务里的onbind()返回去的Ibindl,实现该类的时候只需要继承Stub即可,在调用的应用程序里利用stub的asinstance方法实例将返回的Ibindle实例化成抛出的接口,利用这借口就可以调用服务里的方法了。

    自动生成的Iservicemethod 接口

    /*
     * This file is auto-generated.  DO NOT MODIFY.
     * Original file: D:\毕业设计\adt-bundle-windows-x86_64-20140321\workspace\demoOnlyservice\src\com\example\demoonlyservice\Iservicemethod.aidl
     */
    package com.example.demoonlyservice;
    public interface Iservicemethod extends android.os.IInterface
    {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.demoonlyservice.Iservicemethod
    {
    private static final java.lang.String DESCRIPTOR = "com.example.demoonlyservice.Iservicemethod";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
    this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.example.demoonlyservice.Iservicemethod interface,
     * generating a proxy if needed.
     */
    public static com.example.demoonlyservice.Iservicemethod asInterface(android.os.IBinder obj)
    {
    if ((obj==null)) {
    return null;
    }
    android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
    if (((iin!=null)&&(iin instanceof com.example.demoonlyservice.Iservicemethod))) {
    return ((com.example.demoonlyservice.Iservicemethod)iin);
    }
    return new com.example.demoonlyservice.Iservicemethod.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
    {
    switch (code)
    {
    case INTERFACE_TRANSACTION:
    {
    reply.writeString(DESCRIPTOR);
    return true;
    }
    case TRANSACTION_sayhello:
    {
    data.enforceInterface(DESCRIPTOR);
    this.sayhello();
    reply.writeNoException();
    return true;
    }
    }
    return super.onTransact(code, data, reply, flags);
    }
    private static class Proxy implements com.example.demoonlyservice.Iservicemethod
    {
    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 sayhello() throws android.os.RemoteException
    {
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    try {
    _data.writeInterfaceToken(DESCRIPTOR);
    mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);
    _reply.readException();
    }
    finally {
    _reply.recycle();
    _data.recycle();
    }
    }
    }
    static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    public void sayhello() throws android.os.RemoteException;
    }
    

      3、写一个类mybindle继承stub,在该类里调用服务里的方法来覆写接口里的方法,在onbindle里调用返回给开启服务的程序。 

       4 、在其他的应用程序里创建一个包名,注意包名必须与调用接口aidl所在的原应用程序里的包名相同,将源程序里的接口的aidl文件拷贝到包下,同源服务一样,应用程序下会自动生成aidl文件对应的包名和接口。再调用bindservice开启服务。

      5、实现一个类myconnection,即开启服务的第二个参数,它需要实现ServiceConnection接口,实现接口方法,有方法onServiceConnected(ComponentName name, IBinder service),它是在连接服务成功后返回的Ibindle的时候执行,里面第二个参数就是返回的Ibinlde,它继承了Stub,通过stub里方法实例化service为接口IService = IService.Stub.asInterface(service),利用接口就可以调用服务里的方法。

    注意:在运行的程序的时候发现,点击button响应事件startservice(View v)和startonlyservice(View v)时,在绑定服务了后,用接口调用远程服务方法时候,接口为空,就是说还没初始化。通过打印结果的顺序发现:点击事件执行完了才会去执行的回调事件,即onServiceConnected(ComponentName name, IBinder service)。我将绑定服务的代码移到oncreate方法在程序启动就绑定的服务,在点击事件里再通过接口调用服务里的方法就没错了。

    打印的顺序:

  • 相关阅读:
    rgba()和opacity的比较(转)
    CSS定位以及z-index属性(层叠性)的详解(转)
    hadoop 集群HA高可用搭建以及问题解决方案
    服务容错模式
    分布式系统基础总结
    当Kubernets遇上阿里云 -之七层负载均衡(一).
    HAProxy负载均衡原理及企业级实例部署haproxy集群
    基于Docker Compose构建的MySQL MHA集群
    使用 Mesos 管理虚拟机
    VMware VSAN 入门与配置(一)
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/4733722.html
Copyright © 2011-2022 走看看