realtime database child won't showing because permission denied - kotlin

i want to create child name 'Posts' in addpostactivity by adding data to the firebase. my application running well, it also shows " uploaded successfully ". it just that in my database there's nothing added with the data i already input from my app. i upload image while create the data it's successfully stored in storage firebase, but in realtime database, there's still nothing showing the added data even the 'Posts' child it self
my logchat shows this line.
2023-02-08 12:07:36.353 16589-16674/com.isjieman.ocion W/RepoOperation: updateChildren at /Posts/-NNjQ5njDqkVSZYUIZ-V failed: DatabaseError: Permission denied
2023-02-08 12:07:41.351 16589-16653/com.isjieman.ocion V/FA: Inactivity, disconnecting from the service
here's my database security rules
{
"rules": {
"User" : {
"$uid" : {
".read" : "$uid === auth.uid",
".write" : "$uid === auth.uid",
}
}
}
}
and here's the database structure.
{
"User": {
"6FzpJ2sQC9gewbUIGHB8hiNWK1z2": {
"background_image": "https://firebasestorage.googleapis.com/v0/b/final-project-idn.appspot.com/o/Default%20Images%2Fimg_background.png?alt=media&token=b51e7cf5-2015-4cc4-9583-159373d081e2",
"bio": "Member of NCT",
"email": "mark#gmail.com",
"link": "",
"profile_image": "https://firebasestorage.googleapis.com/v0/b/final-project-idn.appspot.com/o/Profile%20Pictures%2F6FzpJ2sQC9gewbUIGHB8hiNWK1z2.jpg?alt=media&token=17d71d89-353d-44fa-8f06-e33716de0611",
"uid": "6FzpJ2sQC9gewbUIGHB8hiNWK1z2",
"userName": "marklee"
}
}
}
i think it's because of my database security. but i don't really know about how should i change the rules safely.
here's my AddPostActivity.kt
class AddPostActivity : AppCompatActivity(), View.OnClickListener {
private lateinit var firebaseUser: FirebaseUser
private lateinit var addPostBinding: ActivityAddPostBinding
private var checker = ""
private var myUrl = ""
private var imageUri: Uri? = null
private var storagePostImageRef: StorageReference? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
addPostBinding = ActivityAddPostBinding.inflate(layoutInflater)
setContentView(addPostBinding.root)
supportActionBar?.hide()
//Dropdown item adapter
val itemCategory = listOf("Art", "Writing", "Application", "Design")
val adapterCategory = ArrayAdapter(this, R.layout.item_dropdown, itemCategory)
addPostBinding.acChooseCategory.setAdapter(adapterCategory)
val itemPriceRange = listOf("Rp 0 - 10.000", "Rp 10.000 - 50.000", "Rp 50.000 - 100.000")
val adapterPriceRange = ArrayAdapter(this, R.layout.item_dropdown, itemPriceRange)
addPostBinding.acPriceRange.setAdapter(adapterPriceRange)
firebaseUser = FirebaseAuth.getInstance().currentUser!!
storagePostImageRef = FirebaseStorage.getInstance().reference.child("Posts Pictures")
addPostBinding.btnAddImage.setOnClickListener(this)
addPostBinding.btnSavePost.setOnClickListener(this)
}
override fun onClick(v: View) {
when(v.id){
R.id.btnAddImage -> addImagePost()
R.id.btnSavePost -> savePost()
}
}
private fun savePost() {
if (checker == "clicked")
{
uploadPostWithImage()
}
else
{
uploadPost()
}
}
private fun uploadPost() {
when{
TextUtils.isEmpty(addPostBinding.etTitlePost.text.toString()) -> Toast.makeText(this, "Please add Title Post.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etDescPost.text.toString()) -> Toast.makeText(this, "Please add Description.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.acChooseCategory.text.toString()) -> Toast.makeText(this, "Please Choose Category.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.acPriceRange.text.toString()) -> Toast.makeText(this, "Please Choose Price Range.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etDurationPost.text.toString()) -> Toast.makeText(this, "Please add Duration Time.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etPaymentMethods.text.toString()) -> Toast.makeText(this, "Please add Payment Methods.", Toast.LENGTH_LONG).show()
else -> {
val ref = FirebaseDatabase.getInstance().reference.child("Posts")
val postId = ref.push().key
val postMap = HashMap<String, Any>()
postMap["postId"] = postId!!
postMap["title"] = addPostBinding.etTitlePost.text.toString()
postMap["description"] = addPostBinding.etDescPost.text.toString()
postMap["category"] = addPostBinding.acChooseCategory.text.toString()
postMap["priceRange"] = addPostBinding.acPriceRange.text.toString()
postMap["duration"] = addPostBinding.etDurationPost.text.toString()
postMap["paymentMethods"] = addPostBinding.etPaymentMethods.text.toString()
postMap["publisher"] = FirebaseAuth.getInstance().currentUser!!.uid
ref.child(postId).updateChildren(postMap)
Toast.makeText(this, "Post Uploaded successfully.", Toast.LENGTH_LONG).show()
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
}
}
private fun uploadPostWithImage() {
when{
imageUri == null -> Toast.makeText(this, "Please select image first.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etTitlePost.text.toString()) -> Toast.makeText(this, "Please add Title Post.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etDescPost.text.toString()) -> Toast.makeText(this, "Please add Description.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.acChooseCategory.text.toString()) -> Toast.makeText(this, "Please Choose Category.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.acPriceRange.text.toString()) -> Toast.makeText(this, "Please Choose Price Range.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etDurationPost.text.toString()) -> Toast.makeText(this, "Please add Duration Time.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(addPostBinding.etPaymentMethods.text.toString()) -> Toast.makeText(this, "Please add Payment Methods.", Toast.LENGTH_LONG).show()
else -> {
val progressDialog = ProgressDialog(this)
progressDialog.setTitle("Adding New Post")
progressDialog.setMessage("Please wait, we are Uploading your Post...")
progressDialog.show()
val fileRef = storagePostImageRef!!.child(System.currentTimeMillis().toString() + ".jpg")
val uploadTask: StorageTask<*>
uploadTask = fileRef.putFile(imageUri!!)
uploadTask.continueWithTask(Continuation <UploadTask.TaskSnapshot, Task<Uri>>{ task ->
if (!task.isSuccessful)
{
task.exception?.let {
throw it
progressDialog.dismiss()
}
}
return#Continuation fileRef.downloadUrl
}).addOnCompleteListener (OnCompleteListener<Uri> { task ->
if (task.isSuccessful)
{
val downloadUrl = task.result
myUrl = downloadUrl.toString()
val ref = FirebaseDatabase.getInstance().reference.child("Posts")
val postId = ref.push().key
val postMap = HashMap<String, Any>()
postMap["postId"] = postId!!
postMap["title"] = addPostBinding.etTitlePost.text.toString()
postMap["description"] = addPostBinding.etDescPost.text.toString()
postMap["category"] = addPostBinding.acChooseCategory.text.toString()
postMap["priceRange"] = addPostBinding.acPriceRange.text.toString()
postMap["duration"] = addPostBinding.etDurationPost.text.toString()
postMap["paymentMethods"] = addPostBinding.etPaymentMethods.text.toString()
postMap["post_image"] = myUrl
postMap["publisher"] = FirebaseAuth.getInstance().currentUser!!.uid
ref.child(postId).updateChildren(postMap)
Toast.makeText(this, "Post Uploaded successfully.", Toast.LENGTH_LONG).show()
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
progressDialog.dismiss()
}
else
{
progressDialog.dismiss()
}
})
}
}
}
private fun addImagePost() {
checker = "clicked"
CropImage.activity()
.setAspectRatio(2, 1)
.start(this)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null)
{
val result = CropImage.getActivityResult(data)
imageUri = result.uri
addPostBinding.btnAddImage.setImageURI(imageUri)
}
}
}

Add rules for posts too.
{
"rules": {
"User" : {
"$uid" : {
".read" : "$uid === auth.uid",
".write" : "$uid === auth.uid",
}
}
"Posts" : {
"$uid" : {
".read" : "$uid === auth.uid",
".write" : "$uid === auth.uid",
}
}
}
}

Related

RecyclerView and OnItemClick: No value passed for parameter 'click' in Fragment

I'm trying to implement an OnClick listener for specific items in a recyclerview. I've done it before with activities, but now I want to do this in a fragment and I've run into a problem. I'm getting the error No value passed for parameter 'click'. This is the line of code that gives that error:
recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}
This the only error Android Studio is currently showing me. The logcat doesn't show any error. Only the Build Output shows what's wrong and it's exactly what I said earlier
Fragment Class
#Suppress("UNREACHABLE_CODE")
class AbstractWallpapers: Fragment(), PurchasesUpdatedListener, AbstractAdapter.OnItemClickListenerAbstract {
private lateinit var subscribeAbstract: Button
private var billingClient: BillingClient? = null
lateinit var recyclerView: RecyclerView
lateinit var abstractList: ArrayList<Abstract>
private var recyclerAdapterAbstract: AbstractAdapter? = null
private var myRef3: DatabaseReference? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_abstract_wallpaper, container, false)
recyclerView = requireActivity().findViewById(R.id.abstract_recyclerView)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView = view.findViewById(R.id.abstract_recyclerView)
val layoutManager = GridLayoutManager(requireContext(), 2)
recyclerView.layoutManager = layoutManager
recyclerView.setHasFixedSize(true)
myRef3 = FirebaseDatabase.getInstance().reference
abstractList = ArrayList()
ClearAll()
GetDataFromFirebase()
subscribeAbstract = view.findViewById(R.id.abstract_subscribe_btn)
subscribeAbstract.setOnClickListener {
subscribeAbstract()
}
//Establish connection to billing client
//check subscription status from google play store cache
//to check if item is already Subscribed or subscription is not renewed and cancelled
billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
val queryPurchase = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
val queryPurchases = queryPurchase.purchasesList
if (queryPurchases != null && queryPurchases.size > 0) {
handlePurchases(queryPurchases)
} else {
saveSubscribeValueToPref(false)
}
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(requireActivity(), "Service Disconnected", Toast.LENGTH_SHORT).show()
}
})
//item subscribed
if (subscribeValueFromPref) {
subscribeAbstract.visibility = View.GONE
} else {
subscribeAbstract.visibility = View.VISIBLE
}
}
// Code relating to my Firebase storage
#SuppressLint("NotifyDataSetChanged")
private fun GetDataFromFirebase() {
val query: Query = myRef3!!.child("Abstract")
query.addListenerForSingleValueEvent(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
for (dataSnapshot: DataSnapshot in snapshot.children) {
val abstract = Abstract()
abstract.abstract = dataSnapshot.child("abstract").value.toString()
abstractList.add(abstract)}
recyclerAdapterAbstract = abstractList.let {AbstractAdapter(requireActivity(),it)}
recyclerView.adapter = recyclerAdapterAbstract
recyclerAdapterAbstract!!.notifyDataSetChanged()
}
override fun onCancelled(error: DatabaseError) {}
})
if (recyclerAdapterAbstract != null) recyclerAdapterAbstract!!.notifyDataSetChanged()
}
private fun ClearAll() {
abstractList.clear()
abstractList = ArrayList()
}
private val preferenceObject: SharedPreferences
get() = requireActivity().getSharedPreferences(PREF_FILE, 0)
private val preferenceEditObject: SharedPreferences.Editor
get() {
val pref = requireActivity().getSharedPreferences(PREF_FILE, 0)
return pref.edit()
}
private val subscribeValueFromPref: Boolean
get() = preferenceObject.getBoolean(SUBSCRIBE_KEY, false)
private fun saveSubscribeValueToPref(value: Boolean) {
preferenceEditObject.putBoolean(SUBSCRIBE_KEY, value).commit()
}
//initiate purchase on button click
fun subscribeAbstract() {
//check if service is already connected
if (billingClient!!.isReady) {
initiatePurchase()
} else {
billingClient = BillingClient.newBuilder(requireActivity()).enablePendingPurchases().setListener(this).build()
billingClient!!.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
initiatePurchase()
} else {
Toast.makeText(requireActivity(), "Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
override fun onBillingServiceDisconnected() {
Toast.makeText(requireActivity(), "Service Disconnected ", Toast.LENGTH_SHORT).show()
}
})
}
}
private fun initiatePurchase() {
val skuList: MutableList<String> = ArrayList()
skuList.add(ITEM_SKU_SUBSCRIBE)
val params = SkuDetailsParams.newBuilder()
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS)
val billingResult = billingClient!!.isFeatureSupported(BillingClient.FeatureType.SUBSCRIPTIONS)
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
billingClient!!.querySkuDetailsAsync(params.build()
) { billingResult, skuDetailsList ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
if (skuDetailsList != null && skuDetailsList.size > 0) {
val flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuDetailsList[0])
.build()
billingClient!!.launchBillingFlow(requireActivity(), flowParams)
} else {
//try to add subscription item "sub_example" in google play console
Toast.makeText(requireActivity(), "Item not Found", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(requireActivity(),
" Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
} else {
Toast.makeText(requireActivity(),
"Sorry Subscription not Supported. Please Update Play Store", Toast.LENGTH_SHORT).show()
}
}
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
//if item subscribed
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
handlePurchases(purchases)
}
else if (billingResult.responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
val queryAlreadyPurchasesResult = billingClient!!.queryPurchases(BillingClient.SkuType.SUBS)
val alreadyPurchases = queryAlreadyPurchasesResult.purchasesList
alreadyPurchases?.let { handlePurchases(it) }
}
else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
Toast.makeText(requireActivity(), "Purchase Canceled", Toast.LENGTH_SHORT).show()
}
else {
Toast.makeText(requireActivity(), "Error " + billingResult.debugMessage, Toast.LENGTH_SHORT).show()
}
}
fun handlePurchases(purchases: List<Purchase>) {
for (purchase in purchases) {
//if item is purchased
if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
if (!verifyValidSignature(purchase.originalJson, purchase.signature)) {
// Invalid purchase
// show error to user
Toast.makeText(requireActivity(), "Error : invalid Purchase", Toast.LENGTH_SHORT).show()
return
}
// else purchase is valid
//if item is purchased and not acknowledged
if (!purchase.isAcknowledged) {
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient!!.acknowledgePurchase(acknowledgePurchaseParams, ackPurchase)
} else {
// Grant entitlement to the user on item purchase
// restart activity
if (!subscribeValueFromPref) {
saveSubscribeValueToPref(true)
Toast.makeText(requireActivity(), "Item Purchased", Toast.LENGTH_SHORT).show()
recreate(requireActivity())
}
}
} else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.PENDING) {
Toast.makeText(requireActivity(),
"Purchase is Pending. Please complete Transaction", Toast.LENGTH_SHORT).show()
} else if (ITEM_SKU_SUBSCRIBE == purchase.sku && purchase.purchaseState == Purchase.PurchaseState.UNSPECIFIED_STATE) {
saveSubscribeValueToPref(false)
subscribeAbstract.visibility = View.VISIBLE
Toast.makeText(requireActivity(), "Purchase Status Unknown", Toast.LENGTH_SHORT).show()
}
}
}
var ackPurchase = AcknowledgePurchaseResponseListener { billingResult ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
//if purchase is acknowledged
// Grant entitlement to the user. and restart activity
saveSubscribeValueToPref(true)
recreate(requireActivity())
}
}
/**
* Verifies that the purchase was signed correctly for this developer's public key.
*
* Note: It's strongly recommended to perform such check on your backend since hackers can
* replace this method with "constant true" if they decompile/rebuild your app.
*
*/
private fun verifyValidSignature(signedData: String, signature: String): Boolean {
return try {
// To get key go to Developer Console > Select your app > Development Tools > Services & APIs.
val base64Key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhBlajrk5nNjpRTPJjDtGxgtgAeKijz3Wc0KrRKKSCxxsViHl7DhsI+sUZfk4Y1jxSg4/3W1uRo/0UASM77XfJIq34bK9KYgoSAGYSuH8Z+4fK/MrPz7dHhsljkAi4GZkv8x9VhZdDdpn2GSHVFaxs8c+HBOFp9aWAErHrQhi9/7fYf39pQSTC3WkVcy9xNDZxiiKTfDN3dyEvS0XQ617ZJwqDuRdkU5Aw9+R8r+oXyURV/ekgCQkWfCUaTp/jWdySOIcR87Bde24lQAXbvJaL5uAYI4zPwO4sIP1AbXLuDtv3N2rFVmP/1cML/NHDcfI5FOoStz88jzJU26Ngpqu1QIDAQAB"
Security.verifyPurchase(base64Key, signedData, signature)
} catch (e: IOException) {
false
}
}
override fun onDestroy() {
super.onDestroy()
if (billingClient != null) {
billingClient!!.endConnection()
}
}
companion object {
const val PREF_FILE = "MyPref"
const val SUBSCRIBE_KEY = "subscribe"
const val ITEM_SKU_SUBSCRIBE = "abstract_wallpapers"
}
override fun onItemClick(item: String) {
}
}
Adapter class
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract ) :
RecyclerView.Adapter<AbstractAdapter.ViewHolder>() {
interface OnItemClickListenerAbstract{
fun onItemClick(item:String)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.abstract_image_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
Glide.with(mContext)
.load(abstractList[position].abstract)
.into(holder.imageView)
holder.imageView.setOnClickListener {
val intent = Intent(mContext, AbstractPreview::class.java)
intent.putExtra("abstract", abstractList[position].abstract.toString())
Toast.makeText(mContext, "Fullscreen view", Toast.LENGTH_SHORT).show()
mContext.startActivity(intent)
}
holder.downloadBtn.setOnClickListener {
abstractList.get(position).abstract?.let { it1 -> click.onItemClick(it1) }
}
}
override fun getItemCount(): Int {
return abstractList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imageView: ImageView = itemView.findViewById(R.id.abstractImageView)
val downloadBtn: Button = itemView.findViewById(R.id.abstractDownloadBtn)
}
companion object
}
You have 3 parameters for the class AbstractAdapter
class AbstractAdapter(private val mContext: Context, private val abstractList: ArrayList<Abstract>, private val click: OnItemClickListenerAbstract )
but you are instantiating the object with only two parameters
AbstractAdapter(requireActivity(),it)
It's expecting the third parameter for the clickListener
AbstractAdapter(requireActivity(),it,this)
(send the Fragment as the third param)

