android四大组件之service(一)

                    目录

        一服务的概念

        二服务的创建方式

                <1>服务的创建的具体步骤

                <2>服务创建的具体实例

         三服务的启动方式以及相应启动方式之下的生命周期方法

                <1>非绑定式
                           <1.1>非绑定式启动服务的具体的方式
                           <1.2>非绑定式启动服务,那么相对应的这个服务Service的所走的生命周期方法以及服务所在的进程的级别
                            <1.3>采用非绑定式启动服务的目的
                 <2>绑定式
                             <2.1>绑定式启动服务的具体的方式
                              <2.2>绑定式启动服务,相对应的这个服务Service的生命周期以及服务所在的                                        进程的级别
                              <2.3>使用绑定式启动服务的目的
                  <3>混合式
                               <3.1>混合式启动服务的具体方式
                               <3.2>混合式启动后的服务的生命周期以及服务所在的进程的级别
                                <3.3>使用混合式启动服务的目的

          四服务与activity之间的通信

                 <1>服务与activity之间的通信的概述    
                 <2>服务与activity之间的通信 的一般版
                                <2.1>实现服务与activity之间的通信的过程的大概描述
                                <2.2>具体的代码例子
                <3>服务与activity之间的通信 的改进版(添加了接口)
                                <3.1>代码改进的原因描述
                                <3.2>改进之后的代码   
                 <4>服务与activity之间的通信的实质(即通过绑定式启动服务,从而让activity和service进行通信的本质)

            五启动远程服务

                     5.1什么叫做远程服务?什么叫做本地服务?
                     5.2启动远程服务和启动本地服务有什么不同?
                     5.3启动远程服务(绑定式启动和非绑定式启动)的实质,以及为什么要使用aidl?
                     5.4启动远程服务的代码实例

            六进程间通信的AIDL

                      6.1创建aidl的普通的方法(也可以在android studio中使用):
                      6.2在android studio创建aidl
                      6.3创建aidl文件后,启动远程服务实现activity和它的通信的代码变化
                                        <1>创建aidl之后,启动远程服务的代码变化
                                        <2>创建aidl,启动远程服务的全部代码实例(远程办证)

             七进程的优先级

              八注意点

一服务的概念

一服务的概念

       Service是android四大组件之一,运行在后台的组件,没有前台界面,用于运行需要在后台执行代的代码。
       Service和activity一样需要在清单文件中注册才能使用。
       Service可以被显示启动,也可以被隐士启动,对于显示启动而言,配置intent-filter是没有用的,只有隐士启动server的时候,此时才会有用。
       Service是context的一个子类,activity也是context的子类,但是BroadCastReceiver不是context的子类。
       创建一个类A继承Service,android系统中只有有一个类A的对象,不会被重复创建,因为Servic不是被new出来,是通过Intent来启动的,而且创建的这个动作是由android系统做的,并不是我们使用代码做的。

二服务的创建方式

           <1>服务的创建的具体步骤

 <1.1>创建一个类继承Service,重写其生命周期方法oncreate(),onBind(),onUnbind(),onstartCommand(),onDestroy()
 <1.2>在清单文件中注册,根节点是service

           <2>服务创建的具体实例

			<2.1>创建一个类继承Service

public class MyService extends Service {

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		System.out.println("onBind");
		return null;
	}
	
	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		System.out.println("onUnbind");
		return super.onUnbind(intent);
	}
	
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		System.out.println("onCreate");
	}
	
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		System.out.println("onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}
	
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		System.out.println("onDestroy");
	}

}

		<2>在清单文件中进行注册
       <service android:name="com.itheima.runservice.MyService"></service> 

