Doesn't stay on Dashboard and goes back to log in activity - android

val uid = FirebaseAuth.getInstance().currentUser!!.uid
val ref = FirebaseDatabase.getInstance().getReference("/users/$uid")
val uidRef = ref.child("users").child(uid)
val valueEventListener: ValueEventListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
if (dataSnapshot.child("type").getValue(String::class.java) == "a") {
val intent = Intent(this#LoginActivity, DashBoardActivity::class.java)
intent.flags=Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
} else if (dataSnapshot.child("type").getValue(String::class.java) == "b") {
val intent = Intent(this#LoginActivity, DashBoardActivity::class.java)
intent.flags=Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
} else if (dataSnapshot.child("type").getValue(String::class.java) == "c") {
val intent = Intent(this#LoginActivity, AdminDashBoard::class.java)
intent.flags=Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.d("error", databaseError.message);
}
}
uidRef.addListenerForSingleValueEvent(valueEventListener)
}
Okay, I have gotten it to work. No nullpoint, No Crash. The code works, but for someone reason it doesn't stay on the dashboard and goes back to the log in page. Anyway of sorting this out because I am clueless on how to solve this. the login action occurs but doesn't change to another Activity. It Pops up but then goes back to LoginActivity.
D/AutofillManager: onActivityFinishing(): calling cancelLocked()
This is the call that is last made then stop before full opening the n going back to login screen
My database structure is like this
{
"users" : {
"H8pviFh1GVTLYZIrlCt7Xvx6nRE3" : {
"dateofbirth" : "",
"email" : "",
"firstname" : "bilal",
"lastname" : "dar",
"mobile" : "",
"type" : "a",
"uid" : "H8pviFh1GVTLYZIrlCt7Xvx6nRE3"
}
}
}
This is my firebase database structure

Related

Update value from realtime database after button click

I'm trying to create a like functionality in my app, the like function is already working (increment and decrement). My problem is I need to re-enter the activity again to see the new value of the like. But the value in my realtime database is already changed but in the app view, it doesn't increment or decrement (Need to re-enter to see the new value). How do i refresh a value in my app when in a button click? The code is below
//set the likes number on start
likes.text = myPlants.likes.toString();
//When like is clicked
bulbLike.setOnCheckListener(object : OnCheckListener {
override fun onChecked(view: ExpressView?) {
bulbLike(myPlants.plantId,currentUser!!.uid)
//When i remove this the values dosent change
val rootRef = FirebaseDatabase.getInstance().reference
val likeRef = rootRef.child("plants").child(myPlants.plantId).child("likes")
likeRef.get().addOnCompleteListener(OnCompleteListener<DataSnapshot?> { task ->
if (task.isSuccessful) {
val value: Long? = task.result.getValue(Long::class.java)
likes.text = value.toString()
} else {
Log.d("TAG", "Error") //Don't ignore potential errors!
}
})
}
override fun onUnChecked(view: ExpressView?) {
bulbDislike(myPlants.plantId,currentUser!!.uid)
//When i remove this the values dosent change
val rootRef = FirebaseDatabase.getInstance().reference
val likeRef = rootRef.child("plants").child(myPlants.plantId).child("likes")
likeRef.get().addOnCompleteListener(OnCompleteListener<DataSnapshot?> { task ->
if (task.isSuccessful) {
val value: Long? = task.result.getValue(Long::class.java)
likes.text = value.toString()
} else {
Log.d("TAG", "Error") //Don't ignore potential errors!
}
})
}
})
This one works it changes the value but it changes to 1 or -1
This is method or like and dislike
private fun bulbLike(plantId: String, userId: String) {
val dPlant: DatabaseReference = FirebaseDatabase.getInstance().reference
dPlant.child("plants").child(plantId).child("likes").setValue(ServerValue.increment(1))
dPlant.child("plants").child(plantId).child("userLikes").child(userId).child("status").setValue("Liked")
}
private fun bulbDislike(plantId: String, userId: String) {
val dPlant: DatabaseReference = FirebaseDatabase.getInstance().reference
dPlant.child("plants").child(plantId).child("likes").setValue(ServerValue.increment(-1))
dPlant.child("plants").child(plantId).child("userLikes").child(userId).child("status").setValue("Dislike")
}
This here gets the data once, don't use it in your case:
//THIS WONT LISTEN TO UPDATES:
likeRef.get().addOnCompleteListener(OnCompleteListener<DataSnapshot?> { task ->
if (task.isSuccessful) {
val value: Long? = task.result.getValue(Long::class.java)
likes.text = value.toString()
} else {
Log.d("TAG", "Error") //Don't ignore potential errors!
}
})
Read like this instead, using ValueEventListener, like this:
//THIS WILL LISTEN TO UPDATES DIRECTLY
val postListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
//set likes here
val value = dataSnapshot.getValue(Long::class.java)
likes.text = value.toString()
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
}
}
likeRef.addValueEventListener(postListener)

