Hunteerq
Hunteerq

Reputation: 280

Dependency injection with IntentService doesn't work

I want to create TCP_Client which sends data to server in many activities. I decided to use Dependency Injection to inject all samely configured clients to all clients. Unfortunately it stops working on start.

My application module

val appModule = module {
    single<ConnectionService> { ConnectionServiceTcp("192.168.0.1", 8888) }
}

Main Application

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@MainApplication)
            androidLogger()
            modules(appModule)
        }
    }
}
class ConnectionServiceTcp(private val ipAddress: String, private val port : Int)
    : IntentService("TCP_CLIENT"), ConnectionService {

    private var client : Socket? = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)
        return START_STICKY
    }

    override fun onHandleIntent(intent: Intent?) {
        startTcpServer()
    }

    private fun startTcpServer() {
        client = Socket(ipAddress, port)
    }


    override fun isConnectedToServer(): Boolean {
        Log.println(Log.INFO, null, "Adres = ${client?.localAddress} port = ${client?.localPort}")
        return false
    }

}
class MainActivity : AppCompatActivity() {

    private val connectionService : ConnectionService by inject()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        startTcpServer()
    }

    private fun startTcpServer() {
        val serverTcp = Intent(this, ConnectionServiceTcp::class.java)
        startService(serverTcp)
    }


And then I receive

    java.lang.RuntimeException: Unable to instantiate service connection.impl.ConnectionServiceTcp: java.lang.InstantiationException: java.lang.Class<connection.impl.ConnectionServiceTcp> has no zero argument constructor

I can't find a way to Inject background client for sending TCP requests

Upvotes: 1

Views: 1101

Answers (1)

Stanislav Shamilov
Stanislav Shamilov

Reputation: 1828

Just as with Activities, Fragments or some other platform components, Android system implies that Services should have a single no-arg constructor. The system looks for a default constructor in Service class and calls it using reflection. That's why it's prohibited to add non-default constructors (i.e. constuctors with arguments).

To inject dependencies into Service you should do the same as you do in Activities (declare a field and inject it using by inject() delegate. So the final code will look as follows:

class ConnectionServiceTcp()
    : IntentService("TCP_CLIENT"), ConnectionService {

    private val ipAddress: String by inject()
    private val port : Int by inject()
    private var client : Socket? = null

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        super.onStartCommand(intent, flags, startId)
        return START_STICKY
    }

    override fun onHandleIntent(intent: Intent?) {
        startTcpServer()
    }

    private fun startTcpServer() {
        client = Socket(ipAddress, port)
    }

    override fun isConnectedToServer(): Boolean {
        Log.println(Log.INFO, null, "Adres = ${client?.localAddress} port = ${client?.localPort}")
        return false
    }
}

Upvotes: 2

Related Questions