• Android系统是一个基于BInder通信的C/S架构


    Android系统基本上可以看作是一个基于Binder通信的C/S架构。他有服务器端和客户端。比如自己开发一个程序,肯定是基于Activity的而Activity就是作为客户端,他的服务器端就是ActivityManagerService。

    1.Activity客户端和他的服务器ActivityManagerService通信

    客户端和服务器通信都是客户端发出请求,由服务器端来响应的,比如WWW服务就是客户端先知道服务器的地址,然后就可以通过浏览器来访问了。首先我们假设客户端知道服务器的地址(实际上是代理,先不考虑),当Activity要启动的时候,就告诉服务器要求启动,然后服务器就开始启动Activity。

    Intent intent =new Intent(this, FirstActivity.class);//FirstActivity携带者APK安装包的信息,在Android目录结构的时候会详细介绍
            Bundle bundle=new Bundle();
            bundle.putString("test", "FirstActivity Bundle传值");
            startActivity(intent);#向服务器发送请求要求启动FirstActivity.class

    web客户端能让服务器正确启动是因为有一个唯一不重复的URL来标识命令的。Android这个C/S服务也是一样的,Intent在Android也是唯一的。Intent携带的FirstActivity的信息可以唯一的定位到一个Activity的。(PackageManger通过Parse每个Application的AndroidManifest.xml文件,能获得所有Activity的信息,只要把Intent交给PackageManager就可以唯一的定位到一个Activity了。针对每个Intent提供的信息,PM会提供给AMS一个ResolveInfo对象)。就像WWW服务会有很多客户端一样,AMS提供了一个ArrayList mHIstory来管理所有的activity,Activity在AMS中的形式是ActivityRecord。知识拓展:android Application Component研究之Activity(一)

    2.Service客户端和他的服务器ServiceManger的通信

    Service也是有自己的服务器端的就是ServiceManger,这个并不是SystemService提供的服务而是linux init加载的第一个进程,是用来管理服务的,SystemService是java包装的管理系统核心服务的服务,并不是所有的服务都能注册到systemService里的,哪些不能注册的都是由ServiceManger在管理。当然ServiceManger不是java实现的。知识扩展:android service 启动过程 当Service发出startService请求的时候,ServiceManager就会根据Intent找到Service文件的位置,并加载到内存中,如果加载成功就会调用ServiceConnection方法,如果连接建立就会执行 否则就会执行onServiceConnected(ComponentName name, IBinder service)方法,如果连接失败就会执行onServiceDisconnected(ComponentName name)方法。类比Socket通讯连接建立后就是往客户端的Socket写入信息,这里也是如果和服务器建立了连接就会往发送一个服务器端的引用,然后客户端就可以像使用自己的功能一样使用服务端的功能了。

    package com.example.servicedemo3;
    
    import android.os.Bundle;
    import android.os.IBinder;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.view.Menu;
    
    public class MainActivity extends Activity {
        
        
        ServiceConnection connection =new ServiceConnection() { //调用connection是由ServiceManger来调用的,试想这个代码里我们没有在OnCreate方法里调用ServiceConnection,那为什么就能连接服务器哪,现在服务器还没有联通更不可能是服务器调用到自己的连接,不是客户端调用不是服务器端调用自然就是第三方ServieManger调用了。
            
            @Override
            public void onServiceDisconnected(ComponentName name) {
            
    //现在服务器连接已经失败了,服务器什么也做不了了            
            }
            
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                ServiceDemo.MyBlinder mb =(ServiceDemo.MyBlinder)service; //调用成功后就会通过BInder来通讯,所以这里的数据是服务器可以作用的了
                mb.checkWifi();
                
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    //        bindService(new Intent(MainActivity.this, ServiceDemo.class), connection, BIND_AUTO_CREATE);
            
            startService(new Intent(this, ServiceDemo.class)); //向ServieManger申请启动Service
            
            
            
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
    }

    服务端:

    package com.example.servicedemo3;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;
    
    public class ServiceDemo extends Service {
        
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            // TODO Auto-generated method stub
            Log.d("Start COmmand","Startcommad 调用");
            return super.onStartCommand(intent, flags, startId);
        }
        
    
        @Override
        public IBinder onBind(Intent intent) {  //客户端能获得的引用就是这里返回的,也就是这里如同给客户端写数据的ServiceSocket了
            // TODO Auto-generated method stub
            return new MyBlinder();
            
        }
        
        class MyBlinder extends Binder{ //这里就是服务器端的功能调用
            
            public void checkWifi(){
                
                System.out.println("----------------------------");
                System.out.println("------------CheckWIfi----------------");
                Log.d("CHeckWIFT","Service------------------");
                
                
            }
            
        }
    
    }

      3.为什么服务器不是直接和客户端通讯要通过第三方?

    Android内部不是只有一个服务几个客户端,一个服务或很少服务的时候,客户端能直接访问服务器的前提知道服务器的URL,也就是像WWW这中服务,服务是事先对外生命了确定的服务端口的,所以客户端可以直接访问。但是Android有这么多的服务,如果每个都对外声明一个端口那么这个表是非常庞大的,并且一般分配无法动态回收的,所以这样这个系统实现起来是很不好的,关键还是对外暴露了过多的访问端口,对系统的安全性和API的复杂度影响很大。而用了ServiceManger(主要是Linux)和SystemServie(java时间的核心服务管理)和MediaServer就等同于对外没有暴露很多的端口,而是暴露了这很少的几个,只要把需求告诉ServiceManager,他就会匹配自己管理的服务对外端口,然后返回给你,然后让服务器和客户端正常通信就可以了。

  • 相关阅读:
    spart快速大数据分析学习提纲(一)
    Zookeeper的设计模式之观察者模式(十)
    shuffle机制和TextInputFormat分片和读取分片数据(九)
    MapReduce程序开发之流量求和(八)
    分布式系统间通信之RPC简单Demo(七)
    使用JAVA客户端对HDFS进行代码编写(五)
    分布式系统间通信之RPC的基本概念(六)
    DataNode工作原理(四)
    NameNode元数据的管理机制(三)
    javaweb项目部署到服务器(树莓派)上全过程——部署步骤记录与总结
  • 原文地址:https://www.cnblogs.com/zhanghaiyublog/p/3619328.html
Copyright © 2020-2023  润新知