Bmob实现短信登陆验证自动记录密码安卓6.0动态获取权限1.0版本
关于Bmob的问题太多而且那个官方文档看的也云里雾里,解决问题最好就是直接看他那个demo最实在
这个是我基于前面的文章写的如果没有看我前面的一些文章可能有些地方会看不懂
利用Bmob快速实现安卓的简单登陆注册功能Bmobsdk3.6.9版本亲测可用(详细图文攻略附带处理小bug)
利用Bmob快速实现安卓的登陆注册功能带正则手机号注册验证和基本密码的判断0.2版本
本文代码下载地址:https://download.csdn.net/download/qq_16519957/11008139
在原有的基础之上添加自动记录账号密码的功能
解决方案我们就使用SharedPreferences 这个轻量级的存储类。我们先介绍一下SharedPreferences,SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置参数,它是采用xml文件存放数据。SharedPreferences是一个接口,而且在这个接口里没有提供写入数据和读取数据的能力。但它是通过其Editor接口中的一些方法来操作SharedPreference的。(SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现)
先来看一下我们的布局:
非常简单的一个布局1个textview+2个edittext+1个CheckBox+2个button
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
tools:context="com.beta.bmobtest.MainActivity"
android:orientation="vertical">
<TextView
android:gravity="center"
android:textSize="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录" />
<EditText
android:id="@+id/id_username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="手机号"
android:inputType="phone" />
<EditText
android:id="@+id/id_userpassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="password"
android:inputType="textPassword" />
<CheckBox
android:id="@+id/remember"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="是否记住用户名和密码" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/id_ok"
android:layout_width="0dp"
android:text="登录"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<Button
android:id="@+id/id_register"
android:text="注册"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>
private SharedPreferences pref;
private SharedPreferences.Editor editor;
pref= PreferenceManager.getDefaultSharedPreferences(this);
rememberPass=(CheckBox)findViewById(R.id.remember);
boolean isRemenber=pref.getBoolean("remember_password",false);
if(isRemenber){
//将账号和密码都设置到文本中
String account=pref.getString("account","");
String password=pref.getString("password","");
lgUser.setText(account);
lgPassword.setText(password);
rememberPass.setChecked(true);
}
editor=pref.edit();
if(rememberPass.isChecked()){
editor.putBoolean("remember_password",true);
editor.putString("account",lgU);
editor.putString("password",lgp);
}else {
editor.clear();
}
editor.apply();
package com.beta.bmobtest;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
public class MainActivity extends AppCompatActivity {
private Person p2;
private TextView lgUser;
private TextView lgPassword;
private Button btn_ok;
private Button btn_rg;
private CheckBox rememberPass;
private SharedPreferences pref;
private SharedPreferences.Editor editor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bmob.initialize(this, "你自己的appid");
addControl();
addLogin();
}
private void addLogin() {
btn_rg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, RegisterActivity.class);
startActivity(intent);
}
});
btn_ok.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String lgU = lgUser.getText().toString().trim();
String lgp = lgPassword.getText().toString().trim();
editor=pref.edit();
if(rememberPass.isChecked()){
editor.putBoolean("remember_password",true);
editor.putString("account",lgU);
editor.putString("password",lgp);
}else {
editor.clear();
}
editor.apply();
final BmobUser bu2 = new BmobUser();
bu2.setUsername(lgU);
bu2.setPassword(lgp);
bu2.login(new SaveListener<BmobUser>() {
@Override
public void done(BmobUser bmobUser, BmobException e) {
if (e == null) {
Intent in_success = new Intent(MainActivity.this, Success.class);
startActivity(in_success);
} else {
Toast.makeText(MainActivity.this, "账户名或密码不正确", Toast.LENGTH_SHORT).show();
//loge(e);
}
}
});
}
});
}
private void addControl() {
pref= PreferenceManager.getDefaultSharedPreferences(this);
rememberPass=(CheckBox)findViewById(R.id.remember);
lgUser = (TextView) findViewById(R.id.id_username);
lgPassword = (TextView) findViewById(R.id.id_userpassword);
btn_ok = (Button) findViewById(R.id.id_ok);
btn_rg = (Button) findViewById(R.id.id_register);
boolean isRemenber=pref.getBoolean("remember_password",false);
if(isRemenber){
//将账号和密码都设置到文本中
String account=pref.getString("account","");
String password=pref.getString("password","");
lgUser.setText(account);
lgPassword.setText(password);
rememberPass.setChecked(true);
}
}
}
参考:Android:用SharePreferences实现记住密码功能
参考:一行代码搞定漂亮的Android6.0权限申请界面
我们主要用到的就是发送短信那个和读取手机状态的权限申请,其他的权限暂且用不到。
我们使用是hipermissio这个开源来动态获取权限这种就比较方便了自己写的话就麻烦多了。
compile ‘me.weyye.hipermission:library:1.0.7’
然后就非常简单了
private void Permissionx() {
List<PermissionItem> permissions = new ArrayList<PermissionItem>();
permissions.add(new PermissionItem(Manifest.permission.SEND_SMS, getString(R.string.permission_send_sms_phone), R.drawable.permission_ic_sms));
permissions.add(new PermissionItem(Manifest.permission.READ_PHONE_STATE, getString(R.string.permission_read_phone_state), R.drawable.permission_ic_phone));
HiPermission.create(mContext)
.title(getString(R.string.permission_cus_title))
.permissions(permissions)
.msg(getString(R.string.permission_cus_msg))
.animStyle(R.style.PermissionAnimModal)
.style(R.style.PermissionDefaultGreenStyle)
.checkMutiPermission(new PermissionCallback() {
@Override
public void onClose() {
Log.i(TAG, "onClose");
showToast(getString(R.string.permission_on_close));
}
@Override
public void onFinish() {
showToast(getString(R.string.permission_completed));
}
@Override
public void onDeny(String permission, int position) {
Log.i(TAG, "onDeny");
}
@Override
public void onGuarantee(String permission, int position) {
Log.i(TAG, "onGuarantee");
}
});
}
case R.id.btn_countdown: {
mIntent = new Intent(mContext, RegisterCodeTimerService.class);
Permissionx();//安卓6.0动态获取权限
// 将按钮设置为不可用状态
register_countdown.setEnabled(false);
// 启动倒计时的服务
startService(mIntent);
// 通过requestSMSCode方式给绑定手机号的该用户发送指定短信模板的短信验证码
BmobSMS.requestSMSCode(mobile, "1", new QueryListener<Integer>() {
@Override
public void done(Integer smsId, BmobException e) {
if (e == null) {
showToast(getString(R.string.smssuccess) + smsId);
} else {
showToast(getString(R.string.failed) + smsId);
}
}
});
break;
}
这个短信验证真的是坑,3.6.9版本集成了sms的功能以后就不用再去导入sms1.0.1的包但是文档没说,找了其他的别人写的文档又是老版本换成我自己的3.6.9版本导致发送不出去,然后各种问题频发。最后还是在看bmob那个demo后才明白。
不得不说这个demo藏的有多深这里我就不吐槽了。
github:https://github.com/bmob/bmob_android_demo_sms
由于sdk3.6.9集成sms功能所以导包就是这个样子请务必在最开头的时候导入
import cn.bmob.v3.BmobSMS;
这里并没有什么太大的问题只要能获取到editext中的手机号码那个数据然后将其发送出去一般是没有问题。
// 通过requestSMSCode方式给绑定手机号的该用户发送指定短信模板的短信验证码
BmobSMS.requestSMSCode(mobile, "1", new QueryListener<Integer>() {
@Override
public void done(Integer smsId, BmobException e) {
if (e == null) {
showToast(getString(R.string.smssuccess) + smsId);
} else {
showToast(getString(R.string.failed) + smsId);
}
}
});
使用bmob的话自己会有一个在开头需要进行验证码的输入
而且如果根据环境和登陆情况的不同signorlogin这方法也不是一直用的要根据情况来具体要看bmob的开发文档进行使用。
//Bmob注册验证方法
User p2 = new User();
p2.setMobilePhoneNumber(mobile);
p2.setPassword(password);
p2.signOrLogin(valiation,new SaveListener<BmobUser>() {//valiation关于获取到验证码
@Override
public void done(BmobUser bmobUser, BmobException e) {
if (e == null) {
//判断是否注册成功成功则跳转到登陆的页面
Intent intent_register = new Intent(RegisterActivity.this, MainActivity.class);
startActivity(intent_register);
showToast(getString(R.string.user_success));
} else {
showToast(getString(R.string.user_failed)+e.getErrorCode()+e.getMessage());
}
}
});
PS关于这个问题一定要注意
setMobilePhoneNumber就是这个回调如果你用的是手机号注册且没有其他的方式登录一定要用这个不然如果用setUsername来注册的话会不行的手机号登录注册就只能用那个。
RegisterCodeTimerService一个倒计时的广播按钮服务
package com.beta.bmobtest;
import android.app.Service;
import android.content.Intent;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
/**
* 注册验证码计时服务
*
*/
public class RegisterCodeTimerService extends Service {
public static final String IN_RUNNING = "com.beta.bmobtest.IN_RUNNING";
public static final String END_RUNNING = "com.beta.bmobtest.END_RUNNING";
private static Handler mHandler;
private static CountDownTimer mCodeTimer;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 第一个参数是总时间, 第二个参数是间隔
mCodeTimer = new CountDownTimer(60000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
// 广播剩余时间
broadcastUpdate(IN_RUNNING, millisUntilFinished / 1000 + "");
}
@Override
public void onFinish() {
// 广播倒计时结束
broadcastUpdate(END_RUNNING);
// 停止服务
stopSelf();
}
};
// 开始倒计时
mCodeTimer.start();
return super.onStartCommand(intent, flags, startId);
}
// 发送广播
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
// 发送带有数据的广播
private void broadcastUpdate(final String action, String time) {
final Intent intent = new Intent(action);
intent.putExtra("time", time);
sendBroadcast(intent);
}
}
RegisterActivity
package com.beta.bmobtest;
import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cn.bmob.v3.BmobSMS;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.QueryListener;
import cn.bmob.v3.listener.SaveListener;
import me.weyye.hipermission.HiPermission;
import me.weyye.hipermission.PermissionCallback;
import me.weyye.hipermission.PermissionItem;
/**
* Created by Kevein on 2019/3/1.8:03
*/
public class RegisterActivity extends Activity implements View.OnClickListener{
public static final String TAG = "RegisterActivity";
private Intent mIntent;
private Context mContext;
private EditText register_phone;
private EditText register_password;
private Button register_ok, register_countdown;
private EditText register_ValiDation;//输入验证码
private void showToast(String text) {//简化Toast
Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
}
//倒计时广播
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
switch (action) {
case RegisterCodeTimerService.IN_RUNNING:
if (register_countdown.isEnabled())
register_countdown.setEnabled(false);
//正在倒计时
register_countdown.setText("获取验证码(" + intent.getStringExtra("time") + ")");
Log.e(TAG, "倒计时中(" + intent.getStringExtra("time") + ")");
break;
case RegisterCodeTimerService.END_RUNNING:
//完成倒计时
register_countdown.setEnabled(true);
register_countdown.setText("获取验证码");
break;
}
}
};
// 注册广播
private static IntentFilter updateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(RegisterCodeTimerService.IN_RUNNING);
intentFilter.addAction(RegisterCodeTimerService.END_RUNNING);
return intentFilter;
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.register_layout);
mContext = this;
addControl();//加载控件
Bmob.initialize(this, "你自己的appid");
}
@Override
protected void onResume() {
super.onResume();
// 注册广播
registerReceiver(mBroadcastReceiver, updateIntentFilter());
}
@Override
protected void onPause() {
super.onPause();
// 移除注册
unregisterReceiver(mBroadcastReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy 方法调用");
}
private boolean isPhoneNumber(String phoneStr) {
//定义电话格式的正则表达式
String regex = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$";
//设定查看模式
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
//判断Str是否匹配,返回匹配结果
Matcher m = p.matcher(phoneStr);
return m.matches();
}
private boolean PasswordJudge(String pwStr) {
//密码判断以字母开头,长度在6~18之间,只能包含字母、数字和下划线
String pattern = "^[a-zA-Z]\\w{5,17}$";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(pwStr);
return m.find();
}
private void addControl() {
register_ok = (Button) findViewById(R.id.id_register_ok);
register_phone = (EditText) findViewById(R.id.register_phone);
register_password = (EditText) findViewById(R.id.register_password);
register_countdown = (Button) findViewById(R.id.btn_countdown);
register_ValiDation = (EditText) findViewById(R.id.et_validation);
register_countdown.setOnClickListener(this);
register_ok.setOnClickListener(this);
}
//动态获取手机状态和发送短信权限
private void Permissionx() {
List<PermissionItem> permissions = new ArrayList<PermissionItem>();
permissions.add(new PermissionItem(Manifest.permission.SEND_SMS, getString(R.string.permission_send_sms_phone), R.drawable.permission_ic_sms));
permissions.add(new PermissionItem(Manifest.permission.READ_PHONE_STATE, getString(R.string.permission_read_phone_state), R.drawable.permission_ic_phone));
HiPermission.create(mContext)
.title(getString(R.string.permission_cus_title))
.permissions(permissions)
.msg(getString(R.string.permission_cus_msg))
.animStyle(R.style.PermissionAnimModal)
.style(R.style.PermissionDefaultGreenStyle)
.checkMutiPermission(new PermissionCallback() {
@Override
public void onClose() {
Log.i(TAG, "onClose");
showToast(getString(R.string.permission_on_close));
}
@Override
public void onFinish() {
showToast(getString(R.string.permission_completed));
}
@Override
public void onDeny(String permission, int position) {
Log.i(TAG, "onDeny");
}
@Override
public void onGuarantee(String permission, int position) {
Log.i(TAG, "onGuarantee");
}
});
}
@Override
public void onClick(View view) {
String mobile = register_phone.getText().toString().trim();
// String password = register_password.getText().toString().trim();
switch (view.getId()) {
case R.id.btn_countdown: {//发送短信验证
mIntent = new Intent(mContext, RegisterCodeTimerService.class);//接收倒计时广播
Permissionx();//安卓6.0动态获取权限
// 将按钮设置为不可用状态
register_countdown.setEnabled(false);
// 启动倒计时的服务
startService(mIntent);
// 通过requestSMSCode方式给绑定手机号的该用户发送指定短信模板的短信验证码
BmobSMS.requestSMSCode(mobile, "1", new QueryListener<Integer>() {
@Override
public void done(Integer smsId, BmobException e) {
if (e == null) {
showToast(getString(R.string.smssuccess) + smsId);
} else {
showToast(getString(R.string.failed) + smsId);
}
}
});
break;
}
case R.id.id_register_ok:
String password = register_password.getText().toString().trim();//获取密码
String valiation = register_ValiDation.getText().toString();//获取验证码
boolean phone = isPhoneNumber(mobile);
//判断密码
boolean pwd = PasswordJudge(password);
if (mobile.isEmpty()||password.isEmpty()) {
showToast(getString(R.string.user_or_password_empty));
return;
}
else if(!phone)
{
showToast(getString(R.string.phone_failed));
return;
}
else if (!pwd) {
showToast(getString(R.string.userpassword_failed));
return;
} else if(TextUtils.isEmpty(valiation)){
showToast(getString(R.string.valiation_empty));
return;
}else
{
//Bmob注册验证方法
User p2 = new User();
p2.setMobilePhoneNumber(mobile);
p2.setPassword(password);
p2.signOrLogin(valiation,new SaveListener<BmobUser>() {//valiation关于获取到验证码
@Override
public void done(BmobUser bmobUser, BmobException e) {
if (e == null) {
//判断是否注册成功成功则跳转到登陆的页面
Intent intent_register = new Intent(RegisterActivity.this, MainActivity.class);
startActivity(intent_register);
showToast(getString(R.string.user_success));
} else {
showToast(getString(R.string.user_failed)+e.getErrorCode()+e.getMessage());
}
}
});
break;
}
}
}
}
关于我的源码已上传github如果不错的话麻烦点个star和点个赞:https://github.com/307572384/bmobtest