1.post方式提交数据的中文乱码解决(重点)
解决中文乱码的方法:
保证客户端和服务器端使用的字符集编码一致。
Android应用程序默认使用的字符集是UTF-8;
//Tomcat默认的字符集编码是iso-8859-1,默认是iso-8859-1进行转码
String username = request.getParameter("username");
String password = request.getParameter("password");
String newUsername = new String(username.getBytes("iso-8859-1"),"UTF-8");
String newPassword = new String(password.getBytes("iso-8859-1"),"UTF-8");
System.out.println(newUsername);
System.out.println(newPassword);
if("中国".equals(newUsername) && "发展".equals(newPassword)){
//Tomcat默认的字符集编码是iso-8859-1,默认是iso-8859-1进行转码,当它发现使用iso-8859-1不能编码中文的时候, //会使用操作系统使用的本地码表(字符集编码)进行编码
response.getOutputStream().write("登陆成功".getBytes("UTF-8"));
}else
{ response.getOutputStream().write("登陆失败".getBytes("UTF-8"));
}
2.get提交数据乱码的解决:
保证客户端和服务器端使用的字符集编码一致. Android应用程序默认使用的字符集是UTF-8.
3.使用HttpClient向服务器端提交数据
HttpClient是apache下的子项目,轻量级的浏览器。
使用步骤:
1、创建一个浏览器:
2、输入网址:
3、按回车,执行请求:
* 使用GET方式提交数据:
代码:
//1、创建一个浏览器:
HttpClient client = new DefaultHttpClient();
//2、输入网址:
HttpGet http = new HttpGet(path);
//3、按回车,执行请求:
//服务器返回的所有数据都封装到了response里
HttpResponse response = client.execute(http);
//得到响应码(状态码)
int code = response.getStatusLine().getStatusCode();
if (200 == code) {
// 获得服务器端的响应数据
InputStream is = response.getEntity().getContent();
String result = StreamTools.readStream(is);
Message msg = Message.obtain();
msg.obj = result;
handler.sendMessage(msg);
}
* 使用POST方式发送提交数据:
代码:
package com.qaa.qqlogin;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_qq;
private EditText et_pwd;
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
String result = (String) msg.obj;
Toast.makeText(MainActivity.this, result, 0).show();
};
};
@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);
}
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;
}else
{
final String path = "http://192.168.20.91:8080/web/servlet/LoginServlet";
new Thread() {
public void run() {
try {
String data = "username="+URLEncoder.encode(qq,"UTF-8")+"&password="+URLEncoder.encode(pwd,"UTF-8");
// 1、创建一个浏览器:
HttpClient client = new DefaultHttpClient();
// 2、输入网址:
HttpPost http = new HttpPost(path);
//封装提交的参数
BasicNameValuePair value1 = new BasicNameValuePair("username",qq) ;
BasicNameValuePair value2 = new BasicNameValuePair("password",pwd) ;
List<BasicNameValuePair> parameters = new ArrayList<BasicNameValuePair>();
parameters.add(value1);
parameters.add(value2);
//把提交的数据封装到form实体对象中
//默认是iso-8859-1进行url编码,需要显示的指定字符集编码
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters,"UTF-8");
//设置提交的数据实体
http.setEntity(entity);
// 3、按回车,执行请求:
HttpResponse response = client.execute(http);
//得到响应码
int code = response.getStatusLine().getStatusCode();
if (200 == code) {
// 获得服务器端的响应数据
InputStream is = response.getEntity().getContent();
String result = StreamTools.readStream(is);
Message msg = Message.obtain();
msg.obj = result;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
}
5.使用开源项目Asynchttpclient的GET_POST访问网络
* 使用GET方式提交数据:
代码:
package com.qaa.qqlogin;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import org.apache.http.Header;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_qq;
private EditText et_pwd;
@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);
}
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; }
else
{
String path = "http://192.168.20.91:8080/web/servlet/LoginServlet?username=" + qq + "&password="+pwd;
//1、创建一个浏览器对象
AsyncHttpClient client = new AsyncHttpClient();
//2、发送一个GET请求
client.get(path, new AsyncHttpResponseHandler() {
/** * 请求处理成功后调用这个方法
* statusCode 响应码 200 404 503
* headers 响应头信息
* responseBody 服务器返回的响应数据(如:登陆成功、失败等) */
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Toast.makeText(MainActivity.this, new String(responseBody), 0).show(); }
/**
* 请求处理失败后调用这个方法
* statusCode 响应码 200 404 503
* headers 响应头信息
* responseBody 服务器返回的响应数据(如:登陆成功、失败等)
* Throwable 异常对象 */
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
error.printStackTrace();
Toast.makeText(MainActivity.this, "请求处理失败", 0).show();
}
});
}
}
}
* 使用POST方式提交数据:
代码:
package com.qaa.qqlogin;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import org.apache.http.Header;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity
{
private EditText et_qq;
private EditText et_pwd;
@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);
}
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;
}else
{
String path = "http://192.168.20.91:8080/web/servlet/LoginServlet";
AsyncHttpClient client = new AsyncHttpClient();
//封装要提交的数据
RequestParams params = new RequestParams();
params.put("username", qq);
params.put("password", pwd);
//执行post请求
//path 请求的url
//params 封装要提交的数据
//responseHandler 响应的处理器
client.post(path, params, new AsyncHttpResponseHandler()
{
/**
* 请求处理成功后调用这个方法
* statusCode 响应码 200 404 503
* headers 响应头信息
* responseBody 服务器返回的响应数据(如:登陆成功、失败等) */
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Toast.makeText(MainActivity.this, new String(responseBody), 0).show();
}
/**
* 请求处理失败后调用这个方法
* statusCode 响应码 200 404 503
* headers 响应头信息
* responseBody 服务器返回的响应数据(如:登陆成功、失败等)
* Throwable 异常对象 */
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
error.printStackTrace();
Toast.makeText(MainActivity.this, "请求处理失败", 0).show();
}
});
}
}
}
##6上传文件(重点)
代码:
String path = "http://192.168.20.91:8080/web/servlet/UploadServlet";
AsyncHttpClient client = new AsyncHttpClient();
//封装要提交的数据
RequestParams params = new RequestParams();
//上传文件
File file = new File(fildir);
params.put("file", file);
//执行post请求
//path 请求的url
//params 封装要提交的数据
//responseHandler 响应的处理器
client.post(path, params, new AsyncHttpResponseHandler() {
/**
* 请求处理成功后调用这个方法
* statusCode 响应码 200 404 503
* headers 响应头信息
* responseBody 服务器返回的响应数据(如:登陆成功、失败等) */
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Toast.makeText(MainActivity.this, new String(responseBody), 0).show();
}
/**
* 请求处理失败后调用这个方法
* statusCode 响应码 200 404 503
* headers 响应头信息
* responseBody 服务器返回的响应数据(如:登陆成功、失败等)
* Throwable 异常对象 */
@Override
public void onFailure(int statusCode, Header[] headers,byte[] responseBody, Throwable error) {
error.printStackTrace();
Toast.makeText(MainActivity.this, "请求处理失败", 0).show();
}
});
7.多线程下载的原理
多线程下载文件的步骤:
1、在客户端本地创建一个与服务器端一样大小的空白文件:
(1)创建空白文件:RandomAccessFile setlength();
(2)获取空白文件大小:content-length;
2、确定每个子线程下载数据块大小:
blocksize=length/threadCount:10/3=3
确定每个子线程下载数据的起始位置和结束位置:
第0个线程:开始位置 0*3=0 结束位置:(0+1)*3-1
第1个线程:开始位置 1*3=3 结束位置:(1+1)*3-1 ...
第n个线程:开始位置 n*blocksize 结束位置:(n+1)*blocksize-1 n是线程的id 最后一个子线程下载的结束位置:length-1
3、创建子线程,下载对应数据块:
4、确定每个子线程什么下载完毕,标识整个文件都下载完成:使用变量来标识;
##8.多线程下载的Android移植
代码:
MainActivity.java:
package com.qaa.multithreaddownloader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_path;
private EditText et_threadCount;
private static int threadCount = 3;
@Override
protected void onCreate(Bundle savedInstanceState)
{ super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path = (EditText) findViewById(R.id.et_path);
et_threadCount = (EditText) findViewById(R.id.et_threadCount);
}
public void download(View view){
final String path = et_path.getText().toString().trim();
String tcStr = et_threadCount.getText().toString().trim();
if(TextUtils.isEmpty(path)){
Toast.makeText(this, "请输入下载文件的网络路径", 0).show();
return; }
else{
if(!TextUtils.isEmpty(tcStr))
{ threadCount = Integer.parseInt(tcStr);
}
new Thread(){
public void run() {
// 1、在客户端本地创建一个与服务器端一样大小的空白文件:
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
int code = conn.getResponseCode();
if (200 == code) {
int length = conn.getContentLength();
RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory()+"/temp.exe", "rw");
raf.setLength(length);
// 2、确定每个子线程下载数据块大小:
int blockSize = length / threadCount;
for (int threadId = 0; threadId < threadCount; threadId++) {
// blocksize=length/threadCount:10/3=3
// 确定每个子线程下载数据的起始位置和结束位置:
// 第0个线程:开始位置 0*3=0 结束位置:(0+1)*3-1
// 第1个线程:开始位置 1*3=3 结束位置:(1+1)*3-1
// ... // 第n个线程:开始位置 n*blocksize 结束位置:(n+1)*blocksize-1 // n是线程的id
// 最后一个子线程下载的结束位置:length-1
int startIndex = threadId * blockSize;
int endIndex = (threadId + 1) * blockSize - 1;
if (threadId == (threadCount - 1)) {
endIndex = length - 1; }
// 3、创建子线程,下载对应数据块:
new ChildThreadDownLoader(threadId,startIndex,endIndex,path).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
ChildThreadDownLoader.java:
package com.qaa.multithreaddownloader;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import android.os.Environment;
public class ChildThreadDownLoader extends Thread{
private int threadId;
private int startIndex;
private int endIndex;
private String path;
private static int runningThreadCount = 3;
public ChildThreadDownLoader(int threadId, int startIndex, int endIndex, String path) {
super();
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path; }
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
//告诉服务器子线程请求的数据范围
conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
//请求部分数据成功返回的响应码是206
int code = conn.getResponseCode();
if(206 == code){
InputStream is = conn.getInputStream();
RandomAccessFile raf = new RandomAccessFile(Environment.getExternalStorageDirectory()+"/temp.exe","rwd");
raf.seek(startIndex); System.out.println("线程"+threadId+"正在下载...................");
byte[] buffer = new byte[1024*1024];
int len = 0;
while((len = is.read(buffer)) != -1){
raf.write(buffer, 0, len);
}
is.close();
raf.close();
}
System.out.println("线程"+threadId+"下载完毕...................");
// 4、确定每个子线程什么下载完毕,标识整个文件都下载完成:使用变量来标识;
synchronized (ChildThreadDownLoader.class)
{ runningThreadCount --;
if(runningThreadCount == 0){
System.out.println("文件下载完成..............");
}
}
}
catch (Exception e)
{ e.printStackTrace();
}
}
}
10.开源项目XUtils实现多线程下载(重点)
代码:
package com.qaa.multithreaddownloader;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
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 android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_path;
private EditText et_threadCount;
private static int threadCount = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_path = (EditText) findViewById(R.id.et_path);
et_threadCount = (EditText) findViewById(R.id.et_threadCount);
}
public void download(View view){
String path = et_path.getText().toString().trim();
String tcStr = et_threadCount.getText().toString().trim();
if(TextUtils.isEmpty(path))
{
Toast.makeText(this, "请输入下载文件的网络路径", 0).show();
return; }
else{
if(!TextUtils.isEmpty(tcStr))
{ threadCount = Integer.parseInt(tcStr);
}
HttpUtils http = new HttpUtils();
http.download(path, Environment.getExternalStorageDirectory()+"/temp.exe", new RequestCallBack<File>()
{
@Override
public void onStart()
{
Toast.makeText(MainActivity.this, "开始下载...", 0).show();
}
@Override
public void onLoading(long total, long current, boolean isUploading)
{ System.out.println(current+"/"+total+"-------------------------------");
}
@Override
public void onFailure(HttpException arg0, String arg1) {
Toast.makeText(MainActivity.this, "下载失败...", 0).show(); }
@Override
public void onSuccess(ResponseInfo<File> arg0) { Toast.makeText(MainActivity.this, "下载完成,文件保存在"+arg0.result.getPath(), 0).show();
}
});
}
}
}