Bmob是一个移动后端云服务平台,提供了后端服务器的数据服务,文件服务,推送服务等,可以让开发者专注客户端的开发,从而达到快速构建一个APP的目的。
配置
project的build.gradle
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
//Bmob的maven仓库地址--必填
maven { url "https://raw.github.com/bmob/bmob-android-sdk/master" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
app的build.gradle添加依赖
implementation 'cn.bmob.android:bmob-sdk:3.7.3-rc1'
implementation "io.reactivex.rxjava2:rxjava:2.2.2"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'com.squareup.okio:okio:2.1.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
清单文件添加权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
在onCreate中初始化
Bmob.initialize(this, "Your Application ID");
配置ContentProvider
<application>
···
<provider
android:name="cn.bmob.v3.util.BmobContentProvider"
android:authorities="你的应用包名.BmobContentProvider">
</provider>
···
</application>
增删改查数据
创建Person.java
public class Person extends BmobObject {
private String name;
private String address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
创建四个按钮,增删改查,"6b6c11c537"此数值根据添加返回值更改
public void addClick(View view) {
Person p = new Person();
p.setName("lucky");
p.setAddress("北京海淀");
p.save(new SaveListener<String>() {
@Override
public void done(String objectId,BmobException e) {
if(e==null){
Toast.makeText(MainActivity.this,"添加数据成功,返回objectId为:"+objectId,Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"创建数据失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
public void delClick(View view) {
Person p = new Person();
p.setObjectId("6b6c11c537");
p.delete(new UpdateListener() {
@Override
public void done(BmobException e) {
if(e==null){
Toast.makeText(MainActivity.this,"删除成功:"+p.getUpdatedAt(),Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"删除失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
public void updateClick(View view) {
final Person p = new Person();
p.setAddress("北京朝阳");
p.update("6b6c11c537", new UpdateListener() {
@Override
public void done(BmobException e) {
if(e==null){
Toast.makeText(MainActivity.this,"更新成功:"+p.getUpdatedAt(),Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"更新失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
public void queryClick(View view) {
BmobQuery<Person> bmobQuery = new BmobQuery<Person>();
bmobQuery.getObject("6b6c11c537", new QueryListener<Person>() {
@Override
public void done(Person object,BmobException e) {
if(e==null){
Toast.makeText(MainActivity.this,"查询成功" ,Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this,"查询失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
如果出现以下错误
在清单文件的application中添加
android:usesCleartextTraffic="true"
运行结果:
用户注册登录
user.java
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.datatype.BmobFile;
public class User extends BmobUser {
private BmobFile icon;
public BmobFile getIcon() {
return icon;
}
public void setIcon(BmobFile icon) {
this.icon = icon;
}
}
login:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".login.LoginActivity">
<EditText
android:id="@+id/editText_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/editText2"
android:layout_marginTop="160dp"/>
<EditText
android:id="@+id/editText_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText_1"/>
<Button
android:id="@+id/button_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"
android:onClick="loginClick"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/button_reg"
app:layout_constraintTop_toBottomOf="@+id/editText_2"
android:layout_marginLeft="60dp"/>
<Button
android:id="@+id/button_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册"
android:onClick="regClick"
app:layout_constraintLeft_toRightOf="@+id/button_login"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText_2"
android:layout_marginRight="60dp"/>
</android.support.constraint.ConstraintLayout>
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.example.bmapplication.R;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
public class LoginActivity extends AppCompatActivity {
private EditText editText_username,editText_password;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Bmob.initialize(this, "key");
editText_username = (EditText)findViewById(R.id.editText_1);
editText_password = (EditText)findViewById(R.id.editText_2);
}
public void regClick(View view) {
Intent intent = new Intent(this,RegActivity.class);
startActivity(intent);
}
public void loginClick(View view) {
String username = editText_username.getText().toString();
String password = editText_password.getText().toString();
BmobUser bmobUser = new BmobUser();
bmobUser.setUsername(username);
bmobUser.setPassword(password);
bmobUser.login(new SaveListener<User>() {
@Override
public void done(User bmobUser, BmobException e) {
if (e == null) {
User user = BmobUser.getCurrentUser(User.class);
// StringBuffer userMessage = new StringBuffer();
// userMessage.append("username = "+user.getUsername());
// userMessage.append(",email = "+user.getEmail());
Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
Intent intent = new Intent(LoginActivity.this,MainActivity.class);
intent.putExtra("user",user);
startActivity(intent);
// if (user.getEmailVerified()){
// Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_SHORT).show();
// Intent intent = new Intent(LoginActivity.this,MainActivity.class);
// intent.putExtra("user",user);
// startActivity(intent);
// }else {
// Toast.makeText(LoginActivity.this,"用户未激活",Toast.LENGTH_SHORT).show();
// }
}
}
});
}
}
reg:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".login.RegActivity">
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/editText2"
android:layout_marginTop="200dp"/>
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPassword"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText1"/>
<EditText
android:id="@+id/editText3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textEmailAddress"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText2" />
<EditText
android:id="@+id/editText4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName"
android:text="Name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText3" />
<Button
android:id="@+id/button_reg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册"
android:onClick="registerClick"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText4"/>
</android.support.constraint.ConstraintLayout>
package com.example.bmapplication.login;
import android.os.Environment;
import android.provider.SyncStateContract;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.example.bmapplication.R;
import java.io.File;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UploadFileListener;
public class RegActivity extends AppCompatActivity {
private EditText editText_name,editText_pass,editText_email,editText_icon;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reg);
Bmob.initialize(this, "key");
editText_name = (EditText)findViewById(R.id.editText1);
editText_pass = (EditText)findViewById(R.id.editText2);
editText_email = (EditText)findViewById(R.id.editText3);
editText_icon = (EditText)findViewById(R.id.editText4);
}
//注册
public void registerClick(View view) {
final String name = editText_name.getText().toString();
final String pass = editText_pass.getText().toString();
final String email = editText_email.getText().toString();
String icon = editText_icon.getText().toString();
//获取图片文件的路径
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"/1.jpg";
//图片的上传
final BmobFile bmobFile = new BmobFile(new File(path));
bmobFile.uploadblock(new UploadFileListener() {
@Override
public void done(BmobException e) {
if(e==null){
//上传成功
User user = new User();
user.setUsername(name);
user.setPassword(pass);
user.setEmail(email);
user.setIcon(bmobFile);
//注册
user.signUp(new SaveListener<User>() {
@Override
public void done(User user, BmobException e) {
if (e == null) {
Toast.makeText(RegActivity.this,"注册成功",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(RegActivity.this,"注册失败",Toast.LENGTH_SHORT).show();
}
}
});
//bmobFile.getFileUrl()--返回的上传文件的完整地址
Toast.makeText(RegActivity.this,"上传文件成功:" + bmobFile.getFileUrl(),Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(RegActivity.this,"上传文件失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
@Override
public void onProgress(Integer value) {
// 返回的上传进度(百分比)
}
});
}
}
MainActivity(登录后跳转的页面):
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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=".login.MainActivity"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bmob云服务测试"
android:id="@+id/textView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/image_icon"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
</android.support.constraint.ConstraintLayout>
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.bmapplication.R;
import com.squareup.picasso.Picasso;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.datatype.BmobFile;
public class MainActivity extends AppCompatActivity {
private TextView textView;
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
Bmob.initialize(this, "key");
textView = (TextView)findViewById(R.id.textView);
iv = (ImageView) findViewById(R.id.image_icon);
Intent intent = getIntent();
User user = (User)intent.getSerializableExtra("user");
textView.setText(user.getUsername()+"-"+user.getEmail());
BmobFile bf = user.getIcon();
String url = bf.getFileUrl();
//使用Picasso
Picasso.get().load(url).into(iv);
}
}
增删改查便签
Note.java
import cn.bmob.v3.BmobObject;
public class Note extends BmobObject {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
//MainActivity
import android.content.Context;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.bmapplication.R;
import com.example.bmapplication.login.MainActivity;
import java.util.ArrayList;
import java.util.List;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.FindListener;
import cn.bmob.v3.listener.UpdateListener;
public class Main2Activity extends AppCompatActivity {
private static final int DEL_ITEM = 0x1;
private ArrayList<Note> notes;
private ListView listView;
private NoteAdapter na;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Bmob.initialize(this, "key");
listView = (ListView)findViewById(R.id.listView);
loadData();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView tv_content = (TextView)view.findViewById(R.id.text_content);
String content = tv_content.getText().toString();
String objectId = (String)view.getTag();
Intent intent = new Intent(Main2Activity.this,NoteDetailActivity.class);
intent.putExtra("content",content);
intent.putExtra("objectId",objectId);
startActivity(intent);
}
});
registerForContextMenu(listView);
}
@Override
protected void onResume() {
super.onResume();
loadData();
}
private void loadData(){
BmobQuery<Note> query = new BmobQuery<>();
query.setLimit(50);
query.findObjects(new FindListener<Note>() {
@Override
public void done(List<Note> list, BmobException e) {
if (e == null) {
notes = (ArrayList<Note>) list;
na = new NoteAdapter(Main2Activity.this,notes);
listView.setAdapter(na);
} else {
}
}
});
}
static class NoteAdapter extends BaseAdapter{
private Context context;
private List<Note> list;
public NoteAdapter(Context context, List<Note> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.item,null);
}
Note note = list.get(position);
TextView content = (TextView)convertView.findViewById(R.id.text_content);
content.setText(note.getContent());
convertView.setTag(note.getObjectId());
return convertView;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.note_list,menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.add_note:
Intent intent = new Intent(this,NoteNewActivity.class);
startActivity(intent);
break;
}
return true;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(1,DEL_ITEM,100,"删除");
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()){
case DEL_ITEM:
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
View view = info.targetView;
String objectId = (String) view.getTag();
Note note = new Note();
note.delete(objectId,new UpdateListener() {
@Override
public void done(BmobException e) {
if(e==null){
loadData();
Toast.makeText(Main2Activity.this,"删除成功",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(Main2Activity.this,"删除失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
break;
}
return super.onContextItemSelected(item);
}
}
//添加
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.Toast;
import com.example.bmapplication.R;
import com.example.bmapplication.login.MainActivity;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UpdateListener;
public class NoteNewActivity extends AppCompatActivity {
private EditText editText_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_new);
Bmob.initialize(this, "key");
editText_content = (EditText)findViewById(R.id.editText2_content);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK){
String content = editText_content.getText().toString();
if (!TextUtils.isEmpty(content)){
Note note = new Note();
note.setContent(content);
note.save(new SaveListener<String>() {
@Override
public void done(String objectId,BmobException e) {
if(e==null){
Toast.makeText(NoteNewActivity.this,"添加数据成功,返回objectId为:"+objectId,Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(NoteNewActivity.this,"创建数据失败:" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
}
return super.onKeyDown(keyCode, event);
}
}
//修改
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.Toast;
import com.example.bmapplication.R;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.UpdateListener;
public class NoteDetailActivity extends AppCompatActivity {
private EditText editText_content;
private String objectId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_detail);
Bmob.initialize(this, "key");
editText_content = (EditText)findViewById(R.id.edit_content);
objectId = getIntent().getStringExtra("objectId");
editText_content.setText(getIntent().getStringExtra("content"));
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK){
String content = editText_content.getText().toString();
if (!TextUtils.isEmpty(content)){
Note note = new Note();
note.setContent(content);
note.update(objectId, new UpdateListener() {
@Override
public void done(BmobException e) {
if(e==null){
Toast.makeText(NoteDetailActivity.this,"更新成功",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(NoteDetailActivity.this,"更新失败" + e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
}
return super.onKeyDown(keyCode, event);
}
}
布局文件:
activity_main:一个ListView
note_detail以及note_new中都是一个EditText
item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_content"
android:layout_weight="1"/>
</LinearLayout>