kotlin quiz i can't color answer because don't run ContextCompat

Could you help me with the following code, I can't get it to paint the correct option green, or show the animation, of the CorrectResponse function.
If I delete the defaultColors() function, the green color is shown, but it remains in the next question.
when I write the default function it doesn't execute the code:
tv_option_one.background = ContextCompat.getDrawable(this, R.drawable.correct_option_border_bg)
I have tried to insert a sleep to defaultColors() to see the color correct_option_border_bg(green) but it is not displayed.
Any advice?
class QuestionActivity : AppCompatActivity() {
var quizzes: MutableList<Quiz>? = null
var contadorPregunta = 0
var questions: MutableMap<String, Question>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_question)
// VISUALIZACION PREGUNTAS
private fun bindViews() {
if (contadorPregunta == questions!!.size) { // last question
Toast.makeText(this, "HAS COMPLETADO TODAS LAS PREGUNTAS", Toast.LENGTH_SHORT).show()
val intent = Intent(this, ResultActivity::class.java)
startActivity(intent)
}
else{
defaultColors()
}
val pregunta = indicePreguntas[contadorPregunta]
val question = questions!!["question$pregunta"]
question?.let {
tvDescription.text = it.description
tv_option_one.text = it.option1
tv_option_two.text = it.option2
tv_option_three.text = it.option3
tv_option_four.text = it.option4
val respuesta = it.answer
tv_option_one.setOnClickListener {
if (tv_option_one.text == respuesta) {
Toast.makeText(this, "RESPUESTA CORRECTA", Toast.LENGTH_SHORT).show()
tv_option_one.background = ContextCompat.getDrawable(this, R.drawable.correct_option_border_bg)
respuestaCorrecta()
} else {
tv_option_one.background = ContextCompat.getDrawable(this, R.drawable.wrong_option_border_bg)
respuestaFallada()
}
}
tv_option_two.setOnClickListener {
if (tv_option_two.text == respuesta) {
Toast.makeText(this, "RESPUESTA CORRECTA", Toast.LENGTH_SHORT).show()
tv_option_two.background = ContextCompat.getDrawable(this, R.drawable.correct_option_border_bg)
respuestaCorrecta()
} else {
tv_option_two.background = ContextCompat.getDrawable(this, R.drawable.wrong_option_border_bg)
respuestaFallada()
}
}
tv_option_three.setOnClickListener {
if (tv_option_three.text == respuesta) {
Toast.makeText(this, "RESPUESTA CORRECTA", Toast.LENGTH_SHORT).show()
tv_option_three.background = ContextCompat.getDrawable(this, R.drawable.correct_option_border_bg)
contadorPregunta++
indicePreguntas[contadorPregunta]
} else {
tv_option_three.background = ContextCompat.getDrawable(this, R.drawable.wrong_option_border_bg)
respuestaFallada()
}
}
tv_option_four.setOnClickListener {
if (tv_option_four.text == respuesta) {
Toast.makeText(this, "RESPUESTA CORRECTA", Toast.LENGTH_SHORT).show()
tv_option_four.background = ContextCompat.getDrawable(this, R.drawable.correct_option_border_bg)
} else {
tv_option_four.background = ContextCompat.getDrawable(this, R.drawable.wrong_option_border_bg)
respuestaFallada()
}
}
}
}
private fun defaultColors() {
tv_option_one.background = ContextCompat.getDrawable(this, R.drawable.default_option_border_bg)
tv_option_two.background = ContextCompat.getDrawable(this, R.drawable.default_option_border_bg)
tv_option_three.background = ContextCompat.getDrawable(this, R.drawable.default_option_border_bg)
tv_option_four.background = ContextCompat.getDrawable(this, R.drawable.default_option_border_bg)
ivAcierto.visibility = View.INVISIBLE
}
private fun respuestaCorrecta() {
// Ver animacion
ivAcierto.visibility = View.VISIBLE
ivAcierto.animate().apply {
duration=1000
rotationYBy(1400f)
}.start()
contadorPregunta++
indicePreguntas[contadorPregunta]
Thread.sleep(2_000)
bindViews()
}
private fun respuestaFallada() {
//Thread.sleep(1_000)
// FALLO EN EL TEST
val dialog = AlertDialog.Builder(this)
.setTitle(R.string.dialog_one_style_title)
.setMessage(R.string.dialog_one_style_message)
.setPositiveButton(R.string.dialog_one_style_positive_btn) { view, _ ->
view.dismiss()
val intent = Intent(this, ResultActivity::class.java)
val json = Gson().toJson(quizzes!![0])
intent.putExtra("QUIZ", json)
startActivity(intent)
}
.setCancelable(false)
.create()
dialog.show()
}
}
I would like to give a couple of notes here: please use English when you write code, cause I have no idea what "pregunta" is and don't do this !! ... find other way to deal with nullables.
In respuestaCorrecta you call bindViews, which calls defaultColors and your correct color is getting overrided. As I can see, you want to delay calling bindViews by adding 2 sec sleep...
This is a bad idea. See your code runs in a main thread, in the same thread where rendering of Android Views happens... So making it sleep for 2 sec will make sure that no view will render for this period of time, and a user will not see anything in the app - no animation, no color changes, etc.
Thread.sleep cannot be used within main thread. However, if you want something to change after 2 sec, you can post an update. Like this:
tv_option_one.postDelayed({
bindViews()
}, 2000)
lambda is what will be called after a delay
2000 is a delay in millis

