最近使用了FireBase 的Database,感觉入坑了,虽然国内需要科学“那个”,不过还是很舒服,抛弃了服务器的开发,直接写前端,舒服。
这个具体配置还有api key的获取这里不多说,我们来看看项目中具体如何使用。
可能会误人子弟,给别人做demo比较急,有些地方多见谅。
Java
//firebase database
private FirebaseDatabase mDatabase;
private DatabaseReference myRef;
//init database
mDatabase = FirebaseDatabase.getInstance();
//search from users
myRef = mDatabase.getReference("users");
这个地方是初始化,并获得users的怎么说,users是个啥,哈哈差点要说“表”。看一下firebase的后台吧,这个相当于users key 对应的 value,也就是说mDatabase.getReference(“users”);之后我们拿到了users的调用权。
这个user一看就很简陋,哈哈,demo,demo。
把注册信息传到firebase
myRef.child(et_username.getText().toString())
.setValue(et_password.getText().toString())
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Void aVoid) {
progressDialog.dismiss();
Toast.makeText(RegisterActivity.this, "Register Success!!!", Toast.LENGTH_LONG).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
progressDialog.dismiss();
Toast.makeText(RegisterActivity.this, "Register Fail!!!", Toast.LENGTH_LONG).show();
}
});
这个地方myRef.child(“username”).setValue(“password”),可以看出,我们把key-value的用户名密码存储到users中去了。
后边这个.addOnSuccessListener(new OnSuccessListener()是监听事件,插入成功的一个回掉。
完整代码
package com.example.cacp;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
public class RegisterActivity extends AppCompatActivity {
//Ui
private EditText et_username;
private EditText et_password;
private EditText et_password2;
private Button btn_register;
//firebase database
private FirebaseDatabase mDatabase;
private DatabaseReference myRef;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
//bind view
et_username = findViewById(R.id.input_username);
et_password = findViewById(R.id.input_password);
et_password2 = findViewById(R.id.input_password_repeat);
btn_register = findViewById(R.id.btn_register);
//init database
mDatabase = FirebaseDatabase.getInstance();
//search from users
myRef = mDatabase.getReference("users");
//button listener
btn_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//progress
final ProgressDialog progressDialog = new ProgressDialog(RegisterActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Connecting...");
progressDialog.show();
if (et_username.getText().toString().isEmpty() || et_password.getText().toString().isEmpty() || et_password2.getText().toString().isEmpty()) {
Toast.makeText(RegisterActivity.this, "Please enter user information!!!", Toast.LENGTH_LONG).show();
progressDialog.dismiss();
} else {
if (et_password.getText().toString().equals(et_password2.getText().toString())) {
//insert user information
myRef.child(et_username.getText().toString())
.setValue(et_password.getText().toString())
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Void aVoid) {
progressDialog.dismiss();
Toast.makeText(RegisterActivity.this, "Register Success!!!", Toast.LENGTH_LONG).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
progressDialog.dismiss();
Toast.makeText(RegisterActivity.this, "Register Fail!!!", Toast.LENGTH_LONG).show();
}
});
} else {
progressDialog.dismiss();
Toast.makeText(RegisterActivity.this, "The two passwords do not match!!!", Toast.LENGTH_LONG).show();
}
}
}
});
}
}
这个就更误人子弟了,会把整个users中的数据都会拉到本地,哈哈,密码也被人看到了,demo,demo。
初始化的都一样,也是拿到users的调用权
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
progressDialog.dismiss();
//auth username password
if(dataSnapshot.child(et_username.getText().toString()).exists()){
String password = dataSnapshot.child(et_username.getText().toString()).getValue().toString();
if(password.equals(et_password.getText().toString())){
Singleton.getInstance().setUsername(et_username.getText().toString());
Toast.makeText(LoginActivity.this,"Login Success!!!",Toast.LENGTH_LONG).show();
startActivity(new Intent(LoginActivity.this,Main2Activity.class));
finish();
}else{
Toast.makeText(LoginActivity.this,"Password Mistake!!!",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(LoginActivity.this,"The username does not exist!!!",Toast.LENGTH_LONG).show();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
progressDialog.dismiss();
}
});
这个 DataSnapshot dataSnapshot 参数中获取了users的全部数据……
使用 dataSnapshot.child(“username”).exist()判断一下这个用户名是不是存在。
如果存在, 再获取一下这个用户名对应的密码dataSnapshot.child(“username”).getValue().toString(),然后跟输入框里的比较一下,没问题就没问题了。……
完整代码
package com.example.cacp;
import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class LoginActivity extends XPermissionActivity {
//ui
private EditText et_username;
private EditText et_password;
private Button btn_login;
private TextView tx_register;
private Context mContext;
private DatabaseReference myRef;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mContext = this;
//bind view
et_username = findViewById(R.id.input_username);
et_password = findViewById(R.id.input_password);
btn_login = findViewById(R.id.btn_login);
tx_register = findViewById(R.id.tv_register);
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
myRef = database.getReference("users");
tx_register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(LoginActivity.this,RegisterActivity.class));
}
});
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
requireAll();
}
});
}
//Apply for the necessary permissions first
private void requireAll() {
requestPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION
}, new XPermissionActivity.PermissionHandler() {
@Override
public void onGranted() {
//progress
final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this,
R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Connecting...");
progressDialog.show();
if(et_username.getText().toString().isEmpty()||et_password.getText().toString().isEmpty()){
Toast.makeText(LoginActivity.this,"Please input username or password",Toast.LENGTH_LONG).show();
progressDialog.dismiss();
}else{
myRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
progressDialog.dismiss();
//auth username password
if(dataSnapshot.child(et_username.getText().toString()).exists()){
String password = dataSnapshot.child(et_username.getText().toString()).getValue().toString();
if(password.equals(et_password.getText().toString())){
Singleton.getInstance().setUsername(et_username.getText().toString());
Toast.makeText(LoginActivity.this,"Login Success!!!",Toast.LENGTH_LONG).show();
startActivity(new Intent(LoginActivity.this,Main2Activity.class));
finish();
}else{
Toast.makeText(LoginActivity.this,"Password Mistake!!!",Toast.LENGTH_LONG).show();
}
}else{
Toast.makeText(LoginActivity.this,"The username does not exist!!!",Toast.LENGTH_LONG).show();
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
progressDialog.dismiss();
}
});
}
}
@Override
public boolean onNeverAsk() {
new AlertDialog.Builder(mContext)
.setTitle("Permission to apply for")
.setMessage("Enable permissions in Settings - applications - permissions to ensure the normal use of functions")
.setPositiveButton("Allow", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.dismiss();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
finish();
}
})
.setCancelable(false)
.show();
return true;
}
});
}
}
我们登陆成功后,需要对上一篇文章搜索到附近的公园进行评分,这个跟注册差不多。
看一下firebase后台。
获取rating的操作权
//firebase database
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference("rating");
插入评分,只是多了个child
myRef.child(id).child(Singleton.getInstance().getUsername())
.setValue(String.valueOf(v))
.addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Void aVoid) {
progressDialog.dismiss();
Toast.makeText(DetailActivity.this, "Rating Success!!!", Toast.LENGTH_LONG).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
progressDialog.dismiss();
Toast.makeText(DetailActivity.this, "Rating Fail!!!", Toast.LENGTH_LONG).show();
}
});
貌似没有什么区别,我为什么要贴出来……
myRef.child(id).child(“username”).setValue(“3.5”)
公园的id,用户名,评分,没毛病。
记错了,不是这个项目里的,然后再加一点别的项目里的,哈哈,不是项目,demo,demo
可以看一下firebase的后台,这里,comments相当于sql中的表吧,我们下一层是文章id,例如这里的class of 1927 bear,然后下一层,是一个随机key,然后下一层就是用户的评论了,怎么样,这个稍微复杂一点吧。
这个怎么实现呢,看代码。
初始化一样
//firebase database
private FirebaseDatabase mDatabase;
private DatabaseReference myRef;
mDatabase = FirebaseDatabase.getInstance();
myRef = mDatabase.getReference("comments").child(title);
这里我们获取了comments的操作权,并且向下一层扩展了一下,我们点击进入这个文章后,获取了文章的id,就是这个title,也就是我们对这篇文章进行评论,我们的评论都会被插入到这个文章对应的表中。又“表”了,SQL陷的太深。。。。
存储用户评论信息
Comment comment = new Comment(editText.getText().toString(), getUsername(), new Date());
myRef.push().setValue(comment);
这里我们用了Comment,这个是我们自己建的Bean,把一条评论作为对象进行存储。
先说一下这个 push(),就是上边我们看到的文章下一层的随机key,setValue不用多说了。
然后我们看一下Comment类
Comment.java
package com.example.cs160_sp18.prog3;
import java.util.Date;
// custom class made for storing a message. you can update this class
public class Comment {
public String text;
public String username;
public Date date;
public Comment(){
}
public Comment(String text, String username, Date date) {
this.text = text;
this.username = username;
this.date = date;
}
// returns a string indicating how long ago this post was made
protected String elapsedTimeString() {
long diff = new Date().getTime() - date.getTime();
long seconds = diff / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
long days = hours / 24;
int daysInt = Math.round(days);
int hoursInt = Math.round(hours);
int minutesInt = Math.round(minutes);
if (daysInt == 1) {
return "1 day";
} else if (daysInt > 1) {
return Integer.toString(daysInt) + " days";
} else if (hoursInt == 1) {
return "1 hour";
} else if (hoursInt > 1) {
return Integer.toString(hoursInt) + " hours";
} else {
return "less than an hour";
}
}
}
有用户名,评论内容,评论时间,下边还有一个计算多久之前发的这条评论。可以看一下demo界面的展示。
还没完,我们发送了一条评论之后,可以立即就显示在上班,使用firebase监听数据的改变,并把数据添加到recylerview中。
myRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot != null && dataSnapshot.getValue() != null) {
try {
Comment comment = dataSnapshot.getValue(Comment.class);
Log.d("xbw12138",comment.text);
comments.add(comment);
commentAdapter.notifyDataSetChanged();
editText.setText("");
} catch (Exception ex) {
Log.e("MYERROR", ex.getMessage());
}
}
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d("MYERROR", databaseError.getMessage());
}
});
commentAdapter = new CommentAdapter(this, comments);
recyclerView.setAdapter(commentAdapter);
}
这里我们也使用了Comment来承接一条评论数据。
感觉一下说的有点多,那个Redis先不在这里说了,也不是一个内容,误人子弟了各位,完全是为了方便实现demo,记录一下。有需要demo的可以留言评论。