【攻克Android (41)】HttpURLConnection
程序员文章站
2024-01-19 10:10:22
...
本文围绕以下三个部分展开:
一、HttpURLConnection
HttpURLConnection案例一:Get、Post方式访问网络
HttpURLConnection案例二:异步加载图片
一、HttpURLConnection
1. HTTP
(1)“一次连接”:
HTTP通信中客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
(2)
要保持客户端程序的在线状态,需要不断向服务器发起连接请求。
通常的做法是即使不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端(下线),若客户端长时间无法收到服务器的回复,则认为网络已经断开。
2. Get和Post
HTTP通信中,请求网络使用最多的是 GET 和 POST 方式。
(1)Get方式:
Get请求可以获取静态页面,也可以把参数放在Url字符串的后面,传递给服务器。
发送表单数据时:它以重写 URL 的方式,提交数据到服务器。URL 最大长度不超过 1K 。
(2)Post方式
发送表单数据时:其参数不是放在URL字符串里面,而是放在Http请求数据中。
(3)HttpURLConnection的Get和Post
访问不需要传递参数的网页,只需要打开一个HttpURLConnection连接,然后取得流中的数据,完成之后,关闭连接。
需要传递参数时:由于HttpURLConnection默认使用GET方式,所以如果要使用POST方式,则需要setRequestMethod设置,然后将我们要传递的参数内容通过writeBytes写入数据流。
3. URLConnection
(1)抽象类 URLConnection是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。
(2)通常,创建一个到 URL 的连接需要以下几个步骤:
1)通过在 URL 上调用 openConnection方法创建连接对象。
2)操作设置参数和一般请求属性。
3)使用connect方法建立到远程对象的实际连接。
4)远程对象变为可用。远程对象的头字段和内容变为可访问。
4. HttpURLConnection
(1)概念
HttpURLConnection是Java标准类,继承自URLConnection类。
URLConnection与HttpURLConnection是都是抽象类,无法直接实例化对象。 其对象主要是通过URL的openConnection方法获得。
openConnection只是创建URLConnection或者HttpURLConnection实例,但是并不真正进行的连接操作。并且,每次openConnection都将创建一个新的实例。因此,在连接之前需要对一些属性进行操作,比如:Http超时的时间等。
(2)开发步骤
HttpURLConnection案例
一、服务器端
myeclipse开发好服务器端程序,然后将其打包成war包,放到tomcat下面,启动tomcat。
二、Android端
1. AndroidManifest.xml。授予此 APP 访问网络的权限。
2. strings.xml。
3. activity_main.xml
4. 要用到Butter Knife,因此用在build.gradle中导包。
5. StreamTool。处理 云端服务器返回客户端的流(对于客户端而言,是输入流) 的工具类。
6. LoginService。登录的业务逻辑类。
7. MainActivity。写按钮事件,点击按钮提交表单到服务器。获得返回的数据后,更新UI。
HttpURLConnection案例二
一、服务器端
同案例一。
二、Android端
1. AndroidManifest.xml。授予此 APP 访问网络的权限。
2. strings.xml。
3. activity_main.xml
4. 要用到Butter Knife,因此用在build.gradle中导包。
5. MainActivity。异步加载图片,显示在imageView的位置上。
一、HttpURLConnection
HttpURLConnection案例一:Get、Post方式访问网络
HttpURLConnection案例二:异步加载图片
一、HttpURLConnection
1. HTTP
(1)“一次连接”:
HTTP通信中客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。
(2)
要保持客户端程序的在线状态,需要不断向服务器发起连接请求。
通常的做法是即使不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端(下线),若客户端长时间无法收到服务器的回复,则认为网络已经断开。
2. Get和Post
HTTP通信中,请求网络使用最多的是 GET 和 POST 方式。
(1)Get方式:
Get请求可以获取静态页面,也可以把参数放在Url字符串的后面,传递给服务器。
发送表单数据时:它以重写 URL 的方式,提交数据到服务器。URL 最大长度不超过 1K 。
(2)Post方式
发送表单数据时:其参数不是放在URL字符串里面,而是放在Http请求数据中。
(3)HttpURLConnection的Get和Post
访问不需要传递参数的网页,只需要打开一个HttpURLConnection连接,然后取得流中的数据,完成之后,关闭连接。
需要传递参数时:由于HttpURLConnection默认使用GET方式,所以如果要使用POST方式,则需要setRequestMethod设置,然后将我们要传递的参数内容通过writeBytes写入数据流。
3. URLConnection
(1)抽象类 URLConnection是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。
(2)通常,创建一个到 URL 的连接需要以下几个步骤:
1)通过在 URL 上调用 openConnection方法创建连接对象。
2)操作设置参数和一般请求属性。
3)使用connect方法建立到远程对象的实际连接。
4)远程对象变为可用。远程对象的头字段和内容变为可访问。
4. HttpURLConnection
(1)概念
HttpURLConnection是Java标准类,继承自URLConnection类。
URLConnection与HttpURLConnection是都是抽象类,无法直接实例化对象。 其对象主要是通过URL的openConnection方法获得。
openConnection只是创建URLConnection或者HttpURLConnection实例,但是并不真正进行的连接操作。并且,每次openConnection都将创建一个新的实例。因此,在连接之前需要对一些属性进行操作,比如:Http超时的时间等。
(2)开发步骤
HttpURLConnection案例
一、服务器端
myeclipse开发好服务器端程序,然后将其打包成war包,放到tomcat下面,启动tomcat。
二、Android端
1. AndroidManifest.xml。授予此 APP 访问网络的权限。
<!-- 1. 授予此 APP 访问网络的权限 --> <user-permission android:name="android.permission.INTERNET" />
2. strings.xml。
<resources> <string name="app_name">LoginWeb</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="hint_username">用户名</string> <string name="hint_password">密码</string> <string name="btn_do_get">doGet</string> <string name="btn_do_post">doPost</string> </resources>
3. activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <EditText android:id="@+id/txtUsername" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_username" /> <EditText android:id="@+id/txtPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_password" android:inputType="textPassword" /> <Button android:id="@+id/btnDoGet" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_do_get" /> <Button android:id="@+id/btnDoPost" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_do_post" /> </LinearLayout>
4. 要用到Butter Knife,因此用在build.gradle中导包。
5. StreamTool。处理 云端服务器返回客户端的流(对于客户端而言,是输入流) 的工具类。
package com.android.loginweb; import java.io.ByteArrayOutputStream; import java.io.InputStream; /** * 处理 云端服务器返回客户端的流(对于客户端而言,是输入流) 的工具类 */ public class StreamTool { /** * 从输入流中获取数据(可以是文本/图片) * * @param in 输入流 * @return * @throws Exception */ public static byte[] readInputStream(InputStream in) throws Exception { // Byte 数组输出流 ByteArrayOutputStream out = new ByteArrayOutputStream(); // 定义缓存 -- 1k byte[] buffer = new byte[1024]; int len = 0; // !=-1 :没有结束 while ((len = in.read(buffer)) != -1) { // 从0开始写到len,读了多长就写多长。写到 缓存 buffer 里面。 out.write(buffer, 0, len); } in.close(); // 返回输出流输出的字节数组 return out.toByteArray(); } }
6. LoginService。登录的业务逻辑类。
package com.android.loginweb; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; /** * 登录的业务逻辑处理类 */ public class LoginService { /** * doGet: 以重写 URL 的方式提交数据到服务器,URL 最大长度不超过 1K * * @param username * @param password * @return */ public static String doGet(String username, String password) { try { String urlpath = "http://192.168.1.124:8090/androidcloud/LoginServlet?username=" + username + "&password=" + password; /* (1)请求云端服务器 */ // 创建 url 路径对象 URL url = new URL(urlpath); // 通过 url 打开网络连接 // url.openConnection() : 相当于在浏览器地址栏输入后,敲回车键访问网络。 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置网络超时时间:5s conn.setConnectTimeout(5000); // 设置请求方式为 GET conn.setRequestMethod("GET"); /* (2)云端服务器响应请求 */ // 响应代码 int code = conn.getResponseCode(); // code == 200 :OK状态,表示正常响应、正常请求。 if (code == 200) { // 从连接中获得响应的输入流 InputStream in = conn.getInputStream(); // 通过流工具类(StreamTool)把输入流数据转换为 字符串 return new String(StreamTool.readInputStream(in)); } else { return ""; } } catch (Exception e) { return ""; } } /** * doPost: 流的方式,浏览器直接把数据写给服务器 * * @param username * @param password * @return */ public static String doPost(String username, String password) { try { // 路径后面没有附加的参数 String urlpath = "http://192.168.1.124:8090/androidcloud/LoginServlet"; // 返回的参数 String data = "username=" + username + "&password=" + password; /* 请求云端服务器 */ URL url = new URL(urlpath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("POST"); /* 在Web开发的时候,是自动把数据发送到服务器的。 但是,Android开发中,需要用以下几行代码写出来。 */ // 内容类型 -- 指定是来自表单的数据 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 内容长度 conn.setRequestProperty("Content-Length", String.valueOf(data.length())); // 浏览器把数据写给服务器 -- 客户端向服务器输出 conn.setDoInput(true); OutputStream out = conn.getOutputStream(); out.write(data.getBytes()); int code = conn.getResponseCode(); if (code == 200) { InputStream in = conn.getInputStream(); return new String(StreamTool.readInputStream(in)); } else { return ""; } } catch (Exception e) { return ""; } } }
7. MainActivity。写按钮事件,点击按钮提交表单到服务器。获得返回的数据后,更新UI。
package com.android.loginweb; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; public class MainActivity extends Activity { @InjectView(R.id.txtUsername) EditText txtUsername; @InjectView(R.id.txtPassword) EditText txtPassword; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册 butterknife ButterKnife.inject(this); } // 按钮事件 @OnClick(R.id.btnDoGet) public void doGetClick() { // 注:此处,使用 new Thread(){ ... runOnUIThread() ...}.start() 处理耗时任务 // 获得 用户名和密码 这两个值ֵ final String username = txtUsername.getText().toString(); final String password = txtPassword.getText().toString(); // 提交数据到服务器 new Thread(new Runnable() { @Override public void run() { // 获得云端服务器返回的数据 final String result = LoginService.doGet(username, password); // 非 UI 线程开启 UI 线程,然后通过 UI Thread 更新界面 runOnUiThread(new Runnable() { @Override public void run() { if (TextUtils.isEmpty(result)) { Toast.makeText(getApplicationContext(), "连接网络失败!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); // 登录成功,可以更新 UI 界面,也可以跳转到另外一个界面 } } }); } }) { }.start(); } @OnClick(R.id.btnDoPost) public void doPostClick() { // 注:此处,使用 Async Task 处理耗时任务 LoginTask task = new LoginTask(); task.execute(""); } private class LoginTask extends AsyncTask<String, Integer, String> { /** * 在异步任务的后台方法中访问云端服务器 * * @param params * @return */ @Override protected String doInBackground(String... params) { // 获得 用户名和密码 这两个值 String username = txtUsername.getText().toString(); String password = txtPassword.getText().toString(); // 在异步任务中访问网络 String result = LoginService.doPost(username, password); return result; } /** * 后台方法处理完后,更新 UI 界面 * * @param result */ @Override protected void onPostExecute(String result) { if (TextUtils.isEmpty(result)) { Toast.makeText(getApplicationContext(), "连接网络失败!", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); // 登录成功,可以更新 UI 界面,也可以跳转到另外一个界面 } } } // ------------------------------------------------------------------- @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
HttpURLConnection案例二
一、服务器端
同案例一。
二、Android端
1. AndroidManifest.xml。授予此 APP 访问网络的权限。
<!-- 1. 授予此 APP 访问网络的权限 --> <user-permission android:name="android.permission.INTERNET" />
2. strings.xml。
<resources> <string name="app_name">LoginWeb</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="hint_image_url">Image URL</string> <string name="btn_load_image">Load Image</string> </resources>
3. activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <EditText android:id="@+id/txtUrl" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_image_url" android:inputType="textUri" /> <Button android:id="@+id/btnLoadImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_load_image" /> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/app_name" /> </LinearLayout>
4. 要用到Butter Knife,因此用在build.gradle中导包。
5. MainActivity。异步加载图片,显示在imageView的位置上。
package com.android.loginweb; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import butterknife.ButterKnife; import butterknife.InjectView; import butterknife.OnClick; public class MainActivity extends Activity { @InjectView(R.id.txtUrl) EditText txtUrl; @InjectView(R.id.imageView) ImageView imageView; // (1) private String urlpath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册 butterknife ButterKnife.inject(this); } /** * (2) */ @OnClick(R.id.btnLoadImage) public void loadImageClick(){ urlpath = txtUrl.getText().toString(); LoadImageTask imageTask = new LoadImageTask(); imageTask.execute(urlpath); } /** * (3) 获取网络图片任务 * * */ private class LoadImageTask extends AsyncTask<String, Integer, Bitmap> { /** * 在 doInBackground之前被调用,在ui线程执行 */ @Override protected void onPreExecute() { // 设置 imageView 处的图片为空 imageView.setImageBitmap(null); } /** * 在后台线程中执行的任务 */ @Override protected Bitmap doInBackground(String... params) { InputStream inputStream = null; Bitmap imgBitmap = null; try { URL url = new URL(urlpath); if (url != null) { HttpURLConnection connection = (HttpURLConnection) url .openConnection(); connection.setConnectTimeout(2000); connection.setDoInput(true); // 用 get 方法取图片(post是提交数据) connection.setRequestMethod("GET"); int code = connection.getResponseCode(); if (200 == code) { // 输入流中有图片 inputStream = connection.getInputStream(); // 通过 BitmapFactory 把 输入流 变为一张图片 imgBitmap = BitmapFactory.decodeStream(inputStream); } } } catch (Exception e) { return null; } // 这里不是UI线程,故不能直接 使用 setImage(imgBitmap) 直接更新 UI 界面。 return imgBitmap; } /** * 在后台线程执行完成之后,调用该方法,获取数据更新界面 * @param result */ @Override protected void onPostExecute(Bitmap result) { if (result != null) { Toast.makeText(MainActivity.this, "成功获取图片", Toast.LENGTH_LONG).show(); imageView.setImageBitmap(result); } else { Toast.makeText(MainActivity.this, "获取图片失败", Toast.LENGTH_LONG).show(); } } /** * 取消任务,在ui线程执行 */ @Override protected void onCancelled() { super.onCancelled(); } } // ------------------------------------------------------------------- @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
上一篇: 【攻克Android (41)】HttpURLConnection
下一篇: 数学建模04-图论
推荐阅读
-
【攻克Android (41)】HttpURLConnection
-
【攻克Android (40)】JSON解析
-
【攻克Android (41)】HttpURLConnection
-
【攻克Android (43)】WebView (网络视图)
-
【攻克Android (43)】WebView (网络视图)
-
10_Android中通过HttpUrlConnection访问网络,Handler和多线程使用,读取网络html代码并显示在界面上,ScrollView组件的使用_html/css_WEB-ITnose
-
安卓中使用HttpURLConnection连接网络简单示例 --Android网络编程
-
Android程序开发通过HttpURLConnection上传文件到服务器
-
Android中使用HttpURLConnection实现GET POST JSON数据与下载图片
-
Android基于HttpUrlConnection类的文件下载实例代码