设为首页 收藏本站
查看: 731|回复: 0

[经验分享] android连网详解——android.net、org.apache.http联网实现

[复制链接]

尚未签到

发表于 2017-1-11 10:17:14 | 显示全部楼层 |阅读模式
  1.连网相关包介绍

今天我们将深入介绍了Android SDK 中一些与网络有关的package,如下:
包描述
java.net提供与联网有关的类,包括流和数据包(datagram)sockets、Internet 协议和常见 HTTP 处理。该包是一个多功能网络资源。有经验的 Java 开发人员可以立即使用这个熟悉的包创建应用程序。
java.io虽然没有提供显式的联网功能,但是仍然非常重要。该包中的类由其他 Java 包中提供的 socket 和连接使用。它们还用于与本地文件(在与网络进行交互时会经常出现)的交互。
java.nio包含表示特定数据类型的缓冲区的类。适合用于两个基于 Java 语言的端点之间的通信。
org.apache.*表示许多为 HTTP 通信提供精确控制和功能的包。可以将 Apache 视为流行的开源 Web 服务器。
android.net除核心 java.net.* 类以外,包含额外的网络访问 socket。该包包括 URI 类,后者频繁用于 Android 应用程序开发,而不仅仅是传统的联网方面
android.net.http包含处理 SSL 证书的类。
android.net.wifi包含在 Android 平台上管理有关 WiFi(802.11 无线 Ethernet)所有方面的类。并不是所有设备都配备了 WiFi 功能,特别是 Android 在 Motorola 和 LG 等手机制造商的 “翻盖手机” 领域获得了成功。
android.telephony.gsm包含用于管理和发送 SMS(文本)消息的类。一段时间后,可能会引入额外的包来来为非 GSM 网络提供类似的功能,比如 CDMA 或 android.telephony.cdma 等网络。
  

上表并没有列出所有包,但是可以让我们清楚地意识到Android的强大功能。
介绍一个简单的网络示例

在EditView中输入URL后,单击“go!”按钮,界面显示如下
http://dl.javaeye.com/upload/attachment/302454/c3bef9fc-66b9-3deb-a7a8-2e0e7e82f76c.jpg

界面部分的代码简要明了,就不此额外说明了,下面详细解析核心代码,如下:
Java代码


  • finalButtonbutton=(Button)findViewById(R.id.ButtonGo);
  • button.setOnClickListener(newButton.OnClickListener(){
  • publicvoidonClick(Viewv){
  • try{
  • tView.setText(”");
  • //获取输入的URL地址
  • URLurl=newURL(eText.getText().toString());
  • URLConnectionconn=url.openConnection();
  • //获取网页数据流
  • BufferedReaderrd=
  • newBufferedReader(newInputStreamReader(conn.getInputStream()));
  • Stringline=“”;
  • //读取数据
  • while((line=rd.readLine())!=null){
  • Messagelmsg;
  • lmsg=newMessage();
  • lmsg.obj=line;
  • lmsg.what=0;
  • //将数据显示在界面上
  • h.sendMessage(lmsg);
  • }
  • }
  • catch(Exceptione)
  • {
  • //输出异常信息
  • Log.v(”Browse”,e.toString());
  • }
  • }
  • });

  

简要解析如下:URL 和 URLConnection 类共同提供与用户所选的 Web 站点的连接。BufferedReader 的一个实例负责从 Web 站点连接中读取传入的数据。每读取一行代码,文本就被附加到一个 TextView。数据并没有直接指定给 TextView,而是引入了一种设计模式,即创建一个消息对象并将该对象发送到一个处理程序的实例。这是更新 UI 的一种比较可取的方法,对可能需要同时运行多个线程的应用程序而言尤其如此。 A Handler allows you to send and processMessage and Runnable objects associated with a thread’s MessageQueue,这句话简单明了,相信大家一看就完全明白了。
补充说明

以上程序,在实际运行中可能会导致异常,catch (Exception e) 输出异常信息:
java.net.SocketException: Permission denied(maybe missing INTERNET permission)
需要在AndroidManifest.xml中定义相应的权限,如下:
<uses-permission android:name=”android.permission.INTERNET” />
注意在<application>也可以定义INTERNET权限,如下:
<application android:permission=”android.permission.INTERNET”>
这种权限似乎还是会导致异常,看来两种权限除了作用的范围有所不同,具体的作用也是有些不同的,以后开发中需要注意两者的区别。


2、org.apache.http联网实现
Android使用HttpClient完成Post和Get方式的联网请求


Android联网可以采用HttpPost,HttpGet封装post请求和get请求,再使用HttpClient的excute方法发送post或者get请求并返回服务器的响应数据。

1、设置连接和读取超时时间,并新建HttpClient对象:

// 设置连接超时时间和数据读取超时时间
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams,
KeySource.CONNECTION_TIMEOUT_INT);
HttpConnectionParams.setSoTimeout(httpParams,
KeySource.SO_TIMEOUT_INT);
//新建HttpClient对象
HttpClient httpClient = new DefaultHttpClient(httpParams)

