android 使用HttpClient访问网络 服务器端与客户端交互问题
解答:初步判断,json解析有问题。一般情况下,解析json必须要明确json字符串的内容。通俗地来讲,就是说你要知道整个json字符串的结构组成,有几个大括号{},包括嵌套的大括号{},有几个中括号[],包括嵌套的[]。然后由外及内,最外层肯定是大括号{},就是一个json对象,也就是JsonObject,接着再在这一层,看看有没有中括号[],有的话就是json数组,也就是JsonArray,当前层的字段值可以根据当前层的json对象和字段名获取。如此,往内再走下一层json对象,也就是说查看第二个大括号{},依此类推。
这种功能实际上就是数据同步,同时要考虑手机本身、电量、网络流量等等限制因素,所以通常在移动端上有一下两个解决方案:
1一种是定时去server查询数据,通常是使用HTTP协议来访问web服务器,称Polling(轮询);
2还有一种是移动端和服务器建立长连接,使用XMPP长连接,称Push(推送)。
从耗费的电量、流量和数据延迟性各方面来说,Push有明显的优势。但是使用Push的缺点是:
对于客户端:实现和维护相对成本高,在移动无线网络下维护长连接,相对有一些技术上的开发难度。
对于服务器:如何实现多核并发,cpu作业调度,数量庞大的长连接并发维护等技术,仍存在开发难点。
在讲述Push方案的原理前,先了解一下移动无线网络的特点。
移动无线网络的特点:
因为 IP v4 的 IP 量有限,运营商分配给手机终端的 IP 是运营商内网的 IP,手机要连接 Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网 IP、端口到内网 IP、端口的对应关系,以确保内网的手机可以跟 Internet 的服务器通讯
GGSN(Gateway GPRS
Support Node 网关GPRS支持结点)模块就实现了NAT功能。
因为大部分移动无线网络运营商都是为了减少网关的NAT映射表的负荷,所以如果发现链路中有一段时间没有数据通讯时,会删除其对应表,造成链路中断。
Push在Android平台上长连接的实现:
既然自己知道自己移动端要和Internet进行通信,必须通过运营商的网关,所以,为了不让NAT映射表失效,咋们需要定时向Internet发送数据,因为只是为了不然NAT映射表失效,所以只需发送长度为0的数据即可。
这时候就要用到定时器,在android系统上,定时器通常有一下两种:
1javautilTimer
2androidappAlarmManager
分析:
Timer:可以按照计划或者时间周期来执行相关的任务。但是Timer需要用WakeLock来让CPU保持唤醒状态,才能保证任务的执行,这样子会消耗大量流量;当CPU处于休眠的时候,就不能唤醒执行任务,所以应用于移动端明显是不合适。
AlarmManager:AlarmManager类是属于android系统封装好来管理RTC模块的管理类。这里就涉及到RTC模块,要更好地了解两者的区别,就要明白两者真正的区别。
RTC(Real- Time Clock)实时闹钟在一个嵌入式系统中,通常采用RTC
来提供可靠的系统时间,包括时分秒和年月日等;而且要求在系统处于关机状态下它也能够正常工作(通常采用后备电池供电),它的外围也不需要太多的辅助电路,典型的就是只需要一个高精度的32768KHz
晶体和电阻电容等。(如果对这方面感兴趣,可以自己查阅相关资料,这里就说个大概)
好了,回来正题。所以,AlarmManager又称全局定时闹钟。这意味着,当自己用使用AlarmManager来定时执行任务,CPU可以正常地休眠,只有在执行任务是,才唤醒CPU,这个过程是很短时间的。
下面简单来说明其使用:
1类似于Timer功能:
//获得闹钟管理器
AlarmManager
am = (AlarmManager)getSystemService(ALARM_SERVICE);
//设置任务执行计划
amsetRepeating(AlarmManagerELAPSED_REALTIME, firstTime, 51000,
sender);//从firstTime才开始执行,每隔5秒再执行
2实现全局定时功能:
//获得闹钟管理器
AlarmManager
am = (AlarmManager)getSystemService(ALARM_SERVICE);
//设置任务执行计划
amsetRepeating(AlarmManagerELAPSED_REALTIME_WAKEUP, firstTime,
51000, sender);//从firstTime才开始执行,每隔5秒再执行
总结:在android客户端使用Push推送时,应该使用AlarmManager来实现心跳功能,使其真正实现长连接。
OkHttp是一个相对成熟的解决方案,据说Android44的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。
OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。
使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和javanetHttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。
package comtest;
import javaioBufferedReader;
import javaioInputStreamReader;
import javaioOutputStream;
import javanetHttpURLConnection;
import javanetURL;
import javanetURLEncoder;
import javautilHashMap;
import javautilMap;
import orgjsonJSONObject;
import androidappActivity;
import androidcontentIntent;
import androidosBundle;
import androidosHandler;
import androidosLooper;
public class TestPost extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
superonCreate(savedInstanceState);
setContentView(Rlayoutloading);
new Handler()postDelayed(new Runnable() {
@Override
public void run() {
final Map<String, String> params0 = new HashMap<String, String>();
params0put("username", username);
params0put("password", password);
final String url0 = "http://192168011:80/xxxxphp";
Runnable downloadRun = new Runnable() {
@Override
public void run() {
Looperprepare();
try {
String result0 = sendPostRequest(
params0, url0);
JSONObject jsonObject = new JSONObject(result0);
String status = jsonObjectgetString("status");
String message = jsonObjectgetString("message");
if (statusequals("success")) {
//成功干啥
} else {
//失败干啥
}
} catch (Exception e) {
//出现异常干啥
}
}
};
new Thread(downloadRun)start();
}
}, 200);
}
//post请求方法
public String sendPostRequest(Map<String, String> params, String actionurl)
throws Exception {
String URl = actionurl;
StringBuilder sb = new StringBuilder();
if (params != null && !paramsisEmpty()) {
for (MapEntry<String, String> entry : paramsentrySet()) {
sbappend(entrygetKey())append('=')
append(URLEncoderencode(entrygetValue(), "UTF-8"))
append('&');
}
sbdeleteCharAt(sblength() - 1);
}
byte[] entitydata = sbtoString()getBytes();// 得到实体的二进制数据
URL url = new URL(URl);
HttpURLConnection conn = (HttpURLConnection) urlopenConnection();
connsetDoInput(true);
connsetRequestMethod("POST");
connsetConnectTimeout(10000);
connsetDoOutput(true);// 如果通过post提交数据,必须设置允许对外输出数据
connsetUseCaches(false);// 是否缓存
connsetRequestProperty("Content-Type","application/x-www-form-urlencoded");
connsetRequestProperty("Content-Length",StringvalueOf(entitydatalength));
OutputStream outStream = conngetOutputStream();
outStreamwrite(entitydata);
outStreamflush();
outStreamclose();
BufferedReader bufferRead = null;
if(conngetResponseCode() == 200){
bufferRead = new BufferedReader(new InputStreamReader(conngetInputStream()));
}
String result = "";
String readLine = null;
while ((readLine = bufferReadreadLine()) != null) {
result += readLine;
}
bufferReadclose();
conndisconnect();
return result;
}
}
我用的是这种方法
普通不会架tomcat服务器的话,就用myeclipse,安装好tomcat,然后再开启就可以进行调试了。android模拟器访问tomcat的程序,只要访问你本机的ip地址就行了。我当时使用10002不行,一定要使用本地ip地址才能访问到,可能是我当时设置不好吧。要是你的手机要访问本地服务器,则可能要把tomcat架到公网上去解析好,才能进行访问了。我调试程序都是用虚拟机做服务器,或者直接弄到自己的公网服务器去。
虽然只有十分
但是还是给你写一段 android中测试 跑得了 加点分可以继续追问我哦 呵呵~~~~
public static String getHtml( String urlpath,String encoding) throws Exception {
URL url = new URL(urlpath);
//实例化一个HTTP连接对象conn
HttpURLConnection conn = (HttpURLConnection)urlopenConnection();
//定义请求方式为GET,其中GET的格式需要注意
connsetRequestMethod("GET");
//定义请求时间,在ANDROID中最好是不好超过10秒。否则将被系统回收。
connsetConnectTimeout(61000);
if(conngetResponseCode()== 200){
InputStream inStream = conngetInputStream();
byte[] data = readStream(inStream);
return new String(data,encoding);
}
return null;
}
public static byte[] readStream(InputStream inStream) throws Exception{
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len= -1;
//将输入流不断的读,并放到缓冲区中去。直到读完
while((len=inStreamread(buffer))!=-1){
//将缓冲区的数据不断的写到内存中去。
outStreamwrite(buffer, 0, len);
}
outStreamclose();
inStreamclose();
return outStreamtoByteArray();
}
解决方法很多!很简单啊,手机连上的网是广域网,你自己搞的tomcat是局域网上的东西,怎么能访问?
除非你把你的
http://ip:8080/myapp
这个地址弄成一个广域网上的域名才可以的。
0条评论