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,他就会匹配自己管理的服务对外端口,然后返回给你,然后让服务器和客户端正常通信就可以了。

posted on 2014-03-23 17:59  张海玉  阅读(1807)  评论(0编辑  收藏  举报