专栏首页写代码和思考Android开发(12) 无线网络和GPRS连接

Android开发(12) 无线网络和GPRS连接

概述

启用gprs连接?难道说不是自动就调用网络了么?是呀,android 会默认调用当前的活动的网络. 那么什么是活动的网络呢? 看如下代码:

  ConnectivityManager cm = (ConnectivityManager) m_context
  .getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();

使用服务方式获得连接管理器,然后获得当前的活动网络信息.那么这个网络信息都可能是什么呢? 我在说使用中发现,如果wifi打开的话,那么当前的活动网络指向wifi.如果未打开,那么指向默认的apn.

什么是APN?

看下来自百度百科的解释:APN(Access Point Name),即“接入点名称”,是您在通过手机上网时必须配置的一个参数,它决定了您的手机通过哪种接入方式来访问网络,用来标识GPRS的业务种类,目前分为两大类:CMWAP/UNIWAP/3GWAP(通过GPRS访问WAP业务)、CMNET/UNINET/3GNET(除了WAP以外的服务目前都用CMNET,比如连接因特网等)。<摘自:http://baike.baidu.com/view/668.htm>

简单来说: APN 就是一个连接的设置.通过apn可以设置一个拨号连接,通过该拨号连接可以连接到 "网络提供商" 的服务器,由网络 提供商为你提供接入互联网的服务.这个网络提供商,可能是中国移动,联通,电信.

那么这个活动网络的优先级别可能是: 1.如果wifi打开,则指向wif 2.指向一个默认的(活动的,或者'当前的')apn.

APN怎么设置?

一般是用户设置好的.如果你是中国移动的手机卡,那你就要设置 中国移动提供的apn地址.这个地址一般都是固定的,网上也都能搜索到.


那么切入正题,我们在开发软件的时候,有时候需要调用网络连接.可能我们已经写好一个程序,比如说.我们写一个发送EMAIL的程序, 该程序会接入互联网,将EMAIL发送出去.那么在我们的这个应用程序中,我们如何写代码调用当前的网络么?其实...

答案是: 什么都不用写? 吓,开玩笑是吧? 玩我的是吧? 怎么能不写? 我们在本文开头大概了解了,活动网络.实际上android或默认 通过 当前的活动的网络 来为应用程序提供网络的使用服务.也就是说你的 应用程序在调用网络时,会默认使用 android系统默认的活动网络连接.那么,我们如果开启了wifi正常,如果没开启wifi,那就是用默认的apn.实际上,你的应用程序可以仅仅做到这一步. 网络连接的方式交给用户自己去连接,使用者决定使用是wifi,或者自己切换apn.android系统提供了移动网络的设置功能。

问题是: 这样真的行么? 我们看看实际使用环境会出现的问题,apn有很多中,可能是 中国移动的wmwap,wmnet,3g,联通的,电信的等. 由于网络运行商不同,提供的apn接入方式也不同..那可咋办?如果我是移动用户,我的apn指向wap方式,而我的应用程序是需要wmnet方式的.那我的程序就不能用了,必须让用户手动切换APN才行,而用户自己可能根本不懂apn(也可能懂,但很麻烦).

我的解决方案:

1.先获得当前活动的网络,尝试连接,如果可用(通畅),那么就用当前的. 2.如果不可能,活动默认的apn,再次尝试连接,如果通畅,则用当前的. 3.遍历apn列表,尝试连接,如果可能,则用.

也就是.尝试多个方式,直到找到一个可以用的为止.方法很笨,但是能解决问题.

APN相关的操作

android提供了contentProvider来提供apn的数据.我们直接操作这个就行了.切换apn时,使用content://telephony/carriers/preferapn, 更改这个内容就行了. 如果遍历apn? 数据存储在 content://telephony/carriers.同样用contentProvider来操作数据. 更多的操作数据的和contentProvider的使用,请阅读开发文档和google