三服务的启动方式以及相应启动方式之下的生命周期方法

              服务的启动方式有两种,第一种是调用非绑定式,第二种是绑定式,第三种就是混合式的。但是不管是绑定式的,还是非绑定式的,都是通过Intent来启动service的。

              <1>非绑定式

                      <1.1>非绑定式启动服务的具体的方式

				1>使用的方法:
                		startService(Intent intent):启动服务
                        stopService(Intent intent);关闭服务

				2>代码如下:

					public void start(View v){
    						Intent intent = new Intent(this, MyService.class);
    						startService(intent);
    				}
    				public void stop(View v){
    						Intent intent = new Intent(this, MyService.class);
    						stopService(intent);
 				   }

                        <1.2>非绑定式启动服务,那么相对应的这个服务Service的所走的生命周期方法以及服务所在的进程的级别

				1>此时的生命周期方法是oncreate()------onStartCommand()-----onDestroy(),重复调用startService(),此时系统会不断的重复走onStartCommand() 方法,而重复的stopService()则什么也不会做。,其实服务Service的生命周期方法有onStart(),但是现在已经废弃不用了,使用onStartCommand()来代替onStart()方法了。
                2>此时该服务所在的进程就变成了一个服务进程(服务一旦被启动,当启动这个服务的activity死了之后,该服务还是会一直存在)。

                         <1.3>采用非绑定式启动服务的目的

				为了让服务所在的进程变成一个服务进程,提高该进程的优先级。

              <2>绑定式

                    <2.1>绑定式启动服务的具体的方式

			1>绑定式启动服务所使用的方法:
            		//第一个参数:Intent类型,通过Intent来启动服务
                    //第二个参数:ServiceConnection的子类对象,通过它来实现activity访问服务中的方法
                    //第三个参数:服务的创建方式,一般都是BIND_AUTO_CREATE
					bindService(intent, conn, BIND_AUTO_CREATE);
					//第一个参数:ServiceConnection的子类对象
					unbindService(conn);
				当我们要实现开启一个服务和关闭这个服务,此时上述两个方法中的ServiceConneciton的子类对象必须是同一个。
                
            2>绑定式启动服务的具体代码:

public void bind(View v){
    	Intent intent = new Intent(this, MyService.class);
    	bindService(intent, conn, BIND_AUTO_CREATE);//绑定服务
    }
   
    public void unbind(View v){
    	unbindService(conn);//解绑服务
    }

//这是主要的参数:
private MyServiceConn conn;
class MyServiceConn implements ServiceConnection{


		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			
		}

	
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			
		}
    	
    }

                      <2.2>绑定式启动服务,相对应的这个服务Service的生命周期以及服务所在的进程的级别

			1>此时的生命周期方法是oncreate()---onBind()------onUnbind()----onDestroy(),此时重复的绑定服务(即重复的调用bindService()方法绑定服务),此时系统什么也不做,不会重新走oncreate()和onBind()方法;当时重复的解绑服务(即重复的调用unbinderService()来解绑服务),此时系统会崩掉(原因是服务已经解绑过了,此时再重新解绑服务,此时这个服务就是一个没有绑定过的服务,所以程序就崩掉了)
            2>该服务所在的进程不会变成一个服务进程(一旦绑定服务,当执行绑定服务这个动作的activity死了,那么此时这个服务就会自动直接执行onUnbinder()--onDestroy()方法,即这个服务直接就解绑并且销毁了;但是当这个服务执行了unbindService()的代码从而解绑了之后,此时这个activity是可以存在的),此时服务所在的进程该是什么进程就是什么进程。

                         <2.3>使用绑定式启动服务的目的

			为了让activity可以访问service中的方法,通过Ibinder这个中间者。

            <3>混合式

                       <3.1>混合式启动服务的具体方式

			<1>其实就是两种方式都是用,代码如下:

