Android-Studio移动应用开发从入门到实战 第九章 Android网络通信编程.pptx
《Android-Studio移动应用开发从入门到实战 第九章 Android网络通信编程.pptx》由会员分享,可在线阅读,更多相关《Android-Studio移动应用开发从入门到实战 第九章 Android网络通信编程.pptx(43页珍藏版)》请在冰豆网上搜索。
![Android-Studio移动应用开发从入门到实战 第九章 Android网络通信编程.pptx](https://file1.bdocx.com/fileroot1/2023-2/24/be1e5fa4-6398-4270-9cb5-e84f3067e0f1/be1e5fa4-6398-4270-9cb5-e84f3067e0f11.gif)
第九章Android网络通信编程,本章学习目标:
掌握HTTP协议;掌握HttpURLConnection、HttpClient的使用;掌握Socket通信的使用;掌握GET、POST两种数据提交方式。
第九章网络通信编程,9.1网络编程基础,网络的发展,使移动端拥有着无限的发展可能,而Android系统最大的特色和优势之一既是对网络的支持。
目前几乎所有的Android应用程序都会涉及到网络编程。
Android系统提供了Socket通信、HTTP通信、URL通信和WebView。
其中最常用的是HTTP通信,本章将会详细的讲解HTTP通信和Socket通信。
9.1.1HTTP协议简介,HTTP协议是HyperTextTransferProtocol(超文本传输协议)的缩写,是用于从万维网(WWW:
WorldWideWeb)服务器传输超文本到本地浏览器的传送协议。
HTTP是一个基于TCP/IP通信协议来传递数据(HTML文件,图片文件,查询结果等)。
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。
目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中。
HTTP协议工作于客户端-服务端架构为上。
浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。
Web服务器根据接收到的请求后,向客户端发送响应信息。
Http请求到响应的过程,9.1.1HTTP协议简介,Http协议的主要特点:
简单快速:
客户向服务器请求服务时,只需传送请求方法和路径。
请求方法常用的有GET、HEAD、POST。
灵活:
HTTP允许传输任意类型的数据对象。
无连接:
无连接的含义是限制每次连接只处理一个请求。
服务器处理完客户的请求,并收到客户的应答后,即断开连接。
无状态:
HTTP协议是无状态协议。
无状态是指协议对于事务处理没有记忆能力。
缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
支持B/S及C/S模式。
9.1.1HTTP协议简介,9.1.2标准Java接口,标准Java接口是指J.*,它提供与互联网有关的类,包括流和数据包套接字、Internet协议和一些Http处理。
例如创建URL和URLConnection对象、设置连接参数、连接服务器等。
提供的类和接口说明,包的HTTP的方法应用:
try/定义地址URLurl=newURL(http:
/localhost:
8080/Test/index.jsp);/打开链接地址HttpURLConnectionhttp=(HttpURLConnection)url.openConnection();/得到连接状态intstate=http.getResponseCode();if(state=HttpURLConnection.HTTP_OK)/取得数据InputStreamin=http.getInputStream();/处理数据.catch(Exceptione),9.1.3Android网络接口,Android的网络接口即是.*,它实际上是通过对ApacheHttpClient的封装来实现一个HTTP编程接口,比.*API功能更强大。
.*除了具备核心的.*外,还包含额外的网络访问Socket。
该包包括URI类,在Android应用程序开发中使用较多。
同时Android网络接口还提供了HTTP请求队列管理、HTTP连接池管理、网络状态监视等接口。
9.1.3Android网络接口,实现Socket的连接功能的具体代码如下:
try/IP地址定义InetAddressaddress=InetAddress.getByName(192.168.56.1);/端口定义Socketclient=newSocket(address,61111,true);/取得数据InputStreamin=client.getInputStream();OutputStreamout=client.getOutputStream();/处理数据.out.close();in.close();client.close();catch(UnknownHostExceptione)catch(Exceptione),9.2HTTP通信,9.2.1HttpURLConnection的简介,在Android开发中,应用程序经常需要与服务器进行数据交互,包括访问本地服务器以及远程服务器,这些都可以称为访问网络,此时就可以使用HttpURLConnection对象,它是一个标准的Java类。
HttpURLConnection继承自URLConnection类,两者都是抽象类,其对象主要通过URL的openConnection方法获得。
openConnection方法只创建URLConnection或者HttpURLConnection实例,但并不进行真正的连接操作,并且每次openConnection都将创建一个新的实例。
因此在连接之前可以对其一些属性进行设置。
设置超时时间,以及设置请求方式的具体代码如下所示。
/设置请求方式http.setRequestMethod(GET);/设置超时时间http.setConnectionTimeout(4000);需要注意的是在连接时需要设置超时时间,如果不设置超时时间,在网络异常的情况下,会导致取不到数据而一直等待,以至于程序不往下执行。
在开发Android应用程序的过程中,如果应用程序需要访问网络权限,则需要在清单文件中添加如下所示的代码:
9.2.1HttpURLConnection的简介,9.2.2HttpURLConnection接口使用案例,接下来将通过一个输入网址查看图片的例子来讲解HttpURLConnection的使用过程。
9.2.2HttpURLConnection接口使用案例,布局设计MainActivity:
publicvoidonclick(Viewview)/获取输入的网络图片地址finalStringpath=path_edit.getText().toString().trim();newThread()privateHttpURLConnectionconn;privateBitmapbitmap;publicvoidrun()/连接服务器get请求tryURLurl=newURL(path);/根据url发送http的请求conn=(HttpURLConnection)url.openConnection();/设置请求的方式conn.setRequestMethod(GET);/设置超时时间conn.setConnectTimeout(5000);/设置请求头User-Agent浏览器的版本/得到服务器返回的响应码intstate=conn.getResponseCode();Log.v(1111111111,state+);,if(state=200)/请求网络成功,获取输入流InputStreamin=conn.getInputStream();/将流转换为Bitmap对象bitmap=BitmapFactory.decodeStream(in);/告诉消息处理器显示图片Messagemsg=newMessage();msg.what=SUCCESS;msg.obj=bitmap;handler.sendMessage(msg);else/请求网络失败,提示用户Messagemsg=newMessage();msg.what=ERROR;handler.sendMessage(msg);catch(Exceptione)e.printStackTrace();Messagemsg=newMessage();msg.what=ERROR;handler.sendMessage(msg);.start();,9.2.3HttpClient的简介,9.2.3HttpClient的简介,HttpClient是ApacheJakartaCommon下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。
HttpClient已经应用在很多的项目中,比如ApacheJakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。
HttpClient的特性:
基于标准、纯净的Java语言。
实现了Http1.0和Http1.1。
以可扩展的面向对象的结构实现了Http全部的方法(GET,POST,PUT,DELETE,HEAD,OPTIONS,andTRACE)。
支持HTTPS协议。
通过Http代理建立透明的连接。
利用CONNECT方法通过Http代理建立隧道的https连接。
HttpClient的使用方法,创建HttpClient对象。
创建请求方法的实例,并指定请求URL。
发送请求参数时,调用HttpGet、HttpPost的setParams(HetpParamsparams)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntityentity)方法来设置请求参数。
调用HttpClient对象的execute(HttpUriRequestrequest)方法发送请求,该方法返回一个HttpResponse对象。
调用HttpResponse的getAllHeaders()、getHeaders(Stringname)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。
程序可通过该对象获取服务器的响应内容。
释放连接。
无论执行方法是否成功,都必须释放连接。
HttpClient常用类说明,9.2.4HttpClient的使用案例,本案例是使用HttpClient来获取图片。
9.2.4HttpClient的使用案例本案例是使用HttpClient来获取图片。
show_btn.setonclickListener(newView.onclickListener()Overridepublicvoidonclick(Viewview)/获取输入的网络图片地址finalStringpath=path_edit.getText().toString().trim();if(TextUtils.isEmpty(path)Toast.makeText(MainActivity.this,图片路径不能为空,Toast.LENGTH_SHORT).show();else/创建新线程newThread()privateHttpURLConnectionconn;privateBitmapbitmap;publicvoidrun()/使用HttpClient获取图片getImageByHttpClient(path);.start();,OverrideprotectedvoidonCreate(BundlesavedInstanceState)super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);init();/组件初始化privatevoidinit()iv=(ImageView)findViewById(R.id.images);show_btn=(Button)findViewById(R.id.get_show);path_edit=(EditText)findViewById(R.id.address);,privatevoidgetImageByHttpClient(Stringpath)/获取HttpClient对象HttpClientClient=newDefaultHttpClient();HttpGetget=newHttpGet(path);try/获取返回的HttpResponse对象HttpResponseresponse=Client.execute(get);/查看状态码是否为200if(response.getStatusLine().getStatusCode()=200)/请求成功,获取HttpEntity对象HttpEntityentity=response.getEntity();/获取输入流InputStreamin=entity.getContent();/获取Bitmap对象Bitmapbitmap=BitmapFactory.decodeStream(in);/通知消息处理器显示图片Messagemsg=newMessage();msg.what=SUCCESS;msg.obj=bitmap;handler.sendMessage(msg);elseMessagemsg=newMessage();msg.what=ERROR;handler.sendMessage(msg);catch(Exceptione),/创建消息处理器privateHandlerhandler=newHandler()publicvoidhandleMessage(android.os.Messagemsg)if(msg.what=SUCCESS)Bitmapbitmap=(Bitmap)msg.obj;iv.setImageBitmap(bitmap);elseif(msg.what=ERROR)Toast.makeText(MainActivity.this,显示图片错误,Toast.LENGTH_SHORT).show();,9.2.4HttpClient的使用案例,上述代码中,只有在getImageByHttpClient(Stringpath)方法里的代码与使用HttpURLConnection不同。
方法中采用的是HttpGet方式请求获取网络图片资源,访问成功后会返回200的状态码,然后使用HttpResponse的getEntity()方法获得HttpEntity对象,然后通过HttpEntity对象的getContent()方法得到输入流,最后转换为Bitmap对象显示出来。
需要注意的是,谷歌从android6.0(API23)以后,就不建议再用HttpClient了,取而代之的是HttpUrlConnection,所以要使用HttpClient需要在build.gradle加入如下的语句:
androiduseLibraryorg.apache.http.legacy,9.3Socket通信,9.3Socket通信,Android应用程序与服务器通信的方式主要有两种,一种是Http通信,另一种是Socket通信。
Http连接使用的是“请求-响应方式”,即在请求时才建立连接。
而Socket通信则是在双方建立连接后直接进行数据传输。
它在连接时可实现信息的主动推送,而不用每次等客户端先向服务器发送请求。
9.3.1Socket通信原理,Socket通常称为“套接字”,用于描述IP地址和端口,是一个通信链的句柄。
应用程序通常通过套接字向网络发出请求或者答应网络请求,它支持TCP/IP协议的网络通信的基本单元。
它是网络通信过程中端点的抽象表示,包含进行网络通信的五种必备信息:
连接使用的协议、本地主机的IP地址、本地进程的协议端口、远程主机的IP地址、远程进程的协议端口。
(1)创建Socket,连接Socket连接至少需要两个套接字,一个运行于客户端,一个运行于服务端。
它们都已经封装成类,常用的构造方法如下所示:
Socket(InetAddressaddress,intport)。
Socket(InetAddressaddress,intport,booleanstream)。
Socket(Stringhost,intport,Booleanstream)。
ServerSocket(intport)。
ServerSocket(intport,intbacklog)。
ServerSocket(intport,intbacklog,InetAddressbindAddr)。
创建Socket的代码如下所示:
Socketsocket=newSocket(192.168.56.1,35434);ServerSocketserver=newServerSocket(35434);需要注意的是,在选择端口时每一个端口对应一个服务。
01023的端口号为系统所保留,所以在选择端口号时最好选择一个大于1023的数,如上面的35434,以防止发生冲突。
在创建Socket时,需要捕获或抛出异常。
2.输入(输出)流,Socket提供了getInputStream()和getOutPutStream()来得到对应的输入或者输出流来进行读写操作,这两个方法分别返回InputStream和OutputStream类对象。
PrintStreamps=newPrintStream(newBufferedOutputStream(socket.getOutputStream();DataInputStreamis=newDataInputStream(socket.getInputStream();为了便于读写数据,可以在返回输入、输出流对象上建立过滤流。
对于文本方式流对象,可以采用InputStreamReader、OutputStreamWriter和PrintWriter处理,如:
PrintWriterpwriter=newPrintWriter(socket.getOutStream(),true);/PrintWriter(OutputStreamout,booleanautoflush)BufferedReaderbreader=newBufferedReader(newInputStreamReader(socket.getInputStream();,3.关闭Socket流,在Socket使用完毕后需要将其关闭,以释放资源。
需要注意的是,在关闭Socket之前,需要将与Socket相关的输入输出流先关闭。
具体的代码如下:
ps.close();/输出流先关闭is.close();/输入流其次关闭socket.close();/socket最后关闭,9.3.2Socket通信案例,举例说明Socket的使用:
本案例是实现编写客户端负责发送内容,服务器端用来接受内容的程序。
服务器端,客户端,9.3.2Socket通信案例,publicstaticvoidmain(Stringargs)Threadthread=newThread(newtest_Socket();thread.start();,代码中设置了服务器端口为2000,然后通过accept()方法使服务器开始监听客户端的连接,然后通过BufferReader对象来接收输入流。
最后关闭Socket和流。
服务器端代码:
publicclasstest_SocketimplementsRunnablepublicstaticfinalintServer_port=2000;Overridepublicvoidrun()System.out.println(S:
Connectioning.);tryServerSocketserverSocket=newServerSocket(Server_port);while(true)Socketclient=serverSocket.accept();System.out.println(S:
Receing.);tryBufferedReaderbreader=newBufferedReader(newInputStreamReader(client.getInputStream();Stringstr=breader.readLine();System.out.println(S:
Received:
+str);catch(Exceptione)System.out.print(S:
Error);e.printStackTrace();finallyclient.close();System.out.println(S:
Done);,9.3.2Socket通信案例,privatevoidinit()mes=(EditText)findViewById(R.id.mes);send_btn=(Button)findViewById(R.id.send);send_btn.setonclickListener(newView.onclickListener()Overridepublicvoidonclick(Viewview)tryStringstring=mes.getText().toString();if(!
TextUtils.isEmpty(string)SendMes(ip,port,string);elseToast.makeText(MainActivity.this,请先输入内容,Toast.LENGTH_SHORT).show();mes.requestFocus();catch(Exceptione)e.printStackTrace(););,客户端代码:
publicclassMainActivityextendsAppCompatActivityprivateEditTextmes;privateButtonsend_btn;privateStringip=“172.16.39.192”;/服务器端IPprivateintport=2000;/端口号OverridepripvraotteevctoeidvSeoniddMoneCs(rSetartine(gBiupn,dinletpsaovret,dSItnrsitnagnmceeSst)atteh)rowsUnknsuopwenr.HoonsCtrEexacteep(tsiaovne,dIIOnsEtxacnecpetSitoante);streytContentView(R.layout.activity_main);iniSt(o)c;ketsocket=null;,socket=newSocket(ip,port);BufferedWriterwriter=newBufferedWriter(new,OutputStreamWriter(socket.getOutputStream();writer.write(mes);writer.flush();writer.close();socket.close();catch(UnknownHostExceptione)e.printStackTrace();catch(IOExceptione)e.printStackTrace();,9.3.2Socket通信案例,运行结果:
9.3.2Socket通信案例,附加说明:
intSDK_INT=android.os.Build.VERSION.SDK_INT;/查看系统的API级别数字表示if(SDK_INT8)StrictMode.ThreadPolicypolicy=newStrictMode.ThreadPolicy.