Extract Data from firebase

Unable to extract information from the datasnapshot received from firebase.
Currently, I am able to get the dataSnapshot from firebase, but I am having problems extracting the information from it.
In the example below I have a lobby with the code "81MUB" and inside I have a list of players (only using one player in the example). Data from FireBase
{
"81MUB": [
{
"name": "Alejandro",
"points": 0
}
]
}
Data Class
data class Player(
val name: String,
val points: Int
)
Listener
fun getCode(): String {
val index = ('A'..'Z') + ('1'..'9')
var code = ""
for (i in 0..4){
code += index[Random().nextInt(index.size)]
}
return code
}
class MviewModel : ViewModel() {
private val _Players: MutableLiveData<MutableList<Player>> =
MutableLiveData(mutableListOf<Player>(Player("Alejandro", 0)))
private var _LobbyCode: String = ""
private val dataBase = FirebaseDatabase.getInstance()
fun getPlayer(): MutableLiveData<MutableList<Player>> = _Players
fun createLobby() {
_LobbyCode = getCode()
}
fun listener() {
val postListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
}
}
dataBase.reference.child(_LobbyCode).addValueEventListener(postListener)
}
}
Any tips?
Each time you call getCode() you are generating a new random code. When reading data, you always use the exact same code that exists in the database. So in code, it should look like this:
val db = Firebase.database.reference
val codeRef = db.child("81MUB")
codeRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
val name = snapshot.child("name").getValue(String::class.java)
val points = snapshot.child("points").getValue(Long::class.java)
Log.d("TAG", "$name/$points")
} else {
Log.d("TAG", error.getMessage()) //Never ignore potential errors!
}
}
The result in the logcat will be:
Alejandro/0
If you however want to map the 81MUB node into an object of type Player, then your data class should look like this:
data class Player(
val name: String? = null,
val points: Int? = null
)
And in code:
val db = Firebase.database.reference
val codeRef = db.child("81MUB")
codeRef.get().addOnCompleteListener {
if (it.isSuccessful) {
val snapshot = it.result
val player = snapshot.getValue(Player::class.java)
Log.d("TAG", "${player.name}/${player.points}")
} else {
Log.d("TAG", error.getMessage()) //Never ignore potential errors!
}
}
Which will produce the exact same output as above.
You might also take into consideration, using the DatabaseReference#push() method which:
Create a reference to an auto-generated child location. The child key is generated client-side and incorporates an estimate of the server's time for sorting purposes.
Instead of using your codes.

Program wont progress after firebase user registration

This activity registers a user in firebase auth, uploads info in Realtime database and uploads user picture in Storage.
This code (I don't know why) gets stuck when it registers the user. If you see, I've added Log statements to break this entire process. The log is like
STARTING PROCESS
BEFORE
INSIDE
No other statement. 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?A lso any other suggestion will be appreciated.
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
}
}
I implemented only the signup part in a dummy app after fixing some issues with your code, here are my observations:
No other statement
My logs were as follows:
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?
I don't think you're using coroutines as intended, Firebase calls are already asynchronous so you don't require to do it this way, you should use Firebase coroutines instead which have built-in support for this case. I am adding the changes that I made below. (Omitting the stuff that doesn't require any change)
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"
}
}
Note: I have only tested the signup part, you need to test the image upload and upload data part on your own, I've removed the create(email: String,password: String) method as well.

Kotlin:How to wait for function one from object to start another one from fragment?

