先看访问服务器的2种方式--枚举
HttpMethod
package com.jikexueyuan.secret.net; public enum HttpMethod { GET,POST }
package com.jikexueyuan.secret.net; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import com.jikexueyuan.secret.Config; import android.os.AsyncTask; /** * 请求服务器的基类 * */ public class NetConnection { /** * * @param url 服务器url * @param method 请求方式 * @param successCallback 成功回调 * @param failCallback 错误回调 * @param kvs 访问参数 */ public NetConnection(final String url, final HttpMethod method, final SuccessCallback successCallback, final FailCallback failCallback, final String... kvs) { /** * 进行异步请求服务器操作 * http://10.127.0.11:8090/NiMingServer/api.jsp?action=send_pass&phone=电话号码 */ new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... arg0) { StringBuffer paramsStr = new StringBuffer(); for (int i = 0; i < kvs.length; i += 2) { paramsStr.append(kvs[i]).append("=").append(kvs[i + 1]) .append("&"); } try { URLConnection uc; switch (method) { case POST: uc = new URL(url).openConnection(); //post方式需要设置的参数 uc.setDoOutput(true); //将拼接的参数通过BufferedWriter流输出 BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(uc.getOutputStream(), Config.CHARSET)); bw.write(paramsStr.toString()); bw.flush(); break; default: uc = new URL(url + "?" + paramsStr.toString()) .openConnection(); break; } System.out.println("Request url:" + uc.getURL()); System.out.println("Request data:" + paramsStr); /**通过服务器获取的数据进行BufferedReader读取*/ BufferedReader br = new BufferedReader( new InputStreamReader(uc.getInputStream(), Config.CHARSET)); String line = null; StringBuffer result = new StringBuffer(); while ((line = br.readLine()) != null) { result.append(line); } System.out.println("Result:" + result); //{"status":1} return result.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String result) { if (result != null) { if (successCallback != null) { successCallback.onSuccess(result); } } else { if (failCallback != null) { failCallback.onFail(); } } super.onPostExecute(result); } }.execute(); } /** * 请求服务器失败、成功的的接口方法,需要对付进行实现回调接口方法 * */ public static interface SuccessCallback { void onSuccess(String result); } public static interface FailCallback { void onFail(); } }
接下来看项目的入口MainActivity
package com.jikexueyuan.secret; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import com.jikexueyuan.secret.atys.AtyLogin; import com.jikexueyuan.secret.atys.AtyTimeline; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /** * 用户登陆使用手机号+短信验证码的方式登陆, * 登录后服务器端并不保存用户手机号。 * 登陆成功后下发给客户端登陆标识Token值--电话号码的对应值,客户端可以通过登陆标识保持相对长时间的访问服务器的权限。 */ String token = Config.getCachedToken(this); String phone_num = Config.getCachedPhoneNum(this); /**判断是不是第一次登陆,如果缓存中有登陆保存记录的话,就跳转到消息队列*/ if (token != null && phone_num != null) { Intent i = new Intent(this, AtyTimeline.class); i.putExtra(Config.KEY_TOKEN, token); i.putExtra(Config.KEY_PHONE_NUM, phone_num); startActivity(i); } else { /**如果缓存中没有保存之前的登陆记录,就视为首次登陆,跳转到登陆界面*/ startActivity(new Intent(this, AtyLogin.class)); } finish(); } }
第一次登录,手机没有缓存值,需要先跳转到登录界面,先来看登录界面的逻辑
AtyLogin
package com.jikexueyuan.secret.atys; import com.jikexueyuan.secret.Config; import com.jikexueyuan.secret.R; import com.jikexueyuan.secret.net.GetCode; import com.jikexueyuan.secret.net.Login; import com.jikexueyuan.secret.tools.MD5Tool; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class AtyLogin extends Activity { private EditText etPhone = null,etCode; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.aty_login); //手机号码输入框控件 etPhone = (EditText) findViewById(R.id.etPhoneNum); //登陆连接服务器成功后,获取的服务器返回的验证码输入框控件 etCode = (EditText) findViewById(R.id.etCode); /** * 进行获取验证码操作 */ findViewById(R.id.btnGetCode).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { //非空判断 if (TextUtils.isEmpty(etPhone.getText())) { //toast提示 Toast.makeText(AtyLogin.this, R.string.phone_num_can_not_be_empty, Toast.LENGTH_LONG).show(); return; } //进度条提示 final ProgressDialog pd = ProgressDialog.show(AtyLogin.this, getResources().getString(R.string.connecting), getResources().getString(R.string.connecting_to_server)); /** * 获取验证码操作,并且实现错误,正确的回调方法 * 参数:手机号码、接口 */ new GetCode(etPhone.getText().toString(), new GetCode.SuccessCallback() { @Override public void onSuccess() { //获取验证码成功后,去掉进度条 pd.dismiss(); Toast.makeText(AtyLogin.this, R.string.suc_to_get_code, Toast.LENGTH_LONG).show(); } }, new GetCode.FailCallback() { @Override public void onFail() { pd.dismiss(); Toast.makeText(AtyLogin.this, R.string.fail_to_get_code, Toast.LENGTH_LONG).show(); } }); } }); /** * 当获取验证码成功,这里为了项目简单,验证码可以随便输入, * 输入手机号、随便输入的验证码进行登陆 * 因为在获取验证时候,在服务起进行了简单的验证输出过{"status":1},就默认代表获取验证码短信了(项目主要是练手,短信验证码服务器没有实现) */ findViewById(R.id.btnLogin).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { /**判断手机号非空*/ if (TextUtils.isEmpty(etPhone.getText())) { Toast.makeText(AtyLogin.this, R.string.phone_num_can_not_be_empty, Toast.LENGTH_LONG).show(); return; } /**判断验证码非空*/ if (TextUtils.isEmpty(etCode.getText())) { Toast.makeText(AtyLogin.this, R.string.code_can_not_be_empty, Toast.LENGTH_LONG).show(); return; } /** * 进度条 */ final ProgressDialog pd = ProgressDialog.show(AtyLogin.this, getResources().getString(R.string.connecting), getResources().getString(R.string.connecting_to_server)); /** * 进行登陆进入 * 参数手机号的加密MD5方式--在服务器的保存方式 * 以及验证码 * 还有回调接口函数 */ new Login(MD5Tool.md5(etPhone.getText().toString()), etCode.getText().toString(), new Login.SuccessCallback() { @Override public void onSuccess(String token) { /** * 成功后,取消进度条 */ pd.dismiss(); /** * 将服务器的token、和电话号码保存 */ Config.cacheToken(AtyLogin.this, token); Config.cachePhoneNum(AtyLogin.this, etPhone.getText().toString()); /** * 携带服务器返回的Token、和电话号码传递并且启动AtyTimeline列表 */ Intent i = new Intent(AtyLogin.this, AtyTimeline.class); i.putExtra(Config.KEY_TOKEN, token); i.putExtra(Config.KEY_PHONE_NUM, etPhone.getText().toString()); startActivity(i); finish(); } }, new Login.FailCallback() { @Override public void onFail() { pd.dismiss(); Toast.makeText(AtyLogin.this, R.string.fail_to_login, Toast.LENGTH_LONG).show(); } }); } }); } }
new GetCode(phone, successCallback, failCallback)
AtyLogin的GetCode方法实现类如下
package com.jikexueyuan.secret.net; import org.json.JSONException; import org.json.JSONObject; import com.jikexueyuan.secret.Config; public class GetCode { /** * 获取验证码头的方法类 * @param phone * @param successCallback * @param failCallback */ public GetCode(String phone,final SuccessCallback successCallback,final FailCallback failCallback) { /** * 进行链接服务器,进行验证码获取操作 * SERVER_URL * POST方式 * 正确,错误的回调实现 */ new NetConnection(Config.SERVER_URL, HttpMethod.POST, new NetConnection.SuccessCallback() { /** * 请求服务器成功后,实现的回调方法 */ @Override public void onSuccess(String result) { try { //这是返回的结果JSon字符串{"status":1} JSONObject jsonObj = new JSONObject(result); //KEY_STATUS = "status" switch (jsonObj.getInt(Config.KEY_STATUS)) { //RESULT_STATUS_SUCCESS = 1; case Config.RESULT_STATUS_SUCCESS: if (successCallback!=null) { /**解析成功后,这里定义一个接口方法,需要获取验证码进行回调实现*/ successCallback.onSuccess(); } break; default: if (failCallback!=null) { failCallback.onFail(); } break; } } catch (JSONException e) { e.printStackTrace(); if (failCallback!=null) { failCallback.onFail(); } } } }, new NetConnection.FailCallback() { /** * 请求服务器失败后,实现的回调方法 */ @Override public void onFail() { if (failCallback!=null) { failCallback.onFail(); } } }, Config.KEY_ACTION,Config.ACTION_GET_CODE,Config.KEY_PHONE_NUM,phone); //http://10.127.0.11:8090/NiMingServer/api.jsp?action=send_pass&phone=111111& } public static interface SuccessCallback{ void onSuccess(); } public static interface FailCallback{ void onFail(); } }
AtyLogin登录界面的Login方法如下
new Login(phone_md5, code, successCallback, failCallback)
AtyLogin登录界面的Login方法实现类如下
package com.jikexueyuan.secret.net; import org.json.JSONException; import org.json.JSONObject; import com.jikexueyuan.secret.Config; public class Login { /** * 是进行登陆操作 * @param phone_md5 * @param code 这里服务器没有支持,可以随便输入一个验证码即可 * @param successCallback * @param failCallback */ public Login(String phone_md5,String code,final SuccessCallback successCallback,final FailCallback failCallback) { new NetConnection(Config.SERVER_URL, HttpMethod.POST, new NetConnection.SuccessCallback() { @Override public void onSuccess(String result) { try { /** * 对返回的jSon值进行判断 * 返回的格式:out.print("{\"status\":1,\"token\":\"asdasdasdsadasd\"}"); */ JSONObject obj = new JSONObject(result); //获取返回的状态值 switch (obj.getInt(Config.KEY_STATUS)) { case Config.RESULT_STATUS_SUCCESS: if (successCallback!=null) { //登陆成功后,设置回调接口让外部去实现--并且将Token进行回传 successCallback.onSuccess(obj.getString(Config.KEY_TOKEN)); } break; default: if (failCallback!=null) { failCallback.onFail(); } break; } } catch (JSONException e) { e.printStackTrace(); if (failCallback!=null) { failCallback.onFail(); } } } }, new NetConnection.FailCallback() { @Override public void onFail() { if (failCallback!=null) { failCallback.onFail(); } } }, Config.KEY_ACTION,Config.ACTION_LOGIN,Config.KEY_PHONE_MD5,phone_md5,Config.KEY_CODE,code); //http://10.127.0.11:8090/NiMingServer/api.jsp?action=login&phone_md5=phone_md5 & code=code } public static interface SuccessCallback{ void onSuccess(String token); } public static interface FailCallback{ void onFail(); } }