技术开发 频道

Android开发如何实现APN网络切换

  【IT168技术】本文介绍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());

  }

  }

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

0
相关文章