I am building a function in my android app in which user will match two items together
and if both items match to each other a correct icon will display to the item where u clicked to match,and if ur match was wrong then it show u the wrong icon.
There is condition when the match is correct then the both correct items are removed i try various ways to removed but they are not seems perfect.
The matching are based on the languages its a langauge translation app suppose u try to translate the How are u(engilsh) ->to ->Comment vas-tu(french) in that case if those count values are match that mean they are belong to each other so its right
The value of count I provided from the activity where i adding values to the matchdataholder,By the loop count variable saved the ist lang (english text) at count 1 and 2nd language(french) to count 1 as well but with differnt index
Activity Class
package com.blablacards.activity
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import com.blablacards.R
import com.blablacards.adapter.MatchAdapter
import com.blablacards.app.retrofit.ApiCall
import com.blablacards.model.FavListItem
import com.blablacards.model.MatchDataHolder
import com.blablacards.model.MatchList
import com.blablacards.model.ResponseFavList
import com.blablacards.utils.AppPref
import com.blablacards.utils.Constants
import kotlinx.android.synthetic.main.activity_match.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MatchActivity : BaseActivity(), View.OnClickListener {
var matchDataHolder: ArrayList<MatchDataHolder>? = ArrayList<MatchDataHolder>()
var favWordList = ArrayList<FavListItem>()
var matchList = ArrayList<MatchList>()
var categoryId: Int? = null
var categoryName: String? = null
lateinit var matchAdapter: MatchAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_match)
img_back.setOnClickListener(this)
getBundleData()
tv_header.text = categoryName
favWordList.clear()
calFavCategoryListApi("DESC")
// setAdapter()
}
private fun setAdapter(favWordList: ArrayList<MatchDataHolder>) {
Toast.makeText(this#MatchActivity, "Adapter called", Toast.LENGTH_SHORT).show()
matchAdapter = MatchAdapter(
this#MatchActivity,
favWordList
)
println("FAV LIST SIZE ->" + favWordList.size)
rv_match.layoutManager = GridLayoutManager(this#MatchActivity, 2)
rv_match.adapter = matchAdapter
}
private fun getBundleData() {
val extras = intent.extras
if (extras != null) {
categoryId = extras.getInt("CategoryId")
categoryName = extras.getString("CategoryName")
println("!!!categoryId = ${categoryId}")
}
}
private fun calFavCategoryListApi(sortBy: String) {
ApiCall.initApiCall(Constants.BASE_URL).getFavcategoryList(
"Bearer" + AppPref.getValue(AppPref.TOKEN, ""),
AppPref.getValue(AppPref.LOGIN_ID, "")!!, categoryId.toString(), "", "", sortBy
).enqueue(object : Callback<ResponseFavList> {
override fun onResponse(
call: Call<ResponseFavList>,
response: Response<ResponseFavList>
) {
if (response.isSuccessful) {
if (response.body()!!.status!!) {
favWordList.addAll(response.body()!!.data!!)
//
for (i in 0 until favWordList.size) {
matchDataHolder!!.add(MatchDataHolder(favWordList[i].sended_text.toString(),i))
matchDataHolder!!.add(MatchDataHolder(favWordList[i].return_text.toString(),i))
}
for(i in 0 until matchDataHolder!!.size){
println("DATA HOLDER ->"+ matchDataHolder!![i].text)
println("DATA HOLDER Count->"+ matchDataHolder!![i].count)
}
//
setAdapter(matchDataHolder!!)
} else {
showSnackBar(response.message())
}
}
}
override fun onFailure(call: Call<ResponseFavList>, t: Throwable) {
println("!!!t.message = ${t.message}")
}
})
}
override fun onClick(v: View?) {
when (v!!.id) {
R.id.img_back -> {
onBackPressed()
}
}
}
}
Adapter Class
package com.blablacards.adapter
import android.content.Context
import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.blablacards.R
import com.blablacards.model.MatchDataHolder
import kotlinx.android.synthetic.main.row_match.view.*
class MatchAdapter(
var context: Context,
var favWordList: ArrayList<MatchDataHolder>,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var index1 = -1
var index2 = -1
var enabledFlag = false
var oldPos = -1
var newPos = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return ViewHolder(
LayoutInflater.from(context)
.inflate(R.layout.row_match, parent, false)
)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as MatchAdapter.ViewHolder).bind(position)
holder.itemView.rl_match.setBackgroundColor(context.resources.getColor(R.color.white))
holder.itemView.tv_match.visibility = View.VISIBLE
holder.itemView.rl_match.setOnClickListener(View.OnClickListener {
if (!enabledFlag) {
println(enabledFlag)
println("IF block")
it.rl_match.setBackgroundColor(context.resources.getColor(R.color.orange_light3))
holder.itemView.tv_match.visibility = View.INVISIBLE
oldPos = favWordList[position].count
println("OLD POS ->" + oldPos)
index1 = position
println("index 1 = " + index1)
enabledFlag = true
} else {
// show the correct and wrong //
println("ELSE BLOCK")
enabledFlag = false
newPos = favWordList[position].count
println("NEW POS ->" + newPos)
index2 = position
println("index 2 = " + index2)
showCorrectOrFalse(holder.itemView, favWordList[position].count)
}
})
}
override fun getItemCount(): Int {
return favWordList.size
}
private fun timeHandler(itemView: View, status: String, position: Int) {
Handler().postDelayed({
if (status == "right") {
println("inside right")
itemView.tv_match.visibility = View.VISIBLE
itemView.rl_match.setBackgroundColor(context.resources.getColor(R.color.white))
itemView.img_right_or_wrong.visibility = View.INVISIBLE
// favWordList.drop(index1)
// favWordList.drop(index2)
/// THE PROBLEM IS HERE CUZ I'm not able to perfectly removed the item//
favWordList.remove(MatchDataHolder(favWordList[index1].text,newPos))
favWordList.remove(MatchDataHolder(favWordList[index2].text,oldPos))
notifyItemRemoved(index1)
notifyItemRemoved(index2)
notifyItemRangeChanged(index1,favWordList.size)
notifyItemRangeChanged(index2,favWordList.size)
notifyDataSetChanged()
}
if (status == "wrong") {
println("Inside wrong")
itemView.tv_match.visibility = View.VISIBLE
itemView.rl_match.setBackgroundColor(context.resources.getColor(R.color.white))
itemView.img_right_or_wrong.visibility = View.INVISIBLE
notifyDataSetChanged()
}
}, 2000)
}
private fun showCorrectOrFalse(itemView: View, position: Int) {
println("SHOW CORRECT CALLED")
//call handler after click //
println("OLD POS " + oldPos + " New POS " + newPos)
if (oldPos == newPos) {
itemView.img_right_or_wrong.setImageDrawable(context.resources.getDrawable(R.drawable.right_game))
Toast.makeText(context, "true", Toast.LENGTH_SHORT).show()
timeHandler(itemView, "right", position)
} else {
itemView.img_right_or_wrong.setImageDrawable(context.resources.getDrawable(R.drawable.wrong_game))
timeHandler(itemView, "wrong", position)
}
}
internal inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(position: Int) {
itemView.findViewById<TextView>(R.id.tv_match).text =
favWordList[position].text
}
}
}
A model class for hold the data of item
class MatchDataHolder(text:String,num:Int) {
var count = num
var text =text
}
favWordList.remove(MatchDataHolder(favWordList[index1].text,newPos))
you remove a new MatchDataHolder which is not exist in favWordList
you can try this:
favWordList.removeAt(index1)
Related
I am making a studymaterial app, where i want to add a functionality where - when a user download a particular chapter from recyclerview and after the successful download of that item the Download button visivity should make GONE of that item at that time.
I have implemented a method to do thisd but it only works when user finish the activity and come back again on that activity then the download button automatic not showing, but i want to implement at that point of time when user download something.
Here is my DownloadHandler.kt class
package com.tworoot2.class9thhistoryncert.downloadHandler
import android.app.AlertDialog
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.widget.Toast
import com.downloader.*
import com.tworoot2.class9thhistoryncert.DownloadedFiles
import java.io.File
import com.tworoot2.class9thhistoryncert.R
class DownloadHandler {
lateinit var alertDialog: AlertDialog.Builder
lateinit var failed: AlertDialog.Builder
var progressDialog: ProgressDialog? = null
var fileDestination: File? = null
var down: Boolean = false
fun downloadFile(url: String?, fileName: String, context: Context, filePath: File): Boolean {
progressDialog = ProgressDialog(context)
progressDialog!!.setMessage("Downloading....")
progressDialog!!.setCancelable(false)
progressDialog!!.max = 100
progressDialog!!.setProgressStyle(ProgressDialog.STYLE_SPINNER)
progressDialog!!.show()
alertDialog = AlertDialog.Builder(context)
alertDialog.setTitle("Downloaded successfully")
alertDialog.setMessage("$fileName is downloaded successfully")
alertDialog.setIcon(R.drawable.check)
alertDialog.setPositiveButton(
"Open"
) { _, i ->
val intent = Intent(context, DownloadedFiles::class.java)
context.startActivity(intent)
}
failed = AlertDialog.Builder(context)
failed.setTitle("Downloading failed")
failed.setMessage("Your file is not downloaded successfully")
failed.setIcon(R.drawable.failed)
PRDownloader.download(url, filePath.path, fileName)
.build()
.setOnStartOrResumeListener { }
.setOnPauseListener { }
.setOnCancelListener { }
.setOnProgressListener { progress ->
val per = progress.currentBytes * 100 / progress.totalBytes
progressDialog!!.setMessage("Downloading : $per %")
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
down = true
Toast.makeText(context, "Download completed ", Toast.LENGTH_SHORT).show()
progressDialog!!.dismiss()
alertDialog.show()
}
override fun onError(error: Error) {
down = false
Toast.makeText(context, "Something went wrong", Toast.LENGTH_SHORT).show()
failed.show()
progressDialog!!.dismiss()
}
})
return down
}
}
Adapter Class
package com.tworoot2.class9thhistoryncert.adapters
import android.content.Context
import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.tworoot2.class9thhistoryncert.Interface.OnPDFSelectListener
import com.tworoot2.class9thhistoryncert.Interface.PDFDownloadListner
import com.tworoot2.class9thhistoryncert.PDFActivity
import com.tworoot2.class9thhistoryncert.R
import com.tworoot2.class9thhistoryncert.models.StudyMaterials
import java.io.File
import java.lang.String
import kotlin.Int
class MaterialsAdapter(
var context: Context,
var arrayList: List<StudyMaterials>,
var listener: PDFDownloadListner,
var pdfSelectListener: OnPDFSelectListener,
var folderLocations: File
) :
RecyclerView.Adapter<MaterialsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.custom_materials, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.subjectHead.text = arrayList[position].chNo
holder.subjectName.text = arrayList[position].Title
val file =
File(
"$folderLocations/" + String.valueOf(
"Ch-" + arrayList[position].chNo + ". "
+ arrayList[position].Title + " [twoRoot2]" + ".pdf"
)
)
if (file.exists()) {
holder.downloadBtn.visibility = View.GONE
}
holder.itemView.setOnClickListener {
if (file.exists()) {
pdfSelectListener.onPDFSelected(file)
} else {
val intent = Intent(holder.itemView.context, PDFActivity::class.java)
intent.putExtra("link", arrayList[position].Link)
intent.putExtra("flag", "y")
intent.putExtra("title", arrayList[position].Title)
intent.putExtra("chNo", arrayList[position].chNo)
it.context.startActivity(intent)
}
}
holder.downloadBtn.setOnClickListener {
val downloaded = listener.onDownload(
arrayList[position].Link,
String.valueOf("Ch-" + arrayList[position].chNo)
.toString() + ". " + arrayList[position].Title
)
}
}
override fun getItemCount(): Int {
return arrayList.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val subjectName = itemView.findViewById<TextView>(R.id.subjectName);
val subjectHead = itemView.findViewById<TextView>(R.id.subjectHead);
val downloadBtn = itemView.findViewById<LinearLayout>(R.id.downloadBtn);
}
}
Activity Class
package com.tworoot2.class9thhistoryncert
import android.app.ProgressDialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Environment
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.tworoot2.class9thhistoryncert.Interface.OnPDFSelectListener
import com.tworoot2.class9thhistoryncert.Interface.PDFDownloadListner
import com.tworoot2.class9thhistoryncert.adapters.MaterialsAdapter
import com.tworoot2.class9thhistoryncert.application.MyApplicationClass
import com.tworoot2.class9thhistoryncert.downloadHandler.DownloadHandler
import com.tworoot2.class9thhistoryncert.viewModels.MainViewModel
import com.tworoot2.class9thhistoryncert.viewModels.MainViewModelFactory
import com.tworoot2.result10th_12th.Internetconnection.NetworkUtils
import java.io.File
class MaterialsActivity : AppCompatActivity(), PDFDownloadListner, OnPDFSelectListener {
lateinit var recyclerView: RecyclerView
lateinit var mainViewModel: MainViewModel
lateinit var file: File
lateinit var fileDestination: File
lateinit var downloadHandler: DownloadHandler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_materials)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar!!.setDisplayShowHomeEnabled(true)
recyclerView = findViewById(R.id.recView)
recyclerView.layoutManager = LinearLayoutManager(this)
// download listener
downloadHandler = DownloadHandler()
file = File(getExternalFilesDir(null).toString() + "/" + "Class")
fileDestination = File(Environment.getExternalStorageDirectory(), "/Class")
if (!fileDestination.exists()) {
fileDestination.mkdirs()
}
if (!NetworkUtils.isInternetAvailable(this#MaterialsActivity)) {
Toast.makeText(this#MaterialsActivity, "No internet connection", Toast.LENGTH_SHORT)
.show()
}
val progressDialog = ProgressDialog(this)
progressDialog.setMessage("Loading....")
progressDialog.setCancelable(false)
progressDialog.show()
val medium = intent.getStringExtra("medium")
val repository = (application as MyApplicationClass).materialsRepo
mainViewModel =
ViewModelProvider(this, MainViewModelFactory(repository))[MainViewModel::class.java]
if (medium.equals("h")) {
mainViewModel.hisHinLiveData.observe(this) {
this#MaterialsActivity.runOnUiThread(java.lang.Runnable {
val adapter =
MaterialsAdapter(
this#MaterialsActivity, it!!.studyMaterialCS,
this, this, file
)
progressDialog.dismiss()
recyclerView.adapter = adapter
})
}
} else if (medium.equals("e")) {
mainViewModel.hisEngLiveData.observe(this) {
this#MaterialsActivity.runOnUiThread(java.lang.Runnable {
val adapter =
MaterialsAdapter(
this#MaterialsActivity, it!!.studyMaterialCS,
this, this, file
)
progressDialog.dismiss()
recyclerView.adapter = adapter
})
}
} else {
Toast.makeText(this#MaterialsActivity, "Everything is invalid", Toast.LENGTH_SHORT)
.show()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
finish()
return true
}
}
return super.onOptionsItemSelected(item)
}
override fun onDownload(url: String?, title: String?) {
val time = System.currentTimeMillis().toString()
val shortTime = time.substring(8, 12)
val fileName = "$title [twoRoot2]"
// downloadFile(url, fileName + ".pdf");
// downloadFile(url, fileName + ".pdf");
Toast.makeText(applicationContext, "Downloading....", Toast.LENGTH_SHORT).show()
val downloaded =
downloadHandler.downloadFile(url, "$fileName.pdf", this#MaterialsActivity, file)
// Toast.makeText(applicationContext, "D...." + downloaded, Toast.LENGTH_SHORT).show()
}
override fun onPDFSelected(file: File?) {
val intent = Intent(this#MaterialsActivity, PDFActivity::class.java)
intent.putExtra("path", file!!.absolutePath)
intent.putExtra("flag", "n")
startActivity(intent)
}
override fun onDelete(file: File?, position: Int) {
TODO("Not yet implemented")
}
override fun inExternalApp(file: File?, context: Context?) {
TODO("Not yet implemented")
}
}
Repository Class
package com.tworoot2.class9thhistoryncert.repository
import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.tworoot2.class9thhistoryncert.api.MaterialsService
import com.tworoot2.class9thhistoryncert.models.MaterialsElist
import com.tworoot2.class9thhistoryncert.models.MaterialsList
import com.tworoot2.result10th_12th.Internetconnection.NetworkUtils
class MaterialsRepo(private val service: MaterialsService, private val context: Context) {
private val hisHinMutableLiveData = MutableLiveData<MaterialsList>()
private val hisEngMutableLiveData = MutableLiveData<MaterialsList>()
val hisHinLiveData: LiveData<MaterialsList>
get() = hisHinMutableLiveData
val hisEngLiveData: LiveData<MaterialsList>
get() = hisEngMutableLiveData
suspend fun getHisHindi() {
if (NetworkUtils.isInternetAvailable(context)) {
val result = service.getHistoryHindiFromAPI()
if (result.body() != null) {
hisHinMutableLiveData.postValue(result.body())
}
} else {
Log.e("InternetError", "No Internet Connection")
}
}
suspend fun getHisEnglish() {
if (NetworkUtils.isInternetAvailable(context)) {
val result = service.getHistoryEnglishFromAPI()
if (result.body() != null) {
hisEngMutableLiveData.postValue(result.body())
}
}else{
Log.e("InternetError", "No Internet Connection")
}
}
}
[Screen Shot 1]
[Screen Shot 2]
Maybe you want to use LiveData to handle realtime update UI for your case. After download thread run completed, let observer call update item in recyclerview.
Hope it help!
I am trying to get a users profile pic to be displayed beside their booking on a card in my recyclerview. The profile pic is displaying in my nav drawer, a default one for non-google users, or the profile pic of the Google user. However imageUri appears empty when I call it and the images are not being stored in my firebase storage bucket. I have linked my firebase and implemented the relevant SDK.
Here is my model.
#Parcelize
data class BookModel(
// var id : Long = 0,
var uid: String? = "",
var name: String = "N/A",
var phoneNumber: String = "N/A",
var email: String? = "N/A",
var date: String = "",
var bike: Int = 0,
var profilepic: String = "",
/*var lat: Double = 0.0,
var longitude: Double = 0.0,
var zoom: Float = 0f,*/
var pickup: String = "",
var dropoff: String = "",
var price: Double = 20.0,
/*var amount: Int = 0*/
) : Parcelable
{
#Exclude
fun toMap(): Map<String, Any?> {
return mapOf(
// "id" to id,
"uid" to uid,
"name" to name,
"phoneNumber" to phoneNumber,
"email" to email,
"date" to date,
"bike" to bike,
"profilepic" to profilepic,
"pickup" to pickup,
"dropoff" to dropoff,
"price" to price
)
}
}
#Parcelize
data class Location(
var lat: Double = 0.0,
var longitude: Double = 0.0,
var zoom: Float = 0f,
var depot: String = "Waterford"
) : Parcelable
Here is my FirebaseImageManager
package com.wit.mad2bikeshop.firebase
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.widget.ImageView
import androidx.lifecycle.MutableLiveData
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.UploadTask
import com.squareup.picasso.MemoryPolicy
import com.squareup.picasso.Picasso
import com.wit.mad2bikeshop.utils.customTransformation
import timber.log.Timber
import java.io.ByteArrayOutputStream
import com.squareup.picasso.Target
object FirebaseImageManager {
var storage = FirebaseStorage.getInstance().reference
var imageUri = MutableLiveData<Uri>()
fun checkStorageForExistingProfilePic(userid: String) {
val imageRef = storage.child("photos").child("${userid}.jpg")
val defaultImageRef = storage.child("ic_book_nav_header.png")
imageRef.metadata.addOnSuccessListener { //File Exists
imageRef.downloadUrl.addOnCompleteListener { task ->
imageUri.value = task.result!!
}
//File Doesn't Exist
}.addOnFailureListener {
imageUri.value = Uri.EMPTY
}
}
fun uploadImageToFirebase(userid: String, bitmap: Bitmap, updating : Boolean) {
// Get the data from an ImageView as bytes
val imageRef = storage.child("photos").child("${userid}.jpg")
//val bitmap = (imageView as BitmapDrawable).bitmap
val baos = ByteArrayOutputStream()
lateinit var uploadTask: UploadTask
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val data = baos.toByteArray()
imageRef.metadata.addOnSuccessListener { //File Exists
if(updating) // Update existing Image
{
uploadTask = imageRef.putBytes(data)
uploadTask.addOnSuccessListener { ut ->
ut.metadata!!.reference!!.downloadUrl.addOnCompleteListener { task ->
imageUri.value = task.result!!
}
}
}
}.addOnFailureListener { //File Doesn't Exist
uploadTask = imageRef.putBytes(data)
uploadTask.addOnSuccessListener { ut ->
ut.metadata!!.reference!!.downloadUrl.addOnCompleteListener { task ->
imageUri.value = task.result!!
}
}
}
}
fun updateUserImage(userid: String, imageUri : Uri?, imageView: ImageView, updating : Boolean) {
Picasso.get().load(imageUri)
.resize(200, 200)
.transform(customTransformation())
.memoryPolicy(MemoryPolicy.NO_CACHE)
.centerCrop()
.into(object : Target {
override fun onBitmapLoaded(bitmap: Bitmap?,
from: Picasso.LoadedFrom?
) {
Timber.i("DX onBitmapLoaded $bitmap")
uploadImageToFirebase(userid, bitmap!!,updating)
imageView.setImageBitmap(bitmap)
}
override fun onBitmapFailed(e: java.lang.Exception?,
errorDrawable: Drawable?) {
Timber.i("DX onBitmapFailed $e")
}
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
})
}
fun updateDefaultImage(userid: String, resource: Int, imageView: ImageView) {
Picasso.get().load(resource)
.into(object : Target {
override fun onBitmapLoaded(bitmap: Bitmap?,
from: Picasso.LoadedFrom?
) {
Timber.i("DX onBitmapLoaded $bitmap")
uploadImageToFirebase(userid, bitmap!!,false)
imageView.setImageBitmap(bitmap)
}
override fun onBitmapFailed(e: java.lang.Exception?,
errorDrawable: Drawable?) {
Timber.i("DX onBitmapFailed $e")
}
override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}
})
}
}
My FirebaseAuthManager...
package com.wit.mad2bikeshop.firebase
import android.app.Application
import androidx.lifecycle.MutableLiveData
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.GoogleAuthProvider
import com.wit.mad2bikeshop.R
import timber.log.Timber
class FirebaseAuthManager(application: Application) {
private var application: Application? = null
var firebaseAuth: FirebaseAuth? = null
var liveFirebaseUser = MutableLiveData<FirebaseUser>()
var loggedOut = MutableLiveData<Boolean>()
var errorStatus = MutableLiveData<Boolean>()
var googleSignInClient = MutableLiveData<GoogleSignInClient>()
init {
this.application = application
firebaseAuth = FirebaseAuth.getInstance()
if (firebaseAuth!!.currentUser != null) {
liveFirebaseUser.postValue(firebaseAuth!!.currentUser)
loggedOut.postValue(false)
errorStatus.postValue(false)
FirebaseImageManager.checkStorageForExistingProfilePic(
firebaseAuth!!.currentUser!!.uid)
}
configureGoogleSignIn()
}
fun login(email: String?, password: String?) {
firebaseAuth!!.signInWithEmailAndPassword(email!!, password!!)
.addOnCompleteListener(application!!.mainExecutor, { task ->
if (task.isSuccessful) {
liveFirebaseUser.postValue(firebaseAuth!!.currentUser)
errorStatus.postValue(false)
} else {
Timber.i("Login Failure: $task.exception!!.message")
errorStatus.postValue(true)
}
})
}
fun register(email: String?, password: String?) {
firebaseAuth!!.createUserWithEmailAndPassword(email!!, password!!)
.addOnCompleteListener(application!!.mainExecutor, { task ->
if (task.isSuccessful) {
liveFirebaseUser.postValue(firebaseAuth!!.currentUser)
errorStatus.postValue(false)
} else {
Timber.i("Registration Failure: $task.exception!!.message")
errorStatus.postValue(true)
}
})
}
fun logOut() {
firebaseAuth!!.signOut()
Timber.i( "firebaseAuth Signed out")
googleSignInClient.value!!.signOut()
Timber.i( "googleSignInClient Signed out")
loggedOut.postValue(true)
errorStatus.postValue(false)
}
private fun configureGoogleSignIn() {
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(application!!.getString(R.string.default_web_client_id))
.requestEmail()
.build()
googleSignInClient.value = GoogleSignIn.getClient(application!!.applicationContext,gso)
}
fun firebaseAuthWithGoogle(acct: GoogleSignInAccount) {
Timber.i( "DonationX firebaseAuthWithGoogle:" + acct.id!!)
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
firebaseAuth!!.signInWithCredential(credential)
.addOnCompleteListener(application!!.mainExecutor) { task ->
if (task.isSuccessful) {
// Sign in success, update with the signed-in user's information
Timber.i( "signInWithCredential:success")
liveFirebaseUser.postValue(firebaseAuth!!.currentUser)
} else {
// If sign in fails, display a message to the user.
Timber.i( "signInWithCredential:failure $task.exception")
errorStatus.postValue(true)
}
}
}
}
My Home activity
package com.wit.mad2bikeshop.ui.home
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.*
import com.google.firebase.auth.FirebaseUser
import com.squareup.picasso.Picasso
import com.wit.mad2bikeshop.R
import com.wit.mad2bikeshop.databinding.HomeBinding
import com.wit.mad2bikeshop.databinding.NavHeaderBinding
import com.wit.mad2bikeshop.firebase.FirebaseImageManager
import com.wit.mad2bikeshop.ui.auth.LoggedInViewModel
import com.wit.mad2bikeshop.ui.auth.Login
import com.wit.mad2bikeshop.utils.customTransformation
import timber.log.Timber
class Home : AppCompatActivity() {
private lateinit var drawerLayout: DrawerLayout
private lateinit var homeBinding: HomeBinding
private lateinit var navHeaderBinding: NavHeaderBinding
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var loggedInViewModel: LoggedInViewModel
private lateinit var headerView : View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
homeBinding = HomeBinding.inflate(layoutInflater)
setContentView(homeBinding.root)
drawerLayout = homeBinding.drawerLayout
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.bookFragment, R.id.bookingListFragment
), drawerLayout
)
setupActionBarWithNavController(navController, appBarConfiguration)
val navView = homeBinding.navView
navView.setupWithNavController(navController)
initNavHeader()
}
public override fun onStart() {
super.onStart()
loggedInViewModel = ViewModelProvider(this).get(LoggedInViewModel::class.java)
loggedInViewModel.liveFirebaseUser.observe(this, Observer { firebaseUser ->
if (firebaseUser != null)
updateNavHeader(firebaseUser)
})
loggedInViewModel.loggedOut.observe(this, Observer { loggedout ->
if (loggedout) {
startActivity(Intent(this, Login::class.java))
}
})
}
private fun initNavHeader() {
Timber.i("DX Init Nav Header")
headerView = homeBinding.navView.getHeaderView(0)
navHeaderBinding = NavHeaderBinding.bind(headerView)
}
private fun updateNavHeader(currentUser: FirebaseUser) {
FirebaseImageManager.imageUri.observe(this, { result ->
if(result == Uri.EMPTY) {
Timber.i("DX NO Existing imageUri")
if (currentUser.photoUrl != null) {
//if you're a google user
FirebaseImageManager.updateUserImage(
currentUser.uid,
currentUser.photoUrl,
navHeaderBinding.navHeaderImage,
false)
}
else
{
Timber.i("DX Loading Existing Default imageUri")
FirebaseImageManager.updateDefaultImage(
currentUser.uid,
R.drawable.ic_book_nav_header,
navHeaderBinding.navHeaderImage)
}
}
else // load existing image from firebase
{
Timber.i("DX Loading Existing imageUri")
FirebaseImageManager.updateUserImage(
currentUser.uid,
FirebaseImageManager.imageUri.value,
navHeaderBinding.navHeaderImage, false)
}
})
navHeaderBinding.navHeaderEmail.text = currentUser.email
if(currentUser.displayName != null)
navHeaderBinding.navHeaderName.text = currentUser.displayName
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
fun signOut(item: MenuItem) {
loggedInViewModel.logOut()
//Launch Login activity and clear the back stack to stop navigating back to the Home activity
val intent = Intent(this, Login::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
}
My BookViewModel
package com.wit.mad2bikeshop.ui.book
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.google.firebase.auth.FirebaseUser
import com.wit.mad2bikeshop.firebase.FirebaseDBManager
import com.wit.mad2bikeshop.firebase.FirebaseImageManager
import com.wit.mad2bikeshop.model.BookManager
import com.wit.mad2bikeshop.model.BookModel
class BookViewModel : ViewModel() {
private val status = MutableLiveData<Boolean>()
val observableStatus: LiveData<Boolean>
get() = status
fun addBook(firebaseUser: MutableLiveData<FirebaseUser>,
booking: BookModel) {
status.value = try {
booking.profilepic = FirebaseImageManager.imageUri.value.toString()
FirebaseDBManager.create(firebaseUser,booking)
true
} catch (e: IllegalArgumentException) {
false
}
}
// fun updateBook(booking: BookModel){
// status.value = try {
// BookManager.update(booking)
// true
// } catch (e: IllegalArgumentException) {
// false
// }
// }
}
My BookAdapter
package com.wit.mad2bikeshop.adapters
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.net.toUri
import androidx.recyclerview.widget.RecyclerView
import com.squareup.picasso.MemoryPolicy
import com.squareup.picasso.Picasso
import com.wit.mad2bikeshop.R
import com.wit.mad2bikeshop.databinding.CardBookBinding
import com.wit.mad2bikeshop.model.BookModel
import com.wit.mad2bikeshop.utils.customTransformation
interface BookListener {
// fun onDeleteBooking(booking: BookModel)
// fun onUpdateBooking(booking: BookModel)
fun onBookingClick(booking: BookModel)
}
class BookAdapter constructor(
private var bookings: ArrayList<BookModel>,
private val listener: BookListener,
private val readOnly: Boolean)
: RecyclerView.Adapter<BookAdapter.MainHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainHolder {
val binding = CardBookBinding
.inflate(LayoutInflater.from(parent.context), parent, false)
return MainHolder(binding, readOnly)
}
override fun onBindViewHolder(holder: MainHolder, position: Int) {
val booking = bookings[holder.adapterPosition]
holder.bind(booking, listener)
}
fun removeAt(position: Int) {
bookings.removeAt(position)
notifyItemRemoved(position)
}
override fun getItemCount(): Int = bookings.size
inner class MainHolder(val binding: CardBookBinding,private val readOnly : Boolean) :
RecyclerView.ViewHolder(binding.root) {
val readOnlyRow = readOnly
fun bind(booking: BookModel, listener: BookListener) {
binding.root.tag = booking
binding.booking = booking
binding.imageIcon.setImageResource(R.mipmap.ic_launcher_round)
Picasso.get().load(booking.profilepic.toUri())
.resize(200, 200)
.transform(customTransformation())
.centerCrop()
.into(binding.imageIcon)
//
// binding.name.text = booking.name
// binding.phoneNumber.text = booking.phoneNumber
// binding.date.text = booking.date
binding.root.setOnClickListener { listener.onBookingClick(booking) }
// binding.buttonDelete.setOnClickListener { listener.onDeleteBooking(booking) }
// binding.buttonUpdate.setOnClickListener { listener.onUpdateBooking(booking) }
binding.executePendingBindings()
/* binding.imageIcon.setImageResource(R.mipmap.ic_launcher_round)*/
}
}
}
I believe the problem stems from the (FirebaseImageManager.imageUri.value.toString()) on my BookAdapter, as if I run a Timber.I statement it doesn't return anything at all. If I run Timber.i(FirebaseImageManager.imageUri.value.toString()+ "test"), it only returns test.
Here is a link to the full project https://github.com/foxxxxxxx7/MAD2bikeshop
Apologies if I wasn't clear enough, I am a novice.
I figured it out, I had to modify my rules on the firebase storage.
I have integrated mesibo chat and tried to integrate the mesibo push-notification but not receiving the notification. I had set up all the things related push notification and already success integrate with the backend also.
Not sure why i can't receive notification from mesibo related new chat and new call.
This is my code:
package com.project.bucynapp.ui.message
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.mesibo.api.Mesibo.*
import com.mesibo.calls.api.MesiboCall
import com.project.bucynapp.R
import com.project.bucynapp.models.*
import com.project.bucynapp.ui.message.adapter.ChatListAdapter
import com.project.bucynapp.ui.message.presenter.ChatListPresenter
import com.project.bucynapp.ui.message.view.ChatListView
import com.project.bucynapp.utils.*
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.activity_chat_list.*
import kotlinx.android.synthetic.main.app_bar.toolbar
import kotlinx.android.synthetic.main.app_bar_chat_list.*
import kotlinx.android.synthetic.main.loading_view.*
class ChatListActivity : AppCompatActivity(), View.OnClickListener, ChatListView,
MessageListener, ConnectionListener, SyncListener {
private lateinit var presenter: ChatListPresenter
private lateinit var chatListAdapter: ChatListAdapter
private var chatList: MutableList<ChatModel> = mutableListOf()
private val layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
private lateinit var readSession: ReadDbSession
private var userMesibo: MesiboAccountData? = null
var userProfile: UserProfile? = null
private var imageProfile: String? = null
private var nameProfile: String? = null
private var userId: Int = 0
private var email: String? = null
companion object {
private const val USER_ID = "user_id"
private const val IMAGE_PROFILE = "img_profile"
private const val NAME_PROFILE = "name_profile"
private val TAG = ChatListActivity::class.java.canonicalName
fun startActivity(
context: Context,
userId: Int?,
imageProfile: String,
nameProfile: String
) {
Intent(context, ChatListActivity::class.java).apply {
putExtra(USER_ID, userId)
putExtra(IMAGE_PROFILE, imageProfile)
putExtra(NAME_PROFILE, nameProfile)
context.startActivity(this)
}
}
}
private val message: String
get() = edtSendChat.text.toString()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat_list)
initToolbar()
userMesibo = ApplicationPrefs.get(Constant.MESIBO_USER)
presenter = ChatListPresenter(this)
userId = intent.getIntExtra(USER_ID, 0)
imageProfile = intent.getStringExtra(IMAGE_PROFILE)
nameProfile = intent.getStringExtra(NAME_PROFILE)
chatListAdapter = ChatListAdapter(chatList)
rvChatList.adapter = chatListAdapter
rvChatList.layoutManager = layoutManager
rvChatList.addItemDecoration(DefaultItemDecoration(spacing = 10.dp, includeEdge = true))
tvName.text = nameProfile
Picasso.get().load(imageProfile)
.error(R.drawable.com_facebook_profile_picture_blank_square)
.placeholder(R.drawable.com_facebook_profile_picture_blank_square).into(imgProfile)
presenter.getEmailUser(userId)
}
private fun initToolbar() {
setSupportActionBar(toolbar)
val backArrow = ContextCompat.getDrawable(this, R.drawable.ic_back_black)
supportActionBar?.setHomeAsUpIndicator(backArrow)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(false)
tvSeeProfile.setOnClickListener(this)
imgCalling.setOnClickListener(this)
imgVideoCall.setOnClickListener(this)
imgSendChat.setOnClickListener(this)
tilChat.setStartIconOnClickListener {
NotMatchActivity.startActivity(this)
}
}
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
}
override fun getChatListSuccess(response: MutableList<DataAttributes>) {
}
override fun getChatListFailed(message: String) {
}
override fun successPost(response: SuccessModel?) {
}
override fun failedPost(message: String) {
shortToast(message)
}
override fun onGetEmailUser(data: UserEmailResponse?) {
email = data?.email
startMesibo()
email?.let { loadFromDb(it) }
}
override fun onLoading(isShow: Boolean) {
if (isShow) {
rvChatList.gone()
loadingView.visible()
} else {
rvChatList.visible()
loadingView.gone()
}
}
override fun onNoData(msg: String?) {
shortToast(msg.toString())
}
override fun onBadRequest(msg: String?) {
shortToast(msg.toString())
}
override fun onUnauthorized(msg: String?) {
shortToast(msg.toString())
badToken()
}
override fun onClick(v: View?) {
when (v) {
imgSendChat -> if (message.isNotBlank()) onSendMessage()
tvSeeProfile -> {
UserProfileActivity.startActivity(this, userId)
}
imgCalling -> MesiboCall.getInstance().callUi(this, email, false)
imgVideoCall -> MesiboCall.getInstance().callUi(this, email, true)
}
}
override fun Mesibo_onMessage(p0: MessageParams?, p1: ByteArray?): Boolean {
val type: Int = if (p0?.isIncoming == true) 0 else 1
val msg = String(p1!!)
chatList.add(
ChatModel(
id = p0!!.mid,
msg = msg,
date = p0.ts,
type = type,
status = p0.status
)
)
chatListAdapter.notifyItemInserted(chatList.size)
layoutManager.scrollToPositionWithOffset(chatList.size - 1, 0)
return true
}
override fun Mesibo_onMessageStatus(p0: MessageParams?) {
chatList.find { p0?.mid == it.id }?.status = p0?.status
chatListAdapter.notifyDataSetChanged()
Log.i("TAG", "Mesibo_onMessageStatus: ${p0?.status}}")
}
override fun Mesibo_onActivity(p0: MessageParams?, p1: Int) {
Log.i("TAG", "Mesibo_onActivity: $p1")
when (p1) {
ACTIVITY_ONLINE -> {
imgDotOnline.visible()
imgDotOffline.gone()
Log.i(TAG, "MESIBO_ACTIVITY: activity on")
}
ACTIVITY_TYPING -> Log.i(TAG, "MESIBO_ACTIVITY: user typing")
else -> {
imgDotOnline.gone()
imgDotOffline.visible()
Log.i(TAG, "Mesibo_onActivity: $p1")
}
}
}
override fun Mesibo_onLocation(p0: MessageParams?, p1: Location?) {}
override fun Mesibo_onFile(p0: MessageParams?, p1: FileInfo?) {}
override fun Mesibo_onConnectionStatus(p0: Int) {
when (p0) {
STATUS_ONLINE -> {
setPushToken(ApplicationPrefs.tokenFcm)
tvConnectionStatus.gone()
Log.d(TAG, "MESIBO_CONNECTION_STATUS: online")
}
STATUS_OFFLINE -> {
tvConnectionStatus.gone()
Log.d(TAG, "MESIBO_CONNECTION_STATUS: offline")
}
STATUS_CONNECTING -> {
tvConnectionStatus.visible()
tvConnectionStatus.text = getString(R.string.connecting)
Log.d(TAG, "MESIBO_CONNECTION_STATUS: offline")
}
STATUS_CONNECTFAILURE, STATUS_NONETWORK -> {
tvConnectionStatus.visible()
tvConnectionStatus.text = getString(R.string.mesibo_connect_fail_msg)
}
else -> {
Log.d(TAG, "MESIBO_CONNECTION_STATUS: $p0")
Log.d(TAG, "MESIBO_TOKEN: ${userMesibo?.token}")
}
}
}
override fun Mesibo_onSync(p0: Int) {
if (p0 <= 0) return
readSession.read(p0)
}
private fun onSendMessage() {
val p = MessageParams()
p.profile = userProfile
p.peer = email
p.mid = random()
p.flag = FLAG_DELIVERYRECEIPT or FLAG_READRECEIPT
sendMessage(p, p.mid, message)
chatList.add(
ChatModel(
id = p.mid,
msg = edtSendChat.text.toString(),
date = getTimestamp(),
type = 1,
status = 0
)
)
chatListAdapter.notifyItemInserted(chatList.lastIndex)
layoutManager.scrollToPositionWithOffset(chatList.size - 1, 0)
edtSendChat.text?.clear()
}
private fun loadFromDb(address: String) {
setAppInForeground(this, ChatListActivity.hashCode(), true)
readSession = ReadDbSession(address, this)
readSession.enableReadReceipt(true)
readSession.enableCalls(false)
readSession.enableIncomingCalls(false)
readSession.enableMissedCalls(false)
readSession.enableOutgoingCalls(false)
readSession.enableFifo(true)
readSession.read(500)
}
private fun startMesibo() {
addListener(this)
setSecureConnection(true)
setAccessToken(userMesibo?.token)
setDatabase("db_mesibo", 0)
start()
userProfile = UserProfile()
userProfile?.address = email
setUserProfile(userProfile, true)
}
}
Any clue about how to resolve and debug?
this is my env:
Mesibo AP = 2.7.0
Build tools = 29.0.0
compile SDK versions = 30
appid = com.project.bucynapp
Thanks!
Have you tried the custom scripts or mesibo webhook to debug the issue? Have you referred to the Troubleshooting section in the mesibo push-notification document?
https://mesibo.com/documentation/api/push-notifications/
Unless you post logs and steps you have taken, we have no clue what is happening.
How can I make progressbar dialog custom for kotlin
I think I should put it in setonclicklistener.
I already make custom progressbar XML
but I don't active this progressbar in kotlin
In Google
I don't know active in my code
package com.korea50k.tracer.ranking
import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.korea50k.tracer.R
import com.korea50k.tracer.dataClass.InfoData
import kotlinx.android.synthetic.main.recycler_rankfragment_item.view.*
class RankRecyclerViewAdapterMap (val mdata :ArrayList<InfoData>) : RecyclerView.Adapter<RankRecyclerViewAdapterMap.mViewHolder>() {
var context : Context? = null
//생성된 뷰 홀더에 데이터를 바인딩 해줌.
override fun onBindViewHolder(holder: mViewHolder, position: Int) {
val singleItem = mdata[position]
var ranking = position + 1
var cutted = singleItem.mapTitle!!.split("||")
//데이터 바인딩
holder.rank.text = ranking.toString()
holder.maptitle.text = cutted[0]
holder.execute.text = singleItem.execute.toString()
//ranking에 따라 트로피 색 바뀌게 하는 부분
if (ranking == 1)
holder.rank.setBackgroundResource(R.drawable.ic_1)
else if (ranking == 2)
holder.rank.setBackgroundResource(R.drawable.ic_2)
else if (ranking == 3)
holder.rank.setBackgroundResource(R.drawable.ic_3)
else
holder.rank.setBackgroundResource(R.drawable.ic_4)
//클릭하면 맵 상세보기 페이지로 이동
holder.itemView.setOnClickListener{
val nextIntent = Intent(context, RankRecyclerItemClickActivity::class.java)
nextIntent.putExtra("MapTitle", singleItem.mapTitle) //mapTitle 정보 인텐트로 넘김
context!!.startActivity(nextIntent)
}
}
//뷰 홀더 생성
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): mViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recycler_rankfragment_item, parent, false)
Log.d("rank", "onCreateViewHolder호출")
context = parent.context
return mViewHolder(view) //view 객체는 한개의 리사이클러뷰가 디자인 되어 있는 레이아웃을 의미
}
//item 사이즈, 데이터의 전체 길이 반ㅎ환
override fun getItemCount(): Int {
Log.d("rank", "데이터 크기 " + mdata.size.toString())
//return 10 //TODO 갯수 조절 여기서
return mdata.size
}
//여기서 item을 textView에 옮겨줌
inner class mViewHolder(view: View) : RecyclerView.ViewHolder(view!!) {
var rank = view.rankingFragmentCountTextView
var maptitle = view.rankingFragmentMapTitleTextView
var execute = view.rankingFragmentExecuteTextView
}
}
package com.korea50k.tracer.ranking
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.storage.FirebaseStorage
import com.korea50k.tracer.R
import com.korea50k.tracer.dataClass.InfoData
import com.korea50k.tracer.dataClass.RankRecyclerItemClickItem
import com.korea50k.tracer.dataClass.RankingData
import kotlinx.android.synthetic.main.activity_rank_recycler_item_click.*
import kotlinx.android.synthetic.main.fragment_ranking.view.*
class RankRecyclerItemClickActivity : AppCompatActivity() {
lateinit var mapRankingDownloadThread: Thread
var arrRankingData: ArrayList<RankingData> = arrayListOf()
var rankingData = RankingData()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_rank_recycler_item_click)
val intent = getIntent()
//전달 받은 값으로 Title 설정
var mapTitle = intent.extras?.getString("MapTitle").toString()
var cutted = mapTitle.split("||")
rankRecyclerMapTitle.text = cutted[0]
//TODO:ImageView 에 이미지 박는 코드 (firebase)
val imageView = rankRoutePriview
val storage = FirebaseStorage.getInstance("gs://tracer-9070d.appspot.com/")
val mapImageRef = storage.reference.child("mapImage").child(mapTitle)
mapImageRef.downloadUrl.addOnCompleteListener { task ->
if (task.isSuccessful) {
// Glide 이용하여 이미지뷰에 로딩
Log.d("ssmm11", "이미지 뷰 로드 성공 : "+mapImageRef.downloadUrl)
Glide.with(this#RankRecyclerItemClickActivity)
.load(task.result)
.override(1024, 980)
.into(imageView)
} else {
Log.d("ssmm11", "이미지 뷰 로드 실패")
}
}
mapRankingDownloadThread = Thread(Runnable {
val db = FirebaseFirestore.getInstance()
db.collection("rankingMap").document(mapTitle).collection("ranking").orderBy("challengerTime", Query.Direction.ASCENDING)
.get()
.addOnSuccessListener { result ->
for (document in result) {
rankingData = document.toObject(RankingData::class.java)
arrRankingData.add(rankingData)
}
//레이아웃 매니저 추가
rankRecyclerItemClickRecyclerView.layoutManager = LinearLayoutManager(this)
//adpater 추가
Log.d("ssmm11", "받아옴 ? = "+ arrRankingData)
rankRecyclerItemClickRecyclerView.adapter = RankRecyclerViewAdapterTopPlayer(arrRankingData)
}
.addOnFailureListener { exception ->
}
})
mapRankingDownloadThread.start()
rankRecyclerMoreButton.setOnClickListener{
val nextIntent = Intent(this, RankingMapDetailActivity::class.java)
nextIntent.putExtra("MapTitle", mapTitle)
startActivity(nextIntent)
}
}
}
I would like to create and store new users also update the existing users in the following code
What code needs to be added to strore new users in a SQLitedatabase
I have a sqllitehelper class
which has adduser,updateuser,and readuser methods
From what i understand ,the signinfragment activity stores the instance of the logged in user and
if the instance exists then its loaded.When we logout we basically have to make a new user and we login
i would like to create,store,update users using an SQLite database.
package com.google.samples.apps.topeka.fragment
import android.annotation.TargetApi
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.database.sqlite.SQLiteDatabase
import android.os.Build
import android.os.Bundle
import android.support.design.widget.FloatingActionButton
import android.support.v4.app.ActivityOptionsCompat
import android.support.v4.app.Fragment
import android.support.v4.util.Pair
import android.support.v4.view.ViewCompat
import android.support.v4.view.animation.FastOutSlowInInterpolator
import android.text.Editable
import android.text.TextWatcher
import android.transition.Transition
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.EditText
import android.widget.GridView
import android.widget.Toast
import android.widget.Toast.LENGTH_LONG
import com.google.samples.apps.topeka.activity.SignInActivity
import com.google.samples.apps.topeka.adapter.AvatarAdapter
import com.google.samples.apps.topeka.base.R
import com.google.samples.apps.topeka.helper.ActivityLaunchHelper
import com.google.samples.apps.topeka.helper.ApiLevelHelper
import com.google.samples.apps.topeka.helper.DefaultLogin
import com.google.samples.apps.topeka.helper.TAG
import com.google.samples.apps.topeka.helper.TransitionHelper
import com.google.samples.apps.topeka.helper.isLoggedIn
import com.google.samples.apps.topeka.helper.login
import com.google.samples.apps.topeka.helper.onLayoutChange
import com.google.samples.apps.topeka.helper.onSmartLockResult
import com.google.samples.apps.topeka.model.Avatar
import com.google.samples.apps.topeka.model.Player
import com.google.samples.apps.topeka.persistence.PPlayer
import com.google.samples.apps.topeka.widget.TextWatcherAdapter
import com.google.samples.apps.topeka.widget.TransitionListenerAdapter
import com.google.samples.apps.topeka.persistence.TopekaDatabaseHelper;
/**
* Enable selection of an [Avatar] and user name.
*/
class SignInFragment : Fragment() {
private var firstNameView: EditText? = null
private var lastInitialView: EditText? = null
private var doneFab: FloatingActionButton? = null
private var avatarGrid: GridView? = null
private var firstName = ""
private var lastInitial= ""
private var avatar = ""
private val edit by lazy { arguments?.getBoolean(ARG_EDIT, false) ?: false }
private var selectedAvatarView: View? = null
private var player: Player? = null
private var selectedAvatar: Avatar? = null
var a = getContext()
override fun onCreate(savedInstanceState: Bundle?) {
var a = context
val resources = context!!.resources
var ss = TopekaDatabaseHelper(requireActivity())
val newValues = ContentValues().apply {
// Sets the values of each column and inserts the value.
// The arguments to the "put"
// method are "column name" and "value"
}
if (savedInstanceState != null) {
val avatarIndex = savedInstanceState.getInt(KEY_SELECTED_AVATAR_INDEX)
if (avatarIndex != GridView.INVALID_POSITION) {
selectedAvatar = Avatar.values()[avatarIndex]
}
}
activity?.run {
if (isLoggedIn()) {
navigateToCategoryActivity()
Toast.makeText(requireContext(),"old", LENGTH_LONG)
} else {
maketext("new player")
login.loginPlayer(this, ::onSuccessfulLogin)
}
}
super.onCreate(savedInstanceState)
}
/**
* Called when logged in successfully.
*/
private fun onSuccessfulLogin(player: Player) {
if (login != DefaultLogin) return
this.player = player
if (edit) {
with(player) {
firstNameView?.setText(player.firstName)
lastInitialView?.run {
setText(player.lastInitial)
requestFocus()
setSelection(length())
var db = TopekaDatabaseHelper(context)
db.adduser(player.firstName,player.lastInitial)
maketext("saved new")
}
this#SignInFragment.player = player.also {
if (activity != null)
login.savePlayer(activity!!, this, { selectAvatar(it.avatar!!) })
maketext("saved new")
}
}
} else {
Toast.makeText(requireContext(),"new", LENGTH_LONG)
navigateToCategoryActivity()
}
}
private fun maketext(ss:String){
Toast.makeText(requireContext(),ss,LENGTH_LONG)
}
private fun navigateToCategoryActivity() {
activity?.run {
ActivityLaunchHelper.launchCategorySelection(this)
supportFinishAfterTransition()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
activity?.onSmartLockResult(
requestCode,
resultCode,
data,
success = {
player = it
initContents()
navigateToCategoryActivity()
},
failure = {
activity?.run {
login.loginPlayer(this, ::onSuccessfulLogin)
}
}
)
super.onActivityResult(requestCode, resultCode, data)
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val contentView = inflater.inflate(R.layout.fragment_sign_in, container, false)
contentView.onLayoutChange {
avatarGrid?.apply {
adapter = AvatarAdapter(activity!!)
onItemClickListener = AdapterView.OnItemClickListener { _, view, position, _ ->
selectedAvatarView = view
selectedAvatar = Avatar.values()[position]
// showing the floating action button if input data is valid
showFab()
}
numColumns = calculateSpanCount()
selectedAvatar?.run { selectAvatar(this) }
}
}
return contentView
}
/**
* Calculates spans for avatars dynamically.
* #return The recommended amount of columns.
*/
private fun calculateSpanCount(): Int {
val avatarSize = resources.getDimensionPixelSize(R.dimen.size_fab)
val avatarPadding = resources.getDimensionPixelSize(R.dimen.spacing_double)
return (avatarGrid?.width ?: 0) / (avatarSize + avatarPadding)
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putInt(KEY_SELECTED_AVATAR_INDEX, (avatarGrid?.checkedItemPosition ?: 0))
super.onSaveInstanceState(outState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
firstNameView = view.findViewById<EditText>(R.id.first_name)
lastInitialView = view.findViewById<EditText>(R.id.last_initial)
doneFab = view.findViewById<FloatingActionButton>(R.id.done)
avatarGrid = view.findViewById<GridView>(R.id.avatars)
if (edit || (player != null && player!!.valid())) {
initContentViews()
initContents()
}
hideEmptyView()
super.onViewCreated(view, savedInstanceState)
}
private fun hideEmptyView() {
view?.run {
findViewById<View>(R.id.empty).visibility = View.GONE
findViewById<View>(R.id.content).visibility = View.VISIBLE
}
}
private fun initContentViews() {
val textWatcher = object : TextWatcher by TextWatcherAdapter {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
// hiding the floating action button if text is empty
if (s.isEmpty()) {
doneFab?.hide()
}
}
// showing the floating action button if avatar is selected and input data is valid
override fun afterTextChanged(s: Editable) {
if (isAvatarSelected() && isInputDataValid()) doneFab?.show()
}
}
firstNameView?.addTextChangedListener(textWatcher)
lastInitialView?.addTextChangedListener(textWatcher)
doneFab?.setOnClickListener {
if (it.id == R.id.done) {
val first = firstNameView?.text?.toString()
val last = lastInitialView?.text?.toString()
activity?.run {
val toSave = player?.apply {
// either update the existing player object
firstName = first
lastInitial = last
avatar = selectedAvatar
} ?: Player(first, last, selectedAvatar) /* or create a new one */
login.savePlayer(this, toSave) {
Toast.makeText(this,"done",LENGTH_LONG)
Log.d(TAG, "Saving login info successful.")
}
}
}
removeDoneFab {
performSignInWithTransition(selectedAvatarView
?: avatarGrid?.getChildAt(selectedAvatar!!.ordinal))
}
}
}
private fun removeDoneFab(endAction: () -> Unit) {
ViewCompat.animate(doneFab)
.scaleX(0f)
.scaleY(0f)
.setInterpolator(FastOutSlowInInterpolator())
.withEndAction(endAction)
.start()
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private fun performSignInWithTransition(v: View? = null) {
if (v == null || ApiLevelHelper.isLowerThan(Build.VERSION_CODES.LOLLIPOP)) {
// Don't run a transition if the passed view is null
activity?.run {
navigateToCategoryActivity()
}
return
}
if (ApiLevelHelper.isAtLeast(Build.VERSION_CODES.LOLLIPOP)) {
activity?.run {
window.sharedElementExitTransition.addListener(object :
Transition.TransitionListener by TransitionListenerAdapter {
override fun onTransitionEnd(transition: Transition) {
finish()
}
})
val pairs = TransitionHelper.createSafeTransitionParticipants(this, true,
Pair(v, getString(R.string.transition_avatar)))
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(this, *pairs)
ActivityLaunchHelper.launchCategorySelection(this, options)
}
}
}
private fun initContents() {
player?.run {
valid().let {
firstNameView?.setText(firstName)
lastInitialView?.setText(lastInitial)
avatar?.run { selectAvatar(this) }
}
}
}
private fun isAvatarSelected() = selectedAvatarView != null || selectedAvatar != null
private fun selectAvatar(avatar: Avatar) {
selectedAvatar = avatar
avatarGrid?.run {
requestFocusFromTouch()
setItemChecked(avatar.ordinal, true)
}
showFab()
}
private fun showFab() {
if (isInputDataValid()) doneFab?.show()
}
private fun isInputDataValid() =
firstNameView?.text?.isNotEmpty() == true &&
lastInitialView?.text?.isNotEmpty() == true &&
selectedAvatar != null
companion object {
private const val ARG_EDIT = "EDIT"
private const val KEY_SELECTED_AVATAR_INDEX = "selectedAvatarIndex"
fun newInstance(edit: Boolean = false): SignInFragment {
return SignInFragment().apply {
arguments = Bundle().apply {
putBoolean(ARG_EDIT, edit)
}
}
}
}
}