2、Get请求:

// generate get request
HttpGet get = new HttpGet(url);
// set HTTP head parameters
//Map<String, String> headers
if (headers != null)
{
Set<String> setHead = headers.keySet();
Iterator<String> iteratorHead = setHead.iterator();
while (iteratorHead.hasNext())
{
String headerName = iteratorHead.next();
String headerValue = (String) headers.get(headerName);
MyLog.d(headerName, headerValue);
get.setHeader(headerName, headerValue);
}
}
// connect
//need try catch
response = httpClient.execute(get);

3、Post请求:

HttpPost post = new HttpPost(KeySource.HOST_URL_STR);
// set HTTP head parameters
Map<String, String> headers = heads;
Set<String> setHead = headers.keySet();
Iterator<String> iteratorHead = setHead.iterator();
while (iteratorHead.hasNext())
{
String headName = iteratorHead.next();
String headValue = (String) headers.get(headName);
post.setHeader(headName, headValue);
}
/**
* 通常的HTTP实体需要在执行上下文的时候动态生成的。
* HttpClient的提供使用EntityTemplate实体类和ContentProducer接口支持动态实体。
* 内容制作是通过写需求的内容到一个输出流,每次请求的时候都会产生。
* 因此,通过EntityTemplate创建实体通常是独立的,重复性好。
*/
ContentProducer cp = new ContentProducer()
{
public void writeTo(OutputStream outstream)
throws IOException
{
Writer writer = new OutputStreamWriter(outstream,
"UTF-8");
writer.write(requestBody);
writer.flush();
writer.close();
}
};
HttpEntity entity = new EntityTemplate(cp);
post.setEntity(entity);
}
//connect ,need try catch
response = httpClient.execute(post);


4、请求Response响应处理:

if (response.getStatusLine().getStatusCode() == 200)
{
// get response xml.
/**
* 因为直接调用toString可能会导致某些中文字符出现乱码的情况。所以此处使用toByteArray
* 如果需要转成String对象,可以先调用EntityUtils.toByteArray()方法将消息实体转成byte数组,
* 在由new String(byte[] bArray)转换成字符串。
*/
byte[] bResultXml = EntityUtils.toByteArray(response
.getEntity());
if (bResultXml != null)
{
String strXml = new String(bResultXml, "utf-8");
}
}
//Todo xmlAnalysis..





3.java.net 联网详解


本篇幅我们漫游java.net包,按照网络方面的知识来逐步学习java网络编程,并给大家介绍一些小例子,边学习边写代码。
首先,IP地址

IP地址估计大家都明白,我们就直接来看java.net中的类吧。

http://dl.javaeye.com/upload/attachment/302472/307825d3-07b4-39d2-b181-8b3ea8f44922.jpg

详细介绍就不多说了,看2个简单的小例子如下:

Java代码


  • StringGetHostAddress(StringstrHostName)
  • {
  • InetAddressaddress=null;
  • try
  • {
  • address=InetAddress.getByName(strHostName);
  • }
  • catch(UnknownHostExceptione)
  • {
  • System.out.println(e.getMessage());
  • }
  • returnInetAddress.getHostAddress();
  • }

  • voidGetAllIP(StringstrHostName)
  • {
  • InetAddress[]add=null;
  • try
  • {
  • add=InetAddress.getAllByName(strHostName);
  • for(inti=0;i<addr.lenth;i++)
  • System.out.println(addr);
  • }
  • catch(UnknownHostExceptione)
  • {
  • System.out.println(e.getMessage());
  • }
  • }

  

上面2个小例子很简单,但是有一点必须说明的,在写网络编程方面的,必须注意异常的捕获,网络异常是比较正常的现象,比如说当前网络繁忙,网络连 接 超时,更是“家常便饭”。因此在写网络编程的时候,必须养成捕获异常的好习惯,查看完函数说明后,必须要注意网络异常的说明。例如下图中的说明:

public static InetAddress getByAddress (byte[] ipAddress)
Since: API Level 1

