年前发现一个问题, 我们平台搞出来的Android 支付SDK在android 4.0下面出异常了。

查log,发现是在httpClient做http request的时候出异常, 异常如下

android.os.NetworkOnMainThreadException


原因是Google从3开始,强制默认禁止UI主线程发起通信请求,看来Google越来越重视UI体验了。这是好事情


对应的方法, 有两个:

1. 可以临时性的 在Activity初期化的时候,指定StickMode,可以绕开这个OS check, 不过别把这个当彻底的解决方法

具体说起来, 就是在要通信的画面的Activity的OnCreate方法中如下配置stickMode

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath().build());


2. 永久性的对应, 把通信的代码转移到子线程里去做, 比较靠谱的是new一个AyncTask,在里面做通信

有几个细节性的问题是,

第一, 一般原有通信的代码都是共通的API, 被许多个Activity调用, 一个良好的修改方法是在共通API里面new AyncTask

第二, 通信的API一般来说都是同步的, 你通信,然后画面主线程需要堵塞住,等待API的通信结果,再决定下面的业务逻辑的走向。

所以,这块可以采取 AyncTask.get(), 让主线程堵塞,直到通信结束。 当然,如果你需要将通信异步的话, 可以用Handler机制来解决

第三, 用来通信的AyncTask中不能再请求其他子线程, 比如你不能在AyncTask中调用以下的代码

String userAgent = SystemInfo.getUserAgentFromWebView(context);

原因是WebView在App中本身是已单独的子线程的模式存在


具体的代码如下

a. 异步的http请求线程

class HttpReqTask extends AsyncTask<Object, Object, HttpResponse>{         @Override    protected HttpResponse doInBackground(Object... params){                String url = (String)params[0];        String session = (String)params[1];        List<NameValuePair> paierList  = (ArrayList<NameValuePair>)params[2];        HttpClient httpclient  = (HttpClient)params[3];                HttpPost request = new HttpPost(url);        HttpResponse response = null;        if (session != null && session.length() != 0) {            request.addHeader(SM.COOKIE, "sessid" + "=" + session);        }        try {            request.setEntity(new UrlEncodedFormEntity(paierList, HTTP.UTF_8));            response = httpclient.execute(request);        } catch (Exception e) {            throw new RuntimeException(e);        }        return response;    }    }

b.调用的代码

        Object []param = new Object[4];        param[0] = url;        param[1] = session;        param[2] = paierList;        param[3] = httpclient;        AsyncTask res  = new HttpReqTask().execute(param);                HttpResponse response = null;        try {            response = (HttpResponse) res.get();        } catch (Exception e) {            Log.e("HttpAPI.callHttpPost()", "Error", e);        }

#以上#

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 解决: AOSP 编译AndroidQ preview 失败
  3. Android与单片机通信常用数据转换方法总结
  4. Android(安卓)内存泄漏检测
  5. ConditionVariable控制通知栏消息变更
  6. Android(安卓)去掉标题栏,状态栏,导航栏
  7. android快捷设置标题样式布局
  8. Android(安卓)定时器实现的几种方式和removeCallbacks失效问题详
  9. 在线查看android源代码的3种方式

随机推荐

  1. Android(安卓)仿微信“正在输入...”效果
  2. android 环境的安装配置
  3. android httpClient 支持HTTPS的访问方式
  4. android开发过程遇到的一些错误
  5. Android通过URL获取网络资源
  6. [译]Android图形系统 II 图形架构
  7. android实现语音合成
  8. android绘图Path类仿加速球水面波动效果
  9. 如何在android上支持JNA
  10. Android 2.3禁止系统弹出应用程序强制退