Android - 向服务器发送数据(GET).
在此,使用HTTP协议,通过GET请求,向服务器发送请求,这种方式适合于数据量小,数据安全性要求不高的情况下.
一,服务器端,使用Servlet.
在服务器端,定义一个HttpServlet的子类,以及一个Filter的子类(用于统一编码,防止出现乱码).
package spt.servlet; 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; /** * type 'http://localhost:8080/ReceiveAndroid/ServletForGETMethod?name=juk&pwd=lis' * for the browser. */ @WebServlet("/ServletForGETMethod") public class ServletForGETMethod extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public ServletForGETMethod() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); String pwd = request.getParameter("pwd"); System.out.println("name:" + name + " pwd:" + pwd); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } }
package spt.servlet.filter; import java.io.IOException; import java.io.UnsupportedEncodingException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; //filter all servlets. @WebFilter("/*") public class EncodingFilter implements Filter { public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpReq = (HttpServletRequest) servletRequest; if ("GET".equals(httpReq.getMethod())) filterChain.doFilter(new HttpServletRequestEncodingWrapper(httpReq), servletResponse); else { httpReq.setCharacterEncoding("utf-8"); filterChain.doFilter(httpReq, servletResponse); } } public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } /**inner class dealing for 'GET' method. * @author Administrator *2015-1-27 */ private class HttpServletRequestEncodingWrapper extends HttpServletRequestWrapper { public HttpServletRequestEncodingWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { //encode with 'iso', and than decode with 'utf'. String val = super.getRequest().getParameter(name); if (null != val) { try { return new String(val.getBytes("iso8859-1"), "utf-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } return super.getParameter(name); } } public void destroy() { // TODO Auto-generated method stub } }
在主机(服务器)上,往浏览器中输入'http://localhost:8080/ReceiveAndroid/ServletForGETMethod?name=juk&pwd=lis', 若在控制台打印需要的结果,则表示服务器端的Servlet已经编写好.
二,Android的业务逻辑层类,主要是将业务逻辑独立于Android的Activity.
package spt.http.get.assist; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import android.os.Handler; /**用户向服务器端发送数据的类. * @author Administrator * */ public class SendDataToServer { private static final int TIME_OUT = 10000; // 超时时间. // 连接服务器的url. private static final String URL = "http://192.168.1.101:8080/ReceiveAndroid/ServletForGETMethod"; // 标识是否连接到服务器成功. public static final int SEND_SUCCESS = 1; public static final int SEND_FAIL = 0; private Handler handler = null; public SendDataToServer(Handler handler) { this.handler = handler; } /** * 往服务器发送数据. * * @param name * @param pwd */ public void send(String name, String pwd) { // 这里params要传递到另外一个方法,加final为了防止被修改. final Map<String, String> params = new HashMap<String, String>(); params.put("name", name); params.put("pwd", pwd); // 启动新的线程连接服务器. new Thread(new Runnable() { @Override public void run() { // 使用get请求连接. try { if (getSend(params, URL, "utf-8")) handler.sendEmptyMessage(SEND_SUCCESS); else handler.sendEmptyMessage(SEND_FAIL); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } /**发送get请求的方法. * @param params 请求参数的键-值对. * @param url * @param encoding 使用指定编码对参数值进行编码. * @return * @throws MalformedURLException * @throws IOException */ private boolean getSend(Map<String, String> params, String url, String encoding) throws MalformedURLException, IOException { StringBuilder sb = new StringBuilder(); // 向url中添加参数. sb.append(url).append("?"); for (Entry<String, String> param : params.entrySet()) { sb.append(param.getKey()).append("=") .append(URLEncoder.encode(param.getValue(), encoding)) .append("&"); } if (params.size() > 0) sb.deleteCharAt(sb.length() - 1); // 去掉末尾的'&'. HttpURLConnection conn = (HttpURLConnection) new URL(sb.toString()) .openConnection(); conn.setConnectTimeout(TIME_OUT); conn.setRequestMethod("GET"); // GET是大小写敏感的. return conn.getResponseCode() == 200; // 等于200表示发送成功. } }
三:Activity类:
package spt.http.get.activity; import java.lang.ref.WeakReference; import spt.http.get.assist.SendDataToServer; 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.EditText; import android.widget.Toast; public class MainActivity extends Activity { //view. private EditText edt_name = null; private EditText edt_pwd = null; private Button btn_ok = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initListener(); } /** * 初始化View. */ private void initView() { edt_name = (EditText)findViewById(R.id.edt_name); edt_pwd = (EditText)findViewById(R.id.edt_pwd); btn_ok = (Button)findViewById(R.id.btn_ok); //test: edt_name.setText("你好"); edt_pwd.setText("abc"); } /**使用静态内部类,解决'This Handler class should be static or leaks might occur',以免造成内存泄露. * @author Administrator * */ private static class StatusHandler extends Handler { WeakReference<MainActivity> iMainActivity = null; public StatusHandler(MainActivity mainActivity) { iMainActivity = new WeakReference<MainActivity>(mainActivity); } @Override public void handleMessage(Message msg) { switch (msg.what) { case SendDataToServer.SEND_SUCCESS: //有iMainActivity.get()和iMainActivity.getClass(). Toast.makeText(iMainActivity.get(), "发送成功", Toast.LENGTH_SHORT).show(); break; case SendDataToServer.SEND_FAIL: Toast.makeText(iMainActivity.get(), "发送失败", Toast.LENGTH_SHORT).show(); break; default: throw new RuntimeException("未知的发送结果!"); } } } /** * 处理发送是否成功的状态的Handler. */ private final Handler handler = new StatusHandler(this); /** * 初始化监听器. */ private void initListener() { btn_ok.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { String name = edt_name.getText().toString(); String pwd = edt_pwd.getText().toString(); if(name.isEmpty() || pwd.isEmpty()) { Toast.makeText(MainActivity.this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show(); return; } new SendDataToServer(handler).send(name, pwd); } }); } }
稍微留意的是,Activity类中的Handler的子类定义为静态类,并保存对Activity的弱引用,防止内存泄露.简略解释在我的博文 Android - This Handler class should be static or leaks might occur. 中.
四, 添加必要权限
在AndroidManifest.xml中,添加
<uses-permission android:name="android.permission.INTERNET" />
以对网络的访问.