Realtime database not stored data

l cant save data Firebase realtime database no error code. auth create user but database not stored user data inside app. l change database rules
{
"rules": {
".read": true,
".write": true
}
}
l close firewall , try to test another app,I deleted the application completely from firebase and re-created it and downloaded the google-services.json file again. but can't solve problem.I tried a lot of different code structures, none of them worked this is my signup activity code block last version
class SignUpActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.sign_up_activity)
signInView.setOnClickListener {
startActivity(Intent(this, SignInActivity::class.java))
}
sign_up_btn.setOnClickListener {
createAccount()
}
}
private fun createAccount() {
val fullname = fullNameSignUp.text.toString()
val username = userNameSignUp.text.toString()
val email = emailSignUp.text.toString()
val password = passwordSignUp.text.toString()
when{
TextUtils.isEmpty(fullname) -> Toast.makeText(this,"full name is required.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(username) -> Toast.makeText(this,"user name is required.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(email) -> Toast.makeText(this,"email is required.", Toast.LENGTH_LONG).show()
TextUtils.isEmpty(password) -> Toast.makeText(this,"password is required.", Toast.LENGTH_LONG).show()
else -> {
/*
val alert = AlertDialog.Builder(this)
alert.setTitle("SignUp")
alert.setMessage("Please wait, this may take a while...")
alert.setCancelable(false)
alert.show()
*/
val progressDialog = ProgressDialog(this#SignUpActivity)
progressDialog.setTitle("SignUp")
progressDialog.setMessage("Please wait, this may take a while...")
progressDialog.setCanceledOnTouchOutside(false)
progressDialog.show()
val mAuth: FirebaseAuth = FirebaseAuth.getInstance()
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
saveUserInfo(fullname, username, email,progressDialog)
progressDialog.dismiss()
// AlertDialog.Builder(this)
// finish()
} else {
val message = task.exception!!.toString()
Toast.makeText(this, "Error: $message", Toast.LENGTH_LONG).show()
mAuth.signOut()
progressDialog.dismiss()
// AlertDialog.Builder(this)
// finish()
}
}
}
}
}
private fun saveUserInfo(fullname: String, username: String, email: String,progressDialog:ProgressDialog) {
val currentUserID = FirebaseAuth.getInstance().currentUser!!.uid
val usersRef = FirebaseDatabase.getInstance().reference.child("Users")
val userMap = HashMap<String,Any>()
userMap["uid"] = currentUserID
userMap["fullname"] = fullname
userMap["username"] = username
userMap["email"] = email
userMap["bio"] = ""
userMap["image"] = "gs://fart-me-ae78f.appSpot.com/Default Images/profile.png"
// db = FirebaseFirestore.getInstance()
// val usersRef = db.collection("Users").add(userMap)
// usersRef.addOnCompleteListener { task ->
usersRef.child("Users").child(currentUserID).setValue(userMap)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Toast.makeText(this, "Account has been created successfully.", Toast.LENGTH_LONG).show()
progressDialog.dismiss()
val intent = Intent(this#SignUpActivity, MainActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
finish()
// AlertDialog.Builder(this)
// finish()
} else {
val message = task.exception!!.toString()
Toast.makeText(this, "Error: $message", Toast.LENGTH_LONG).show()
FirebaseAuth.getInstance().signOut()
progressDialog.dismiss()
//AlertDialog.Builder(this)
// finish()
}
}
}
}
The solutions found by those with the same problem did not work for me. I would be glad if anyone can help me solve this problem