private MyServiceConn conn= new MyServiceConn();


 public void start(View v){
    	Intent intent = new Intent(this, MyService.class);
    	startService(intent);
    }
    public void stop(View v){
    	Intent intent = new Intent(this, MyService.class);
    	stopService(intent);
    }
    
    public void bind(View v){
    	Intent intent = new Intent(this, MyService.class);
    	bindService(intent, conn, BIND_AUTO_CREATE);
    }
   
    public void unbind(View v){
    	unbindService(conn);
    }
    private MyServiceConn conn;
    class MyServiceConn implements ServiceConnection{

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			
		}
    }

                        <3.2>混合式启动后的服务的生命周期以及服务所在的进程的级别

			<1>混合启动的依次调用的方法为:startService()--->bindService()->unbindService()-->stopServer(),注意这个过程一般来说不要变,否则容易出问题;在执行上述方法的时候,serview执行的周期方法如下:(注意:所谓的混合式启动可以是startService()+bindService()+unbindService(),也可以是startService()+bindService()+unbindService()+stopService(),或者startService()+bindService()就是这三种了),使用混合式启动服务,每个对应的方法所走的生命周期方法,如下图:
              在混合方式启动service之后,重复的点击startService()方法,系统会重复的走onStartCommand()周期方法:重复的点击bindService()方法,系统什么也不会干;重复的点击unbindService()方法,此时系统会崩溃掉;重复的点击stopService方法,此时系统什么也不会做。
            <2>使用混合式方式启动服务,此时服务所在的进程会变成一个服务进程。

                         <3.3>使用混合式启动服务的目的

一方面是为了将服务Service所在的进程变成一个服务进程,提高该进程的优先级;第二个方面为了让activtiy可以调用服务Service中的方法。

四服务与activity之间的通信

                         <1>服务与activity之间的通信的概述   

			 <1>所谓的服务与activity之间的通信,其实就是在activity中调用服务Service中的方法,通过Ibinder这个中间者。
             <2>只有通过绑定式启动的服务才能实现activity和服务之间的通信。
             <3>Ibinder是如何充当中间者的?
             		 什么是中间者?比如说, 两个地方的某个对象是一样的,然后这两个地方通过这个一样的对象进行通信,而这个在两个地方一样的对象就是中间者,Ibinder就是这样的,
                     在代码中的具体体现就是:binderService方法的第二个参数(ServiceConnection的子类对象)中的方法onServiceConnected的第二个参数(IBinder service)和
                     Service中onbind()方法的返回值IBinder对象,这个IBinder对象是同一个对象。     
             <4>Ibinder是一个接口,有很多的抽象方法需要实现,在android中有一个实现了Ibinder接口的基本类Binder,所以我们基本都使用Binder来代替Ibinder

                         <2>服务与activity之间的通信 的一般版

                                    <2.1>实现服务与activity之间的通信的过程的大概描述

                      **首先确定该server是以绑定的方式进行启动的,再调用bindService(Intent intent,ServiceConnect connect ,创建方式(一般为自动创建)),此时创建一个内部类B类用于继承ServiceConenction类,有两个方法要实现onServiceConnect( IBinder ibinder),onServicedisConnect().
                       **在继承server的子类中创建一个内部类A类继承Binder类(Binder类为实现IBinder接口的一个基础类) ,然后在该内部类(即A类)中创建一个方法D用于调用继承server的子类中的方法。
                       **在继承server的子类中的Onbinder()方法中,直接返回上述内部类(即A类)即可。
                       **在绑定服务的activity中,  创建一个全局变量C---A类对象,然后将在B类的方法onServiceConect(IBinder ibinder)上的形参 ibinder通过强转赋值给C。
                        **此时就可以通过对象C来调用 方法D,从而达到调用继承Server的子类中的方法了。

                                    <2.2>具体的代码例子

//1这是activity中的代码
public class Main3Activity extends AppCompatActivity {

    //在这声明一个全局变量(service中继承了Binder类的子类的对象)
    MyServer.Renmishu mishu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        initView();
        Intent intent = new Intent(this, MyServer.class);
        bindService(intent, new MyServiceConnection(), BIND_AUTO_CREATE);
    }


    public class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //此处的IBinder对象service就是继承了Service的子类中的onBinder()方法的返回值。
            //通过强转将IBinder对象service转成全局变量mishu(service中继承了Binder类的子类的对象)
            if (null == mishu) {
                mishu = (MyServer.Renmishu) service;
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    private void initView() {
        Button bt_banzheng = (Button) findViewById(R.id.bt_banzheng);
        bt_banzheng.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //3.在这里通过对象调用其方法, 因为这个对象已经被赋值了。
                mishu.banzhengle();
            }
        });
    }
    

