【Android-网络通讯】 客户端与.Net服务端Http通讯
以登陆系统为例:
一、创建服务端程序
1、打开VS2012,新建项目,创建ASP.NET WEB应用程序 ,命名为MyApp
2、添加新建项,选择一般处理程序,创建Login.ashx
C# Code: Login.ashx
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace MyApp.Remote { /// <summary> /// Login 的摘要说明 /// </summary> public class Login : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; switch (context.Request["type"]) { case "login": loginValidate(context); break; default: break; } } /// <summary> /// 验证登陆 /// </summary> /// <param name="context"></param> private void loginValidate(HttpContext context) { string account = context.Request["Account"].ToString(); string password = context.Request["Password"].ToString(); if (account == "123" && password == "123") { string realName="HelloWord"; context.Response.Write("{\"Result\":\"1\",\"RealName\":\""+realName+"\"}"); //实际输出:{"Result":"1","RealName":"HelloWord"} //注意:双引号需要用转义符\ } else { context.Response.Write("{\"Result\":\"0\"}"); } } public bool IsReusable { get { return false; } } } }
3、到这里就完成服务端的验证代码登陆了。
浏览器输入地址访问:http://localhost:11946/Remote/Login.ashx?type=login&Account=123&Password=123
4、这时候程序还没有部署到IIS,那么如何在VS调试的时候,客户端可以通过IP访问该程序?
二、创建客户端程序
1、界面布局 layout \ activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_margin="10dp" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:text="账号" /> <EditText android:id="@+id/edittext_loginAccount" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" android:inputType="number" > <requestFocus /> </EditText> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:text="密码" /> <EditText android:id="@+id/editetext_loginPassword" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" android:inputType="textPassword" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" > <CheckBox android:id="@+id/checkbox_remindPassword" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="记住密码" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" > <Button android:id="@+id/button_login" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="登录" /> </LinearLayout> </LinearLayout>
2、Java Code : MainActivity.java
package com.example.net; import java.io.BufferedReader; import java.io.InputStreamReader; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private String ServerUrl = "http://192.168.137.210:11946/Remote/"; private EditText et_loginAccount; private EditText et_loginPassword; private CheckBox cb_remindPassword; private Button btn_login; private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build()); et_loginAccount = (EditText) findViewById(R.id.edittext_loginAccount); et_loginPassword = (EditText) findViewById(R.id.editetext_loginPassword); cb_remindPassword = (CheckBox) findViewById(R.id.checkbox_remindPassword); btn_login = (Button) findViewById(R.id.button_login); btn_login.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // loading 对话框 progressDialog = ProgressDialog.show(MainActivity.this, "", "服务器连接中...", true, false); // 开启线程去验证登录 new Thread() { @Override public void run() { // 向handler发消息 mHandler.sendEmptyMessage(0); } }.start(); } }); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // 登录验证 loginValidate(); } }; private void loginValidate() { // 打开网络连接 HttpClient client = new DefaultHttpClient(); StringBuilder builder = new StringBuilder(); // 服务器提交地址 String url = ServerUrl + "Login.ashx?type=login&Account=" + et_loginAccount.getText().toString() + "&Password=" + et_loginPassword.getText().toString(); HttpGet httpGet = new HttpGet(url); try { HttpResponse response = client.execute(httpGet); BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); // 填充数据流 for (String s = reader.readLine(); s != null; s = reader.readLine()) { builder.append(s); } // 读取Json返回数组 JSONObject jsonObject = new JSONObject(builder.toString()); String re_result = jsonObject.getString("Result"); String re_realName = jsonObject.getString("RealName"); if (re_result.equals("1")) { Toast.makeText(MainActivity.this, "验证成功!" + re_realName, Toast.LENGTH_SHORT).show(); // TODO:跳转页面 } else { Toast.makeText(MainActivity.this, "登录失败", Toast.LENGTH_SHORT).show(); } progressDialog.dismiss(); } catch (Exception e) { e.printStackTrace(); Toast.makeText(MainActivity.this, "服务器数据读取失败", Toast.LENGTH_SHORT).show(); progressDialog.dismiss(); } } }
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
少了上面两句代码会报错android.os.NetworkOnMainThreadException即,在主线程访问网络时出的异常
Android在4.0之前的版本支持在主线程中访问网络,但是在4.0以后对这部分程序进行了优化,也就是说访问网络的代码不能写在主线程中了。
稍后研究多线程
3、别放了加上权限 AndroidManifest.xml
<!-- sd卡读取权限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <!-- 访问网络权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- 完全退出程序权限 --> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />