`
XiangdongLee
  • 浏览: 91179 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

【攻克Android (41)】HttpURLConnection

阅读更多
本文围绕以下三个部分展开:

一、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);
    }
}



0
1
分享到:
评论

相关推荐

    Android HttpUrlConnection json使用方法

    在Android开发中,HttpUrlConnection是用于网络通信的一种基础组件,尤其在处理JSON数据时,它扮演了重要的角色。本文将详细介绍如何使用HttpUrlConnection进行HTTP的POST和GET请求,并处理JSON响应。 首先,理解...

    Android-使用HttpURLConnection实现断点续传

    HttpURLConnection是Java标准库提供的一种网络连接接口,适用于Android系统,它提供了更高效、更灵活的网络通信方式。本文将详细介绍如何利用HttpURLConnection实现Android应用中的断点续传功能。 首先,理解断点续...

    android+httpurlconnection

    本项目聚焦于如何利用HTTPURLConnection实现从网络上下载图片并显示在Android Activity中。这个过程涉及到网络请求、多线程处理、数据解码以及UI更新等多个关键知识点。 首先,我们来讲解HTTPURLConnection的基本...

    AsyncTask结合HttpUrlConnection的例子

    在Android中,`HttpURLConnection`相比`HttpClient`更轻量级,更适合用于简单的HTTP请求。使用步骤如下: 1. 建立连接:通过URL对象获取`HttpURLConnection`实例。 2. 设置请求方法:如GET或POST。 3. 设置请求属性...

    Android 简单使用 HttpURLConnection

    本篇文章将深入探讨如何在Android中简单使用`HttpURLConnection`进行网络请求。 首先,了解`HttpURLConnection`的基本用法。在Android中,网络操作通常在子线程(非UI线程)中进行,以避免阻塞主线程导致应用无响应...

    Android httpUrlConnection Post方式访问网络简单demo

    在Android开发中,HTTP请求是应用与服务器交互的重要方式之一,`...此外,Android 9.0(Pie)及以上版本不再推荐使用`HttpURLConnection`,而是建议使用`OkHttp`这样的第三方库,它提供了更好的性能和易用性。

    HttpURLConnection和简单的Android服务器交互

    在Android应用开发中,与服务器进行数据交互是常见的需求,HttpURLConnection是Android SDK提供的一种轻量级、低级别的网络通信接口。本主题将深入探讨如何使用HttpURLConnection进行Android与服务器的简单交互,...

    Android使用HttpURLConnection访问网络

    本篇文章将深入探讨如何在Android应用中利用HttpURLConnection访问网络,包括设置请求方法、添加请求头、处理响应以及解决常见问题。 1. HttpURLConnection简介: HttpURLConnection是Java内置的类,它是...

    Android基于HttpUrlConnection类的文件下载实例代码

    Android基于HttpUrlConnection类的文件下载实例代码 Android操作系统中,文件下载是一种常见的功能,为了实现文件下载,Android提供了多种方式,包括使用HttpUrlConnection类和OkHttp库等。HttpUrlConnection类是...

    android HttpURLConnection上传图片demo

    这个"android HttpURLConnection上传图片demo"提供了一个具体的示例,教我们如何使用HttpURLConnection来完成这一任务。HttpURLConnection是Java标准库中的一个类,它允许Android应用程序与HTTP服务器进行通信,执行...

    android 联网请求的两种方式HttpURLConnection和HttpClient

    总的来说,HttpURLConnection更现代,更适合Android,而HttpClient虽然被弃用,但在某些情况下仍然适用。选择哪种方式取决于项目需求和个人偏好。理解这两种方法的工作原理以及如何处理GET和POST请求,是每个Android...

    Android网络请求框架基于HttpUrlConnection的封装

    HttpUrlConnection是Android系统提供的一个基础网络通信接口,相较于其他如Volley、OkHttp等第三方库,它更轻量级,适合对性能有较高要求或需要自定义网络操作的场景。 首先,我们来看HttpUrlConnection的基本用法...

    Android HttpURLConnection.getResponseCode()错误解决方法

    正文:我在使用HttpURLConnection.getResponseCode()的时候直接报错是IOException错误,responseCode = -1。一直想不明白,同一个程序我调用了两次,结果有一个链接一直OK,另一个却一直报这个错误。后来发现两个...

    android使用HTTPURLconnection/get方法访问HTTP

    以上就是使用`HttpURLConnection`在Android中进行GET请求的基本流程。注意,由于Android的安全策略,从Android 9(Pie)开始,你可能需要在AndroidManifest.xml中声明`usesCleartextTraffic`属性来允许非加密(HTTP...

    AndroidHttpURLConnection发送GET请求

    调用URL对象的openConnection( )来获取HttpURLConnection对象实例: HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 设置HTTP请求使用的方法:conn.setRequestMethod("GET"); 设置连接超时,...

    Httpurlconnection请求网络数据,使用Android Studio.zip

    `HttpURLConnection`是Java标准库提供的一种网络通信方式,适用于Android Studio项目。相较于其他网络库如OkHttp或Volley,`HttpURLConnection`更轻量级,适合小规模或者简单的网络请求。本教程将深入探讨如何使用`...

    Android 中HttpURLConnection与HttpClient使用的简单实例

    在Android 5.0之前,由于HttpURLConnection存在一些问题,HttpClient是首选。但随着Android版本的更新,这些问题得到了解决,现在HttpURLConnection成为了首选。 在实际应用中,你可能还需要处理更多细节,例如添加...

    Android移动开发-使用HttpURLConnection实现多线程的下载

    实例Demo程序来示范使用HttpURLConnection实现多线程下载。 使用多线程下载文件可以更快完成文件的下载,因为客户端启动多条线程进行下载就意味着服务器也需要为该客户端提供响应的服务。假设服务器同时最多服务100...

    彻底解决android用HttpUrlConnection与web服务器之间session保持问题

    在Android开发中,当使用HttpURLConnection与Web服务器进行通信时,常常遇到的一个问题是无法正确保持session,导致每次请求都被服务器视为新的独立会话。这主要由于HTTP协议本身的无状态特性,以及Android客户端与...

Global site tag (gtag.js) - Google Analytics