贴出我的代码.我写了两个类,一个操作apn的,一个用于多次尝试连接网络的类.使用多次尝试连接 http://www.baidu.com/ 来确定是否连接到互联网.

  package surveySys.Core;
    
    import java.util.ArrayList;
    import java.util.List;
    import android.content.BroadcastReceiver;
    import android.content.ContentResolver;
    import android.content.ContentValues;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.database.Cursor;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.net.Uri;
    import android.util.Log;
    
    public class APNHelper {
     public static final Uri CURRENT_APN_URI = Uri
       .parse("content://telephony/carriers/preferapn");
    
     public static final Uri APN_URI = Uri.parse("content://telephony/carriers");
    
     private Context m_context;
     private ContentResolver m_ContentResolver;
    
     public APNHelper(Context ctx) {
      super();
      if (ctx == null) {
       throw new NullPointerException("m_context");
      }
      m_context = ctx;
      m_ContentResolver = m_context.getContentResolver();
     }
    
     /*
      * 获得当前的apn编号
      */
     public String getCurrentApnId() {
      Cursor cur = null;
      try {
       cur = m_ContentResolver.query(CURRENT_APN_URI, null, null, null,
         null);
       if (cur != null && cur.moveToFirst()) {
        String apnID = cur.getString(cur.getColumnIndex("_id"));
        cur.close();
        return apnID;
       }
       return null;
      } catch (Exception e) {
       e.printStackTrace();
       return null;
      } finally {
       if (cur != null) {
        cur.close();
       }
      }
    
     }
    
     /*
      * 获得当前的apn
      */
     public APN getCurrentAPN() {
      List<APN> lst = getApnList();
      String id = getCurrentApnId();
      APN tmp = null;
      for (APN apn : lst) {
       if (apn._id.equals(id)) {
        tmp = apn;
        break;
       }
      }
      return tmp;
     }
    
     /*
      * 设置当前的apn
      */
     public boolean setCurrentAPN(String apnId) {
      try {
       ContentValues values = new ContentValues();
       values.put("apn_id", apnId);
       m_ContentResolver.update(CURRENT_APN_URI, values, null, null);
    
       return true;
      } catch (Exception e) {
       e.printStackTrace();
       return false;
      }
     }
    
     /*
      * 获得apn列表
      */
     public List<APN> getApnList() {
      return query(null);
     }
    
     /*
      * 获得有效的apn列表
      */
     public List<APN> getValidApnList() {
      return query("current=1");
     }
    
     public class APN {
      public String name;
      public String numeric;
      public String _id;
      public String mcc;
      public String mnc;
      public String apn;
      public String user;
      public String server;
      public String password;
      public String proxy;
      public String port;
      public String mmsproxy;
      public String mmsport;
      public String mmsc;
      public String authtype;
      public String type;
      public String current;
    
      public APN(String name, String numeric, String id, String mcc,
        String mnc, String apn, String user, String server,
        String password, String proxy, String port, String mmsproxy,
        String mmsport, String mmsc, String authtype, String type,
        String current) {
       super();
       this.name = name;
       this.numeric = numeric;
       _id = id;
       this.mcc = mcc;
       this.mnc = mnc;
       this.apn = apn;
       this.user = user;
       this.server = server;
       this.password = password;
       this.proxy = proxy;
       this.port = port;
       this.mmsproxy = mmsproxy;
       this.mmsport = mmsport;
       this.mmsc = mmsc;
       this.authtype = authtype;
       this.type = type;
       this.current = current;
      }
    
      public APN() {
       super();
      }
    
      public String toString() {
    
       return String
         .format(
           "name=%s,numeric=%s,_id=%s,mcc=%s,mnc=%s,apn=%s,user=%s,server=%s,password=%s,proxy=%s,port=%s,mmsproxy=%s,mmsport=%s,mmsc=%s, authtype=%s,type=%s,current=%s,",
           name, this.numeric, _id, mcc, mnc, apn, user,
           server, password, proxy, port, mmsproxy, mmsport,
           mmsc, authtype, type, current);
      }
     }
    
     /*
      * 查找
      */
     public List<APN> query(String query) {
      List<APN> lst = new ArrayList<APN>();
      Cursor cur = null;
      try {
       cur = m_ContentResolver.query(APN_URI, null, query, null, null);
       while (cur != null && cur.moveToNext()) {
        APN apn = new APN();
        apn.name = cur.getString(cur.getColumnIndex("name"));
        apn.numeric = cur.getString(cur.getColumnIndex("numeric"));
        apn._id = cur.getString(cur.getColumnIndex("_id"));
        apn.mcc = cur.getString(cur.getColumnIndex("mcc"));
        apn.mnc = cur.getString(cur.getColumnIndex("mnc"));
        apn.apn = cur.getString(cur.getColumnIndex("apn"));
        apn.user = cur.getString(cur.getColumnIndex("user"));
        apn.server = cur.getString(cur.getColumnIndex("server"));
        apn.password = cur.getString(cur.getColumnIndex("password"));
        apn.proxy = cur.getString(cur.getColumnIndex("proxy"));
        apn.port = cur.getString(cur.getColumnIndex("port"));
    
        apn.mmsproxy = cur.getString(cur.getColumnIndex("mmsproxy"));
        apn.mmsport = cur.getString(cur.getColumnIndex("mmsport"));
        apn.mmsc = cur.getString(cur.getColumnIndex("mmsc"));
        apn.authtype = cur.getString(cur.getColumnIndex("authtype"));
        apn.type = cur.getString(cur.getColumnIndex("type"));
        apn.current = cur.getString(cur.getColumnIndex("current"));
        lst.add(apn);
       }
       return lst;
      } catch (Exception e) {
       e.printStackTrace();
       return null;
      } finally {
       if (cur != null) {
        cur.close();
       }
      }
     }
    
    }

