Search code examples
androidkotlinandroid-servicebackground-process

How do games work in the background on Android?


I am developing a game that has a certain number of moves that replenish every 10 seconds, only 250 moves. You may have seen this in many modern mobile games as energy units.

The method that counts down 10 seconds and adds moves is implemented in the "Service". But the fact is that after the death of the application, the service does not work for a long time. Or it is restarted by first calling "OnStartCommand", then immediately "onDestroy" and somehow works. In the event of such a restart, if you open an application where the "Service" is launched in "OnCreate", another "Service" is launched and works in parallel with another (this breaks the logic of the recovery of moves, because you can create a lot of "Service" in this way) ... And even in this case, the "Service" do not live long and die.

class MyService : Service() {

lateinit var pref: SharedPreferences

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    Log.i("MYTAG", "Сервис работает")
    return START_STICKY
}

fun check() {
    if (pref.getInt("servicestep", 250) < 250) {
        reload()
    } else stopSelf()
}

private fun reload() {

    var progress = 0

    val b = "com.example.driverclicker"
    val intent = Intent(b)

    object : CountDownTimer(10100, 1000) {
        override fun onTick(millisUntilFinished: Long) {
            Log.i("MYTAG", Thread.currentThread().name)
            Log.i("MYTAG", "Таймер $millisUntilFinished")
            progress += 1
            intent.putExtra("step", progress)
            sendBroadcast(intent)
            if (progress == 10) {
                var step = pref.getInt("servicestep", 249)
                step += 1
                pref.edit().putInt("servicestep", step).commit()
                Log.i("MYTAG", "Таймер сохранился $step")
                Log.i("MYTAG", "Progress if= $progress")
            }
            Log.i("MYTAG", "Progress после if= $progress")

        }

        override fun onFinish() {
            intent.putExtra("step", 0)
            sendBroadcast(intent)

            check()

            Log.i("MYTAG", "Таймер закончился")
        }
    }.start()
}

override fun onCreate() {
    super.onCreate()
    pref = getSharedPreferences("save", Context.MODE_PRIVATE)
    check()
    Log.i("MYTAG", "Сервис запущен")
}

override fun onDestroy() {
    super.onDestroy()
    Log.i("MYTAG", "Сервис отключен")
}



override fun onBind(intent: Intent): IBinder {
    TODO("Return the communication channel to the service.")
}

} BroadcastReceiver in Activity

 br = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val serviceSteps = intent?.getIntExtra("step", 0)
            if (serviceSteps != null) {
                showProgress(serviceSteps, R.id.moves_bar)

                if (serviceSteps == 10) {
                    val steps = presenter.loadMoveValue()
                    Log.i(TAGNAME, "Ресивер получил $steps")
                    presenter.showText("$steps", R.id.text_movesValue)
                    Log.i(TAGNAME, "Ресивер отобразил $steps")
                }
            }
        }
    }

    registerReceiver(br, IntentFilter(BROAD))

I have a question. How do, for example, farm games work on Android? Resources are generated there in the background, and you just come and collect. How to implement this in the background in Android?


Solution

  • There are different methods to handle this, the easiest is to implement an offline calculation. Get a timestamp, when the service stopped working and get a timestamp when it is recreated and working again, with the time between these two timestamps you can calculate how often your service would have triggered.

    This is as you already noticed not very safe and can easily be manipulated.

    The 2nd approach is have a server handle the current moves and sync with the device. This needs a server, serverlogic and a database, but this can't be manipulated easy.

    For multiplayer a serversynced solution is the better choice, if your game is single player only you can do it locally with services and offline calculation.

    Which method you chose is your free choice.