// 2.这是继承了Service的子类。
    public class MyServer extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //返回内部类对象,传递这个对象,一般activity中获取该对象。
        return new Renmishu();
    }


    //Binder类是实现了IBinder接口的一个子类。
    //1.创建一个内部类用于继承Binder对象(这是一个桥梁),然后在该类中创建一个方法调用Myserver中的方法。
    public class Renmishu extends Binder {
        public void banzhengle() {
            banzheng();
        }
    }

    //这是Myserver中的方法。
    public void banzheng() {
        Log.d("qindong", "banzheng");
    }
}

                         <3>服务与activity之间的通信 的改进版(添加了接口)

                                     <3.1>代码改进的原因描述

 在继承了service的子类中,有些方法(A方法)是可以让activity进行访问的,
 但是有些方法(B方法)是不想让activity进行访问的,但是此时在继承了service的子类中的内部类C类
 (继承了Binder类)处于某种需要,必须在本类中创建方法来调用B方法(不想让activity访问的方法),
 此时在activity就可以直接方法B方法了,为了避免这个问题,一下方案:直接创建一个接口,在接口中定义一些方法,
 让C类去实现这个接口,然后我们就可以将那些想让activity访问的方法让直接写到这些接口定义的方法中,
 而那些不想让activity访问的方法则不定义为这个接口的方法;在activity中,我们也不用创建C类对象了,
 而是创建接口对象,通过接口对象调用C类中接口定义的方法即可。

                                     <3.2>改进之后的代码  

//1.创建的接口
public interface BusinessInterface {
public void banzhengle();
}

//2.继承了Service的子类
public class MyServer extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //返回内部类对象,传递这个对象,一般activity中获取该对象。
        return new Renmishu();
    }


    //Binder类是实现了IBinder接口的一个子类。
    //1.创建一个内部类用于继承Binder对象(这是一个桥梁),然后在该类中创建一个方法调用Myserver中的方法。
    //实现接口BusinessInterface,将MyServer中的想让activity访问和不想让activity访问的方法区分开
    //而接口中定义的方法就是会直接调用MyServer中想让activity访问的方法
    public class Renmishu extends Binder implements BusinessInterface {

        @Override
        public void banzhengle() {
            banzheng();
        }
    }

    //这个方法是想让activity访问的。
    public void banzheng() {
        Log.d("qindong", "banzheng");
    }

    //这个方法是不想让activity访问的。
    public void yule() {
        Log.d("qindong", "哈哈哈");
    }

}

//3.activity的代码
public class Main3Activity extends AppCompatActivity {

    //在这声明一个全局变量(service中继承了Binder类的子类的对象)
    //MyServer.Renmishu mishu;
    //此处将上述对象换成接口对象
    BusinessInterface mishu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        initView();
        Intent intent = new Intent(this, MyServer.class);
        bindService(intent, new MyServiceConnection(), BIND_AUTO_CREATE);
    }


    public class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //此处的IBinder对象service就是继承了Service的子类中的onBinder()方法的返回值。
            //通过强转将IBinder对象service转成全局变量mishu(service中继承了Binder类的子类的对象)
            if (null == mishu) {
                //此处就是多态,子类对象指向了父类引用。
                mishu = (MyServer.Renmishu) service;
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

    private void initView() {
        Button bt_banzheng = (Button) findViewById(R.id.bt_banzheng);
        bt_banzheng.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //3.在这里通过对象调用其方法,
                mishu.banzhengle();
            }
        });
    }
}

                    <4>服务与activity之间的通信的实质(即通过绑定式启动服务,从而让activity和service进行通信的本质)

				使用BindService()方法绑定服务,此时会调用服务中的oncreate()和onbind()方法,当onbind()方法有返回值的时候,此时系统就会调用bindservice()方法中第二个参数中的方法onServiceConnect(Ibind ibind),将onbind()方法的返回值赋值给onServiceConnect(Ibind ibind)方法中的Ibind对象;但是当onbind()方法没有返回值的时候,此时系统是不会调用bindservice()方法中第二个参数中的方法onServiceConnect(Ibind ibind)
