美文网首页
一些跨进程通信包括不同应用之间和同一应用不同进程之间

一些跨进程通信包括不同应用之间和同一应用不同进程之间

作者: niudeyang | 来源:发表于2018-04-11 11:25 被阅读13次

    跨进程之不通应用之间

    1在app中启动另外一个app
    A应用拉起B应用的非主页面的某个页面,并且传值(一般是鉴权token值、type值以及其他参数值,本文仅仅以传递type值为例),B应用根据传递过来的不同的值启动不同的页面。需要注意的是A应用拉起B应用的启动页(SplashActivity)并传值(token值和type值以及其他参数值),在启动页获取到值并且存储到SharedPreferences中,最好再存储一个Boolean值,代表这是从第三方应用拉起来的。然后有两种情况,通过Activity的管理工具类判断栈中是否含有B应用的主页面(即B应用是否已经运行在后台)①不含有:代表后台并没有运行B应用,那么我们正常启动主页面,在主页(MainActivity)从SharedPreferences中获取到这个Boolean值与A应用传递过来的值,由主页根据A应用传递过来的值打开相应的页面,这样用户点击返回顺序为:B应用相应页面-B应用主页面-A应用;②含有:代表B应用已经运行在后台,并且现在可能停留在某个页面,此时,我们不应该在启动页继续走启动主页面的逻辑了,如果继续启动主页面,由于我们设置了主页的启动模式为android:launchMode=”singleTask”,那么B应用栈中主页面以上页面都会出栈,用户将看不到刚刚浏览过的页面,这样太不友好了。因此此时的解决方案是我们要在启动页发个静态广播,在广播接收者中获取到SharedPreferences中的Boolean值与A应用传递过来的值,并且通过Activity的管理工具类获取到栈顶的Activity,然后在栈顶Activity的基础上启动相应的页面,(当然,这里也可以不发送广播,直接在启动页通过Activity的管理工具类获取到栈顶的Activity,然后在栈顶Activity的基础上启动相应的页面,这样效果是一样的)这样用户点击返回的顺序为:B应用相应页面-B应用用户拉起客户端之前浏览的页面-B应用主页面-A应用。

    b应用启动页清单文件配置
     <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
    
                <!--ACTION启动配置用于隐士启动app host path选填-->
                <intent-filter>
                    <data
                        android:host="pull.csd.demo"
                        android:path="/cyn"
                        android:scheme="csd" />
                    <action android:name="android.intent.action.VIEW" />
    
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
                </intent-filter>
    A应用启动B的代码
    Intent intent = new Intent();
                intent.setData(Uri.parse("csd://pull.csd.demo/cyn?type=110"));
                intent.putExtra("", "");//这里Intent当然也可传递参数,但是一般情况下都会放到上面的URL中进行传递
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
    B应用获取A传递的信息
     if(null!=intent&&null!=intent.data) {
                val uri:Uri = intent.data
                if (uri != null) {
                   Toast.makeText(this,uri.scheme + "--" + uri.host + "--" + uri.path + uri.getQueryParameter("type"),Toast.LENGTH_SHORT).show()
                }
            }
    

    2广播

    public class BroadcastActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_broadcast);
            View send = findViewById(R.id.send_broad_cast);
            send.setOnClickListener(v->{
                Intent intent=new Intent();
                intent.setAction("test_send_cast");
                intent.putExtra("info", "传递内容");
                sendBroadcast(intent);
                System.out.println("发送了广播");
            });
        }
    另外一个项目中接受广播
    package com.example.shanghai.daojishiapplication;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.text.TextUtils;
    
    public class ReceiveBroadcastActivity extends AppCompatActivity {
        BroadcastReceiver broadcastReceiver;
        IntentFilter intentFilter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_receive_broadcast);
            intentFilter=new IntentFilter();
            intentFilter.addAction("test_send_cast");
            broadcastReceiver=new MyReceiver();
            registerReceiver(broadcastReceiver,intentFilter);
        }
        class MyReceiver extends BroadcastReceiver
        {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                // TODO Auto-generated method stub
                if(intent!=null){
                    if(!TextUtils.isEmpty(intent.getAction())){
                        System.out.println("!TextUtils.isEmpty(intent.getAction()");
                    }
                    if(!TextUtils.isEmpty(intent.getStringExtra("info"))){
                       System.out.println(intent.getStringExtra("info"));
                    }
                }
            }
    
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(broadcastReceiver);
        }
    }
    
    

    3AIDL (Android interface definition language)
    在AndroidStudio 中新建aidl文件

    
    // Declare any non-default types here with import statements
    
    interface IMyAidlInterface {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                double aDouble, String aString);
               
                boolean forwardPayMoney(float money);
    
    
    }
    

    新建一个service隐士启动

            <service
                android:name=".service.ProvideService"
                android:enabled="true"
                android:exported="true"
                >
                <intent-filter>
                    <action android:name="com.example.shanghai.daojishiapplication.action.AIDL"></action>
                </intent-filter>
            </service>
    package com.example.shanghai.daojishiapplication.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.annotation.Nullable;
    
    import com.example.shanghai.daojishiapplication.IMyAidlInterface;
    
    /**
     * Created by shanghai on 2018/4/10.
     */
    
    public class ProvideService extends Service{
        private static final String TAG="ProvideService";
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            System.out.println(TAG+"onBind");
            return new MyBinder();
        }
    
        private class MyBinder extends IMyAidlInterface.Stub{
    
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
    
            }
    
            @Override
            public boolean forwardPayMoney(float money) throws RemoteException {
                System.out.println(TAG+"public boolean forwardPayMoney(float money) throws RemoteException");
                return false;
            }
        }
    }
    
    

    把main目录下的aidl包拷贝到在另外一个app中的main目录下build项目
    在activity中bindservice调用service中的方法

    package com.github.zackratos.rvitemam;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    
    import com.example.shanghai.daojishiapplication.IMyAidlInterface;
    
    public class TestAidlActivity extends AppCompatActivity {
    
      private View btn_bind;
      private View btn_invoke;
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_test_aidl);
          btn_bind = findViewById(R.id.btn_bind);
          btn_invoke = findViewById(R.id.btn_invoke);
    
          btn_bind.setOnClickListener(v->{
              System.out.println("TestAidlActivity--btn_bind");
              bindservice();
          });
          btn_invoke.setOnClickListener(v -> {
              System.out.println("TestAidlActivity--btn_invoke");
              try {
                  boolean b = mIService.forwardPayMoney(0.1f);
                  System.out.println("TestAidlActivity-forwarpay="+b);
              } catch (RemoteException e) {
                  e.printStackTrace();
              }
          });
      }
      /**
       * 绑定远程服务
       */
      public void bindservice() {
          Intent mIntent = new Intent();
          mIntent.setAction("com.example.shanghai.daojishiapplication.action.AIDL");
          mIntent.setPackage("com.example.shanghai.daojishiapplication");//需要指定提供服务的程序包名
          MyConnection myConnection = new MyConnection();
          bindService(mIntent, myConnection,BIND_AUTO_CREATE);
    
      }
    
      private IMyAidlInterface mIService;
    
      class MyConnection implements ServiceConnection {
          @Override
          public void onServiceConnected(ComponentName name, IBinder service) {
              mIService = IMyAidlInterface.Stub.asInterface(service);
          }
    
          @Override
          public void onServiceDisconnected(ComponentName name) {
    
          }
      }
    
    
    }
    
    

    4Messenger

    不需要创建aidl文件
    service隐士启动

    <service
              android:name=".service.MyService"
              android:enabled="true"
              android:exported="true"
              android:process=":remote">
              <intent-filter>
                  <action android:name="com.example.shanghai.daojishiapplication.service.MyService"></action>
              </intent-filter>
          </service>
    package com.example.shanghai.daojishiapplication.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.support.v4.app.INotificationSideChannel;
    import android.util.Log;
    
    /**
    * 与客户端跨进程通信
    */
    public class MyService extends Service {
      /** Command to the service to display a message */
      public static final int MSG_SAY_HELLO = 1;
      private static final String TAG ="wzj" ;
    
      /* 用于接收从客户端传递过来的数据 */
      class IncomingHandler extends Handler {
          @Override
          public void handleMessage(Message msg) {
              switch (msg.what) {
                  case MSG_SAY_HELLO:
                      System.out.println("thanks,Service had receiver message from client!");
                      Messenger client=msg.replyTo;
                      Message replyMsg=Message.obtain(null,MyService.MSG_SAY_HELLO);
                      Bundle bundle=new Bundle();
                      bundle.putString("reply","ok~,I had receiver message from you! ");
                      replyMsg.setData(bundle);
                      try {
                          client.send(replyMsg);
                      } catch (RemoteException e) {
                          e.printStackTrace();
                      }
                      break;
                  default:
                      super.handleMessage(msg);
              }
          }
      }
    
      /* 创建Messenger并传入Handler实例对象 */
      final Messenger mMessenger = new Messenger(new IncomingHandler());
    
      /* 当绑定Service时,该方法被调用,将通过mMessenger返回一个实现IBinder接口的实例对象 */
      @Override
      public IBinder onBind(Intent intent) {
          System.out.println("Service is invoke onBind");
          return mMessenger.getBinder();
      }
    
    
    }
    
    activity
    package com.github.zackratos.rvitemam;
    
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.content.pm.PackageManager;
    import android.content.pm.ResolveInfo;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    public class MessageActivity extends AppCompatActivity {
      /* 与服务端交互的Messenger */
      Messenger mService = null;
      /**
       * Flag indicating whether we have called bind on the service.
       */
      boolean mBound;
      private View btn;
      private StringBuffer printMessage = new StringBuffer();
      private View send;
      private View unbind;
      private String SERVICE_ACTION="com.example.shanghai.daojishiapplication.service.MyService";
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_message);
          btn = findViewById(R.id.btn_bind);
          send = findViewById(R.id.btn_send);
          unbind = findViewById(R.id.btn_unbind);
          btn.setOnClickListener(v -> {
              System.out.println("onClick-->bindService");
              Intent mIntent = new Intent();
              mIntent.setAction("com.example.shanghai.daojishiapplication.service.MyService");
              mIntent.setPackage("com.example.shanghai.daojishiapplication");//需要指定提供服务的程序包名
              bindService(mIntent, mConnection,BIND_AUTO_CREATE);
          });
    
          send.setOnClickListener(v -> {
              System.out.println("click"+"sayHello");
              sayHello();
          });
    
    
          unbind.setOnClickListener(v -> {
              if (mBound) {
                  System.out.println("onClick-->unbindService");
                  unbindService(mConnection);
                  mBound = false;
              }
          });
      }
    
      /* 实现与服务端链接的对象ServiceConnection */
      private ServiceConnection mConnection = new ServiceConnection() {
          public void onServiceConnected(ComponentName className, IBinder service) {
              System.out.println("onServiceConnected");
              /* 通过服务端传递的IBinder对象,创建相应的Messenger
               * 通过该Messenger对象与服务端进行交互 */
              mService = new Messenger(service);
              mBound = true;
          }
    
          public void onServiceDisconnected(ComponentName className) {
              // This is called when the connection with the service has been
              // unexpectedly disconnected -- that is, its process crashed.
              mService = null;
              mBound = false;
          }
      };
    
      public void sayHello() {
          if (!mBound) return;
          System.out.println("sayHello");
          // 创建与服务交互的消息实体Message
          Message msg = Message.obtain();
          msg.what=1;
          msg.replyTo=mRecevierReplyMsg;
          try {
              //发送消息
              mService.send(msg);
          } catch (RemoteException e) {
              e.printStackTrace();
          }
    
      }
    
      private static class ReceiverReplyMsgHandler extends Handler {
          private static final String TAG = "zj";
    
          @Override
          public void handleMessage(Message msg) {
              System.out.println("receiver message from service:");
              switch (msg.what) {
                  //接收服务端回复
                  case 1:
                      System.out.println("receiver message from service:" + msg.getData().getString("reply"));
                      break;
                  default:
                      super.handleMessage(msg);
              }
          }
    
    
      }
    
    
      private Messenger mRecevierReplyMsg = new Messenger(new ReceiverReplyMsgHandler());
    }
    
    

    2跨进程通信之与service之间

    (首先讲一下两种启动方式,Service以及service与activity交互)

    startService():
    1、启动服务对象多次启动同时只会产生一个,onCreate()方法只会在Service第一次被创建的时候调用,多次点击启动会执行多次onStartCommand()方法,onDestroy()方法只会在Service第一次被停止的时候调用,多次点击停止不会报异常,也不再执行onDestroy()方法。
    2、一旦启动,Service将一直运行在后台(run in the background indefinitely)即便启动Service的组件已被destroy。
    3、停止一个started服务有两种方法:
    (1)在外部使用stopService()手动停止。
    (2)在服务内部(onStartCommand方法内部)使用stopSelf()方法,使服务执行完毕后自动停止。比如说,一个start的Service执行在后台下载或上传一个文件的操作,完成之后,Service应自己停止。

    bindService()
    仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。(通过 unbindService()方法来关闭这种连接)

    service与activity交互

    (1)startService可以通过intent传递
    (2)bindservice()如果我们的服务仅供本地应用使用,不需要跨进程工作,则可以实现自有 Binder 类,让客户端通过该类直接访问服务中的公共方法。其使用开发步骤如下
    创建BindService服务端,继承自Service并在类中,创建一个实现IBinder 接口的实例对象并提供公共方法给客户端调用
    从 onBind() 回调方法返回此 Binder 实例。
    在客户端中,从 onServiceConnected() 回调方法接收 Binder,并使用提供的方法调用绑定服务。
    注意:此方式只有在客户端和服务位于同一应用和进程内才有效,如对于需要将 Activity 绑定到在后台播放音乐的自有服务的音乐应用,此方式非常有效。另一点之所以要求服务和客户端必须在同一应用内,是为了便于客户端转换返回的对象和正确调用其 API。服务和客户端还必须在同一进程内,因为此方式不执行任何跨进程编组
    (3)同一个进程eventbus也可
    (4)service在独立的进程中采用Messenger进行传递,或者aidl下面讲一下Messenger的使用方法,aidl放在后面跨进程通信中讲解

    package com.example.shanghai.daojishiapplication.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.support.v4.app.INotificationSideChannel;
    import android.util.Log;
    
    /**
     * 与客户端跨进程通信
     */
    public class MyService extends Service {
        /** Command to the service to display a message */
        public static final int MSG_SAY_HELLO = 1;
        private static final String TAG ="wzj" ;
    
        /* 用于接收从客户端传递过来的数据 */
        class IncomingHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_SAY_HELLO:
                        System.out.println("thanks,Service had receiver message from client!");
                        Messenger client=msg.replyTo;
                        Message replyMsg=Message.obtain(null,MyService.MSG_SAY_HELLO);
                        Bundle bundle=new Bundle();
                        bundle.putString("reply","ok~,I had receiver message from you! ");
                        replyMsg.setData(bundle);
                        try {
                            client.send(replyMsg);
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }
    
        /* 创建Messenger并传入Handler实例对象 */
        final Messenger mMessenger = new Messenger(new IncomingHandler());
    
        /* 当绑定Service时,该方法被调用,将通过mMessenger返回一个实现IBinder接口的实例对象 */
        @Override
        public IBinder onBind(Intent intent) {
            System.out.println("Service is invoke onBind");
            return mMessenger.getBinder();
        }
    
    
    }
    package com.example.shanghai.daojishiapplication;
    
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    
    import com.example.shanghai.daojishiapplication.service.MyService;
    
    public class MessageActivity extends AppCompatActivity {
        /* 与服务端交互的Messenger */
        Messenger mService = null;
        /**
         * Flag indicating whether we have called bind on the service.
         */
        boolean mBound;
        private View btn;
        private StringBuffer printMessage = new StringBuffer();
        private View send;
        private View unbind;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_message);
            btn = findViewById(R.id.btn_bind);
            send = findViewById(R.id.btn_send);
            unbind = findViewById(R.id.btn_unbind);
            btn.setOnClickListener(v -> {
                System.out.println("onClick-->bindService");
                //当前Activity绑定服务端
                bindService(new Intent(MessageActivity.this, MyService.class), mConnection,
                        Context.BIND_AUTO_CREATE);
            });
    
            send.setOnClickListener(v -> {
                sayHello();
            });
    
    
            unbind.setOnClickListener(v -> {
                if (mBound) {
                    System.out.println("onClick-->unbindService");
                    unbindService(mConnection);
                    mBound = false;
                }
            });
        }
    
        /* 实现与服务端链接的对象ServiceConnection */
        private ServiceConnection mConnection = new ServiceConnection() {
            public void onServiceConnected(ComponentName className, IBinder service) {
                /* 通过服务端传递的IBinder对象,创建相应的Messenger
                 * 通过该Messenger对象与服务端进行交互 */
                mService = new Messenger(service);
                mBound = true;
            }
    
            public void onServiceDisconnected(ComponentName className) {
                // This is called when the connection with the service has been
                // unexpectedly disconnected -- that is, its process crashed.
                mService = null;
                mBound = false;
            }
        };
    
        public void sayHello() {
            if (!mBound) return;
            System.out.println("sayHello");
            // 创建与服务交互的消息实体Message
            Message msg = Message.obtain(null, MyService.MSG_SAY_HELLO, 0, 0);
            msg.replyTo=mRecevierReplyMsg;
            try {
                //发送消息
                mService.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
    
        }
    
        private static class ReceiverReplyMsgHandler extends Handler {
            private static final String TAG = "zj";
    
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    //接收服务端回复
                    case MyService.MSG_SAY_HELLO:
                        System.out.println("receiver message from service:" + msg.getData().getString("reply"));
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
    
    
        }
    
    
        private Messenger mRecevierReplyMsg = new Messenger(new ReceiverReplyMsgHandler());
    }
    清单文件中配置
     <service
                android:name=".service.MyService"
                android:enabled="true"
                android:exported="true"
                android:process=":remote" />
    

    intentservice解决servcie不能执行耗时操作这一问题,service保活可以
    将service设置为前台服务,或者设置两个服务相互监听,在ondestory中发送广播
    在另外一个服务中接收到广播再start服务

    关于service更多使用方法信息参考(https://www.jianshu.com/p/086869a2f0ac

    相关文章

      网友评论

          本文标题:一些跨进程通信包括不同应用之间和同一应用不同进程之间

          本文链接:https://www.haomeiwen.com/subject/glvnhftx.html