I would like for my fragment to first end launch job and then do rest of the code, but it does not and i don't understand why.
runBlocking {
val job = launch {
Stopers.ITEMS.clear()
val database =
Firebase.database("myurl")
val user = Firebase.auth.currentUser
Log.e(TAG, "User: ${user?.uid.toString()}")
val myRef = database.getReference("${user?.uid.toString()}")
myRef.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
Stopers.ITEMS.clear()
Stopers.COUNT = dataSnapshot.child("Number_of_stopers").getValue<Long>()!!.toLong()
for (i in 1..Stopers.COUNT) {
.getValue<String>().toString()
Stopers.addStoper()
}
})
}
job.join()
adapter = MyStoperRecyclerViewAdapter(Stopers.ITEMS, eventListListener)
Log.d(TAG,"Adapter: done")
}
Ok the problem is your calling job inside the runBlocking itself, try this way.
val job = launch {
{
//your first code
}
}
runBlocking {
job.join()
//do what you wanted to do after
}

How to resolve the error "LifecycleOwners must call register before they are STARTED"

I am using registerForActivityResult for google sign in implementation in my development. Everything was working fine until I upgraded my fragment dependency to 1.3.0-beta01. The application current crash with the error
java.lang.IllegalStateException: LifecycleOwner SignupChoicesFragment{8e0e269} (193105b9-afe2-4941-a368-266dbc433258) id=0x7f090139} is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
I have used the function before oncreate using lazy loading but it wont work still.
class SignupChoicesFragment : DaggerFragment() {
#Inject
lateinit var viewModelProviderFactory: ViewModelFactory
val userViewModel: UserViewModel by lazy {
ViewModelProvider(this, viewModelProviderFactory).get(UserViewModel::class.java)
}
#Inject
lateinit var mGoogleSignInClient:GoogleSignInClient
val arg:SignupChoicesFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_signup_choices, container, false)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
google_sign_in_button.setOnClickListener {
val intent = mGoogleSignInClient.signInIntent
val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), ActivityResultCallback {result->
if (result.resultCode == Activity.RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
task.addOnCompleteListener {
if (it.isSuccessful) {
val account: GoogleSignInAccount? =
it.getResult(ApiException::class.java)
val idToken = it.result?.idToken
val email = account?.email
val lastName = account?.familyName
val firstName = account?.givenName
val otherName = account?.displayName
val imageUrl = account?.photoUrl
val category = arg.category
val newUser = User()
newUser.firstName = firstName
newUser.lastName = lastName
newUser.otherName = otherName
newUser.category = category
newUser.email = email
newUser.imageUrl = imageUrl.toString()
userViewModel.currentUser = newUser
newUser.token = idToken
i(title, "idToken $idToken")
requireActivity().gdToast("Authentication successful", Gravity.BOTTOM)
val action = SignupChoicesFragmentDirections.actionSignupChoicesFragmentToEmailSignupFragment()
action.newUser = newUser
goto(action)
} else {
requireActivity().gdToast(
"Authentication Unsuccessful",
Gravity.BOTTOM
)
Log.i(title, "Task not successful")
}
}
} else {
Log.i(title, "OKCODE ${Activity.RESULT_OK} RESULTCODE ${result.resultCode}")
}
}).launch(intent)
}
}
For me, the issue was that I was calling registerForActivityResult within an onClickListener which was only invoked on clicking a button (the app at this point is in state RESUMED). Moving the call outside the button's onClickListener and into the Activity's onCreate method fixed it.
quote from documentation
registerForActivityResult() is safe to call before your fragment or activity is created, allowing it to be used directly when declaring member variables for the returned ActivityResultLauncher instances.
Note: While it is safe to call registerForActivityResult() before your fragment or activity is created, you cannot launch the ActivityResultLauncher until the fragment or activity's Lifecycle has reached CREATED.
so to solve your issue move your register call outside the onCreate() and put it in fragment scope, and on google_sign_in_button click-listener call launch function
Note: if you are using Kotlin-Android-Extention move your click-listener call to onViewCreated()
If you are using a Fragment, please make sure that you are NOT performing the registerForActivityResult on the activity. Fragments also have a registerForActivityResult and that's the one you should use.
you must remove val launcher = registerForActivityResult... out of the setOnClickListener, then save it in a variable, in your example is launcher and in the setOnClickListener execute the variable with .launch, in your example es launcher.
your code would look like this
google_sign_in_button.setOnClickListener {
val intent = mGoogleSignInClient.signInIntent
launcher.launch(intent)
}
private val launcher = registerForActivityResult(ActivityResultContracts.StartActivityForResult(), ActivityResultCallback {result->
if (result.resultCode == Activity.RESULT_OK) {
val task = GoogleSignIn.getSignedInAccountFromIntent(result.data)
task.addOnCompleteListener {
if (it.isSuccessful) {
val account: GoogleSignInAccount? =
it.getResult(ApiException::class.java)
val idToken = it.result?.idToken
val email = account?.email
val lastName = account?.familyName
val firstName = account?.givenName
val otherName = account?.displayName
val imageUrl = account?.photoUrl
val category = arg.category
val newUser = User()
newUser.firstName = firstName
newUser.lastName = lastName
newUser.otherName = otherName
newUser.category = category
newUser.email = email
newUser.imageUrl = imageUrl.toString()
userViewModel.currentUser = newUser
newUser.token = idToken
i(title, "idToken $idToken")
requireActivity().gdToast("Authentication successful", Gravity.BOTTOM)
val action = SignupChoicesFragmentDirections.actionSignupChoicesFragmentToEmailSignupFragment()
action.newUser = newUser
goto(action)
} else {
requireActivity().gdToast(
"Authentication Unsuccessful",
Gravity.BOTTOM
)
Log.i(title, "Task not successful")
}
}
} else {
Log.i(title, "OKCODE ${Activity.RESULT_OK} RESULTCODE ${result.resultCode}")
}
})
Source : https://medium.com/codex/android-runtime-permissions-using-registerforactivityresult-68c4eb3c0b61
registerForActivityResult() is safe to call before your fragment or activity is created, allowing it to be used directly when declaring member variables for the returned ActivityResultLauncher instances.
you should call registerForActivityResult before view created. member variables or onCreate()
If you are working with any third party library then it may happens that you can't see the "registerForActivityResult" in your code but it should be present in classes provided by that same library.
So in this case I will suggest to move out the lines which is related to that library from any listener to the onCreate method.
for example -
btnBackup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final RoomBackup roomBackup = new RoomBackup(GoogleDriveActivity.this);
roomBackup.database(LocalDataBase.getInstance(getApplicationContext()));
roomBackup.enableLogDebug(true);
roomBackup.backupIsEncrypted(false);
roomBackup.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL);
roomBackup.onCompleteListener((success, message, exitCode) -> {
Log.d(TAG, "success: " + success + ", message: " + message + ", exitCode: " + exitCode);
if (success) roomBackup.restartApp(new Intent(getApplicationContext(), GoogleDriveActivity.class));
});
roomBackup.restore();
}
});
//// remove other code from listener and shift in onCreate
roomBackup = new RoomBackup(GoogleDriveActivity.this);
roomBackup.database(LocalDataBase.getInstance(getApplicationContext()));
roomBackup.enableLogDebug(true);
roomBackup.backupIsEncrypted(false);
roomBackup.backupLocation(RoomBackup.BACKUP_FILE_LOCATION_INTERNAL);
roomBackup.maxFileCount(5);
roomBackup.onCompleteListener((success, message, exitCode) -> {
Log.d(TAG, "success: " + success + ", message: " + message + ", exitCode: " + exitCode);
if (success) roomBackup.restartApp(new Intent(getApplicationContext(), GoogleDriveActivity.class));
});
/// you can keep only required lines in listener
btnBackup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
roomBackup.backup();
}
});
That's it!
Found the same issue and manage to get to work with some magic.
In my case, it was happening in an Activity, so I went about it as such:
//...other bits
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
// doing the setup here
setupViews()
}
private fun setupViews() {
val buttonLauncher = navigator.gotoScreenForResult(this) { success ->
if (success) {
setResult(Activity.RESULT_OK)
finish()
}
}
binding.myButton.setOnClickListener {
buttonLauncher.launch(Unit)
}
Where the navigator.gotoScreenForResult would look like the following:
override fun gotoScreenForResult(context: AppCompatActivity, callback: (Boolean) -> Unit): ActivityResultLauncher<Unit> {
val contract = object : ActivityResultContract<Unit, Boolean>() {
override fun createIntent(context: Context, input: Unit?): Intent {
return Intent(context, MyNextActivity::class.java)
}
override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
return resultCode == Activity.RESULT_OK
}
}
return context.registerForActivityResult(contract) { callback(it) }
}
Just make sure the setupViews is done within the onCreate and not on the resume step.

Categories

Resources