代码:

    package surveySys.Core;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.List;
    
    import surveySys.Core.APNHelper.APN;
    import surveySys.Dev.TestModule.ActTest;
    
    import android.content.Context;
    import android.content.Intent;
    import android.net.ConnectivityManager;
    import android.net.NetworkInfo;
    import android.net.NetworkInfo.State;
    import android.provider.Settings;
    
    public class NetHelper {
    
     private Context m_context;
     // private static final String URLNameForTry = "http://www.google.com/";
    
     public String URL_ForTry = "http://www.baidu.com/";
    
     public NetHelper(Context context) {
      super();
      if (context == null) {
       throw new NullPointerException("context");
      }
      m_context = context;
     }
    
     private boolean open(String urlForTry) {
      
      this.URL_ForTry = urlForTry;
      if (checkNetworkState(m_context)) {
       if (tryGetURL(m_context, urlForTry)) {
        return true;
       }
      }
      // 判断网络是否可用,不可用,尝试启用 gprs APN
      if (trySwitchToValidApn(m_context, urlForTry)) {
       return true;
      }
      return false;
     }
    
     public static boolean TryConnect(Context ctx, String urlForTry) {
      if (ctx == null) {
       throw new NullPointerException("Context");
      }
      if(!urlForTry.startsWith("http://"))
      {
       throw new IllegalArgumentException("测试使用的网址参数参数必须以http://开头");
      }
      NetHelper scope = null;
      scope = new NetHelper(ctx);
      return scope.open(urlForTry);
     }
    
     /*
      * 无线网络配置界面
      */
     public static void OpenActivityWIRELESS_SETTINGS(Context ctx) {
      // startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
      // //进入手机中的wifi网络设置界面
      ctx.startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));// 进入无线网络配置界面
     }
    
     /*
      * 进入手机中的wifi网络设置界面
      */
     public static void OpenActivityWIFI_SETTINGS(Context ctx) {
      ctx.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
     }
    
     /*
      * 检测网络设置
      */
     private boolean checkNetworkState(Context context) {
    
      ConnectivityManager conMan = (ConnectivityManager) context
        .getSystemService(Context.CONNECTIVITY_SERVICE);
    
      NetworkInfo[] infoArray = conMan.getAllNetworkInfo();
      for (int i = 0; i < infoArray.length; i++) {
       NetworkInfo var = infoArray[i];
       System.out.println(String.format("%s", var));
      }
    
      // mobile 3G Data Network
      State mobile = conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
        .getState();
    
      State wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
        .getState();
    
      if (wifi == State.CONNECTED || wifi == State.CONNECTING) {
       return true;
      }
    
      // 如果3G网络和wifi网络都未连接,且不是处于正在连接状态 则进入Network Setting界面 由用户配置网络连接
      if (mobile == State.CONNECTED || mobile == State.CONNECTING) {
       return true;
      }
    
      return false;
     }
    
     public static String getCurrentNetInfo(Context ctx) {
      ConnectivityManager cm = (ConnectivityManager) ctx
        .getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo info = cm.getActiveNetworkInfo();
      String str = "无";
      if (info != null) {
    
       str = info.getState().name();
      }
      return String.format("%s,%s,%s", info.getTypeName(), info
        .getExtraInfo(), info.getState());
     }
    
     /*
      * 超时时间10秒
      */
     public boolean tryGetURL(Context ctx, String urlStr) {
      try {
       URL url = new URL(urlStr);
       HttpURLConnection urlConn = (HttpURLConnection) url
         .openConnection();
    
       // 使用HttpURLConnection打开连接
       HttpURLConnection urlConn1 = (HttpURLConnection) url
         .openConnection();
       // 得到读取的内容(流)
    
       InputStreamReader in = new InputStreamReader(urlConn
         .getInputStream());
       // 为输出创建BufferedReader
    
       String resultData = "";
       BufferedReader buffer = new BufferedReader(in);
       String inputLine = null;
       // 使用循环来读取获得的数据
       while (((inputLine = buffer.readLine()) != null)) {
        // 我们在每一行后面加上一个"\n"来换行
        resultData += inputLine + "\n";
       }
       // 关闭InputStreamReader
       in.close();
       // 关闭http连接
       urlConn.disconnect();
    
       return resultData != null;
      } catch (Exception e) {
       e.printStackTrace();
       String str = e.getMessage();
       return false;
      }
     }
    
     private boolean trySwitchToValidApn(Context context, String urlForTry) {
      try {
       APNHelper helper = new APNHelper(context);
       APN currentApn = helper.getCurrentAPN();
       boolean isConnectied = false;
       if (currentApn != null) {
        isConnectied = tryGetURL(context, urlForTry);
        if (isConnectied) {
         return true;
        }
       }
       List<APN> lst = helper.getValidApnList();
       for (APN apnTemp : lst) {
        if (apnTemp == null) {
         continue;
        }
        if (currentApn != null) {
         if (apnTemp._id.equals(currentApn._id)) {
          continue;
         }
        }
        helper.setCurrentAPN(apnTemp._id);
        try {
         Thread.sleep(11000);
        } catch (Exception e) {
        }
    
        ConnectivityManager cm = (ConnectivityManager) m_context
          .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        String str = "无";
        if (info != null) {
         int i = 0;
         while (info.getState() != State.CONNECTED) {
          try {
           Thread.sleep(1000);
          } catch (Exception e) {
          }
          if (i++ > 3) {
           break;
          }
         }
        }
        isConnectied = tryGetURL(context, urlForTry);
        String st1 = String.format("apn=%s,type=%s,canConnected=%s",
          apnTemp.apn, apnTemp.type, isConnectied);
        System.out.println(st1);
        if (isConnectied) {
         return true;
        }
       }
       return false;
      } catch (Exception e) {
       e.printStackTrace();
       return false;
      }
     }
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android开发 - 处理 null 和 预防空指针异常(NullPointerException) 的一些经验

    比如: 通过intent传参到新的目标 activity,而且一定需要这个参数,那么在新的目标activity中 onCreate方法中 判断中这个参数,如果n...

    zhangyunfeiVir
  • Android开发 - 汉字转拼音首字母

    工作中经常会遇到的一些排序问题,比如 按汉字的拼音首字母排序,比如人名排序等,就要用到下面的方法了,思路:

    zhangyunfeiVir
  • Android开发(49) Snackbar 底部弹出提醒

    Snackbar 类似toast,用于向 用户展示信息,和用户交互,它能够显示一个 按钮 获得用户的操作。它的特点如下:

    zhangyunfeiVir
  • Android WebView 上传文件支持全解析

    声明:原文地址:http://blog.isming.me/2015/12/21/android-webview-upload-file/,转载请注明出处。 默...

    非著名程序员
  • ASP.NET MVC5+EF6+EasyUI 后台管理系统(32)-swfupload多文件上传[附源码]

    文件上传这东西说到底有时候很痛,原来的asp.net服务器控件提供了很简单的上传,但是有回传,还没有进度条提示。这次我们演示利用swfupload多文件上传,项...

    用户1149182
  • Spring MVC ControllerAdvice深入解析

      Spring 在3.2版本后面增加了一个ControllerAdvice注解。网上的资料说的都是ControllerAdvice配合ExceptionHan...

    良辰美景TT
  • Android拍照或者选取本地图片

    从selectPhotoActivity中启动图册或者相机,再根据获取的uri进行裁剪,返回uri,再对这个uri执行一系列操纵。

    用户1665735
  • 小程序谁都能注册?Naive!| 小程序问答 #31

    那么,哪些个人或者组织,才能注册小程序呢?每个人、每个组织,又可以注册多少个小程序呢?

    知晓君
  • 小程序开发|我有实体店,为什么还要做小程序?

    如果要让我来回答这个问题,那么我的答案会是:因为你的客户在用微信啊!但很多老板,似乎认为这个理由还不够充足,那好,我今天就跟大家详细的聊一下。

    用户1745481
  • 干货丨小程序功能解读白皮书(五)

    此次小程序官方发布“小程序可关联最多50个公众号”,据悉被关注的50个公众号没有主体限制,这意味着,小程序推广者可以主动出击,将企业小程序在一个月内投放在50个...

    齿轮易创说互联网

扫码关注云+社区

领取腾讯云代金券