skip to Main Content

I’m a beginner at programming! I’m trying to create an app that will send a notification in a specific time. The description of the notification must be one from an array previously defined inside the app.
Right now, I am doing it by parts: The Notification is created by a WorkManager, which is activated by a button. It is a OneTimeWorkRequest, for now.

My problem right now is: how do I get the Notification to get its description from the array? I tried using a while loop, but it only uses the first string from the array.

My code for the activity:

class CatPicsActivity : AppCompatActivity() {

lateinit var notifBtn: MaterialButton;
lateinit var catBtn: ImageButton;
lateinit var title: String;
lateinit var catImg: ImageView;
var url: String = "https://api.thecatapi.com/v1/"

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_cat_pics)

    notifBtn = findViewById(R.id.botaoNotificacao);
    catBtn = findViewById(R.id.catbtn);
    catImg = findViewById(R.id.imgCat);

    title = getResources().getString(R.string.titulo_notificacao);

    notifBtn.setOnClickListener {


        Log.i("WorkButton", "clicado")

        val notifcWorker: OneTimeWorkRequest =
                OneTimeWorkRequestBuilder<NotificationWorker>()
                        .build()

        WorkManager.getInstance(this)
                .enqueueUniqueWork(
                        "notification_worker",
                        ExistingWorkPolicy.KEEP,
                        notifcWorker
                )
    }

    catBtn.setOnClickListener {
        catFunction();
    }
}

private fun catFunction() {
    val retrofit = Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create())
            .build()

    val catService: CatService = retrofit.create(CatService::class.java)
    catService.randomCat().enqueue(object : Callback<List<Cat>> {
        override fun onResponse(call: Call<List<Cat>>, response: Response<List<Cat>>) {
            val randomCat = response.body()!!

            Picasso.get()
                    .load(randomCat[0].url)
                    .into(catImg)
        }

        override fun onFailure(call: Call<List<Cat>>, t: Throwable) {
            Toast.makeText(this@CatPicsActivity, "Deu errado! Tente novamente, por favor", Toast.LENGTH_SHORT).show()
            Log.i("CatPics", "Erro: $t")
        }
    })

}}

My worker class:

class NotificationWorker(private val context: Context, params: WorkerParameters) : Worker(context, params) {


lateinit var descricao: String

fun generateDescription (): String {
    var razoes = arrayOf(
            "Esta é uma notificação de teste, por favor me avise no Telegram se chegou",
            "1 - ",
            "2 - ",
            "3 - ",
            "4 - ",
            "5 - ",
            "6 - ",
            "7 - ",
            "8 - ",
            "9 - ",
            "10 - ",
            "11 - ",
            "12 - ",
            "13 - ",
            "14 - ",
            "15 - ",
            "16 - ",
            "17 - ",
            "18 - ",
            "19 - ",
            "20 - ",
            "21 - ",
            "22 - ",
            "23 - ",
            "24 - ",
            "25 - ",
            "26 - ",
            "27 - ",
            "28 - ",
            "29 - ",
            "30 - ")

    var array = razoes
    var i = 0

    while(i < array.size){
        descricao = array[i]
        i += 1
        return descricao
    }

    return descricao
}

var title: String = "Você recebeu uma nova mensagem!"

override fun doWork(): Result {

    generateDescription()
    Log.i("WorkerDescricao2", descricao)
    Log.i("WorkBeforeNotification", "Trabalho criado")

    NotificationUtils.createNotification(context, title, descricao)

    Log.i("WorkAfterNotification", "notificação enviada")

    return Result.success()

}}

So, how do I get the "descricao" variable from the array "razoes"?

Thank you!

EDIT:

I want each of the values from array to be used in a different notification, which will be sent after clicking the button (or each day in the future).

2