I want to upload image on server using Volley Library

I'm selecting the image from my phone gallery and want to upload image on server but my app crash every time i don't know the reason.. i already study many tutorials and Question but i did not understand. please help me.
Here is my code
class profileCreate : AppCompatActivity() {
var context: Context? = null
var imageUri: Uri? = null
var picturePath: String? = null
val url = "https://apps.faizeqamar.website/charity/api/donnor_add"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile_create)
val et_name = findViewById<EditText>(R.id.et_name)
val et_cnic = findViewById<EditText>(R.id.et_cnic)
val et_email = findViewById<EditText>(R.id.et_email)
val et_phon = findViewById<EditText>(R.id.et_phon)
val et_address = findViewById<EditText>(R.id.et_address)
val profile_image = findViewById<ImageView>(R.id.profile_image)
profile_image.setOnClickListener {
checkPermission()
}
val btn_create_profile = findViewById<Button>(R.id.btn_create_profile)
btn_create_profile.setOnClickListener {
imageUpload()
}
}
Volley Code
private fun imageUpload() {
val smr =
SimpleMultiPartRequest(
Request.Method.POST, url,
Response.Listener { response ->
Log.d("Response", response)
Toast.makeText(
applicationContext,
"xyz",
Toast.LENGTH_LONG
).show()
}, Response.ErrorListener { error ->
Toast.makeText(
applicationContext,
error.message,
Toast.LENGTH_LONG
).show()
})
var fname = et_name.text.toString()
var cnic = et_cnic.text.toString()
var email = et_email.text.toString()
var phone = et_phon.text.toString()
var address = et_address.text.toString()
smr.addFile("user_image", picturePath)
smr.addStringParam("fname", fname)
smr.addStringParam("cnic", cnic)
smr.addStringParam("email", email)
smr.addStringParam("phone", phone)
smr.addStringParam("address", address)
val mRequestQueue = Volley.newRequestQueue(applicationContext)
mRequestQueue.add(smr)
}
Pick Image from phone
//*********pick image from phone************
var READIMAGE: Int = 253
fun checkPermission() {
if (Build.VERSION.SDK_INT >= 23) {
if (ActivityCompat.checkSelfPermission(
this,
android.Manifest.permission.READ_EXTERNAL_STORAGE
) !=
PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
READIMAGE
)
return
}
}
loadImage()
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
when (requestCode) {
READIMAGE -> {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
loadImage()
} else {
Toast.makeText(
applicationContext,
"cannot access your images",
Toast.LENGTH_LONG
).show()
}
}
else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
val PICK_IMAGE_CODE = 123
fun loadImage() {
var intent = Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
)
startActivityForResult(intent, PICK_IMAGE_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PICK_IMAGE_CODE && data != null && resultCode == RESULT_OK) {
imageUri = data.data
val filePathColum = arrayOf(MediaStore.Images.Media.DATA)
val cursor = contentResolver.query(imageUri!!, filePathColum, null, null, null)
cursor!!.moveToFirst()
val columnIndex = cursor.getColumnIndex(filePathColum[0])
picturePath = cursor.getString(columnIndex)
cursor.close()
profile_image?.setImageBitmap(BitmapFactory.decodeFile(picturePath))
}
}
}
Encode your image to string and send to the server like sending strings
change your onACtivityresult as below
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
try {
if (requestCode == PICK_IMAGE_CODE && data != null && resultCode == RESULT_OK) {
val contentURI = data!!.data
try {
logBitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, contentURI)
encodedImgString = getStringImage(logBitmap!!)
profile_image!!.setImageBitmap(logBitmap)
} catch (e: IOException) {
e.printStackTrace()
Toast.makeText(this, "Failed!", Toast.LENGTH_SHORT).show()
}
}else if (requestCode== IMAGE_CAPTURE_CODE){
img_logo.setImageURI(image_uri)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
here is the getStringImage function
private fun getStringImage(bmp: Bitmap): String {
val baos = ByteArrayOutputStream()
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos)
val imageBytes = baos.toByteArray()
return Base64.encodeToString(imageBytes, Base64.DEFAULT)
}
You can send the encodedImgString to the server and decode from there

