Android开发之APN网络切换

本文介绍Android平台中关于APN网络切换的相关知识。
 
APN(Access Point Name),即“接入点名称”,用来标识GPRS的业务种类,目前分为两大类:CMWAP(通过GPRS访问WAP业务)、CMNET(除了WAP以外的服务目前都用CMNET,比如连接因特网等)。
 
APN的英文全称是Access Point Name,中文全称叫接入点,是您在通过手机上网时必须配置的一个参数,它决定了您的手机通过哪种接入方式来访问网络。
 
移动手机的默认上网配置有两种:CMWAP和CMNET。一些使用移动办公的大客户,通常会使用专用APN,其接入点随意定义,只要和该省运营商其他APN不冲突即可。
   
CMWAP也叫移动梦网,通过该接入点可接入一个比较大的移动私网,网内有大量的手机应用下载及资源访问。因为CMWAP不接入互联网,只接入移动运营商的私网,所以流量费用比较低廉。
   
CMNET也叫GPRS连接互联网,通常每个省的运营商会提供若干个Internet出口以供CMNET拨号用户使用。其流量费用较CMWAP要高一些。
   
目前国内销售的手机,如果是非智能机,通常已配置好CMWAP连接,智能机通常会配置CMWAP和CMNET连接。如需手动添加这些配置,请参考手机说明书。
   
专有APN在功能上可以和Internet的VPN做类比,实际上他就是基于GPRS的VPN网络。
 
专有APN常见组网方式
1,运营商部署一条专线接入到企业的网络中,局端和企业端路由器之间采用私有IP进行连接。
 
    2,局端互连路由器与GGSN采用GRE隧道连接。
 
专有APN的几个重要特点:
1,除非运营商分配一个Internet IP地址,否则计算机没有任何办法通过Internet访问该APN中的主机。
 
2,只有手机卡号在APN中的白名单之列,该手机才可以接入该APN。
 
3,企业客户可以建立一套RADIUS和DHCP服务器,GGSN向RADIUS服务器提供用户主叫号码,采用主叫号码和用户账号相结合的认证方式;用户通过认证后由DHCP服务器分配企业内部的静态IP地址。补充:该认证方式不一定适合于每个省的运营商,这取决于该省运营商的APN管理平台。
 
GPRS专网系统终端上网登录服务器平台的流程为:
  
1)用户发出GPRS登录请求,请求中包括由运营商为GPRS专网系统专门分配的专网APN;
 
  
2)根据请求中的APN,SGSN向DNS服务器发出查询请求,找到与企业服务器平台连接的GGSN,并将用户请求通过GTP隧道封装送给GGSN;
 
  
3)GGSN将用户认证信息(包括手机号码、用户账号、密码等)通过专线送至Radius进行认证;
 
  
4)Radius认证服务器看到手机号等认证信息,确认是合法用户发来的请求,向DHCP服务器请求分配用户地址;
 
  
5)Radius认证通过后,由Radius向GGSN发送携带用户地址的确认信息;
 
  
6)用户得到了IP地址,就可以携带数据包,对GPRS专网系统信息查询和业务处理平台进行访问。
 
