3. Android框架和工具之 xUtils(HttpUtils)
2016-04-28 08:24
591 查看
1. HttpUtils 作用:
支持同步,异步方式的请求;
支持大文件上传,上传大文件不会oom;
支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD请求;
下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件;
返回文本内容的GET请求支持缓存,可设置默认过期时间和针对当前请求的过期时间。
2. HttpUtils全面注释:
3. HttpUtils使用post/get 方法访问网络:
(1)新建一个Android工程,命名为"HttpUtils",如下:
(2)首先我们来到主布局文件,如下:
(3)下面来到AndroidManifest.xml配置文件,添加权限。如下:
(4)来到MainActivity,如下:
布署程序到手机中,如下:
我们可以知道使用 HttpUtils 访问网络的时候不用new Thread一个子线程,HttpUtils内部自己实现了子线程。
同时我们在RequestCallBack回调的方法中可以直接操作UI界面的更新。
4. HttpUtils使用Get方法提交数据到服务器:
(1)首先我们搭建一个服务器平台,如下:
(2)我们先看看LoginServlet,如下:
布署上面的web工程到Tomcat服务器上。
(3)接下来我们来到客户端,我们新建一个Android工程,如下:
(4)首先我们这里写了一个工具类StreamTools,如下:
(5)我们首先来到主布局文件activity_main.xml,如下:
布局效果如下:
(6)接下来我们来到MainActivity,如下:
上面使用到res/values/string.xml,如下:
(7)这里需要网络权限
(8)布署程序到模拟器上,如下:
输入账号和密码,如下:
保存账号到手机内存data/data/包名/files目录下,如下:
导出info.txt,查看里面内容如下:
我们查看服务器端,说明提交数据到服务器端成功。如下:
5. 使用HttpUtils下载文件
支持断点续传,随时停止下载任务,开始任务
(1)开启Apache服务器,如下:
(2)在Apache服务器安装(解压)目录下htdocs存放文件夹movies,文件夹内部存放一个MP4文件,如下:
(3)新建一个Android工程,如下:
(4)首先我们来到主布局文件,如下:
(5)这里需要使用 网络,则在AndroidManifest.xml中添加相应的权限,如下:
(6)接着,我们来到MainActivity,如下:
(7)布署程序到模拟器上,如下:
点击"下载",等待下载成功。
我们追踪data/data/com.himi.httputils02/files/video.mp4,如下:
点击"下载",没有下载完,就点击"取消".
观察比较下载中断之后的数据和原来服务器端的数据的大小,结果如下:
支持同步,异步方式的请求;
支持大文件上传,上传大文件不会oom;
支持GET,POST,PUT,MOVE,COPY,DELETE,HEAD请求;
下载支持301/302重定向,支持设置是否根据Content-Disposition重命名下载的文件;
返回文本内容的GET请求支持缓存,可设置默认过期时间和针对当前请求的过期时间。
2. HttpUtils全面注释:
/* /** * 网络请求工具类 * @author 阿福 * */ public class HttpUtils { public final static HttpCache sHttpCache = new HttpCache(); private final DefaultHttpClient httpClient; private final HttpContext httpContext = new BasicHttpContext(); private HttpRedirectHandler httpRedirectHandler; /** * 构造方法,默认联网15秒超时 */ public HttpUtils() { this(HttpUtils.DEFAULT_CONN_TIMEOUT, null); } /** * 构造方法设置超时时间 * @param connTimeout 超时时间毫秒 */ public HttpUtils(int connTimeout) { this(connTimeout, null); } /** * 构造方法,浏览器的信息包 * @param userAgent */ public HttpUtils(String userAgent) { this(HttpUtils.DEFAULT_CONN_TIMEOUT, userAgent); } /** * 构造方法 * @param connTimeout 链接超时时间,毫秒单位 * @param userAgent 浏览器的信息包 */ public HttpUtils(int connTimeout, String userAgent) { HttpParams params = new BasicHttpParams(); ConnManagerParams.setTimeout(params, connTimeout); HttpConnectionParams.setSoTimeout(params, connTimeout); HttpConnectionParams.setConnectionTimeout(params, connTimeout); if (TextUtils.isEmpty(userAgent)) { userAgent = OtherUtils.getUserAgent(null); } HttpProtocolParams.setUserAgent(params, userAgent); ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(10)); ConnManagerParams.setMaxTotalConnections(params, 10); HttpConnectionParams.setTcpNoDelay(params, true); HttpConnectionParams.setSocketBufferSize(params, 1024 * 8); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", DefaultSSLSocketFactory.getSocketFactory(), 443)); httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(params, schemeRegistry), params); httpClient.setHttpRequestRetryHandler(new RetryHandler(DEFAULT_RETRY_TIMES)); httpClient.addRequestInterceptor(new HttpRequestInterceptor() { @Override public void process(org.apache.http.HttpRequest httpRequest, HttpContext httpContext) throws org.apache.http.HttpException, IOException { if (!httpRequest.containsHeader(HEADER_ACCEPT_ENCODING)) { httpRequest.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP); } } }); httpClient.addResponseInterceptor(new HttpResponseInterceptor() { @Override public void process(HttpResponse response, HttpContext httpContext) throws org.apache.http.HttpException, IOException { final HttpEntity entity = response.getEntity(); if (entity == null) { return; } final Header encoding = entity.getContentEncoding(); if (encoding != null) { for (HeaderElement element : encoding.getElements()) { if (element.getName().equalsIgnoreCase("gzip")) { response.setEntity(new GZipDecompressingEntity(response.getEntity())); return; } } } } }); } // ************************************ default settings & fields **************************** private String responseTextCharset = HTTP.UTF_8; private long currentRequestExpiry = HttpCache.getDefaultExpiryTime(); private final static int DEFAULT_CONN_TIMEOUT = 1000 * 15; // 15s private final static int DEFAULT_RETRY_TIMES = 3; private static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding"; private static final String ENCODING_GZIP = "gzip"; private final static int DEFAULT_POOL_SIZE = 3; private final static PriorityExecutor EXECUTOR = new PriorityExecutor(DEFAULT_POOL_SIZE); public HttpClient getHttpClient() { return this.httpClient; } // ***************************************** config ******************************************* /** * 配置请求文本编码,默认UTF-8 * @param charSet * @return */ public HttpUtils configResponseTextCharset(String charSet) { if (!TextUtils.isEmpty(charSet)) { this.responseTextCharset = charSet; } return this; } /** * http重定向处理 * @param httpRedirectHandler * @return */ public HttpUtils configHttpRedirectHandler(HttpRedirectHandler httpRedirectHandler) { this.httpRedirectHandler = httpRedirectHandler; return this; } /** * 配置http缓存大小 * @param httpCacheSize * @return */ public HttpUtils configHttpCacheSize(int httpCacheSize) { sHttpCache.setCacheSize(httpCacheSize); return this; } /** * 配置默认http缓存失效 ,默认是60秒 * @param defaultExpiry * @return */ public HttpUtils configDefaultHttpCacheExpiry(long defaultExpiry) { HttpCache.setDefaultExpiryTime(defaultExpiry); currentRequestExpiry = HttpCache.getDefaultExpiryTime(); return this; } /** * 配置当前http缓存失效,时间默认60秒 * @param currRequestExpiry * @return */ public HttpUtils configCurrentHttpCacheExpiry(long currRequestExpiry) { this.currentRequestExpiry = currRequestExpiry; return this; } /** * cookie存储配置 * @param cookieStore * @return */ public HttpUtils configCookieStore(CookieStore cookieStore) { httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); return this; } /** * 配置浏览器信息包 * @param userAgent * @return */ public HttpUtils configUserAgent(String userAgent) { HttpProtocolParams.setUserAgent(this.httpClient.getParams(), userAgent); return this; } /** * 配置时间链接超时 * @param timeout * @return */ public HttpUtils configTimeout(int timeout) { final HttpParams httpParams = this.httpClient.getParams(); ConnManagerParams.setTimeout(httpParams, timeout); HttpConnectionParams.setConnectionTimeout(httpParams, timeout); return this; } /** * 配置socket时间连接溢出 * @param timeout * @return */ public HttpUtils configSoTimeout(int timeout) { final HttpParams httpParams = this.httpClient.getParams(); HttpConnectionParams.setSoTimeout(httpParams, timeout); return this; } /** * 配置注册Scheme * @param scheme * @return */ public HttpUtils configRegisterScheme(Scheme scheme) { this.httpClient.getConnectionManager().getSchemeRegistry().register(scheme); return this; } /** * 配置SSLSocketFactory * @param sslSocketFactory * @return */ public HttpUtils configSSLSocketFactory(SSLSocketFactory sslSocketFactory) { Scheme scheme = new Scheme("https", sslSocketFactory, 443); this.httpClient.getConnectionManager().getSchemeRegistry().register(scheme); return this; } /** * 配置请求重试次数 * @param count 重试次数 * @return */ public HttpUtils configRequestRetryCount(int count) { this.httpClient.setHttpRequestRetryHandler(new RetryHandler(count)); return this; } /** * 配置请求线程池个数 * @param threadPoolSize 线程池个数 * @return */ public HttpUtils configRequestThreadPoolSize(int threadPoolSize) { HttpUtils.EXECUTOR.setPoolSize(threadPoolSize); return this; } // ***************************************** send request 发送请求******************************************* /** * 发送异步网络请求 -重要 * @param method get或者post请求等等 * @param url 网络请求路径 * @param callBack 回调 * @return */ public <T> HttpHandler<T> send(HttpRequest.HttpMethod method, String url, RequestCallBack<T> callBack) { return send(method, url, null, callBack); } /** * 发送异步网络请求 -重要 * @param method get或者post请求等等 * @param url 网络请求路径 * @param params 请求参数 * @param callBack 回调 * @return */ public <T> HttpHandler<T> send(HttpRequest.HttpMethod method, String url, RequestParams params, RequestCallBack<T> callBack) { if (url == null) throw new IllegalArgumentException("url may not be null"); HttpRequest request = new HttpRequest(method, url); return sendRequest(request, params, callBack); } /** * 发送同步网络请求 -用得不多 * @param method get或者post等方法 * @param url 联网网络url * @return * @throws HttpException */ public ResponseStream sendSync(HttpRequest.HttpMethod method, String url) throws HttpException { return sendSync(method, url, null); } /** * 发送同步网络请求 -用得不多 * @param method get或者post等方法 * @param url 联网网络url * @param params 请求参数 * @return * @throws HttpException */ public ResponseStream sendSync(HttpRequest.HttpMethod method, String url, RequestParams params) throws HttpException { if (url == null) throw new IllegalArgumentException("url may not be null"); HttpRequest request = new HttpRequest(method, url); return sendSyncRequest(request, params); } // ***************************************** download 下载******************************************* /** * 下载文件方法 * @param url 下载文件的url * @param target 下载保存的目录 * @param callback 回调 * @return */ public HttpHandler<File> download(String url, String target, RequestCallBack<File> callback) { return download(HttpRequest.HttpMethod.GET, url, target, null, false, false, callback); } /** * 下载文件方法 * @param url 下载文件的url * @param target 下载保存的目录 * @param autoResume 是否自动恢复下载 * @param callback 回调 * @return */ public HttpHandler<File> download(String url, String target, boolean autoResume, RequestCallBack<File> callback) { return download(HttpRequest.HttpMethod.GET, url, target, null, autoResume, false, callback); } /** * 下载文件方法 * @param url 下载文件的url * @param target 下载保存的目录 * @param autoResume 是否自动恢复下载 * @param autoRename 是否自动重命名 * @param callback 回调 * @return */ public HttpHandler<File> download(String url, String target, boolean autoResume, boolean autoRename, RequestCallBack<File> callback) { return download(HttpRequest.HttpMethod.GET, url, target, null, autoResume, autoRename, callback); } /** * 下载文件方法 * @param url 下载文件的url * @param target 下载保存的目录 * @param params 参数类 * @param callback 回调 * @return */ public HttpHandler<File> download(String url, String target, RequestParams params, RequestCallBack<File> callback) { return download(HttpRequest.HttpMethod.GET, url, target, params, false, false, callback); } /** * 下载文件方法 * @param url 下载文件的url * @param target 下载保存的目录 * @param params 参数类 * @param autoResume 是否自动恢复下载 * @param callback 回调 * @return */ public HttpHandler<File> download(String url, String target, RequestParams params, boolean autoResume, RequestCallBack<File> callback) { return download(HttpRequest.HttpMethod.GET, url, target, params, autoResume, false, callback); } /** * 下载文件方法 * @param url 下载文件的url * @param target 下载保存的目录 * @param params 参数 * @param autoResume 是否自动恢复 * @param autoRename 是否自动命名 * @param callback 回调 * @return */ public HttpHandler<File> download(String url, String target, RequestParams params, boolean autoResume, boolean autoRename, RequestCallBack<File> callback) { return download(HttpRequest.HttpMethod.GET, url, target, params, autoResume, autoRename, callback); } /** * 下载文件方法 * @param method 请求用get还是post等 * @param url 下载文件的url * @param target 下载保存的目录 * @param params 参数 * @param callback 回调 * @return */ public HttpHandler<File> download(HttpRequest.HttpMethod method, String url, String target, RequestParams params, RequestCallBack<File> callback) { return download(method, url, target, params, false, false, callback); } /** * 下载文件方法 * @param method 请求用get还是post等 * @param url 下载文件的url * @param target 下载保存的目录 * @param params 参数 * @param autoResume 是否自动恢复下载 * @param callback 回调 * @return */ public HttpHandler<File> download(HttpRequest.HttpMethod method, String url, String target, RequestParams params, boolean autoResume, RequestCallBack<File> callback) { return download(method, url, target, params, autoResume, false, callback); } /** * 下载文件方法 * @param method 请求用get还是post等 * @param url 下载文件的url * @param target 下载保存的目录 * @param params 参数 * @param autoResume 是否自动恢复下载 * @param autoRename 是否自动重命名 * @param callback 回调 * @return */ public HttpHandler<File> download(HttpRequest.HttpMethod method, String url, String target, RequestParams params, boolean autoResume, boolean autoRename, RequestCallBack<File> callback) { if (url == null) throw new IllegalArgumentException("url may not be null"); if (target == null) throw new IllegalArgumentException("target may not be null"); HttpRequest request = new HttpRequest(method, url); HttpHandler<File> handler = new HttpHandler<File>(httpClient, httpContext, responseTextCharset, callback); handler.setExpiry(currentRequestExpiry); handler.setHttpRedirectHandler(httpRedirectHandler); if (params != null) { request.setRequestParams(params, handler); handler.setPriority(params.getPriority()); } handler.executeOnExecutor(EXECUTOR, request, target, autoResume, autoRename); return handler; } //////////////////////////////////////////////////////////////////////////////////////////////// private <T> HttpHandler<T> sendRequest(HttpRequest request, RequestParams params, RequestCallBack<T> callBack) { HttpHandler<T> handler = new HttpHandler<T>(httpClient, httpContext, responseTextCharset, callBack); handler.setExpiry(currentRequestExpiry); handler.setHttpRedirectHandler(httpRedirectHandler); request.setRequestParams(params, handler); if (params != null) { handler.setPriority(params.getPriority()); } handler.executeOnExecutor(EXECUTOR, request); return handler; } private ResponseStream sendSyncRequest(HttpRequest request, RequestParams params) throws HttpException { SyncHttpHandler handler = new SyncHttpHandler(httpClient, httpContext, responseTextCharset); handler.setExpiry(currentRequestExpiry); handler.setHttpRedirectHandler(httpRedirectHandler); request.setRequestParams(params); return handler.sendRequest(request); } }
3. HttpUtils使用post/get 方法访问网络:
(1)新建一个Android工程,命名为"HttpUtils",如下:
(2)首先我们来到主布局文件,如下:
<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" tools:context="com.himi.httputils.MainActivity" > <Button android:id="@+id/net" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/replynet" /> <TextView android:id="@+id/loading" android:layout_width="match_parent" android:layout_height="wrap_content"/> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/success" android:layout_width="match_parent" android:layout_height="wrap_content"/> </ScrollView> </LinearLayout>
(3)下面来到AndroidManifest.xml配置文件,添加权限。如下:
(4)来到MainActivity,如下:
package com.himi.httputils; import com.lidroid.xutils.HttpUtils; import com.lidroid.xutils.ViewUtils; import com.lidroid.xutils.exception.HttpException; import com.lidroid.xutils.http.ResponseInfo; import com.lidroid.xutils.http.callback.RequestCallBack; import com.lidroid.xutils.http.client.HttpRequest; import com.lidroid.xutils.view.annotation.ViewInject; import com.lidroid.xutils.view.annotation.event.OnClick; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { @ViewInject(R.id.net) private Button net; @ViewInject(R.id.loading) private TextView loading; @ViewInject(R.id.success) private TextView success; /** * handler线程是主要用来和UI主线程进行交互的 *//* private Handler handler = new Handler(){ public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: break; default: break; } }; };*/ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewUtils.inject(this); } @OnClick(R.id.net) public void reply(View v) { HttpUtils http = new HttpUtils(); http.send(HttpRequest.HttpMethod.GET, "http://www.lidroid.com", new RequestCallBack<String>() { @Override public void onLoading(long total, long current, boolean isUploading) { System.out.println("数据加载中……"); //System.out.println(current + "/" + total); loading.setText(current + "/" + total); } @Override public void onSuccess(ResponseInfo<String> responseInfo) { System.out.println("数据加载完毕……"); //System.out.println(responseInfo.result); success.setText(responseInfo.result); } @Override public void onStart() { System.out.println("数据开始加载……"); } @Override public void onFailure(HttpException error, String msg) { System.out.println("数据加载失败……"); } }); } }
布署程序到手机中,如下:
我们可以知道使用 HttpUtils 访问网络的时候不用new Thread一个子线程,HttpUtils内部自己实现了子线程。
同时我们在RequestCallBack回调的方法中可以直接操作UI界面的更新。
4. HttpUtils使用Get方法提交数据到服务器:
(1)首先我们搭建一个服务器平台,如下:
(2)我们先看看LoginServlet,如下:
package web; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class LoginServlet */ @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String qq = request.getParameter("qq"); String password = request.getParameter("password"); System.out.println("qq:"+qq); System.out.println("password:"+password); /** * 模拟服务器操作,查询数据库,看qq和密码是否正确. * response.getOutputStream()获得一个输出流,向浏览器写入数据(提示数据). * 这里是输出Output,服务器输出到浏览器 */ if("10086".equals(qq) && "123456".equals(password)) { response.getOutputStream().write("Login Success".getBytes()); }else { response.getOutputStream().write("Login Failed".getBytes()); } } }
布署上面的web工程到Tomcat服务器上。
(3)接下来我们来到客户端,我们新建一个Android工程,如下:
(4)首先我们这里写了一个工具类StreamTools,如下:
package com.himi.httputils01; import java.io.ByteArrayOutputStream; import java.io.InputStream; /** * 流的工具类 * @author Administrator * */ public class StreamTools { /** * 把输入流的内容转换成字符串 * @param is * @return null解析失败, string读取成功 */ public static String readStream(InputStream is) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while((len = is.read(buffer)) != -1) { baos.write(buffer, 0, len); } is.close(); String result = baos.toString(); baos.close(); return result; } }
(5)我们首先来到主布局文件activity_main.xml,如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:paddingLeft="10dp" android:paddingRight="10dp" android:orientation="vertical" > <ImageView android:layout_width="50dip" android:layout_height="50dip" android:src="@drawable/ic_launcher" /> <EditText android:id="@+id/et_qq" android:inputType="text" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入qq号码" /> <EditText android:id="@+id/et_pwd" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入密码" android:inputType="textPassword" /> <CheckBox android:id="@+id/cb_remember" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="记住密码" /> <Button android:onClick="login" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="登陆" /> </LinearLayout>
布局效果如下:
(6)接下来我们来到MainActivity,如下:
package com.himi.httputils01; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import com.lidroid.xutils.HttpUtils; import com.lidroid.xutils.exception.HttpException; import com.lidroid.xutils.http.ResponseInfo; import com.lidroid.xutils.http.callback.RequestCallBack; import com.lidroid.xutils.http.client.HttpRequest; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private static final String Tag = "MainActivity"; private EditText et_qq; private EditText et_pwd; private CheckBox cb_remember; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 查询关心的控件 et_qq = (EditText) findViewById(R.id.et_qq); et_pwd = (EditText) findViewById(R.id.et_pwd); cb_remember = (CheckBox) findViewById(R.id.cb_remember); Log.i(Tag, "oncreate 被调用"); // 完成数据的回显。 readSavedData(); } // 读取保存的数据 private void readSavedData() { // getFilesDir() == /data/data/包名/files/ 获取文件的路径 一般系统是不会清理的。 // 用户手工清理,系统会有提示。 // getCacheDir()== /data/data/包名/cache/ 缓存文件的路径 当系统内存严重不足的时候 系统会自动的清除缓存 // 用户手工清理系统没有提示 File file = new File(getFilesDir(), "info.txt"); if (file.exists() && file.length() > 0) { try { // FileInputStream fis = new FileInputStream(file); FileInputStream fis = this.openFileInput("info.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(fis)); // 214342###abcdef String info = br.readLine(); String qq = info.split("###")[0]; String pwd = info.split("###")[1]; et_qq.setText(qq); et_pwd.setText(pwd); fis.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 登陆按钮的点击事件,在点击事件里面获取数据 * * @param view */ public void login(View view) { final String qq = et_qq.getText().toString().trim(); final String pwd = et_pwd.getText().toString().trim(); if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(pwd)) { Toast.makeText(this, "qq号码或者密码不能为空", 0).show(); return; } // 判断用户是否勾选记住密码。 if (cb_remember.isChecked()) { // 保存密码 Log.i(Tag, "保存密码"); try { // File file = new File(getFilesDir(),"info.txt"); // FileOutputStream fos = new FileOutputStream(file); FileOutputStream fos = this.openFileOutput("info.txt", 0); // 214342###abcdef fos.write((qq + "###" + pwd).getBytes()); fos.close(); Toast.makeText(this, "保存成功", 0).show(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(this, "保存失败", 0).show(); } } else { // 无需保存密码 Log.i(Tag, "无需保存密码"); } /** * 传统方法:使用子线程访问网络 */ /*new Thread() { public void run() { // String path // ="http://localhost:8080/web/LoginServlet";这里不能写成localhost try { String path = getString(R.string.serverip); URL url = new URL(path + "?qq=" + qq + "&password=" + pwd); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); int code = conn.getResponseCode(); if (code == 200) { InputStream is = conn.getInputStream(); String result = StreamTools.readStream(is); showToastInAnyThread(result); } else { showToastInAnyThread("请求失败"); } } catch (Exception e) { e.printStackTrace(); showToastInAnyThread("请求失败"); } }; }.start();*/ /** * 使用HttpUtils Get方式访问网络 */ HttpUtils http = new HttpUtils(); String path = getString(R.string.serverip); URL url = null; try { url = new URL(path+"?qq="+ qq + "&password="+pwd); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } http.send(HttpRequest.HttpMethod.GET, url.toString(), new RequestCallBack<String>() { @Override public void onFailure(HttpException arg0, String arg1) { showToastInAnyThread("提交数据失败"); } @Override public void onSuccess(ResponseInfo<String> arg0) { showToastInAnyThread("提交数据成功"); } }); } /** * 显示土司 在主线程更新UI * * @param text */ public void showToastInAnyThread(final String text) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, text, 0).show(); } }); } }
上面使用到res/values/string.xml,如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">HttpUtils01</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="serverip">http://49.123.72.28:8088/web/LoginServlet</string> </resources>
(7)这里需要网络权限
(8)布署程序到模拟器上,如下:
输入账号和密码,如下:
保存账号到手机内存data/data/包名/files目录下,如下:
导出info.txt,查看里面内容如下:
我们查看服务器端,说明提交数据到服务器端成功。如下:
5. 使用HttpUtils下载文件
支持断点续传,随时停止下载任务,开始任务
(1)开启Apache服务器,如下:
(2)在Apache服务器安装(解压)目录下htdocs存放文件夹movies,文件夹内部存放一个MP4文件,如下:
(3)新建一个Android工程,如下:
(4)首先我们来到主布局文件,如下:
<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" tools:context=".MainActivity" > <Button android:text="下载" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:onClick="download" /> <Button android:text="取消" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:onClick="cancel_download" /> <TextView android:id="@+id/tv_info" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:text="提示信息" /> </LinearLayout>
(5)这里需要使用 网络,则在AndroidManifest.xml中添加相应的权限,如下:
<uses-permission android:name="android.permission.INTERNET"/>
(6)接着,我们来到MainActivity,如下:
package com.himi.httputils02; import java.io.File; import com.lidroid.xutils.HttpUtils; import com.lidroid.xutils.exception.HttpException; import com.lidroid.xutils.http.HttpHandler; import com.lidroid.xutils.http.ResponseInfo; import com.lidroid.xutils.http.callback.RequestCallBack; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.TextView; public class MainActivity extends Activity { private TextView tv; private HttpHandler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv_info); } public void download(View v) { String download_url = getString(R.string.source_url); String target_url = getString(R.string.target_url); HttpUtils http = new HttpUtils(); /** * 下载文件方法 * * @param url * 下载文件的url * @param target * 下载保存的目录 * @param autoResume * 是否自动恢复下载 * @param autoRename * 是否自动重命名 * @param callback * 回调 * @return */ handler = http.download(download_url, target_url, true, // 如果目标文件存在,接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。 true, // 如果从请求返回信息中获取到文件名,下载完成后自动重命名。 new RequestCallBack<File>() { @Override public void onStart() { tv.setText("conn..."); } @Override public void onLoading(long total, long current, boolean isUploading) { //当然这里也可以使用进度条 tv.setText(current + "/" + total); } @Override public void onSuccess(ResponseInfo<File> responseInfo) { tv.setText("downloaded:" + responseInfo.result.getPath()); } @Override public void onFailure(HttpException error, String msg) { tv.setText(msg); } }); } public void cancel_download(View v){ //调用cancel()方法停止下载 handler.cancel(); tv.setText("It's canceled"); } }
(7)布署程序到模拟器上,如下:
点击"下载",等待下载成功。
我们追踪data/data/com.himi.httputils02/files/video.mp4,如下:
点击"下载",没有下载完,就点击"取消".
观察比较下载中断之后的数据和原来服务器端的数据的大小,结果如下:
相关文章推荐
- 使用Git上传本地代码到http://git.oschina.net/(SSH方式)
- 一个java 开源神经网络引擎 joone
- Android开发本地及网络Mp3音乐播放器(九)音乐收藏与列表切换
- Android开发本地及网络Mp3音乐播放器(九)音乐收藏与列表切换
- Android_GitHub_xUtils之DbUtils、ViewUtils、HttpUtils、BitmapUtils
- Android_GitHub_xUtils之DbUtils、ViewUtils、HttpUtils、BitmapUtils
- linux的网络配置及ip命令的使用详解
- [Android]通过JNI实现卸载自身App后台发送Http请求~
- CAS支持http协议
- unix网络编程中的unp.h
- 从网络获取数据显示到TableViewCell容易犯的错
- IOS开发网络阶段之NSURLConnection
- IOS开发网络阶段之NSURLSession
- iOS中http加的代码
- SDWebImage加载网络图片
- unix编程之socket编程系列之 简单的tcp和udp编程(二)
- 网络--七层协议
- IPerf——网络测试工具介绍与源码解析(5)
- 关于http urlencode 特殊箱号的那些事
- 为什么要进行URL编码