Kotlin: Remove list in Recycerview using AlertDialog button

I hope to remove items in Recyclerview by AlertDialog button.
Do you have idea?
Adapter & Viewholer
class ProjectsRecyclerAdapter(val list:List<ProjectListDataModel>, var clickListner: OnProjectListClickListner) : RecyclerView.Adapter<ProjectRecyclerViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProjectRecyclerViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_cardview, parent, false)
return ProjectRecyclerViewHolder(
view
)
}
override fun getItemCount(): Int {
return list.count()
}
override fun onBindViewHolder(holder: ProjectRecyclerViewHolder, position: Int) {
holder.initialize(list[position], clickListner)
}
}
class ProjectRecyclerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun initialize(item: ProjectListDataModel, action: OnProjectListClickListner) {
itemView.projectNameText.text = item.name
itemView.modifiedTimeText.text = item.modTime
itemView.descriptionText.text = item.description
itemView.setOnClickListener {
action.onItemClick(item, adapterPosition)
}
}
}
interface OnProjectListClickListner {
fun onItemClick(item: ProjectListDataModel, position: Int)
}
And here is Main Activity
class LocalProjectListActivity :
AppCompatActivity(),
OnProjectListClickListner,
NavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
val localProjectList = listOf(
ProjectListDataModel(
"Project A",
"Sun, 01/DEC/2020, 22:23GMT",
"Testing 1",
"AAAA",
"A, A",
8,
232
),
ProjectListDataModel(
"Project B",
"Sun, 01/JUL/2020, 10:23GMT",
"Testing 2",
"BBBB",
"B, B",
6,
354
),
ProjectListDataModel(
"Project C",
"Sun, 11/MAR/2020, 08:31GMT",
"Testing 3",
"CCCC",
"C,C",
15,
632
)
)
val adapter = ProjectsRecyclerAdapter(localProjectList, this)
projectNameText.adapter = adapter
projectNameText.setHasFixedSize(true)
projectNameText.layoutManager = LinearLayoutManager(this)
}
override fun onItemClick(item: ProjectListDataModel, position: Int) {
val builder = AlertDialog.Builder(this)
val ad = builder.create()
val dialogView = layoutInflater.inflate(R.layout.project_onclick, null)
dialogView.projectNameText.text = item.name
dialogView.modifiedTimeText.text = item.modTime
dialogView.descriptionText.text = item.description
dialogView.fileNumberText.text = item.fileNumber.toString() + "EA"
dialogView.fileSizeText.text = item.fileSize.toString() + "MB"
dialogView.scopeText.text = item.scope
dialogView.userIdText.text = item.resposible
ad.setView(dialogView)
ad.show()
//when click Load button
dialogView.loadButton.setOnClickListener {
ad.dismiss()
val dialog = AlertDialog.Builder(this)
dialog.setTitle("Question1")
dialog.setMessage("You want to go to the project?")
dialog.setPositiveButton("Yes", DialogInterface.OnClickListener { _, _ ->
})
dialog.setNegativeButton("No", DialogInterface.OnClickListener { _, _ ->
val fileFilterIntent = Intent(this, ProjectFileActivity::class.java)
startActivity(fileFilterIntent)
})
dialog.setNeutralButton("Cancel", DialogInterface.OnClickListener {dialog, _ ->
dialog.dismiss()
})
//if(isMarker == true) {
dialog.show()
//} else {}
}
dialogView.deleteButton.setOnClickListener {
ad.dismiss()
val dialog = AlertDialog.Builder(this)
dialog.setTitle("Delet project list")
dialog.setMessage("You want to delete project?")
dialog.setPositiveButton("Yes", DialogInterface.OnClickListener { _, _ ->
**//Delete items in RecyclerView**
})
dialog.setNeutralButton("Cancel", null)
dialog.show()
}
dialogView.cancleButton.setOnClickListener { ad.dismiss() }
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.remoteProjects -> {
val serverProjIntent = Intent(this, ServerProjectListActivity::class.java)
startActivity(serverProjIntent)
}
R.id.settings -> {
Toast.makeText(this, "Go to Settings", Toast.LENGTH_SHORT).show()
}
}
mainLocal.closeDrawer(GravityCompat.START)
return true
}
}
I posted all the code like that.
I can get the lists using Recyclerview, and made the AlertDialog But I don't know how to delete the items using the "Yes" button in AlertDialog.
Please give me some advises.
You'll need to have a reference to the list and the adapter outside of onCreate
private val localProjectList = mutableListOf(
ProjectListDataModel(
"Project A",
"Sun, 01/DEC/2020, 22:23GMT",
"Testing 1",
"AAAA",
"A, A",
8,
232
),
ProjectListDataModel(
"Project B",
"Sun, 01/JUL/2020, 10:23GMT",
"Testing 2",
"BBBB",
"B, B",
6,
354
),
ProjectListDataModel(
"Project C",
"Sun, 11/MAR/2020, 08:31GMT",
"Testing 3",
"CCCC",
"C,C",
15,
632
)
)
private lateinit var adapter: ProjectsRecyclerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
adapter = ProjectsRecyclerAdapter(localProjectList, this)
projectNameText.adapter = adapter
projectNameText.setHasFixedSize(true)
projectNameText.layoutManager = LinearLayoutManager(this)
}
And then delete the list and notify the adapter
private fun deleteItemsAndNotifyAdapter() {
localProjectList.clear()
adapter.notifyDataSetChanged()
}
You can delete and notify adapter in you dialog:
private var alertDialog: AlertDialog? = null
private fun showDeleteDialog() {
val builder = AlertDialog.Builder(activity)
builder.run {
setTitle("Delete project list")
setMessage("You want to delete project?")
setPositiveButton("Yes") { _, _ ->
deleteItemsAndNotifyAdapter()
}
setNegativeButton("Cancel") { _, _ ->
}
}
alertDialog = builder.create()
alertDialog?.show
}