Returns the InetAddress corresponding to the array of bytes. In the case of an IPv4 address there must be exactly 4 bytes and for IPv6 exactly 16 bytes. If not, an UnknownHostException is thrown.

The IP address is not validated by a name service.

The high order byte is ipAddress[0].
Parameters
ipAddress is either a 4 (IPv4) or 16 (IPv6) byte long array.
Returns

* an InetAddress instance representing the given IP address ipAddress.

Throws
UnknownHostException if the given byte array has no valid length.



在使用getByAddress ()函数的时候就必须捕获UnknownHostException这个异常。
然后,URL地址

http://dl.javaeye.com/upload/attachment/302480/332bc94e-8665-37b2-a6da-ed5602e90f39.jpg


看到这个类,不仅让我想起来MFC在网络编程方面的复杂,一个

BOOL AFXAPI AfxParseURL(LPCTSTR pstrURL, DWORD& dwServiceType,CString& strServer, CString& strObject, INTERNET_PORT& nPort);

函数,让人看起来就感觉不知道在说明,在编写MFC网络编程方面的时候一般都会自己写个URL类,而在JAVA中的直接提供了这个类,让初学者看起 来明白多了。一个简单的例子如下:

Java代码


  • VoidEasyURL(StringstrURL)
  • {
  • URLurl=newURL(strURL);
  • try
  • {
  • InputStreamhtml=url.openStream();
  • intc;
  • do{
  • c=html.read();
  • cf(c!=-1)System.out.println((char)c);
  • }while(c!=-1)
  • }
  • catch(IOExceptione)
  • {
  • System.out.println(e.getMessage());
  • }
  • }

  


其次,套接字socket类

http://dl.javaeye.com/upload/attachment/302482/6b56d5e5-3c78-3211-b1c6-c51efaf0eeb2.jpg

套接字通信的基本思想比较简单,客户端建立一个到服务器的链接,一旦连接建立了,客户端就可以往套接字里写入数据,并向服务器发送数据;反过来,服 务器读取客户端写入套接字里的数据。几乎就那样简单,也许细节会复杂些,但是基本思想就这么简单。举个简单的例子如下:
Java代码


  • voidWebPing(StringstrURL)
  • {
  • try
  • {
  • InetAddressaddr;
  • Socketsock=newSocket(strURL,80);
  • Addr=sock.getInetAddress();
  • System.out.println(“Conncetedto”+addr);
  • Sock.close();
  • }
  • catch(IOExceptione)
  • {
  • System.out.println(e.getMessage());
  • }
  • }

  

如果使用本地主机(localhost)来测试这个程序,输出结果如下:
Connceted to localhost/127.0.0.1
InetAddress.toString()的隐含调用(println调用)自动输出主机名和IP地址。

至于其他套接字:DatagramSocket (通过UDP通信的套接字),MulticastSocket (一 种用于多点传送的套接字)以及ServerSocket (一种用于监听来自客户端的连接的套接字),在这里就不一一说 明。
最后,URLConncetion类

在一般情况下,URL这个类就可以满足我们的需求,但是在一些特殊情况下,比如HTTP数据头的传递,这个时候我们就得使用 URLConncetion,如下图所示:

http://dl.javaeye.com/upload/attachment/302484/d2d616e6-3ecf-3de1-8724-0835fd41410e.jpg

使用URLConncetion,我们对网络的控制就增加了很多,举个例子如下:
Java代码


  • voidSendRequest(StringstrURL)
  • {
  • URLurl=URL(strURL);
  • HttpURLConnectionconn=(HttpURLConnection)url.openConnection();
  • conn.setDoInput(true);
  • conn.setDoOutput(true);
  • conn.setRequestProperty(“Content-type”,”application/xxx”);
  • conn.connect();
  • System.out.println(Conn.getResponseMessage());
  • InputMessageis=Conn.getIputStream();
  • intc;
  • do{
  • c=is.read();
  • if(c!=-1)System.out.println((char)c);
  • }while(c!=-1)
  • }

  


关于HTTP数据头方面的知识,前段时间在编写流媒体下载的时候学习了下HTTP数据头的结构,下面列举一个HTTP request/response的一个完整流程如下,有兴趣的可以看下:

http://dl.javaeye.com/upload/attachment/302486/dd576378-f191-359a-898f-ebad79d037b4.jpg

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-326904-1-1.html 上篇帖子: Apache ActiveMQ Queue Topic 详解 教程 加入代码解释说明 下篇帖子: Java工具类之Apache的Commons Lang和BeanUtils
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表