目录
14.网络编程及Internet应用(一)
1.通过HTTP访问网络
在Android中也可以使用HTTP协议访问网络。例如,在使用应用宝App下载游戏时,或者刷新朋友圈时,都需要通过HTTP协议访问网络。
在Android中提供了两个用于HTTP通信的API,即HttpURLConnection和Apache的HttpClient。由于Android 6.0版本已经基本将HttpClient从SDK中移除了。所以这里主要介绍HttpURLConnection。
HttpURLConnection类位于java.net 包中,用于发送HTTP请求和获取HTTP响应。由于该类是抽象类,不能直接实例化对象,则需要使用URL的openConnection()方法来获得。例如,要创建一个http://www.example.com 网站对应的HttpURLConnection对象,可以使用下面的代码:
URL url = new URL("http://www.example.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
HttpURLConnection是URLConnection的一个子类,它在URLConnection的基础上提供了如表14.1所示的方法,从而方便发送和响应HTTP请求。
表14.1 HttpURLConnection常用的方法
| 方法 | 描述 |
|---|---|
| int getResponseCode() | 获取服务器的响应代码 |
| String getResponseMessage() | 获取服务器的响应消息 |
| String getRequestMethod() | 获取发送请求的方法 |
| void setRequestMethod(String method) | 设置发送请求的方法 |
创建了HttpURLConnection对象后,就可以使用该对象发送HTTP请求了。
1-1.发送GET请求
使用HttpURLConnection对象发送请求时,默认发送的就是GET请求。因此,发送GET请求比较简单,只需要在指定连接地址时,先将要传递的参数通过“?参数名=参数值”的形式进行传递(多个参数间使用英文半角的“&”符号分隔。例如,要传递用户名和E-mail地址这两个参数,可以使用“?user=abc&email= abc@qq.com”实现),然后获取输入流中的数据,并关闭连接即可。
注:使用HTTP协议访问网络就是客户端与服务器的通信,所以运行本章实例不仅需要创建客户端app实例,还需要创建简单的后台服务器。
(1) 永远不要在主线程上执行网络调用。
(2) 在Service而不是Activity 中执行网络操作。
例 :

MainActivity.java
package com.example.getrequest;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
public class MainActivity extends Activity {
private EditText content; //定义一个输入文本内容的编辑框对象
private Handler handler; //定义一个android.os.Handler对象
private String result = ""; //定义一个代表显示内容的字符串
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
content = (EditText) findViewById(R.id.main_et1); //获取输入文本内容的EditText组件
final TextView resultTV = (TextView) findViewById(R.id.main_tv1); //获取显示结果的TextView组件
Button button = (Button) findViewById(R.id.main_btn1); //获取“发表”按钮组件
button.setOnClickListener(new View.OnClickListener() { //单击发送按钮,实现读取服务器微博信息
@Override
public void onClick(View v) {
//判断输入内容是否为空,为空给出提示消息,否则访问服务器
if ("".equals(content.getText().toString())) {
Toast.makeText(MainActivity.this, "请输入要发表的内容!",
Toast.LENGTH_SHORT).show(); //显示消息提示
return;
}
handler = new Handler() { //将服务器中的数据,显示在UI界面中
@Override
public void handleMessage(Message msg) {
if (result != null) { //如果服务器返回结果不为空
resultTV.setText(result); // 显示获得的结果
content.setText(""); //清空文本框
}
super.handleMessage(msg);
}
};
new Thread(new Runnable() { // 创建一个新线程,用于发送并读取微博信息
public void run() {
send(); //调用send()方法,用于发送文本内容到Web服务器
Message m = handler.obtainMessage(); // 获取一个Message
handler.sendMessage(m); // 发送消息
}
}).start(); // 开启线程
}
});
}
public void send() { //创建send()方法,用于建立一个HTTP连接,并将输入的内容发送到Web服务器上,再读取服务器的处理结果
String target = "";
String test=base64(content.getText().toString().trim());
target = "http://192.168.3.19:8080/example/get.jsp?content="
+test.substring(0,test.length()-3); //要访问的URL地址
Log.i("test",test.trim());
URL url;
try {
url = new URL(target);
Log.i("test", url.toString());
HttpURLConnection urlConn = (HttpURLConnection) url
.openConnection(); //创建一个HTTP连接
InputStreamReader in = new InputStreamReader(
urlConn.getInputStream()); // 获得读取的内容
BufferedReader buffer = new BufferedReader(in); // 获取输入流对象
String inputLine = null;
//通过循环逐行读取输入流中的内容
while ((inputLine = buffer.readLine()) != null) {
result += inputLine+"\n";
}
Log.i("test01",buffer.toString());
in.close(); //关闭字符输入流对象
urlConn.disconnect(); //断开连接
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public String base64(String content) { //对字符串进行Base64编码
try {
//对字符串进行Base64编码
content = Base64.encodeToString(content.getBytes("utf-8"), Base64.DEFAULT);
content = URLEncoder.encode(content, "utf-8"); //对字符串进行URL编码
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return content;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:padding="18dp"
android:background="@drawable/bg"
android:orientation="vertical">
<EditText
android:id="@+id/main_et1"
android:hint="输入想要发表的内容~~~"
android:textSize="22sp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/main_btn1"
android:text="发表"
android:background="#0373EC"
android:textSize="22sp"
android:layout_marginTop="175dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- 滚动视图-->
<ScrollView
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:layout_marginTop="40dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/main_tv1"
android:textSize="22sp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</ScrollView>
</LinearLayout>
AndroidManifest.xml
<!--访问网络-->
<uses-permission android:name="android.permission.INTERNET"/>
<application>节点下(Android9.0以上联网需要添加):
android:usesCleartextTraffic="true"
在Tomcat安装路径的webapps文件夹中新建一个文件夹,命名为example,在example文件夹下新建一个.jsp文件,命名为get.jsp,在get.jsp中编写代码:
<%@page contentType="text/html; charset=utf-8" language="java" import="java.util.Base64,java.util.Base64.Decoder"%>
<%
String content=request.getParameter("content");//获取输入的微博信息
if(content!=null){
Decoder decoder= Base64.getDecoder();
content=new String(decoder.decode(content),"utf-8"); //进行base64解码
String date=new java.util.Date().toLocaleString(); //获取系统时间
%>
<%="[Lisa]于 "+date+" 发表一条微博,内容如下:"%>
<%=content%>
<% }%>
运行Tomcat,连接真机运行Android项目。
注:真机需要能够连接到客户端的Tomcat服务器才能运行该项目,步骤如下:
(1)关闭电脑的防火墙

(2)电脑创建热点,用手机连接到电脑热点
设置->网络和Internet->移动热点

(3)用手机浏览器访问Tomcat网址,如果能显示Tomcat首页即为连接成功
1-2.发送POST请求
在Android中,使用HttpURLConnection类发送请求时,默认采用的是GET请求,如果要发送POST请求,需要通过其setRequestMethod()方法进行指定。例如,创建一个 HTTP 连接,并为该连接指定请求的发送方式为POST,可以使用下面的代码:
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();//创建一个HTTP连接
urlConn.setRequestMethod("POST");//指定请求方式为POST
发送POST请求要比发送GET请求复杂一些,它需要通过HttpURLConnection类及其父类URLConnection提供的方法设置相关内容,常用的方法如表14.2 所示。
表14.2 发送POST请求时常用的方法
| 方法 | 描述 |
|---|---|
| setDoInput(boolean newValue) | 用于设置是否向连接中写入数据,如果参数值为 true,表示写入数据;否则不写入数据 |
| setDoOutput(boolean newValue) | 用于设置是否从连接中读取数据,如果参数值为true,表示读取数据;否则不读取数据 |
| setUseCaches(boolean newValue) | 用于设置是否缓存数据,如果参数值为true,表示缓存数据;否则表示禁用缓存 |
| setInstanceFollowRedirects(boolean followRedirects) | 用于设置是否应该自动执行HTTP重定向,参数值为true时,表示自动执行;否则不自动执行 |
| setRequestProperty(String field, String newValue) | 用于设置一般请求属性,例如,要设置内容类型为表单数据,可以进行以下设置setRequestProperty("Content-Type","application/x-www-form-urlencoded") |
例:


MainActivity.java
package com.example.postrequest;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
public class MainActivity extends AppCompatActivity {
private EditText edit_Username;//输入账号的编辑框
private EditText edit_Password;//输入密码的编辑框
private Handler handler;
private String result="";//显示内容
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar=getSupportActionBar();
actionBar.hide();
edit_Username=findViewById(R.id.main_username);
edit_Password=findViewById(R.id.main_password);
ImageButton btn_login=findViewById(R.id.main_login);
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if("".equals(edit_Username.getText().toString()) ||
"".equals(edit_Password.getText().toString())){
Toast.makeText(MainActivity.this, "请填写账号或密码!", Toast.LENGTH_SHORT).show();
return;
}
handler=new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
//如果服务器返回值为“ok”证明账号密码正确
if("ok".equals(result)){
//跳转登录后界面
Log.i("test",result);
Intent intent=new Intent(MainActivity.this,MessageActivity.class);
startActivity(intent);
}else {
Toast.makeText(MainActivity.this, "请填写正确的账号和密码!", Toast.LENGTH_SHORT).show();
}
super.handleMessage(msg);
}
};
//创建一个新线程,用于从网络上获取数据
new Thread(new Runnable() {
@Override
public void run() {
send();
Message message=handler.obtainMessage();
handler.sendMessage(message);//发送消息
}
}).start();//开启线程
}
});
}
//建立HTTP连接,发送POST请求到服务器并读取服务器的处理结果
public void send(){
//要提交的服务器地址
String target="http://192.168.3.19:8080/example/post.jsp";
URL url;
try {
url=new URL(target);//创建URL对象
HttpURLConnection urlConnection= (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");//指定使用POST请求方式
urlConnection.setDoInput(true);//允许向连接写入数据
urlConnection.setDoOutput(true);//允许向连接读取数据
urlConnection.setUseCaches(false);//禁止缓存
urlConnection.setInstanceFollowRedirects(true);//自动执行HTTP重定向
urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");//设置内容类型
DataOutputStream outputStream=new DataOutputStream(urlConnection.getOutputStream());//获取输出流
String param="username="+ URLEncoder.encode(edit_Username.getText().toString(),"utf-8")
+"&password="+URLEncoder.encode(edit_Password.getText().toString(),"utf-8");
outputStream.writeBytes(param);//将要传递的数据写入输入流
outputStream.flush();//输出缓存
outputStream.close();//关闭输出流
if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){
InputStreamReader inputStreamReader=new InputStreamReader(urlConnection.getInputStream());//读取内容
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
String inputLine=null;
//逐行读取输入流中的内容
while((inputLine=bufferedReader.readLine())!=null){
result+=inputLine;
}
inputStreamReader.close();//关闭字节输入流
}
urlConnection.disconnect();//断开连接
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
AndroidManifest.xml
<!-- 访问网络-->
<uses-permission android:name="android.permission.INTERNET"/>
<application>节点下:
android:usesCleartextTraffic="true"
在Tomcat安装路径的webapps文件夹中新建一个文件夹,命名为example,在example文件夹下新建一个.jsp文件,命名为post.jsp,在post.jsp中编写代码:
<%@ page contentType="text/html; charset=utf-8" language="java" %>
<%String password=request.getParameter("password");//获取输入的密码
String username=request.getParameter("username");//获取输入的用户名
if(password!=null && username!=null){
username=new String(username.getBytes("iso-8859-1"),"utf-8"); //对用户名进行转码
password=new String(password.getBytes("iso-8859-1"),"utf-8"); //对密码进行转码
if("test".equals(username)&&"123".equals(password)){
%>
<%="ok"%>
<%}%>
<%}%>
运行Tomcat,连接真机运行Android项目。
本文介绍了Android中使用HttpURLConnection进行HTTP网络编程的基本方法,包括发送GET和POST请求。强调了不在主线程进行网络操作的重要性,并给出了相关代码示例以及如何在本地搭建测试服务器的说明。
&spm=1001.2101.3001.5002&articleId=126089790&d=1&t=3&u=2fe8cf758f8548d6af7372376a524941)
729

被折叠的 条评论
为什么被折叠?



