本文为菜鸟窝作者蒋志碧的连载。“从 0 开始开发一款直播 APP ”系列来聊聊时下最火的直播 APP,如何完整的实现一个类"腾讯直播"的商业化项目
视频地址:http://www.cniao5.com/course/10121
【从 0 开始开发一款直播 APP】4.1 网络封装之 Okhttp -- 基础回顾
【从 0 开始开发一款直播 APP】4.2 网络封装之 OkHttp -- GET,POST,前后端交互
【从 0 开始开发一款直播 APP】4.3 网络封装之 OkHttp -- 封装 GET,POST FORM,POST JSON
【从 0 开始开发一款直播 APP】4.4 网络封装之 OkHttp -- 网络请求实现直播登录
上一章讲了 OkHttp 的封装,现在来使用一下封装吧。
网络请求进行手机登录和用户名登录。
先来介绍一个请求工具 postman,Google 浏览器上的一个插件,也有对应的应用程序,亲测很好用,推荐给大家。
好了,开始讲解网络请求,测试一下封装的 Okhttp 框架。
讲解之前添加依赖以及相关权限
compile 'com.google.code.gson:gson:2.3.1'
compile 'com.zhy:okhttputils:2.6.2'
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
一、界面布局
里面用到了一个控件,很漂亮,看到输入框的文字会跳动对吧,就是这个控件。android.support.design.widget.TextInputLayout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg_dark"
android:id="@+id/rl_login_root"
tools:context="com.dali.admin.livestreaming.activity.LoginActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginTop="19dp"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="100dp">
//验证码
<Button
android:id="@+id/btn_verify_code"
android:layout_width="90dp"
android:layout_height="35dp"
android:layout_alignEnd="@+id/til_login"
android:layout_alignRight="@+id/til_login"
android:layout_below="@+id/til_login"
android:layout_marginRight="5dp"
android:layout_marginTop="2dp"
android:background="@drawable/btn_login"
android:clickable="true"
android:minWidth="0dp"
android:padding="4dp"
android:text="@string/activity_login_verify_code"
android:textSize="12sp"
style="@style/loginButton"
/>
<android.support.design.widget.TextInputLayout
android:id="@+id/til_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
//用户名
<AutoCompleteTextView
android:id="@+id/et_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:hint="@string/activity_login_username"
android:inputType="textEmailAddress"
android:maxLength="24"
android:maxLines="1"
android:singleLine="true"
android:textColor="@drawable/tv_selector"
android:textColorHint="@color/white"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/til_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/til_login">
//密码
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/et_login"
android:ellipsize="end"
android:hint="@string/activity_login_password"
android:imeActionId="@+id/login"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLength="24"
android:maxLines="1"
android:singleLine="true"
android:textColor="@color/white"
android:textColorHint="@color/white"/>
</android.support.design.widget.TextInputLayout>
//登录
<Button
android:id="@+id/btn_login"
android:layout_alignParentEnd="true"
android:layout_below="@+id/til_password"
android:background="@drawable/btn_login"
android:clickable="true"
android:padding="0dp"
android:text="@string/activity_login_btnlogin"
style="@style/loginButton"/>
//手机号登录
<Button
android:id="@+id/btn_phone_login"
android:layout_width="wrap_content"
android:layout_below="@+id/btn_login"
android:layout_marginTop="10dp"
android:text="@string/activity_login_btnphone"
android:background="?attr/selectableItemBackground"
style="@style/loginButton"
/>
//注册新用户
<Button
android:id="@+id/btn_register"
android:layout_width="wrap_content"
android:layout_alignEnd="@+id/btn_login"
android:layout_alignRight="@+id/btn_login"
android:layout_below="@+id/btn_login"
android:background="?attr/selectableItemBackground"
android:layout_marginTop="10dp"
android:text="@string/activity_login_register"
style="@style/loginButton"
/>
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignTop="@+id/btn_login"
android:layout_centerHorizontal="true"
android:visibility="gone"/>
</RelativeLayout>
</RelativeLayout>
二、登录界面逻辑实现
2.1、类的初始化
创建 LoginActivity 类,继承 BaseActivity,实现其抽象方法。实例化控件。
public class LoginActivity extends BaseActivity implements View.OnClickListener{
//控件
private ProgressBar progressBar;
private EditText etPassword;
private EditText etLogin;
private Button btnLogin;
private Button btnPhoneLogin;
private TextInputLayout tilLogin, tilPassword;
private Button btnRegister;
private TextView tvVerifyCode;
//是否是手机号登录
private boolean isPhoneLogin = false;
@Override
protected void setActionBar() {
}
@Override
protected void setListener() {
}
@Override
protected void initData() {
}
@Override
protected void initView() {
etLogin = obtainView(R.id.et_username);
etPassword = obtainView(R.id.et_password);
btnRegister = obtainView(R.id.btn_register);
btnPhoneLogin = obtainView(R.id.btn_phone_login);
btnLogin = obtainView(R.id.btn_login);
progressBar = obtainView(R.id.progressbar);
tilLogin = obtainView(til_login);
tilPassword = obtainView(R.id.til_password);
tvVerifyCode = obtainView(R.id.btn_verify_code);
//第一次进入系统默认是用户名登录
userNameLoginViewInit();
}
@Override
protected int getLayoutId() {
return R.layout.activity_login;
}
@Override
public void onClick(View v) {
}
}
2.2、用户名登录实现
这里实现逻辑,解释一下实现思路,而登录请求网络后面介绍。
//用户名登录方法
public void userNameLoginViewInit() {
//用户名登录控件初始化
userLoginTrans();
//注册监听
btnRegister.setOnClickListener(this);
//这里只是用做切换界面,用户名登录情况下点击按钮显示到手机号登录,显示获取验证码按钮
btnPhoneLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//手机号登录切换
phoneLoginViewinit();
}
});
//登录按钮监听
btnLogin.setOnClickListener(this);
}
//用户名登录界面控件显示
private void userLoginTrans() {
//将手机号登录设置为 false
isPhoneLogin = false;
//隐藏获取验证码按钮
tvVerifyCode.setVisibility(View.GONE);
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
alphaAnimation.setDuration(250);
tvVerifyCode.setAnimation(alphaAnimation);
//设置输入框输入类型为 文本输入
etLogin.setInputType(EditorInfo.TYPE_CLASS_TEXT);
//清空输入框内容
etLogin.setText("");
etPassword.setText("");
//设置用户名登录按钮文字为 手机号登录
btnPhoneLogin.setText("手机号登录");
//设置 TextInputLayout 文字为 用户名和密码
tilLogin.setHint("用户名");
tilPassword.setHint("密码");
}
2.3、手机号登录实现
如上,实现逻辑,登录请求网络接下来介绍。
//手机号登录方法
public void phoneLoginViewinit() {
//用户名登录控件初始化
phoneLoginTrans();
//这里只是用做切换界面,用户名登录情况下点击按钮显示到手机号登录,显示获取验证码按钮
btnPhoneLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//转换为用户名登录界面
userNameLoginViewInit();
}
});
//登录按钮监听
btnLogin.setOnClickListener(this);
}
//手机号登录控件显示
private void phoneLoginTrans() {
//将手机号登录设置为 true
isPhoneLogin = true;
//显示获取验证码按钮
tvVerifyCode.setVisibility(View.VISIBLE);
AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(250);
tvVerifyCode.setAnimation(alphaAnimation);
//设定点击优先级于最前(避免被EditText遮挡的情况)
tvVerifyCode.bringToFront();
//设置输入框输入类型为 手机号
etLogin.setInputType(EditorInfo.TYPE_CLASS_PHONE);
//清空输入框内容
etLogin.setText("");
etPassword.setText("");
//手机号登录按钮文字改为 用户名登录
btnPhoneLogin.setText("用户名登录");
//设置 TextInputLayout 文字为 手机号和密码
tilLogin.setHint("手机号");
tilPassword.setHint("密码");
}
2.4、请求网络实现登录
2.4.1、用户名登录
之前介绍的工具还没用上呢,现在来请求网络,看看需要那些数据,请求参数有登录方式 action,用户名 userName 和 密码 password。
2.4.2、为如上数据创建一个请求实体类。
public class LoginRequest extends IRequest {
public LoginRequest(int requestId, String userName, String password) {
mRequestId = requestId;
mParams.put("action", "login");
mParams.put("userName", userName);
mParams.put("password", password);
}
//getHost():返回的 API,这里在封装 OkHttp 框架的时候有的,HOST_PUBLIC = "http://live.demo.cniao5.com/Api/";
@Override
public String getUrl() {
return getHost() + "User";
}
@Override
public Type getParserType() {
return new TypeToken<Response<UserInfo>>() {
}.getType();
}
}
2.4.3、网络请求实现用户名登录
public void usernameLogin(final String userName, final String password) {
//检查网络状态,需要添加网络使用权限:ACCESS_NETWORK_STATE
if (checkUserNameLogin(userName, password)) {
// RequestComm.login 是 requestId:值是120,后台提供
LoginRequest req = new LoginRequest(RequestComm.login, userName, password);
AsyncHttp.instance().postJson(req, new AsyncHttp.IHttpListener() {
@Override//请求网络之前调用
public void onStart(int requestId) {
//显示环形进度条
showOnLoading(true);
}
@Override
public void onSuccess(int requestId, Response response) {
//RequestComm.SUCCESS 状态验证:值是0,上面请求网络有显示
if (response.status == RequestComm.SUCCESS) {
Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
//隐藏环形进度条
showOnLoading(false);
}
@Override
public void onFailure(int requestId, int httpStatus, Throwable error) {
showOnLoading(false);//隐藏环形进度条
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
});
}
}
2.5、手机登录实现
手机号登录先来测试网络数据API,看看实体类需要的数据。请求参数有登录方式 action,手机号 mobile 和 验证码 verifyCode。
2.5.1、创建手机登录请求实体类
public class PhoneLoginRequest extends IRequest {
public PhoneLoginRequest(int requestId, String mobile, String verifyCode) {
mRequestId = requestId;
mParams.put("action", "phoneLogin");
mParams.put("mobile", mobile);
mParams.put("verifyCode", verifyCode);
}
//getHost():返回的 API,这里在封装 OkHttp 框架的时候有的,HOST_PUBLIC = "http://live.demo.cniao5.com/Api/";
@Override
public String getUrl() {
return getHost() + "User";
}
@Override
public Type getParserType() {
return new TypeToken<Response>() {
}.getType();
}
}
2.5.2、网络请求实现手机号登录
public void phoneLogin(final String mobile, String verifyCode) {
//检查网络状态,需要添加网络使用权限:ACCESS_NETWORK_STATE
if (checkPhoneLogin(mobile, verifyCode)) {//requestId = 1200,后台提供
PhoneLoginRequest req = new PhoneLoginRequest(1200, mobile, verifyCode);
AsyncHttp.instance().postJson(req, new AsyncHttp.IHttpListener() {
@Override//请求网络之前调用
public void onStart(int requestId) {
showOnLoading(true);//显示环形进度条
}
@Override
public void onSuccess(int requestId, Response response) {
//RequestComm.SUCCESS 状态验证:值是0,上面请求网络有显示
if (response.status == RequestComm.SUCCESS) {
Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
showOnLoading(false);//隐藏环形进度条
}
@Override
public void onFailure(int requestId, int httpStatus, Throwable error) {
showOnLoading(false);//隐藏环形进度条
Toast.makeText(LoginActivity.this, "网络异常", Toast.LENGTH_SHORT).show();
}
});
}
}
检查用户名登录、手机登录、环形进度条显示或隐藏代码
//监测用户名登录
public boolean checkUserNameLogin(String userName, String password) {
if (OtherUtils.isUsernameVaild(userName)) {
if (OtherUtils.isPasswordValid(password)) {
if (OtherUtils.isNetworkAvailable(this)) {
return true;
} else {
ToastUtils.showShort(this, "当前无网络连接");
}
} else {
ToastUtils.showShort(this, "密码过短");
}
} else {
ToastUtils.showShort(this, "用户名不符合规范");
}
return false;
}
//监测手机号登录
public boolean checkPhoneLogin(String phone, String verifyCode) {
if (OtherUtils.isPhoneNumValid(phone)) {
if (OtherUtils.isVerifyCodeValid(verifyCode)) {
if (OtherUtils.isNetworkAvailable(this)) {
return true;
} else {
ToastUtils.showShort(this, "当前无网络连接");
}
} else {
ToastUtils.showShort(this, "验证码错误");
}
} else {
ToastUtils.showShort(this, "手机格式错误");
}
return false;
}
//进度条显示与隐藏
public void showOnLoading(boolean active) {
if (active) {
//显示进度条
progressBar.setVisibility(View.VISIBLE);
//显示登录按钮
btnLogin.setVisibility(View.INVISIBLE);
//输入框设置不可用
etLogin.setEnabled(false);
etPassword.setEnabled(false);
//手机号按钮和按钮设置为不可点击
btnPhoneLogin.setClickable(false);
btnRegister.setClickable(false);
btnRegister.setTextColor(getResources().getColor(R.color.colorTransparentGray)); btnPhoneLogin.setTextColor(getResources().getColor(R.color.colorTransparentGray));
} else {
//隐藏进度条
progressBar.setVisibility(View.GONE);
//隐藏登录按钮
btnLogin.setVisibility(View.VISIBLE);
//输入框设置可用
etLogin.setEnabled(true);
etPassword.setEnabled(true);
//手机号按钮和按钮设置为可点击
btnPhoneLogin.setClickable(true);
btnRegister.setClickable(true);
btnRegister.setTextColor(getResources().getColor(R.color.white));
btnPhoneLogin.setTextColor(getResources().getColor(R.color.white));
}
}
2.6、手机号登录和用户名登录切换
@Override
public void onClick(View v) {
if (isPhoneLogin){
phoneLogin(etLogin.getText().toString(), etPassword.getText().toString());
}else {
usernameLogin(etLogin.getText().toString(), etPassword.getText().toString());
}
}
三、完整的代码实现
public class LoginActivity extends BaseActivity implements View.OnClickListener {
private ProgressBar progressBar;
private EditText etPassword;
private EditText etLogin;
private Button btnLogin;
private Button btnPhoneLogin;
private TextInputLayout tilLogin, tilPassword;
private Button btnRegister;
private TextView tvVerifyCode;
private boolean isPhoneLogin = false;
@Override
protected void setActionBar() {
}
@Override
protected void setListener() {
}
@Override
protected void initData() {
}
@Override
protected void initView() {
etLogin = obtainView(R.id.et_username);
etPassword = obtainView(R.id.et_password);
btnRegister = obtainView(R.id.btn_register);
btnPhoneLogin = obtainView(R.id.btn_phone_login);
btnLogin = obtainView(R.id.btn_login);
progressBar = obtainView(R.id.progressbar);
tilLogin = obtainView(til_login);
tilPassword = obtainView(R.id.til_password);
tvVerifyCode = obtainView(R.id.btn_verify_code);
userNameLoginViewInit();
}
@Override
protected int getLayoutId() {
return R.layout.activity_login;
}
/**
* 用户名密码登录界面
*/
public void userNameLoginViewInit() {
userLoginTrans();
btnRegister.setOnClickListener(this);
btnPhoneLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//手机号登录
phoneLoginViewinit();
}
});
//用户名登录
btnLogin.setOnClickListener(this);
}
public void phoneLoginViewinit() {
phoneLoginTrans();
//转换为用户名登录界面
userNameLoginViewInit();
}
});
btnLogin.setOnClickListener(this);
}
private void phoneLoginTrans() {
isPhoneLogin = true;
tvVerifyCode.setVisibility(View.VISIBLE);
AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(250);
tvVerifyCode.setAnimation(alphaAnimation);
tvVerifyCode.bringToFront();
etLogin.setInputType(EditorInfo.TYPE_CLASS_PHONE);
etLogin.setText("");
etPassword.setText("");
btnPhoneLogin.setText("用户名登录");
tilLogin.setHint("手机号");
tilPassword.setHint("密码");
}
private void userLoginTrans() {
isPhoneLogin = false;
tvVerifyCode.setVisibility(View.GONE);
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
alphaAnimation.setDuration(250);
tvVerifyCode.setAnimation(alphaAnimation);
etLogin.setInputType(EditorInfo.TYPE_CLASS_TEXT);
etLogin.setText("");
etPassword.setText("");
btnPhoneLogin.setText("手机号登录");
tilLogin.setHint("用户名");
tilPassword.setHint("密码");
}
/**
* 手机登录和用户名登录界面显示或隐藏
*/
public void showOnLoading(boolean active) {
if (active) {
progressBar.setVisibility(View.VISIBLE);
btnLogin.setVisibility(View.INVISIBLE);
etLogin.setEnabled(false);
etPassword.setEnabled(false);
btnPhoneLogin.setClickable(false);
btnRegister.setTextColor(getResources().getColor(R.color.colorTransparentGray)); btnPhoneLogin.setTextColor(getResources().getColor(R.color.colorTransparentGray));
btnRegister.setClickable(false);
} else {
progressBar.setVisibility(View.GONE);
btnLogin.setVisibility(View.VISIBLE);
etLogin.setEnabled(true);
etPassword.setEnabled(true);
btnPhoneLogin.setClickable(true);
btnRegister.setClickable(true);
btnRegister.setTextColor(getResources().getColor(R.color.white));
btnPhoneLogin.setTextColor(getResources().getColor(R.color.white));
}
}
public void phoneLogin(final String mobile, String verifyCode) {
if (checkPhoneLogin(mobile, verifyCode)) {
PhoneLoginRequest req = new PhoneLoginRequest(1200, mobile, verifyCode);
AsyncHttp.instance().postJson(req, new AsyncHttp.IHttpListener() {
@Override
public void onStart(int requestId) {
showOnLoading(true);
}
@Override
public void onSuccess(int requestId, Response response) {
if (response.status == RequestComm.SUCCESS) {
Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
showOnLoading(false);
}
@Override
public void onFailure(int requestId, int httpStatus, Throwable error) {
showOnLoading(false);
Toast.makeText(LoginActivity.this, "网络异常", Toast.LENGTH_SHORT).show();
}
});
}
}
public boolean checkPhoneLogin(String phone, String verifyCode) {
if (OtherUtils.isPhoneNumValid(phone)) {
if (OtherUtils.isVerifyCodeValid(verifyCode)) {
if (OtherUtils.isNetworkAvailable(this)) {
return true;
} else {
ToastUtils.showShort(this, "当前无网络连接");
}
} else {
ToastUtils.showShort(this, "验证码错误");
}
} else {
ToastUtils.showShort(this, "手机格式错误");
}
return false;
}
public void usernameLogin(final String userName, final String password) {
if (checkUserNameLogin(userName, password)) {
LoginRequest req = new LoginRequest(RequestComm.login, userName, password);
AsyncHttp.instance().postJson(req, new AsyncHttp.IHttpListener() {
@Override
public void onStart(int requestId) {
showOnLoading(true);
}
@Override
public void onSuccess(int requestId, Response response) {
if (response.status == RequestComm.SUCCESS) {
Toast.makeText(LoginActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
showOnLoading(false);
}
@Override
public void onFailure(int requestId, int httpStatus, Throwable error) {
showOnLoading(false);
Toast.makeText(LoginActivity.this, "登录失败", Toast.LENGTH_SHORT).show();
}
});
}
}
public boolean checkUserNameLogin(String userName, String password) {
if (OtherUtils.isUsernameVaild(userName)) {
if (OtherUtils.isPasswordValid(password)) {
if (OtherUtils.isNetworkAvailable(this)) {
return true;
} else {
ToastUtils.showShort(this, "当前无网络连接");
}
} else {
ToastUtils.showShort(this, "密码过短");
}
} else {
ToastUtils.showShort(this, "用户名不符合规范");
}
return false;
}
@Override
public void onClick(View v) {
if (isPhoneLogin){
phoneLogin(etLogin.getText().toString(), etPassword.getText().toString());
}else {
usernameLogin(etLogin.getText().toString(), etPassword.getText().toString());
}
}
}
140套Android优秀开源项目源码,领取地址:http://mp.weixin.qq.com/s/afPGHqfdiApALZqHsXbw-A
写得不到位的地方还望大家指正。