firebase 用户注册后程序不会继续
Program wont progress after firebase user registration
此 activity 在 firebase auth 中注册用户,在实时数据库中上传信息并在存储中上传用户图片。
这段代码(我不知道为什么)在注册用户时卡住了。如果您看到了,我已经添加了 Log 语句来中断整个过程。日志就像
STARTING PROCESS
BEFORE
INSIDE
没有其他声明。我想我正确地使用了协程,但我不知道为什么这个程序没有比这个更进一步 ^。我应该使用回调吗?我是否以错误的方式使用协程?如果有任何其他建议,我们将不胜感激。
class SignUpActivity : AppCompatActivity() {
private lateinit var binding: ActivitySignUpBinding
private lateinit var firebaseAuth : FirebaseAuth
private lateinit var firebaseStorage: FirebaseStorage
private lateinit var firebaseDatabase: FirebaseDatabase
val TAG ="SIGNUPATAG"
var selectedPhoto : Uri? = null
var IMAGE_RESPONE_CODE = 1;
var isOk = false;
val imageUrl : String = "."
var userUID = "."
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySignUpBinding.inflate(layoutInflater)
setContentView(binding.root)
firebaseAuth = FirebaseAuth.getInstance()
binding.signupTvSelectPhoto.setOnClickListener {
val intent = Intent();
intent.type = "image/*"
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Pic"),IMAGE_RESPONE_CODE)
}
binding.signupBtnSignUp.setOnClickListener {
val email = binding.signupEtvEmail.text.toString()
if(email.isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
binding.signupEtvEmail.error = "Invalid Email Address"
binding.signupEtvEmail.requestFocus()
return@setOnClickListener
}
if(binding.signupEtvName.text.length < 3) {
binding.signupEtvName.error= "Name should at least have 3 characters"
binding.signupEtvName.requestFocus()
return@setOnClickListener
}
val password = binding.signupEtvPassword.text.toString()
if(password.length < 4) {
binding.signupEtvPassword.error = "Password should at least have 4 characters."
binding.signupEtvPassword.requestFocus()
return@setOnClickListener
}
// All Okay
Log.d(TAG,"STARTING PROCESS")
binding.pbSignup.visibility = View.VISIBLE
createAccount(email,password,binding.signupEtvName.text.toString())
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == 1) {
if(data != null) {
selectedPhoto = data?.data
binding.signupImgvPhoto.setImageURI(selectedPhoto)
}
else {
val context = this
selectedPhoto = Uri.parse(
ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ context.getResources().getResourcePackageName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceTypeName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceEntryName(R.drawable.profilepicnormall) )
}
}
}
private fun createAccount(email : String, password : String,name:String) {
val context = this
selectedPhoto = Uri.parse(
ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ context.getResources().getResourcePackageName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceTypeName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceEntryName(R.drawable.profilepicnormall) )
lifecycleScope.async(Dispatchers.Main) {
async {
create(email,password)
}.await()
Log.d(TAG,"The isOk is $isOk")
if(isOk){
async {
Log.d(TAG,"in 1 async")
uploadImage()
}.await()
async {
Log.d(TAG,"in 2 async")
uploadDataToRealtimeDatabase(userUID,email,name,imageUrl)
}.await()
binding.pbSignup.visibility = View.GONE
val intent = Intent(applicationContext,MainActivity::class.java)
startActivity(intent)
finish()
}
binding.pbSignup.visibility = View.GONE
}
}
suspend fun create(email: String,password: String) {
Log.d(TAG,"BEFORE")
firebaseAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(parent) {task ->
if(task.isSuccessful) {
Toast.makeText(this@SignUpActivity,"SignUp Successful.",Toast.LENGTH_SHORT).show()
isOk = true;
userUID = firebaseAuth.currentUser!!.uid
Log.d(TAG,"INSIDE")
return@addOnCompleteListener
}
else {
Log.d(TAG,"${task.exception} . ")
Toast.makeText(this@SignUpActivity,"SignUp Not Successful.",Toast.LENGTH_SHORT).show()
}
}
Log.d(TAG,"AFTER")
}
suspend fun uploadDataToRealtimeDatabase(UID:String,userEmail: String,userName : String,url:String) {
Log.d(TAG,"in upload data")
val ref = FirebaseDatabase.getInstance("https://firechat-931d2-default-rtdb.asia-southeast1.firebasedatabase.app/")
.getReference("/users/$UID")
val userinfo = UserInfo(userEmail,UID,userName,url)
ref.setValue(userinfo).addOnSuccessListener {
Log.d(TAG,"UPLOADED USER INFORMATION")
}.addOnFailureListener{
Log.d(TAG,"${it.message} $it")
}
}
suspend fun uploadImage() : String {
Log.d(TAG,"in upload Image")
val profilePicName = "${firebaseAuth.uid}.profileImage"
var url = "."
val storage_reference = FirebaseStorage.getInstance("gs://firechat-931d2.appspot.com").getReference("/ProfileImages/$profilePicName")
storage_reference.putFile(selectedPhoto!!).continueWithTask { task ->
if (!task.isSuccessful) {
Log.d(TAG,"${task.exception}")
}
storage_reference.downloadUrl.addOnSuccessListener {
url = it.toString()
}.addOnFailureListener{
Log.d(TAG,"$it ${it.message}")
}
}
if(url.length < 2) {
Log.d(TAG,"Going with default url.")
url = "https://firebasestorage.googleapis.com/v0/b/firechat-931d2.appspot.com/o/ProfileImages%2FsqE6s03wgXQm7gl03xxQIM3JVQc2.profileImage?alt=media&token=640266a5-6611-4e09-b8ed-72ba8bdfdc1f"
}
Log.d(TAG,"returning the img url $url")
return url
}
}
在修复了您的代码的一些问题后,我只在虚拟应用程序中实现了注册部分,以下是我的观察结果:
No other statement
我的日志如下:
D/SIGNUPATAG: STARTING PROCESS
D/SIGNUPATAG: INSIDE
D/SIGNUPATAG: The isOk is true
D/SIGNUPATAG: in 1 async
D/SIGNUPATAG: in upload Image
D/SIGNUPATAG: in 2 async
D/SIGNUPATAG: in upload data
I think I am using coroutines correctly but I don't know why this program doesn't go further than this ^. Should I use callbacks? Am I using coroutines in a wrong way?
我认为您没有按预期使用协程,Firebase
调用已经是异步的,因此您不需要这样做,您应该使用内置的 Firebase 协程支持这个案例。我正在添加我在下面所做的更改。 (省略不需要任何更改的内容)
build.gradle
//firebase coroutines dependency
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.2"
SignUpActivity.kt
class SignUpActivity : AppCompatActivity() {
private lateinit var binding: ActivitySignUpBinding
.
.
override fun onCreate(savedInstanceState: Bundle?) {
.
.
}
private fun createAccount(email : String, password : String,name:String) {
lifecycleScope.launch(Dispatchers.Main) {
val createdUserJob = launch {
try {
Toast.makeText(this@SignUpActivity,"SignUp Successful.",Toast.LENGTH_SHORT).show()
isOk = true;
userUID = firebaseAuth.currentUser!!.uid
Log.d(TAG,"INSIDE")
firebaseAuth.createUserWithEmailAndPassword(email, password).await()
} catch (e: Exception) {
Toast.makeText(this@SignUpActivity,"SignUp Not Successful.",Toast.LENGTH_SHORT).show()
e.printStackTrace()
}
}
createdUserJob.join()
Log.d(TAG,"The isOk is $isOk")
if(isOk){
val uploadImageJob = launch {
Log.d(TAG,"in 1 async")
uploadImage()
}
uploadImageJob.join()
val uploadDataJob = launch {
Log.d(TAG,"in 2 async")
uploadDataToRealtimeDatabase(userUID,email,name,imageUrl)
}
uploadDataJob.join()
binding.pbSignup.visibility = View.GONE
val intent = Intent(applicationContext,MainActivity::class.java)
startActivity(intent)
finish()
}
binding.pbSignup.visibility = View.GONE
}
}
suspend fun uploadDataToRealtimeDatabase(UID:String,userEmail: String,userName : String,url:String) {
Log.d(TAG,"in upload data")
.
.
}
suspend fun uploadImage() : String {
Log.d(TAG,"in upload Image")
.
.
return "dummy"
}
}
注意:我只测试了注册部分,图片上传和上传数据部分你需要自己测试,我去掉了create(email: String,password: String)
还有方法。
此 activity 在 firebase auth 中注册用户,在实时数据库中上传信息并在存储中上传用户图片。 这段代码(我不知道为什么)在注册用户时卡住了。如果您看到了,我已经添加了 Log 语句来中断整个过程。日志就像
STARTING PROCESS
BEFORE
INSIDE
没有其他声明。我想我正确地使用了协程,但我不知道为什么这个程序没有比这个更进一步 ^。我应该使用回调吗?我是否以错误的方式使用协程?如果有任何其他建议,我们将不胜感激。
class SignUpActivity : AppCompatActivity() {
private lateinit var binding: ActivitySignUpBinding
private lateinit var firebaseAuth : FirebaseAuth
private lateinit var firebaseStorage: FirebaseStorage
private lateinit var firebaseDatabase: FirebaseDatabase
val TAG ="SIGNUPATAG"
var selectedPhoto : Uri? = null
var IMAGE_RESPONE_CODE = 1;
var isOk = false;
val imageUrl : String = "."
var userUID = "."
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySignUpBinding.inflate(layoutInflater)
setContentView(binding.root)
firebaseAuth = FirebaseAuth.getInstance()
binding.signupTvSelectPhoto.setOnClickListener {
val intent = Intent();
intent.type = "image/*"
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Pic"),IMAGE_RESPONE_CODE)
}
binding.signupBtnSignUp.setOnClickListener {
val email = binding.signupEtvEmail.text.toString()
if(email.isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
binding.signupEtvEmail.error = "Invalid Email Address"
binding.signupEtvEmail.requestFocus()
return@setOnClickListener
}
if(binding.signupEtvName.text.length < 3) {
binding.signupEtvName.error= "Name should at least have 3 characters"
binding.signupEtvName.requestFocus()
return@setOnClickListener
}
val password = binding.signupEtvPassword.text.toString()
if(password.length < 4) {
binding.signupEtvPassword.error = "Password should at least have 4 characters."
binding.signupEtvPassword.requestFocus()
return@setOnClickListener
}
// All Okay
Log.d(TAG,"STARTING PROCESS")
binding.pbSignup.visibility = View.VISIBLE
createAccount(email,password,binding.signupEtvName.text.toString())
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == 1) {
if(data != null) {
selectedPhoto = data?.data
binding.signupImgvPhoto.setImageURI(selectedPhoto)
}
else {
val context = this
selectedPhoto = Uri.parse(
ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ context.getResources().getResourcePackageName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceTypeName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceEntryName(R.drawable.profilepicnormall) )
}
}
}
private fun createAccount(email : String, password : String,name:String) {
val context = this
selectedPhoto = Uri.parse(
ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ context.getResources().getResourcePackageName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceTypeName(R.drawable.profilepicnormall) + '/'
+ context.getResources().getResourceEntryName(R.drawable.profilepicnormall) )
lifecycleScope.async(Dispatchers.Main) {
async {
create(email,password)
}.await()
Log.d(TAG,"The isOk is $isOk")
if(isOk){
async {
Log.d(TAG,"in 1 async")
uploadImage()
}.await()
async {
Log.d(TAG,"in 2 async")
uploadDataToRealtimeDatabase(userUID,email,name,imageUrl)
}.await()
binding.pbSignup.visibility = View.GONE
val intent = Intent(applicationContext,MainActivity::class.java)
startActivity(intent)
finish()
}
binding.pbSignup.visibility = View.GONE
}
}
suspend fun create(email: String,password: String) {
Log.d(TAG,"BEFORE")
firebaseAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(parent) {task ->
if(task.isSuccessful) {
Toast.makeText(this@SignUpActivity,"SignUp Successful.",Toast.LENGTH_SHORT).show()
isOk = true;
userUID = firebaseAuth.currentUser!!.uid
Log.d(TAG,"INSIDE")
return@addOnCompleteListener
}
else {
Log.d(TAG,"${task.exception} . ")
Toast.makeText(this@SignUpActivity,"SignUp Not Successful.",Toast.LENGTH_SHORT).show()
}
}
Log.d(TAG,"AFTER")
}
suspend fun uploadDataToRealtimeDatabase(UID:String,userEmail: String,userName : String,url:String) {
Log.d(TAG,"in upload data")
val ref = FirebaseDatabase.getInstance("https://firechat-931d2-default-rtdb.asia-southeast1.firebasedatabase.app/")
.getReference("/users/$UID")
val userinfo = UserInfo(userEmail,UID,userName,url)
ref.setValue(userinfo).addOnSuccessListener {
Log.d(TAG,"UPLOADED USER INFORMATION")
}.addOnFailureListener{
Log.d(TAG,"${it.message} $it")
}
}
suspend fun uploadImage() : String {
Log.d(TAG,"in upload Image")
val profilePicName = "${firebaseAuth.uid}.profileImage"
var url = "."
val storage_reference = FirebaseStorage.getInstance("gs://firechat-931d2.appspot.com").getReference("/ProfileImages/$profilePicName")
storage_reference.putFile(selectedPhoto!!).continueWithTask { task ->
if (!task.isSuccessful) {
Log.d(TAG,"${task.exception}")
}
storage_reference.downloadUrl.addOnSuccessListener {
url = it.toString()
}.addOnFailureListener{
Log.d(TAG,"$it ${it.message}")
}
}
if(url.length < 2) {
Log.d(TAG,"Going with default url.")
url = "https://firebasestorage.googleapis.com/v0/b/firechat-931d2.appspot.com/o/ProfileImages%2FsqE6s03wgXQm7gl03xxQIM3JVQc2.profileImage?alt=media&token=640266a5-6611-4e09-b8ed-72ba8bdfdc1f"
}
Log.d(TAG,"returning the img url $url")
return url
}
}
在修复了您的代码的一些问题后,我只在虚拟应用程序中实现了注册部分,以下是我的观察结果:
No other statement
我的日志如下:
D/SIGNUPATAG: STARTING PROCESS
D/SIGNUPATAG: INSIDE
D/SIGNUPATAG: The isOk is true
D/SIGNUPATAG: in 1 async
D/SIGNUPATAG: in upload Image
D/SIGNUPATAG: in 2 async
D/SIGNUPATAG: in upload data
I think I am using coroutines correctly but I don't know why this program doesn't go further than this ^. Should I use callbacks? Am I using coroutines in a wrong way?
我认为您没有按预期使用协程,Firebase
调用已经是异步的,因此您不需要这样做,您应该使用内置的 Firebase 协程支持这个案例。我正在添加我在下面所做的更改。 (省略不需要任何更改的内容)
build.gradle
//firebase coroutines dependency
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.4.2"
SignUpActivity.kt
class SignUpActivity : AppCompatActivity() {
private lateinit var binding: ActivitySignUpBinding
.
.
override fun onCreate(savedInstanceState: Bundle?) {
.
.
}
private fun createAccount(email : String, password : String,name:String) {
lifecycleScope.launch(Dispatchers.Main) {
val createdUserJob = launch {
try {
Toast.makeText(this@SignUpActivity,"SignUp Successful.",Toast.LENGTH_SHORT).show()
isOk = true;
userUID = firebaseAuth.currentUser!!.uid
Log.d(TAG,"INSIDE")
firebaseAuth.createUserWithEmailAndPassword(email, password).await()
} catch (e: Exception) {
Toast.makeText(this@SignUpActivity,"SignUp Not Successful.",Toast.LENGTH_SHORT).show()
e.printStackTrace()
}
}
createdUserJob.join()
Log.d(TAG,"The isOk is $isOk")
if(isOk){
val uploadImageJob = launch {
Log.d(TAG,"in 1 async")
uploadImage()
}
uploadImageJob.join()
val uploadDataJob = launch {
Log.d(TAG,"in 2 async")
uploadDataToRealtimeDatabase(userUID,email,name,imageUrl)
}
uploadDataJob.join()
binding.pbSignup.visibility = View.GONE
val intent = Intent(applicationContext,MainActivity::class.java)
startActivity(intent)
finish()
}
binding.pbSignup.visibility = View.GONE
}
}
suspend fun uploadDataToRealtimeDatabase(UID:String,userEmail: String,userName : String,url:String) {
Log.d(TAG,"in upload data")
.
.
}
suspend fun uploadImage() : String {
Log.d(TAG,"in upload Image")
.
.
return "dummy"
}
}
注意:我只测试了注册部分,图片上传和上传数据部分你需要自己测试,我去掉了create(email: String,password: String)
还有方法。