这个需要验证;onServiceConnect()方法,onServiceDisConnect()方法----是之前服务已经绑定了(即onbind()方法有返回值),之后有解绑了,此时才会调用onServiceDisConnect()方法
                            对于远程服务而言,过程是一样的,当onbind()方法有返回值的时候,此时系统会调用onServiceConnect(Ibind ibind)方法,同时将onBind()方法中的返回值复制给该方法中的Ibind对象,也就是我们本地的activity其实已经拿到了远程服务的IBinder对象,但是问题是,我们如何对这个IBinder对象进行强转呢,因为之前创建的business接口和服务中的充当中间人的内部类都是在远程服务service中的呀,我们在一个应用中怎么拿到另一个应用中的服务service中创建的充当中间的内部类以及在服务所在项目中定义的接口呢,结果就是拿不到,所以此时就要使用进程间的通讯AIDL  
                 AIDL的实质:  
                 	在服务所在的项目和启动服务所在的项目都会有一个文件,business.aidl文件,系统会根据aidl文件,自动创建相关的java文件。也就是buiness.java类,此时的buiness还是一个接口,此时系统就会将两个business.java是为同一个类。而这个buiness.java类中有一个静态内部类Stub类,该Stub类继承了Binder和接口Business,此时我们就可以强转了,就实现了actiity和service的通信(也就是actiity可以调用service中的方法了)

五启动远程服务

               5.1什么叫做远程服务?什么叫做本地服务?

			<1>本地服务:activity和service在同一个项目中叫做本地服务
            <2>远程远程:actiivty和service不在同一个项目中叫做远程服务。

               5.2启动远程服务和启动本地服务有什么不同?

<1>启动方式不同:远程服务只能通过intent的隐士意图启动,而本地服务则通过Intent的显示意图和隐士意图都可以启动,只不过推荐使用Intent的显示意图而已。
    <2>当我们想要实现服务和activity之间进行通信,实现的过程不一样,
    	我们想要实现服务和activity之间进行通信,肯定是使用绑定式启动服务,此时
    		对于本地服务而言,就按照正常的步骤进行即可。
            对于远程服务而言,需要配合aidl才能实现这个效果。
        当时当我们使用非绑定式启动远程服务的时候,此时启动本地服务和启动服务的代码是一样的,都可以达到效果。

               5.3启动远程服务(绑定式启动和非绑定式启动)的实质,以及为什么要使用aidl?