下面是相关代码:
public void openAPN(){   
List list = getAPNList();  
        for (APN apn : list) {  
            ContentValues cv = new ContentValues();  
            cv.put("apn", APNMatchTools.matchAPN(apn.apn));  
            cv.put("type", APNMatchTools.matchAPN(apn.type));  
            getContentResolver().update(uri, cv, "_id=?", new String[]{apn.id});  
        }  
   }
 

  public void closeAPN(){   
List list = getAPNList(); 
       
        for (APN apn : list) {      
            ContentValues cv = new ContentValues();  
            cv.put("apn", APNMatchTools.matchAPN(apn.apn)+"mdev");  
            cv.put("type", APNMatchTools.matchAPN(apn.type)+"mdev");  
            getContentResolver().update(uri, cv, "_id=?", new String[]{apn.id});  
        }   
    }   
 

   private List getAPNList(){  
String tag = "Main.getAPNList()";  
        //current不为空表示可以使用的APN  
        String projection[] = {"_id,apn,type,current"};  
        Cursor cr = this.getContentResolver().query(uri, projection, null, null, null);  
        List list = new ArrayList();  
         
        while(cr!=null && cr.moveToNext()){  
            Log.d(tag, cr.getString(cr.getColumnIndex("_id")) + " " + cr.getString(cr.getColumnIndex("apn")) + " " + cr.getString(cr.getColumnIndex("type"))+ " " + cr.getString(cr.getColumnIndex("current")));  
            APN a = new APN();  
            a.id = cr.getString(cr.getColumnIndex("_id"));   
            a.apn = cr.getString(cr.getColumnIndex("apn"));  
            a.type = cr.getString(cr.getColumnIndex("type"));  
            list.add(a);  
        }  
         
        if(cr!=null)  
        cr.close();  
        return list;  
    }  
         
    public static class APN{  
        String id;  
        String apn;  
        String type;  
    } 

 
    /**
     * @Name: setDefaultApn
     * @Description: 设置默认APN
     * @param apnId
     * @return boolean 返回类型
     * @throws
     */
    public boolean setDefaultApn(int apnId) {
        boolean res = false;
        ContentResolver resolver = context.getContentResolver();
        ContentValues values = new ContentValues();
        values.put("apn_id", apnId);

        try {
            resolver.update(PREFERRED_APN_URI, values, null, null);
            Cursor c = resolver.query(PREFERRED_APN_URI, new String[] { "name",
                    "apn" }, "_id=" + apnId, null, null);
            if (c != null) {
                res = true;
                c.close();
            }
        } catch (SQLException e) {

        }
        return res;
}

 
    /**
     * 得到当前使用的APN
     * @return
     */
    public ApnNode getDefaultAPN() {
        String id = "";
        String apn = "";
        String name = "";
        String type = "";
        ApnNode apnNode = new ApnNode();
        Cursor mCursor = context.getContentResolver().query(PREFERRED_APN_URI,
                null, null, null, null);
        if (mCursor == null) {
            return null;
        }
        while (mCursor != null && mCursor.moveToNext()) {
            id = mCursor.getString(mCursor.getColumnIndex("_id"));
            name = mCursor.getString(mCursor.getColumnIndex("name"));
            apn = mCursor.getString(mCursor.getColumnIndex("apn"))
                    .toLowerCase();
            type = mCursor.getString(mCursor.getColumnIndex("type"))
                    .toLowerCase();
        }
        OLD_APN_ID = Integer.valueOf(id);
        apnNode.setName(name);
        apnNode.setApn(apn);
        apnNode.setType(type);
       
        System.out.println("old_name:" + name + "--old_apn:" + apn + "--old_type:" + type);
       
        return apnNode;
}

   
    /**
     * @Name: SwitchApn
     * @Description: 转换APN状态
     * @param 设定文件
     * @return void 返回类型
     * @throws
     */
    public void SwitchApn() {
        switch (GetCurrentNetType()) {
        case NET_3G:
            if (!IsCurrentEmergencyApn()) {
                EM_APN_ID = IsEmergencyApnExisted(EMERGENCY_APN);
                System.out.println(EM_APN_ID);
               
                if (EM_APN_ID == -1) {
                    setDefaultApn(AddEmergencyApn());
                } else {
                    setDefaultApn(EM_APN_ID);
                }
            }
           
            break;
        case NET_WIFI:
            break;
        case NET_OTHER:
            break;
        default:
            break;
        }
}

   
public final class APNMatchTools {  
    public static class APNNet{  
        /* 
        * 中国移动cmwap 
        */ 
        public static String CMWAP = "cmwap";  
        /*
        * 中国移动cmnet 
        */ 
        public static String CMNET = "cmnet";  
        //中国联通3GWAP设置 中国联通3G因特网设置 中国联通WAP设置 中国联通因特网设置  
        //3gwap 3gnet uniwap uninet  
        /*
        * 3G wap 中国联通3gwap APN 
        */ 
        public static String GWAP_3 = "3gwap";  
        /* 
        * 3G net 中国联通3gnet APN 
        */ 
        public static String GNET_3="3gnet";  
        /** 
        * uni wap 中国联通uni wap APN 
        */ 
        public static String UNIWAP="uniwap";  
        /** 
        * uni net 中国联通uni net APN 
        */ 
        public static String UNINET="uninet";  
         
        }  
         
        public static String matchAPN(String currentName) {  
            if("".equals(currentName) || null==currentName){  
            return "";  
        }  
         
        currentName = currentName.toLowerCase();  
         
        if(currentName.startsWith(APNNet.CMNET))  
            return APNNet.CMNET;  
        else if(currentName.startsWith(APNNet.CMWAP))  
            return APNNet.CMWAP;  
        else if(currentName.startsWith(APNNet.GNET_3))  
            return APNNet.GNET_3;  
        else if(currentName.startsWith(APNNet.GWAP_3))  
            return APNNet.GWAP_3;  
        else if(currentName.startsWith(APNNet.UNINET))  
            return APNNet.UNINET;  
        else if(currentName.startsWith(APNNet.UNIWAP))  
            return APNNet.UNIWAP;  
        else if(currentName.startsWith("default"))  
            return "default";  
        else return "";  
        // return currentName.substring(0, currentName.length() - SUFFIX.length());   
    }  
}  



<!-- 开关APN的权限 -->
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />


对于Android APN接入点相关的开发,有一个不错的开源项目APNDroid的源代码本地下载,里面包含了一个不错的Widget框架,大家可以通过APNDroid源码学习到有关接入点的相关问题,可以解决GPRS,尤其是国内的CMNET、CMWAP的切换和管理。工程API Level为3,可以运行在Android 1.5或更高的版本上。
 
下载地址:点击下载 http://www.2cto.com/uploadfile/2012/0330/20120330114042736.zip

 
完毕。^_^
 

 

摘自  HarHar
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值