• Android -- Service绑定解绑和aidl


    Service是安卓四大组件之一,先前讲到了Service的生命周期,以及非绑定类型的生命周期的例子,这次来分享一下绑定形式的。

    应用组件(客户端)可以调用bindService()绑定到一个service。Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder。

    绑定是异步的,bindService()会立即返回,它不会返回IBinder给客户端。要接收IBinder,客户端必须创建一个ServiceConnection的实例并传给bindService()。ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder。

    • 实现ServiceConnection

    实现必须重写两个回调方法:

    onServiceConnected()

    系统调用这个来传送在service的onBind()中返回的IBinder。

    OnServiceDisconnected()

    Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用。

    • 调用bindService(),传给它ServiceConnection的实现。

    • 当系统调用你的onServiceConnected()方法时,你就可以使用接口定义的方法们开始调用service了。

    • 要与service断开连接,调用unbindService()。

    • 程序                                                                                          

      public class MainActivity extends Activity {
      
          private Button btn_start;
          private Button btn_stop;
          private Button btn_change;
          private Button btn_bind;
          private Button btn_unbind;
          
          private MyConn myConn;
          
          private IService myBinder;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
              btn_start = (Button) findViewById(R.id.btn_start);
              btn_stop = (Button) findViewById(R.id.btn_stop);
              btn_change = (Button) findViewById(R.id.btn_change);
              btn_bind = (Button) findViewById(R.id.btn_bind);
              btn_unbind = (Button) findViewById(R.id.btn_unbind);
              buttonListener bl = new buttonListener();
              btn_change.setOnClickListener(bl);
              btn_start.setOnClickListener(bl);
              btn_stop.setOnClickListener(bl);
              btn_bind.setOnClickListener(bl);
              btn_unbind.setOnClickListener(bl);
      
              
      
          }
      
          class buttonListener implements OnClickListener
          {
      
              @Override
              public void onClick(View v) {
                  switch (v.getId()) {
                  case R.id.btn_start:
                      Intent intent_start = new Intent(getApplicationContext(),BindService.class);
                      startService(intent_start);
                      break;
                  case R.id.btn_stop:
                      Intent intent_stop = new Intent(getApplicationContext(),BindService.class);
                      stopService(intent_stop);
                      break;
                  case R.id.btn_change:
                      if(myBinder != null)
                          myBinder.doChange("啦啦啦");
                      break;
                  case R.id.btn_bind:
                      if(myConn == null)
                      {
                          myConn = new MyConn();
                          Intent intent_bind = new Intent(getApplicationContext(),BindService.class);
                          bindService(intent_bind, myConn, BIND_AUTO_CREATE);
                      }
                      break;
                  case R.id.btn_unbind:
                      Intent intent_unbind = new Intent(getApplicationContext(),BindService.class);
                      if(myConn != null && myBinder != null)
                      {
                          unbindService(myConn);
                          myConn = null;
                          myBinder = null;
                      }
                      break;
      
                  default:
                      break;
                  }
      
              }
      
          }
          
          private class MyConn implements ServiceConnection
          {
      
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  System.out.println("代理人返回回来了,onServiceConnected");
                  myBinder = (IService) service;
                  
              }
      
              @Override
              public void onServiceDisconnected(ComponentName name) {
                  System.out.println("接触绑定了,onServiceDisconnected");
                  
              }
              
          }
          
          
      }

      Service类:

      public class BindService extends Service {
      
          @Override
          public IBinder onBind(Intent intent) {
              System.out.println("Service绑定成功,onBind");
              //返回自定义的代理对象
              return new MyBinder();//这里的返回是返回到MainActivity里面的绑定myConn
          }
          
          
          
          @Override
          public boolean onUnbind(Intent intent) {
              System.out.println("Service解绑成功,onUnbind");
              return super.onUnbind(intent);
          }
      
      
      
          public class MyBinder extends Binder implements IService
          {
              //间接的利用代理人调用了changeServiceThing的方法
              public void doChange(String what)
              {
                  changeServiceThing(what);
              }
          }
      
          @Override
          public void onCreate() {
              System.out.println("Service开启,onCreate");
              super.onCreate();
          }
      
          @Override
          public void onDestroy() {
              System.out.println("Service关闭,onDestroy");
              super.onDestroy();
          }
          
          public void changeServiceThing(String what)
          {
              Toast.makeText(getApplicationContext(), what+"变换了,changeServiceThing", Toast.LENGTH_LONG).show();
          }
      
          
          
      }

      IService:

      public interface IService {
          public void doChange(String what);
      }

      结果                                                                                           

      点击“开启服务”之后,再“绑定服务”,这样执行之后直接点“关闭服务”是没用的,要先“解除服务”,再“关闭服务”。如果直接“绑定服务”,那么点击“关闭服务”没有用,需要点击“解绑服务”。

      aidl                                                                                           

      进程间通信->调用者和Service如果不在一个进程内,就需要使用android中的远程Service调用机制。

      android使用AIDL定义进程间的通信接口。AIDL的语法与java接口类似,需要注意以下几点:

      • AIDL文件必须以.aidl作为后缀名。
      • AIDL接口中用到的数据类型, 除了基本类型, String, List, Map, CharSequence之外, 其他类型都需要导包, 即使两种在同一个包内. List和Map中的元素类型必须是AIDL支持的类型。
      • 接口名需要和文件名相同。
      • 方法的参数或返回值是自定义类型时, 该自定义的类型必须实现了Parcelable接口。
      • 所有非java基本类型参数都需要加上in, out, inout标记, 以表明参数是输入参数, 输出参数, 还是输入输出参数。
      • 接口和方法前不能使用访问修饰符和static, final等修饰。

      进程间通信需要创建aidl文件,IService.aidl:

      public interface IService {
          public void doChange(String what);
      }

      接口中有一个static的抽象内部类Stub,Stub类继承了Binder类并实现了IRemoteService接口。

      public class MainActivity extends Activity {
      
          private Intent intent;
          private IService iService;
          private ServiceConnection myConn;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
      
          }
      
          public void bind(View view) {
              intent = new Intent();
              intent.setAction("com.yydcdut.alipay");
              myConn = new MyConn();
              boolean flag = bindService(intent, myConn, BIND_AUTO_CREATE);
              System.out.println("flag------>" + flag);
          }
      
          private class MyConn implements ServiceConnection {
              @Override
              public void onServiceConnected(ComponentName name, IBinder service) {
                  iService = IService.Stub.asInterface(service);
              }
      
              @Override
              public void onServiceDisconnected(ComponentName name) {
              }
          }
      
          public void method(View view) {
              try {
                  iService.callMethodInService();
              } catch (RemoteException e) {
                  // TODO 自动生成的 catch 块
                  e.printStackTrace();
              }
          }
      
      }

      在实现这个的时候我建立了两个程序,这样可以做到进程间通信。附带了源码。

      我是天王盖地虎的分割线                                                               

      源代码:http://pan.baidu.com/s/1dD1Qx01

      service学习2.zip

      aidl学习.zip

      aidl学习配套2.zip

      转载请注明出处:http://www.cnblogs.com/yydcdut

  • 相关阅读:
    C#泛型
    Chrome 中调试Javascript
    Oracle分页查询语句
    WordCount2.2
    第一周博客作业
    WordCount--统计输入文件的字符数、行数、单词数(java)--初级功能
    PHP数据库操作
    PHP安全函数
    PHP基础
    用户/目录操作
  • 原文地址:https://www.cnblogs.com/yydcdut/p/3810816.html
Copyright © 2020-2023  润新知