转载原文博客地址
不知不觉就好久没有写过博客了,一直打算写,但是总由于各种原因耽搁了,最近先开个内容,然后慢慢写着吧。
我们现在要自己做一个app,但是不像做公司项目,会有专门的人配合我们去给我们写后台。所以我们用到一个第三方的后台—-bmob云服务平台
我们项目中会用到的东西:
- bmob云服务平台
- 采用MVP模式开发
- 首页侧边菜单DrawerLayout
- 首页下方4个tab键,fragment,viewpager,BottomNavigationView的运用
- 图片加载 Glide
- butterknife 注解
- infiniteindicator 图片轮播
- eventbus 组件之间消息的传递与交互
- 一个开源的recycleView
- 本地数据库realm 和 一篇使用教程
- 高德地图的应用。
- 未完待续……
在bmob上注册登录,创建应用
注册登录 略。。。
创建应用:
成功之后,我们这里会显示出我们刚才创建的那个名称的应用。
点击我们创建的应用之后:
我们可以看到,默认的给我们创建了一个 User 表,里面有 id,username,password等等一些常用的字段,紫色框里面给我们提供了一些常用的操作键。
集成bomoSDK 到我们的项目中。
首先,我们用AndroidStudio 新建一个SelfApp 的项目。
在 Project 的 build.gradle 文件中添加 Bmob的maven仓库地址
图中的地址为:url “https://raw.github.com/bmob/bmob-android-sdk/master”在app的build.gradle文件中添加compile依赖文件:
//bmob-sdk
compile ‘cn.bmob.android:bmob-sdk:3.5.3’在android 下添加:useLibrary ‘org.apache.http.legacy’ 这句是为了兼容Android6.0系统所需,如果这句话报错,可在dependencies标签下使用compile ‘cn.bmob.android:http-legacy:1.0’
在你的应用程序的AndroidManifest.xml文件中添加相应的权限:
<!--允许联网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--获取GSM(2g)、WCDMA(联通3g)等网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取wifi网络状态的信息 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--保持CPU 运转,屏幕和键盘灯有可能是关闭的,用于文件上传和下载 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--获取sd卡写的权限,用于文件上传和下载-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许读取手机状态 用于创建BmobInstallation-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
4 初始化BombSDK:可以在启动的Activity或者我们的Application 中的onCreate方法中去初始化。
//第一:默认初始化
Bmob.initialize(this, "Your Application ID");
//第二:自v3.4.7版本开始,设置BmobConfig,允许设置请求超时时间、文件分片上传时每片的大小、文件的过期时间(单位为秒),
//BmobConfig config =new BmobConfig.Builder(this)
////设置appkey
//.setApplicationId("Your Application ID")
////请求超时时间(单位为秒):默认15s
//.setConnectTimeout(30)
////文件分片上传时每片的大小(单位字节),默认512*1024
//.setUploadBlockSize(1024*1024)
////文件的过期时间(单位为秒):默认1800s
//.setFileExpiration(2500)
//.build();
//Bmob.initialize(config);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
5 上面4中初始化需要的applicationid所在的位置:
登录、注册、退出登录、修改密码
用户管理
用户是一个应用程序的核心。对于个人开发者来说,自己的应用程序积累到越多的用户,就会给自己带来越强的创作动力。因此Bmob提供了一个专门的用户类——BmobUser来自动处理用户账户管理所需的功能。
有了这个类,你就可以在你的应用程序中添加用户账户功能。
BmobUser是BmobObject的一个子类,它继承了BmobObject所有的方法,具有BmobObject相同的功能。不同的是,BmobUser增加了一些特定的关于用户账户管理相关的功能。
属性
BmobUser除了从BmobObject继承的属性外,还有几个特定的属性:
username: 用户的用户名(必需)。
password: 用户的密码(必需)。
email: 用户的电子邮件地址(可选)。
emailVerified:邮箱认证状态(可选)。
mobilePhoneNumber:手机号码(可选)。
mobilePhoneNumberVerified:手机号码的认证状态(可选)。
扩展用户类
很多时候,你的用户表还会有很多其他字段,如性别、年龄、头像等。那么,你需要对BmobUser类进行扩展,添加一些新的属性。我们新建一个继承于BombUser类的bean,然后添加新的属性就行。
- 我们现在系统生成的user表中创建一个用户:
或者我们通过代码来实现注册功能:
BmobUser bu = new BmobUser();
bu.setUsername("sendi");
bu.setPassword("123456");
bu.setEmail("sendi@163.com");
//注意:不能用save方法进行注册
bu.signUp(new SaveListener<UserBean>() {
@Override
public void done(UserBean s, BmobException e) {
if(e==null){
toast("注册成功:" +s.toString());
}else{
loge(e);
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
2 然后我们通过下列方法来登录试试:
BmobUser bu = new BmobUser();
bu.setUsername(username);
bu.setPassword(password);
bu.login(new SaveListener<BmobUser>() {
@Override
public void done(BmobUser bmobUser, BmobException e) {
if(e==null){
// toast("登录成功:");
showToast("登录成功");
//通过BmobUser user = BmobUser.getCurrentUser()获取登录成功后的本地用户信息
//如果是自定义用户对象MyUser,可通过MyUser user = BmobUser.getCurrentUser(MyUser.class)获取自定义用户信息
}else{
showToast(e.toString());
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
或者用:
//UserBean是需要继承bombsdk中的BmobUser类的。
BmobUser.loginByAccount(username, password, new LogInListener<UserBean>() {
@Override
public void done(UserBean userBean, BmobException e) {
if (userBean!=null){
//登录成功 doSomething
}else {
//登录失败
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
如果用户在每次打开你的应用程序时都要登录,这将会直接影响到你应用的用户体验。为了避免这种情况,你可以使用缓存的CurrentUser对象。缓存的用户有效期为1年。
每当你应用的用户注册成功或是第一次登录成功,都会在本地磁盘中有一个缓存的用户对象,这样,你可以通过获取这个缓存的用户对象来进行登录:
BmobUser bmobUser = BmobUser.getCurrentUser();
if(bmobUser != null){
// 允许用户使用应用
}else{
//缓存用户对象为空时, 可打开用户注册界面…
}
- 1
- 2
- 3
- 4
- 5
- 6
在扩展了用户类的情况下获取当前登录用户,可以使用如下的示例代码(MyUser类可参看上面):
UserBean userInfo = BmobUser.getCurrentUser(UserBean .class);
- 1
获取userbean中的某个字段的内容:
//BmobUser中的特定属性
String username = (String) userInfo .getObjectByKey("username");
//MyUser中的扩展属性
Integer age = (Integer) userInfo .getObjectByKey("age");
Boolean sex = (Boolean) userInfo .getObjectByKey("sex");
- 1
- 2
- 3
- 4
- 5
3 我们根据条件查询一个人的信息:
这是我们用用户名,手机号码,邮箱 共同来验证,匹配此内容的用户会返回,不匹配返回的List的size 为0 , 出错了会有e的返回。
BmobQuery<UserBean> query = new BmobQuery<>();
query.addWhereEqualTo("username", username).addWhereEqualTo("mobilePhoneNumber", tel).addWhereEqualTo("email", email);
query.findObjects(new FindListener<UserBean>() {
@Override
public void done(List<UserBean> object, BmobException e) {
if (e == null) {
// toast("查询用户成功:"+object.size());
listener.onSuccess();
} else {
// toast("更新用户信息失败:" + e.getMessage());
listener.onFailed(e.getErrorCode());
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
我们试着查询了一条信息,发现返回的信息就是我们注册的信息,只是不会给我们返回密码(password)的那个字段的值。
我们本来是想着根据几个信息查询出用户的所有信息,然后我们从里面取出来旧密码,然后就可以调用SDK的方法去修改密码来实现用户忘记密码的事件。但是发现行不通了。
通过旧密码来修改密码的方法为:
BmobUser.updateCurrentUserPassword("旧密码", "新密码", new UpdateListener() {
@Override
public void done(BmobException e) {
if(e==null){
toast("密码修改成功,可以用新密码进行登录啦");
}else{
toast("失败:" + e.getMessage());
}
}
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
所以只能暂时改为 短信通知管理员 去在后台更改密码了。流程还是先根据条件去查询,查询成功后,让其输入一个新密码,然后弹出对话框询问是否将此内容发送给管理员,让其去帮助修改密码,修改成功后会有短信回复来通知用户。
4 退出登录
BmobUser.logOut(); //清除缓存用户对象
BmobUser currentUser = BmobUser.getCurrentUser(); // 现在的currentUser是null了
- 1
- 2
方向指示
我们要实现一个指南针的功能。而这种。利用手机的Sensor就可以简单的实现了。
- 我们先在布局中放置一张图片:
布局代码为:
<TextView
android:id="@+id/tvCompass"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_margin="10dp"
android:background="@mipmap/comp" />- 获取手机的Sensor 并且实现对应的监听
//方向传感器的使用。指北针
SensorManager mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
Sensor mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Sensor mMagneticField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagneticField, SensorManager.SENSOR_DELAY_NORMAL);
- 1
- 2
- 3
- 4
- 5
- 6
并且我们的Activity要 implements SensorEventListener
4 在 onSensorChanged 方法处理改变了的Sensor内容。
5 设置动画旋转图片。
6 指南针完整的代码下载地址点我
高德地图的使用
高德控制台创建项目
http://lbs.amap.com/ 高德LBS官网。
然后去创建一个号,然后登录。
- 点击头像旁边的控制台进入后台管理
- 进入后台管理之后,然后点击右上角创建新应用
- 弹出
- 上面的随便填。然后点击创建。
- 创建成功后就有了我们刚才创建的一条信息,最后面有个“添加新key”,点之。
- 弹出
填写弹出框中的内容,然后勾选同意条款,然后点“提交”,就可以了。 - 这就是我们创建成功之后的key
- 至此,我们创建这一步就完成了。至于如何获取sha1,点吧
集成高德到项目中
在AS里面调整项目到project文件形式
- 将我们下载的sdk复制到 app下的lib文件夹中
- 然后右键上图的sdk,选择Add as library 选项。然后会出来如上图示的可以展开的小三角箭头。
添加我们下载的so文件到我们的项目中,复制粘贴呗,如果项目中没有jniLibs文件夹,我们需要先自己创建。然后将我们下载的so全部复制进去
配置key:
<application
android:icon="@drawable/icon"
android:label="@string/app_name" >
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="请输入您的用户Key"/>
……
</application>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
7 需要的权限:
//地图包、搜索包需要的基础权限
<!--允许程序打开网络套接字-->
<uses-permission android:name="android.permission.INTERNET" />
<!--允许程序设置内置sd卡的写权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--允许程序获取网络状态-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--允许程序访问WiFi网络信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许程序读写手机状态和身份-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--允许程序访问CellID或WiFi热点来获取粗略的位置-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
简单使用
- 再我们的布局中添加地图控件:
<com.amap.api.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- 1
- 2
- 3
- 4
- 在Activity中:
//声明
MapView mMapView = null;
AMap aMap;
//在onCreate方法中
mMapView.onCreate(savedInstanceState);
if (aMap == null) {
aMap = mMapView.getMap();
}
initView();
//initView方法
MyLocationStyle myLocationStyle;
myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);//定位一次、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)如果不设置myLocationType,默认也会执行此种模式。
myLocationStyle.interval(2000); //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
myLocationStyle.radiusFillColor(R.color.colorAccent);
aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style
aMap.getUiSettings().setMyLocationButtonEnabled(true);//设置默认定位按钮是否显示,非必需设置。
aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
// 其他的生命周期方法
@Override
protected void onDestroy() {
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),销毁地图
mMapView.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView.onResume (),重新绘制加载地图
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//在activity执行onPause时执行mMapView.onPause (),暂停地图的绘制
mMapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态
mMapView.onSaveInstanceState(outState);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
3.这样最简单的地图展示就出来了。界面上包含缩放按钮 和 定位按钮
其他
遇到的问题
- 因为用到了AS模板生成的侧滑页,然后想更改划出部分的内容和结构,总是报错。
原因:因为更改的地方是app:headerLayout 里面的东西。它和include不是一个机制。项目中的整体机制是用ButterKnife 免去findViewById的。但是在这里就不行了。所以只能是:
TextView userName =(TextView)navigationView.getHeaderView(0).findViewById(R.id.tvUserName);
ImageView image = navigationView.getHeaderView(0).findViewById(R.id.headImage);
- 1
- 2
这样来实现一个效果: