How to display Telugu data retrieved from API into Spinner using kotlin? - android

I need to display the Telugu texts of Districts retrieved from API into Spinner, but random characters are displayed instead. How do I convert these characters to Telugu readable texts?
Sample Codes:
class MainActivity : AppCompatActivity() {
lateinit var spDistrict: Spinner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
districtData = mutableListOf()
spDistrict = findViewById<Spinner>(R.id.district)
getDistrictData()
val jsonObject = JSONObject()
jsonObject.put("profile_pic", userImage.toString().replace("/storage/emulated/0/Pictures/",""))
jsonObject.put("district_id", districtData!![spDistrict.selectedItemPosition].id)
jsonObject.put("token", token)
Log.e("jsonObject", jsonObject.toString())
val url = Constant.BASE_URL + "register/"
Log.e("url", "---->$url")
val request = object : StringRequest(
Method.POST, url, Response.Listener { response ->
try {
val responseObj = JSONObject(response)
if (response.isNotEmpty()) {
next.hideProgress("నమోదు")
val status = responseObj.getString("status")
if (status == "success" && lang=="telugu") {
val message = responseObj.getString("response")
val token = responseObj.getString("token")
val prefs = SharedPrefs(this#TReg3)
prefs.token = (token)
if (userImage.isNotEmpty()) {
fileUpload()
} else {
showSuccessDialog(message)
dialog.dismiss()
}
} else {
next.hideProgress("నమోదు")
val message = responseObj.getString("response")
showCustomAlertDialog(message)
dialog.dismiss()
}
} else {
next.hideProgress("నమోదు")
showCustomAlertDialog("Something went wrong")
dialog.dismiss()
}
} catch (ex: Exception) {
next.hideProgress("నమోదు")
showCustomAlertDialog("Something went wrong")
dialog.dismiss()
}
},
Response.ErrorListener { error ->
next.hideProgress("ప్రవేశించండి")
val errorMessage = VolleyErrorParser.getVolleyErrorMessage(error)
showCustomAlertDialog(errorMessage)
dialog.dismiss()
}) {
override fun getHeaders(): MutableMap<String, String> {
val params = java.util.HashMap<String, String>()
params["Content-Type"] = "application/json"
return params
}
override fun getBody(): ByteArray {
return jsonObject.toString().toByteArray()
}
}
MySingleton.getInstance(this).addToRequestQueue(request)
}
}
private fun getDistrictData() {
val url = Constant.BASE_URL + "getDistricts/"
Log.e("districteUrl", url)
val request = StringRequest(Request.Method.GET, url, { response ->
try {
if (!response.isNullOrEmpty()) {
val jsonObject = JSONObject(response)
val status = jsonObject.getString("status")
if (status == "success") {
val data = jsonObject.getJSONArray("districts")
districtData = listOf(
*Gson().fromJson(
data.toString(),
Array<DistrictData>::class.java
)
)
if (districtData!!.isNotEmpty()) {
val categoryDataAdapter = ArrayAdapter<DistrictData>(
this,
android.R.layout.simple_list_item_1,
districtData!!)
categoryDataAdapter.setDropDownViewResource(android.R.layout.simple_list_item_1)
spDistrict.adapter = categoryDataAdapter
// getMandalData()
} else {
dialog.dismiss()
val response = jsonObject.getString("response")
Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
}
} else {
dialog.dismiss()
val response = jsonObject.getString("response")
Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
}
} else {
dialog.dismiss()
Toast.makeText(this, "Something Went Wrong", Toast.LENGTH_SHORT).show()
}
} catch (ex: Exception) {
Toast.makeText(this, "Something Went Wrong", Toast.LENGTH_SHORT).show()
dialog.dismiss()
ex.printStackTrace()
}
}, { error ->
dialog.dismiss()
val errorMessage = VolleyErrorParser.getVolleyErrorMessage(error)
Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT).show()
})
VolleySingleton.getInstance(this!!).addToRequestQueue(request)
}
}
How do I make my app automatically detetct the Telugu text? Do I have to use a flag value?

Related

How to disable / Remove reCaptcha in firebase phone-auth (OTP) android?

I had Enabled the Google Android Device Verification API.
I had added the SHA-256 onto Firebase setting and updated the GSON file.
and After adding :
Firebase.auth.firebaseAuthSettings.setAppVerificationDisabledForTesting(true)
I am getting error that SafetyNet or Captcha are not succeded (kind of error).
Can anyone tell me how can i disable the captcha check ?
Here is my code
class OTPNewActivity : AppCompatActivity(), OnKeyboardVisibilityListener, View.OnClickListener {
var TAG = "OTPNewActivity"
lateinit var binding: ActivityOtpnewBinding
val action = "android.provider.Telephony.SMS_RECEIVED"
var userEnteredCode = ""
var systemGeneratedCode = ""
var phoneNumer = ""
var phoneDigits = ""
private lateinit var auth: FirebaseAuth
private lateinit var resendToken: PhoneAuthProvider.ForceResendingToken
private var callbacks: PhoneAuthProvider.OnVerificationStateChangedCallbacks =
object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
Log.d(TAG, "onVerificationCompleted: $credential")
val code = credential.smsCode
if (code != null) {
binding.otpView.setText(code)
verifyPhoneNumberWithCode(systemGeneratedCode, code!!)
}
}
override fun onVerificationFailed(e: FirebaseException) {
Log.d(TAG, "onVerificationFailed $e")
if (e is FirebaseAuthInvalidCredentialsException) {
Constants.showToast(
this#OTPNewActivity,
Constants.TOAST_TYPE_FAIL,
"Invalid request"
)
} else if (e is FirebaseTooManyRequestsException) {
Constants.showToast(
this#OTPNewActivity,
Constants.TOAST_TYPE_FAIL,
"The SMS quota for the project has been exceeded $e"
)
} else {
Constants.showToast(
this#OTPNewActivity,
Constants.TOAST_TYPE_FAIL, "Something wents wrong"
)
}
}
override fun onCodeSent(
verificationId: String,
token: PhoneAuthProvider.ForceResendingToken
) {
// The SMS verification code has been sent to the provided phone number, we
// now need to ask the user to enter the code and then construct a credential
// by combining the code with a verification ID.
Log.d(TAG, "onCodeSent: $verificationId")
systemGeneratedCode = verificationId
resendToken = token
countdownTimer()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_otpnew)
initListeners()
}
private fun initListeners() {
LocalSharedPreference.getInstance(this).isPhoneNumberVerified = false
// Firebase.auth.firebaseAuthSettings.setAppVerificationDisabledForTesting(true)
auth = Firebase.auth
setKeyboardVisibilityListener(this)
binding.btnNext.setOnClickListener(this)
binding.tvCount.setOnClickListener(this)
binding.icBack.setOnClickListener(this)
val intent = intent
intent?.let {
phoneNumer = intent.getStringExtra(Constants.PHONE_NUMBER).toString()
phoneDigits = intent.getStringExtra(Constants.SAVE_PHONE_DIGITS).toString()
binding.textView.text =
"${this.resources.getString(R.string.digit_code)} $phoneNumer"
val options = PhoneAuthOptions.newBuilder(auth)
.setPhoneNumber(phoneNumer)
.setTimeout(15L, TimeUnit.SECONDS)
.setActivity(this)
.setCallbacks(callbacks)
.build()
PhoneAuthProvider.verifyPhoneNumber(options)
}
binding.otpView.setOtpCompletionListener(OnOtpCompletionListener { otp -> // do Stuff
userEnteredCode = otp
binding.icNext.visibility = View.VISIBLE
binding.pbNext.visibility = View.GONE
verifyPhoneNumberWithCode(systemGeneratedCode, userEnteredCode)
})
}
private fun verifyPhoneNumberWithCode(verificationId: String?, code: String) {
try {
val credential = PhoneAuthProvider.getCredential(verificationId!!, code)
signInWithPhoneAuthCredential(credential);
} catch (e: Exception) {
binding.otpView.setText("")
Constants.showToast(
this#OTPNewActivity,
Constants.TOAST_TYPE_FAIL,
this#OTPNewActivity.resources.getString(R.string.wrong_Code)
)
e.printStackTrace()
}
}
private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
auth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success")
LocalSharedPreference.getInstance(this).isPhoneNumberVerified = true
if (phoneNumer.contains("+52")) {
LocalSharedPreference.getInstance(this).setSaveCountry("MX")
} else if (phoneNumer.contains("+92")) {
LocalSharedPreference.getInstance(this).setSaveCountry("PK")
} else if (phoneNumer.contains("+1")) {
LocalSharedPreference.getInstance(this).setSaveCountry("US")
}
LocalSharedPreference.getInstance(this).savePhoneNumber(phoneNumer)
LocalSharedPreference.getInstance(this).setPhoneDigits(phoneDigits)
val user = task.result?.user
val intent = Intent(this#OTPNewActivity, ProfileActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
finish()
} else {
// Sign in failed, display a message and update the UI
Log.w(TAG, "signInWithCredential:failure", task.exception)
if (task.exception is FirebaseAuthInvalidCredentialsException) {
Constants.showToast(
this#OTPNewActivity,
Constants.TOAST_TYPE_FAIL,
"${task.exception}"
)
}
// Update UI
}
}
}
private fun setKeyboardVisibilityListener(onKeyboardVisibilityListener: OnKeyboardVisibilityListener) {
val parentView: View = (findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0)
parentView.getViewTreeObserver()
.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
private var alreadyOpen = false
private val defaultKeyboardHeightDP = 100
private val EstimatedKeyboardDP =
defaultKeyboardHeightDP + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 48 else 0
private val rect: Rect = Rect()
override fun onGlobalLayout() {
val estimatedKeyboardHeight = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
EstimatedKeyboardDP.toFloat(),
parentView.getResources().getDisplayMetrics()
)
.toInt()
parentView.getWindowVisibleDisplayFrame(rect)
val heightDiff: Int =
parentView.getRootView().getHeight() - (rect.bottom - rect.top)
val isShown = heightDiff >= estimatedKeyboardHeight
if (isShown == alreadyOpen) {
Log.d("Keyboard state", "Ignoring global layout change...")
return
}
alreadyOpen = isShown
onKeyboardVisibilityListener.onVisibilityChanged(isShown)
}
})
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Checks whether a hardware keyboard is available
if (newConfig.hardKeyboardHidden === Configuration.HARDKEYBOARDHIDDEN_NO) {
Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show()
} else if (newConfig.hardKeyboardHidden === Configuration.HARDKEYBOARDHIDDEN_YES) {
Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show()
}
}
override fun onVisibilityChanged(visible: Boolean) {
if (!visible) {
val imm: InputMethodManager =
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.otpView, InputMethodManager.SHOW_IMPLICIT)
}
}
override fun onResume() {
super.onResume()
binding.otpView.requestFocus()
val imm: InputMethodManager =
getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.otpView, InputMethodManager.SHOW_IMPLICIT)
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
registerReceiver(receiver, IntentFilter(action))
}
private fun countdownTimer() {
binding.pbNext.visibility = View.VISIBLE
binding.icNext.visibility = View.GONE
object : CountDownTimer(15000, 1000) {
override fun onTick(millisUntilFinished: Long) {
binding.tvCount.setText("Resend Code in : " + millisUntilFinished / 1000)
}
override fun onFinish() {
binding.tvCount.setText("I didn`t receive a code")
binding.icNext.visibility = View.VISIBLE
binding.pbNext.visibility = View.GONE
}
}.start()
}
override fun onClick(view: View) {
when (view.id) {
R.id.btn_next -> {
if (binding.otpView.text.toString().length == 6) {
LocalSharedPreference.getInstance(this#OTPNewActivity).isPhoneNumberVerified =
true
verifyPhoneNumberWithCode(systemGeneratedCode, userEnteredCode)
}
}
R.id.tv_count -> {
if (binding.tvCount.text.equals(this#OTPNewActivity.resources.getString(R.string.i_dont_received_code)))
resendVerificationCode(phoneNumer, resendToken)
}
R.id.ic_back -> {
finish()
}
}
}
private fun resendVerificationCode(
phoneNumber: String,
token: PhoneAuthProvider.ForceResendingToken?
) {
val optionsBuilder = PhoneAuthOptions.newBuilder(auth)
.setPhoneNumber(phoneNumber) // Phone number to verify
.setTimeout(15L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(this) // Activity (for callback binding)
.setCallbacks(callbacks) // OnVerificationStateChangedCallbacks
if (token != null) {
optionsBuilder.setForceResendingToken(token) // callback's ForceResendingToken
}
PhoneAuthProvider.verifyPhoneNumber(optionsBuilder.build())
}
var receiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
if (intent.action == "android.provider.Telephony.SMS_RECEIVED") {
val bundle = intent.extras
var msgs: Array<SmsMessage?>? = null
var msg_from: String? = ""
Log.d(TAG, "onReceive called ")
if (bundle != null) {
try {
val pdus = bundle["pdus"] as Array<Any>?
msgs = arrayOfNulls(pdus!!.size)
for (i in msgs.indices) {
msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray)
msg_from = msgs[i]!!.getOriginatingAddress()
val msgBody: String = msgs[i]!!.getMessageBody()
if (msgBody.contains("is your verification code for running-errands.firebaseapp.com")) {
val _1: Char = msgBody[0]
val _2: Char = msgBody[1]
val _3: Char = msgBody[2]
val _4: Char = msgBody[3]
val _5: Char = msgBody[4]
val _6: Char = msgBody[5]
val code: String =
_1.toString() + _2.toString() + _3.toString() + _4.toString() + _5.toString() + _6.toString()
// binding.otpView.text = SpannableStringBuilder(code!!)
binding.otpView.setText(code)
verifyPhoneNumberWithCode(systemGeneratedCode, code!!)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver);
}
}

user login is not working using retrofit and viewmodel

my login is not working ..im using retrofit and viewmodel ...actually scenerio is onclick of login shows the transition(loginpage to loginpage) but it is not moving to loginpage to homepage....
this method model.ResponseData.observeis not getting call
i dont know where im going wrong
need help thanks
Loginactivity:--
class LoginActivity : AppCompatActivity() {
lateinit var model: LoginViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.login_activity)
val button = findViewById<ImageView>(R.id.plusbutton)
val forgotpassword=findViewById<TextView>(R.id.forgotpassword)
button.setOnClickListener {
val i = Intent(applicationContext, RegisterActivity::class.java)
startActivity(i)
}
forgotpassword.setOnClickListener{
val i = Intent(applicationContext, ForgotPassword::class.java)
startActivity(i)
}
model = ViewModelProvider(this)[LoginViewModel::class.java]
model.ResponseData.observe(this, object : Observer<LoginResponse?> {
override fun onChanged(t: LoginResponse?) {
val intent = Intent(applicationContext, HomeActivity::class.java)
intent.flags =
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
})
loginbtn.setOnClickListener {
val email = loginuser.text.toString().trim()
val password = loginpassword.text.toString().trim()
if (email.isEmpty()) {
Toast.makeText(
applicationContext, "Data is missing", Toast.LENGTH_LONG
).show()
loginuser.error = "Email required"
loginuser.requestFocus()
return#setOnClickListener
} else if (password.isEmpty()) {
loginpassword.error = "Password required"
loginpassword.requestFocus()
return#setOnClickListener
}
else {
model.loadAccountData(email,password)
}
}
}}
viewmodel:--
class LoginViewModel(context: Application,private val savedStateHandle: SavedStateHandle) : AndroidViewModel(context) {
private var _aResponseData = MutableLiveData<LoginResponse?>()
val user: MutableLiveData<String> = savedStateHandle.getLiveData("user", "")
val password: MutableLiveData<String> = savedStateHandle.getLiveData("password", "")
val ResponseData: MutableLiveData<LoginResponse?>
get() {
if (_aResponseData == null) {
_aResponseData = MutableLiveData<LoginResponse?>()
loadAccountData(user.toString(), password.toString())
}
return _aResponseData
}
fun loadAccountData(email:String, password:String) {
RetrofitClient.instance.userLogin(email, password)
.enqueue(object : Callback<LoginResponse> {
override fun onFailure(call: Call<LoginResponse>, t: Throwable) {
Log.d("res", "" + t)
_aResponseData.value = null
}
override fun onResponse(
call: Call<LoginResponse>,
response: Response<LoginResponse>
) {
var res = response
if (res.body()?.status == 200) {
_aResponseData.value = response.body()
} else {
try {
val jObjError =
JSONObject(response.errorBody()!!.string())
Toast.makeText(
getApplication(),
jObjError.getString("user_msg"),
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Log.e("errorrr", e.message)
}
}
}
})
}
}
After discussion and debugging, looks like issue was not on observer but actually during parsing of response from API call via retrofit.
_aResponseData.value = response.body()
Here response.body() was not able to parse response as LoginResponse class object which was eventually causing issue further more on navigation.
Fixing issue on parsing helps O.P. through debugging on main concern.
Try this
if (res.body()?.status == 200) {
_aResponseData.postValue(response.body())
}

Handle Edittext in AlertDialog in android

i have a edittext in Alert Dialog.....my operation is performing well if ediitext is not empty.....i want to set focus when ediitext is empty in alertdialog ..
need help thanks in advance
i tried the following code please have a look:---
buynow.setOnClickListener {
val mBuild: AlertDialog.Builder = AlertDialog.Builder(this#Product_details)
val mView: View = layoutInflater.inflate(R.layout.buynowdialog, null)
val titleimage=mView.findViewById<TextView>(R.id.titleimage2) as TextView
val imagerate=mView.findViewById<ImageView>(R.id.imagebuy) as ImageView
titleimage.setText(ygd)
Glide.with(getApplicationContext()).load(res?.body()!!.data.product_images.get(0).image).into(imagerate);
val buynumber = mView.findViewById<EditText>(R.id.editbuy)
val btnSubmit =
mView.findViewById(R.id.btnbuynow) as Button
Log.e("checkid",id.toString())
mBuild.setView(mView)
val dialog: AlertDialog = mBuild.create()
btnSubmit.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
val value: String = buynumber.getText().toString()
val finalValue = value.toInt()
if (value.isEmpty()) {
Toast.makeText(
applicationContext, "Data is missing",Toast.LENGTH_LONG
).show()
editbuy.error = "Email required"
editbuy.requestFocus()
}
val token: String =
SharedPrefManager.getInstance(
applicationContext
).user.access_token.toString()
RetrofitClient.instancecart.buynow(token,id,finalValue)
.enqueue(object : Callback<ResponseBaseCartAdd> {
override fun onFailure(call: Call<ResponseBaseCartAdd>, t: Throwable) {
Log.d("res", "" + t)
}
override fun onResponse(
call: Call<ResponseBaseCartAdd>,
response: Response<ResponseBaseCartAdd>
) {
Log.e("hi",id)
var res = response
Log.e("checkres",res.toString())
Log.d("response check ", "" + response.body()?.status.toString())
if (res.isSuccessful) {
Toast.makeText(
applicationContext,
res.body()?.user_msg,
Toast.LENGTH_LONG
).show()
dialog.dismiss()
Log.d("kjsfgxhufb",response.body()?.user_msg.toString())
}
else{
try {
val jObjError =
JSONObject(response.errorBody()!!.string())
Toast.makeText(
applicationContext,
jObjError.getString("message")+jObjError.getString("user_msg"),
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show()
Log.e("errorrr",e.message)
}
}
}
})
}
})
dialog.show()
}
above code is crashing with an error in logcat:-- java.lang.NumberFormatException: For input string: ""
need help thanks :)
NumberFormatException is an Exception that might be thrown when you
try to convert a String into a number, where that number might be an
int , a float , or any other Java numeric type.
val finalValue = value.toInt() // value is empty. That's why problem
Your finalValue is Empty or null. You must check it.
isNotEmpty() is used to find if the String is not empty/String is
length 0 and not null.
DEMO
if (value.isNotEmpty()) {
val finalValue = value.toInt()
val token: String =SharedPrefManager.getInstance(applicationContext).user.access_token.toString()
RetrofitClient.instancecart.buynow(token,id,finalValue)
.....your task.....
}
else
{
Toast.makeText(applicationContext, "Data is missing",Toast.LENGTH_LONG).show()
editbuy.error = "Email required"
editbuy.requestFocus()
}

Upload and show data Firestore kotlin

I have a problem whit my code, but I get no errors. The problem arise when I try change my variables ”artistName” and ”trackName” to my object ”SoundTrack”. If I use my variables ”artistName” and ”trackName” it works fine, I can upload, delete and display data etc. But when I try o use my object nothing is happend, It’s like it doesn’t connect to my database.
My class:
class SoundTrack (val name : String, val track : String)
Here is my MainActivity:
class MainActivity : AppCompatActivity(), View.OnClickListener {
val collection = "song"
//val artistName = "name"
//val trackName = "track"
var docId =""
lateinit var newTrack : SoundTrack
lateinit var db : FirebaseFirestore
lateinit var alSongs : ArrayList<HashMap<String,Any>>
lateinit var adapter: SimpleAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
alSongs = ArrayList()
addData.setOnClickListener(this)
updateInfo.setOnClickListener(this)
deleteInfo.setOnClickListener(this)
IsData.setOnItemClickListener(itemClick)
}
override fun onStart() {
super.onStart()
db = FirebaseFirestore.getInstance()
db.collection(collection).addSnapshotListener { querySnapshot, e ->
if(e != null) Log.d("fireStore", e.message)
showData()
}
}
//add new data by input
override fun onClick(v: View?) {
when(v?.id){
R.id.addData ->{
println("hej")
if(::newTrack.isInitialized){
val hm = HashMap<String, Any>()
hm.set(newTrack.name,artistNametxt.text.toString())
hm.set(newTrack.track,trackNametxt.text.toString())
db.collection(collection).document(artistNametxt.text.toString()).set(hm).
addOnSuccessListener {
Toast.makeText(this, "Data Successfully added", Toast.LENGTH_SHORT)
.show()
}.addOnFailureListener { e ->
Toast.makeText(this, "Data unSuccessfully added : ${e.message}", Toast.LENGTH_SHORT)
.show()
}
}
}
//Update input
R.id.updateInfo -> {
if(::newTrack.isInitialized){
val hm = HashMap<String, Any>()
hm.set(newTrack.name,artistNametxt.text.toString())
hm.set(newTrack.track,trackNametxt.text.toString())
db.collection(collection).document(docId).update(hm)
.addOnSuccessListener { Toast.makeText(this, "Data Successfully updated", Toast.LENGTH_SHORT)
.show() }
.addOnFailureListener { e ->
Toast.makeText(this, "Data unSuccessfully updated : ${e.message}", Toast.LENGTH_SHORT)
.show()
}
}
}
//delete Input
R.id.deleteInfo -> {
if(::newTrack.isInitialized){
db.collection(collection).whereEqualTo(newTrack.name,docId).get().addOnSuccessListener {
results ->
for(doc in results){
db.collection(collection).document(doc.id).delete()
.addOnSuccessListener {
Toast.makeText(this, "Data Successfully updated", Toast.LENGTH_SHORT)
.show()
}.addOnFailureListener { e ->
Toast.makeText(this, "Data unSuccessfully updated : ${e.message}", Toast.LENGTH_SHORT)
.show()
}
}
}.addOnFailureListener { e ->
Toast.makeText(this, "Cant get data reference: ${e.message}", Toast.LENGTH_SHORT)
.show()
}
}
}
}
}
val itemClick = AdapterView.OnItemClickListener { parent, view, position, id ->
val hm = alSongs.get(position)
docId = hm.get(newTrack.name).toString()
artistNametxt.setText(hm.get(newTrack.name).toString())
trackNametxt.setText(hm.get(newTrack.name).toString())
}
//Show input data
fun showData(){
if(::newTrack.isInitialized){
db.collection(collection).get().addOnSuccessListener { result ->
alSongs.clear()
for(doc in result){
val hm = HashMap<String,Any>()
hm.set(newTrack.name,doc.get(newTrack.name).toString())
hm.set(newTrack.track,doc.get(newTrack.track).toString())
alSongs.add(hm)
}
}
adapter = SimpleAdapter(this,alSongs,R.layout.row_data,
arrayOf(newTrack.name,newTrack.track),
intArrayOf(R.id.txName, R.id.TxTrack))
IsData.adapter = adapter
}
}
}
Try this
fun getSongs(): LiveData<MutableList<SongTrack>> {
firestoreInstance.collection(SONG_COLLECTION)
.addSnapshotListener { querySnapshot,
firebaseFirestoreException ->
song.clear()
querySnapshot?.documents?.forEach {document ->
val songTrack = document.toObject(SongTrack::class.java)
songTrack?.let {
song.add(it)
}
}
}
songList.postValue(song)
return songList
}
First i would change
class SoundTrack (val name : String, val track : String)
to
data class SoundTrack(val name : String ="",val track : String ="")
and delete
lateinit var newTrack : SoundTrack
so you don't need to do this anymore
if(::newTrack.isInitialized)
delete
lateinit var db : FirebaseFirestore
and create Object class
object FirestoreUtil {
private val firestoreInstance: FirebaseFirestore by lazy {
FirebaseFirestore.getInstance()
}
}
or better yet
class MainActivity : AppCompatActivity() {
lateinit var adapter: SimpleAdapter
val itemClick = AdapterView.OnItemClickListener { parent, view, position, id ->
val selectedSong = FirestoreUtils.songList.value?.get(position)
selectedSong?.let {
artistNametxt.setText(it.name.toString())
trackNametxt.setText(it.track.toString())
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
FirestoreUtils.getSongs().observe(this, Observer { songList ->
adapter = SimpleAdapter(
this, songList, R.layout.row_data,
arrayOf(SongTrack().name, SongTrack().track),
intArrayOf(R.id.txName, R.id.TxTrack)
)
IsData.adapter = adapter
})
addData.setOnClickListener {
FirestoreUtils.addSong(
SongTrack(
artistNametxt.text.toString(),
trackNametxt.text.toString()
)
) { message -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show() }
}
updateInfo.setOnClickListener {
FirestoreUtils.updateSong(
SongTrack(
artistNametxt.text.toString(),
trackNametxt.text.toString()
)
) { message ->
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
}
deleteInfo.setOnClickListener(FirestoreUtils.deleteSong(artistNametxt.text.toString()) { message ->
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
})
IsData.setOnItemClickListener {
itemClick
}
}
}
const val SONG_COLLECTION = "song"
data class SongTrack(val name: String = "", val track: String = "")
object FirestoreUtils {
private val firestoreInstance: FirebaseFirestore by lazy {
FirebaseFirestore.getInstance()
}
private val songCollection = firestoreInstance.collection(SONG_COLLECTION)
private val song = mutableListOf<SongTrack>()
val songList: MutableLiveData<MutableList<SongTrack>> = MutableLiveData()
fun getSongs(): LiveData<MutableList<SongTrack>> {
firestoreInstance.collection(SONG_COLLECTION)
.addSnapshotListener { querySnapshot,
firebaseFirestoreException ->
song.clear()
querySnapshot?.documents?.forEach {
it.toObject<SongTrack>()?.let { songTrack ->
song.add(songTrack)
}
}
}
songList.postValue(song)
return songList
}
fun addSong(songTrack: SongTrack, onComplete: (String) -> Unit) {
songCollection.document(songTrack.name)
.set(songTrack)
.addOnSuccessListener { onComplete("Data Successfully added") }
.addOnFailureListener { onComplete("Data unSuccessfully added : ${it.message}") }
}
fun updateSong(songTrack: SongTrack, onComplete: (String) -> Unit) {
songCollection.document(songTrack.name)
.set(songTrack)
.addOnSuccessListener { onComplete("Data Successfully updated") }
.addOnFailureListener { onComplete("Data unSuccessfully updated : ${it.message}") }
}
fun deleteSong(songTrack: SongTrack, onComplete: (String) -> Unit) {
val deleteSong = songTrack.name
songCollection.document(songTrack.name).delete()
.addOnSuccessListener { onComplete("Song $deleteSong deleted") }
.addOnFailureListener { onComplete("Not found the song id : ${songTrack.name}") }
}
}
I just edit from your code, Did not test yet!!!
Enjoy.

Kotlin class is returning false before it has finished

In my main activity i have a function that runs once the login button it pressed. I'm calling a class that attempts to login via an API which takes a second or two to run. However, when i'm calling the login class it seems to be threaded and doesn't wait for the login to complete and returns false which is the default. Example code is as follows:
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun loginBtnClicked(view: View) {
progressBar.visibility = View.VISIBLE
// get domain info
val domain: TextView = findViewById<TextView>(R.id.loginDomain)
val domainUrl = domain.text.toString()
val url = "$domainUrl/api/"
// get username info
val username = loginUsername
// get password info
val password = loginPassword
if (ApiGet(
url = url,
username = username.text.toString(),
password = password.text.toString()
).login()) {
println("It worked")
val dashboard = Intent(this, DashboardActivity::class.java)
Consts.DOMAIN = url
Consts.USERNAME = username.text.toString()
Consts.PASSWORD = password.text.toString()
startActivity(dashboard)
} else {
println("It didn't work")
progressBar.visibility = View.INVISIBLE
runOnUiThread {
Log.i(ContentValues.TAG, "runOnUiThread")
Toast.makeText(
applicationContext,
"Please check the domain, username and password then try again.",
Toast.LENGTH_SHORT
).show()
}
}
}
}
class ApiGet(val url: String, val username: String = Consts.USERNAME, val password: String = Consts.PASSWORD) {
fun login(): Boolean {
var loginAttempt: Boolean = false
var apiData: ApiLogin
val creds = Credentials.basic(username, password)
val request = Request.Builder().url(url).header("Authorization", creds).build()
val client = OkHttpClient()
client.newCall(request).enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
val body: String? = response.body()?.string()
val gson: Gson = GsonBuilder().create()
apiData = gson.fromJson(body, ApiLogin::class.java)
if (apiData.detail == "Invalid username/password.") {
loginAttempt = false
println(loginAttempt)
} else {
loginAttempt = true
println(loginAttempt)
}
}
override fun onFailure(call: Call, e: IOException) {
Toast.makeText(
MainActivity().getApplicationContext(),
"Please check your connection and try again.",
Toast.LENGTH_SHORT
).show()
loginAttempt = false
}
})
return loginAttempt
}
class ApiLogin(val detail: String)
}
It is because your newCall method runs async to the main thread meaning the rest of your code keeps running after you call it while it waits on another thread. To fix this rather than returning your result you can handle it in a callback like so:
class ApiGet(val url: String, val username: String = Consts.USERNAME, val password: String = Consts.PASSWORD) {
fun login(completion: (Boolean)->Unit) {
var loginAttempt: Boolean = false
var apiData: ApiLogin
val creds = Credentials.basic(username, password)
val request = Request.Builder().url(url).header("Authorization", creds).build()
val client = OkHttpClient()
client.newCall(request).enqueue(
object : Callback {
override fun onResponse(call: Call, response: Response) {
val body: String? = response.body()?.string()
val gson: Gson = GsonBuilder().create()
apiData = gson.fromJson(body, ApiLogin::class.java)
if (apiData.detail == "Invalid username/password.") {
println(loginAttempt)
completion(False)
} else {
print(loginAttempt)
completion(True)
}
}
override fun onFailure(call: Call, e: IOException) {
Toast.makeText(
MainActivity().getApplicationContext(),
"Please check your connection and try again.",
Toast.LENGTH_SHORT
).show()
completion(False) }
})
}
You can call the login function like so:
ApiGet(url = url,
username = username.text.toString(),
password = password.text.toString()).login { result ->
if (result) {
// success
} else {
// failure
}
}

Categories

Resources