Answers


  1. In your code you have a return in while loop. So in first iteration you are exiting while loop and returning in your descricao variable the value of razoes[0]. Also there is no need to use extra array, you can access razoes instantly:

     var i = 0
        while(i < razoes.size) {
            descricao = razoes[i]
            i += 1
            //return descricao
        }
    

    So i do not know what value of descricao you want to keep. If you want all of razoes then you should call NotificationUtils.createNotification(context, title, descricao)
    in a loop. If you want to get a specific value from razoes you should change your generateDescription fun something like

    fun generateDescription(position: Int): String {
        var razoes = arrayOf(
                "Esta é uma notificação de teste, por favor me avise no Telegram se chegou",
                "1 - ",
                "2 - ",
                "3 - ",
                "4 - ",
                "5 - ",
                "6 - ",
                "7 - ",
                "8 - ",
                "9 - ",
                "10 - ",
                "11 - ",
                "12 - ",
                "13 - ",
                "14 - ",
                "15 - ",
                "16 - ",
                "17 - ",
                "18 - ",
                "19 - ",
                "20 - ",
                "21 - ",
                "22 - ",
                "23 - ",
                "24 - ",
                "25 - ",
                "26 - ",
                "27 - ",
                "28 - ",
                "29 - ",
                "30 - ")
        descricao = razoes[position]
        return descricao
    }
    

    If I have understood correctly you want on button click to send a notification with description each time the next array item of razors. So here is an example of handling click button (i toast a dummy message, just to show the logic):

    private var razoes = intArrayOf(1, 2, 3, 4, 5)
    private var position: Int = -1
    
     binding.button.setOnClickListener {
                handleButtonClick()
            }
    
     private fun handleButtonClick() {
            position += 1
            if (position > razoes.size -1) {
                Toast.makeText(this@DemoActivity, "There are no other items in razoes", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this@DemoActivity, razoes[position].toString(), Toast.LENGTH_SHORT).show()
            }
        }
    
    Login or Signup to reply.
  2. I think what you were trying to do is get the generateDescription() function to continue where it left off in the while loop each time you call it. Functions simply don’t work that way. Every time you call them, they run from the very beginning (with no memory of any previous times it has been called) until they hit a return.

    So you have to keep a property that tracks where you left off. So the way to do minimal changes to your code and get this to work would be to create a property that keeps track of which index of the array you want to show next. Each time you call this function, you would increase this variable and use it to get the next value of the array. To get it to circle back around to the beginning of your array when it gets to the end, you can use the remainder operator % with the array size.

    You can get rid of the descricao property since it serves no purpose other than to hold the result of this function call. You can use a local variable to hold the result right where you’re using it.

    I used an iterator to make the creation of the array more concise, but I realize you are probably planning to change the values for each day, so you won’t be able to do that long term.

    private var notificationIndex = -1
    
    fun generateDescription (): String {
        val razoes = Array<String>(31) {
            if (it == 0)
                "Esta é uma notificação de teste, por favor me avise no Telegram se chegou"
            else
                "$it - "
        }
        notificationIndex = (notificationIndex + 1) % razoes.size
        return razoes[notificationIndex]
    }
    
    override fun doWork(): Result {
    
        val descricao = generateDescription()
        Log.i("WorkerDescricao2", descricao)
        Log.i("WorkBeforeNotification", "Trabalho criado")
    
        NotificationUtils.createNotification(context, title, descricao)
    
        Log.i("WorkAfterNotification", "notificação enviada")
    
        return Result.success()
    
    }
    

    There’s more that should be done to make the code more sensible. For instance, if the descriptions are constant, the array should not be created in the function. The whole array should just be created and stored in a property at the declaration site. And literal Strings should not be hard-coded like this, but rather pulled from the XML resources.

    You also mentioned in the comments that you want a different notification each day. That makes this more complicated, and way more than I want to explain here. If it is different each day, you can’t just rely on a notificationIndex property as above, because it will be forgotten the next time the app comes on screen. You would need to persist the value, which you can read about in the Android documentation.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search