<1>使用非绑定式方法启动远程服务的实质:
        		当我们使用startSerice()启动远程服务的时候,此时系统会寻找与该方法内的参数intent相匹配的Intnent-filter,且根节点是service,如果找到了,就调用该service的oncreate()和onStartCommand()方法,不过没有找到,那就算了,不报异常;当我们使用stopService()关闭远程服务的时候,此时系统还是回去寻找与本intent相匹配的intnet-filter,且根节点是service,如果找到了,就调用该service的ondestroy()方法,如果没有找到,那就算了,不报异常。
                
        <2>使用绑定式方式启动远程服务的实质
        		当我们在一个activity使用binderService()启动远程服务的时候,此时系统寻找与该方法内的参数intent相匹配的Intent-filter,且根节点是service,如果找到了,就调用该service类的oncreate()和onBind()方法,如果onBind()方法有返回值,不为null,此时系统就会将远程服务中的方法onbind()的返回值 跨进程的赋值给另一个应用(也就是activity所在的应用)中相对应的启动服务的方法binderService()中的第二个参数(ServiceConnection的子类)中的方法onServiceConnection(ComponentName name, IBinder service)中的第二个参数service;如果onBind()方法的返回值为null的时候,此时系统就不会调用activity中的bindservice的第二个参数中的onServiceConneciton()方法了。
                ;当系统没有找到与binderService内的参数intent相匹配的Intent-filter,且根节点是service的service的时候,那就算了,什么也不做,也不报异常。
                当我们在一个activity使用unBinderService()关闭远程服务的时候,此时与上述过程一样,先找到远程服务service,之后直接调用service的onUnbind()和ondestroy()方法。
             注意:也就是说只要远程服务中的onbind()方法有的返回值不为null的时候,此时activity就可以拿到远程服务中的onbind()方法的返回值,而IBinder的跨进程通信已经完成了。   
        
        <3>为什么要使用aidl?
			  首先说明,当我们使用非绑定启动远程服务的时候,是不需要使用aidl的;只有当我们使用绑定式或者混合式启动方式启动远程服务(使用binderService()方法了),想要和远程服务进行通信的时候,此时才需要使用到aidl.
              当我们使用binderService()方法启动远程服务,且远程服务的onbind()方法的返回值不为null的时候,此时我们已经拿到了onBind()方法的返回值了,也就是binderService()中的第二个参数(ServiceConnection的子类)中的onServiceConnection(ComponentName name, IBinder service)中的第二个参数service,我们此时想要通过该对象调用远程服务中的相关的方法的想法是不能实现的,当然,返回的对象实际上是远程服务Service中的内部类对象,该内部类继承了binder实现了拓展的接口(这里姑且叫做Business),但是此时这里是使用了多态,如下
              IBinder service=远程服务中继承了IBinder,实现了拓展的接口(姑且叫business)的一个内部类对象。
              因为参数service是IBinder类型的,而IBinder接口中是没有我们想要调用的特定的方法的,此时我们就需要进行强转,但是强转需要远程服务中的那个拓展的接口(business)和内部类对象呀,否则如何进行强转?此时aidl就应运而生了。
              AIDL的实质:  
                 	在服务所在的项目和启动服务所在的项目都会有一个文件,business.aidl文件,系统会根据aidl文件,自动创建相关的java文件。也就是buiness.java类,此时的buiness还是一个接口,此时系统就会将两个business.java是为同一个类。而这个buiness.java类中有一个静态内部类Stub类,该Stub类继承了Binder和接口Business,我们可以通过该Stub类的相关方法来进行强转,如下,这样就实现了actiity和service的通信(也就是actiity可以调用service中的方法了)
                   Bussinesss  bussinesss = Bussinesss.Stub.asInterface(service);
                   //此时就可以通过对象bussinesss就可以调用远程服务中相关的方法(当然这个方法需要在business中定义过)了

               5.4启动远程服务的代码实例

//1这是第一个应用,其中MainActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        Button mainactivity_bt_banzheng= (Button) findViewById(R.id.mainactivity_bt_banzheng);
        mainactivity_bt_banzheng.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //此时点击远程办证
                Intent intent=new Intent();
                intent.setAction("zhongguo.henan.qindong");
                bindService(intent, new ServiceConnection() {
                    @Override
                    public void onServiceConnected(ComponentName name, IBinder service) {
                        //其实系统已经将远程服务的IBinder对象拿过来了,只是我们无法处理而已
                        //输出的日志表明service不为null,且是一个对象了。而这个方法					                //onServiceConnected()也被调用了
                        Log.d("qindong","我们收到远程服务的消息了");
                        Log.d("qindong","我们收到Ibinder对象了,是:"+service.toString());
                        Log.d("qindong","我们收到的IBinder是否为null:"+(service==null));
                    }
                    @Override
                    public void onServiceDisconnected(ComponentName name) {

                    }
                },BIND_AUTO_CREATE);
            }
        });

    }
}


//2.这是第二个应用,其中继承了Service的子类BanZhengService.java

public class BanZhengService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //2 返回我们的内部类对象。
        return new MyStub();
    }

    public void banzheng(){
        Log.d("qindong","我来远程给你办证了");
    }

    //1创建一个内部类继承Binder,实现接口Business
    public class MyStub extends Binder implements Business{

        @Override
        public void banzheng() {
            BanZhengService.this.banzheng();
        }
    }
}
//3.这是第二个应用,具体的接口Business.java

public interface Business {
    void banzheng();
}

//4.这是第二个应用的清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.trueregistrationoneapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".BanZhengService">
            <intent-filter>
                <action android:name="zhongguo.henan.qindong"/>
            </intent-filter>
        </service>
    </application>
</manifest>

六进程间通信(即本地activity和远程服务之间的通信)的aidl

                       6.1创建aidl的普通的方法(也可以在android studio中使用):

 *********远程服务所在的项目
                                1.创建AIDl文件,把定了中间人方法的接口文件后缀名修改aidl
                                2.aidl文件中的所有方法和变量以及本身的接口都是默认为public的,所以说不能再定义访问权限修饰符
                                3.然后sync一下项目,让系统根据aidl文件生成接口文件,接口文件中有一个静态抽象类Stub,这就是新的中间人。
                    **********activity所在的项目
                           1.将远程服务所在的项目的aidl文件复制到本项目中,要保证aidl文件包名一致,然后将工程重新编译,即sync一下。
                           		在项目中,所谓的包名是从目录下
                                  src/main/java/之后的是包名,在两个项目中只需要保证在两个项目中java之后,aidl文件的目录一致就行了。
                           2.在onServiceConnected方法中,使用Stub的方法asInterface将IBinder对象service强转为接口的对象(这里使用了多态,即父类引用指向了子类对象)

                       6.2在android studio创建aidl

                                        <1> 这是启动服务的项目,首先点击main目录,创建一个aidl文件夹:如图

 

                                        <2>在aidl文件夹中直接创建aidl文件,在aidl文件夹,创建一个新的aidl文件,然后将该文件中的类的所有东西直接删除,将我们写好的aidl文件中的接口的内容直接复制过来就行,如图:

 

 

                                         <3>aidl文件写好之后,要将项目sync一下,点击如图按钮:

 

                                         <4>接下来就是处理远程服务所在的项目的aidl文件了,首先在远程服务所在的项目中,如第一步中创建一个aidl文件夹。

 

                                        <5>进入到启动服务的项目中的aidl文件夹中,直接将复制我们所需要的com包,复制到远程服务所在的项目的aidl文件夹下,然后重新编译以下服务所在的项目即可,如图所示

 

 

 

                                        <6>最后的结果如下,那就成功了:

 

 

                       6.3创建aidl文件后,启动远程服务实现activity和它的通信的代码变化

                                <1>创建aidl之后,启动远程服务的代码变化

		当在activity所在的项目和远程服务所在的项目都已经有aidl文件了,此时代码的修改如下:
        <1>对于远程服务而言,原来内部类继承Binder实现接口Business,现在内部类直接继承Business接口中的Stub类即可。
        <2>对于activity其启动服务的应用而言,binderService的第二个参数中的方法onServiceConnection(ComponentName name, IBinder service)中,使用Stub的方法asInterface将IBinder对象强转成为中间人接口Business的子类对象,这样我们就可以调用远程服务service中的内部类的实现了接口的方法了。

            //这里使用了多态,即父类引用指向了子类对象。
            business = Businesss.Stub.asInterface(service);

                                <2>创建aidl,启动远程服务的全部代码实例(远程办证)

//1.这是第二项目中的远程服务Service

public class RemoteOneService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d("qindong", "onBind");
        return new zhongjianren();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("qindong", "onUnbind");
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        Log.d("qindong", "onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("qindong", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d("qindong", "onDestroy");
        super.onDestroy();
    }

    //在aidl文件生成的接口文件中,该Stub是一个静态的抽象类,其继承了Binder类,并且实现了Businesss接口,
    //所以在这直接继承Stub就行了。
    public class zhongjianren extends Businesss.Stub{
        public void zhaorenbanzhang() {
            banzheng();
        }
    }
    //远程办证
    public void banzheng(){
        Log.d("qindong","吴局长远程来帮你办证了!");
        System.out.print("吴局长远程来帮你办证了");
    }
}

//2.这是第一个项目中的activity

public class ServiceOneActivity extends Activity {

    private MyServiceConnection myServiceConnection = new MyServiceConnection();
    private Businesss business;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service_one);
        initView();
    }

    private void initView() {
        Button bt_start_service = (Button) findViewById(R.id.start_service);
        Button bt_bind_service = (Button) findViewById(R.id.bind_service);
        Button bt_unbind_service = (Button) findViewById(R.id.unbind_service);
        Button bt_stop_service = (Button) findViewById(R.id.stop_service);
        Button bt_banzheng = (Button) findViewById(R.id.bt_banzheng);

        bt_bind_service.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //使用隐示意图绑定远程服务
                Intent intent = new Intent("henan.sanmenxia.shanxian");
                intent.setDataAndType(Uri.parse("nishi:"), "text/name");
                bindService(intent, myServiceConnection, BIND_AUTO_CREATE);
            }
        });
        bt_unbind_service.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //解绑远程服务
                unbindService(myServiceConnection);
            }
        });
        bt_banzheng.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               //远程办证来进行(调用远程服务中的方法会有一个异常,在这里直接进行trycach就行。)
                //在aidl文件生成的接口文件中,这个远程方法抛出了一个异常,在这里直接进行捕获就行了。
                try {
                    business.zhaorenbanzhang();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    public class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //使用Stub的方法asInterface将IBinder对象强转成为中间人接口的子类对象。
            //这里使用了多态,即父类引用指向了子类对象。
            business = Businesss.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

}

七.进程的优先级:

####前台进程(foreground Process):优先级最高,一般不会被杀死,如果被杀死了,内存充足的时候,就会重启。

        1.该进程拥有一个正在可用户交互的activity(onresume()方法被调用)

         2.进程拥有一个正在执行onreceive()方法的广播接收者。

        3.进程拥有一个只在执行生命周期方法oncreate ondestroy onstartCommand()方法的回调方法的server(短暂的提高进程级别,保证该方法执行完)

        4.拥有一个“运行在前台”的服务--服务的startForeground()调用(提高进程级别,保证该进程的东西执行完)(用于保证服务的内容一定要执行完,可以继承Service的子类中直接调用上述方法,当这个内容执行完之后再调用stopForeground()方法来停止将这个server作为一个前台进程的作用,回归本来面目)

        5.进程拥有一个和前台activity绑定的服务的进程。(针对远程服务而言,当一个远程服务绑定到一个前台的activity时候,此时那个远程服务就是一个前台进程。)

####可见进程(available Process) :(不到万不得已的时候,该进程不会被杀死;真被杀死了,当内存充足的时候,该进程会被重新启动

          1.进程拥有一个不再前台但是对用于来说依旧可见的activity(onpause()方法执行)

            2.进程拥有以绑定到可见的activity的服务(这是说远程服务的,那个远程服务就是一个服务进程。)

####服务进程(server process):不到万不得已的时候,该进程不会被杀死;真被杀死了,当内存充足的时候,该进程会被重新启动

          1.进程中正在运行一个通过startService方法启动的服务的时候。(所以说下载的文件的时候一般用服务)

####后台进程(background Process):比较容易被杀死,而且不会重启

        1.拥有一个不可见的activity(onstop方法执行)

        2.当该进程拥有一个绑定感到不可见的activity的service的时候,且该activity没有调用unbind()方法时,此时这个服务所在的进程就是一个后台进程。

                例如:当app只有一个页面的时候,按下home键,此时app的进程就是一个后台进程。

####空进程(empty process):很容易就会被杀死,而且不会重启

        1.进程中没有任务活动的应用组件(activvity和service)

                例如:当app之后一个页面的时候,然后按下返回键,销毁了这个activity,那么此时这个app的进程就是一个空进程。

八注意点:

                8.1使用隐士启动方式启动服务注意点

Android 5.0对Service Intent的调用策略发生改变了,必须通过显示Intent来启动Service,如果想要隐士intent启动Service,需要如下做:
Intent intent = new Intent();
intent.setAction("要启动的servcie其在清单文件中配置的action");
intent.setPackage("要启动的service所在的项目的包名");
context.startService(intent);

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值