I am building an application for student attendance for my college. Where in the attendance is being taken via the college network. Each class room has a separate 'routers', and the system detects if student has present in the range.
For the same, what I am trying to do is establish a socket connection, and every time that it connects, the server in return receives the WiFi information to judge the class room.
To establish, I first made this index.js file, here is the code for it
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req,res){
res.sendFile(__dirname+'/index.html');
})
http.listen(4040, function(){
console.log("Server is listening on port 4040");
})
io.on('connection', function(socket){
console.log('connect', "A user connected "+ socket.id)
io.on('disconnect', function(socket){
console.log("disconnect A user disconnected" + socket.id)
})
})
Problem: The problem is that, 'connection' event is not working. It says that it's listening but nothing is getting console logged. I am using an Emulator as client and a local XAMPP server. However, the 'connection' event does work when I use browser as a client.
Here is my client side code:
private val socket = Socket()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_student_home)
setSupportActionBar(student_toolbar)
val toggle = ActionBarDrawerToggle(
this, student_drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
student_drawer_layout.addDrawerListener(toggle)
toggle.syncState()
student_nav_view.setNavigationItemSelectedListener(this)
socket.connect()
}
override fun onResume() {
super.onResume()
socket.connect()
}
override fun onStart() {
super.onStart()
socket.connect()
}
override fun onDestroy() {
super.onDestroy()
socket.disconnect()
}//[End : onDestroy]
fun Socket() : Socket{
val socket : Socket
try {
socket = IO.socket("http://localhost:4040")
} catch (e: URISyntaxException) {
throw RuntimeException(e)
}
return socket;
}
try to change "localhost" to your machine's ip address like "http://192.168.1.100:4040". can you post screenshot of backtrace?
Related
I'm working on simple TCP/IP application on Android that sends/receives packages.
I have set up code to find to host and join network. My code works where client is able to auto join the server when it's available, however, when i discover a open server, i want to send request/message to server that I want to join your server.
here's my code.
// Activity to hold our server socket
serverSocket: ServerSocket? = null
// Create a listen socket
val port: Int
serverSocket = ServerSocket(0).also { socket ->
// Store the chosen port.
port = socket.localPort
}
Thread(Runnable {
while (serverSocket != null) {
try {
serverSocket?.accept()?.let {
Log.d("ServerSocket", "accepted client")
// client found, connect to client automatically
connectToClient()
}
} catch (e: SocketException) {
break
}
}
}).start()
nsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener)
than for client i'm using this to discover server
nsdManager.discoverServices("_LocalNetworkingApp._tcp.", NsdManager.PROTOCOL_DNS_SD, discoveryListener)
private val discoveryListener = object : NsdManager.DiscoveryListener {
...
override fun onServiceFound(service: NsdServiceInfo) {
Log.d(TAG, "Service found ${service.serviceName}")
nsdManager.resolveService(service, resolveListener)
}
}
// in resolverServices' `onServiceResolved` function is where i'm connected to the server
The answer for checking internet was posted back in 2014 in this post: https://stackoverflow.com/a/27312494/12359431
However, in one of the answer, there is this piece of code
fun hasInternetConnection(): Single<Boolean> {
return Single.fromCallable {
try {
// Connect to Google DNS to check for connection
val timeoutMs = 1500
val socket = Socket()
val socketAddress = InetSocketAddress("8.8.8.8", 53)
socket.connect(socketAddress, timeoutMs)
socket.close()
true
} catch (e: IOException) {
false
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
I have tried it by implementing the code above to my code at the bottom. However, it just crashes and I could not get any finding of the error as to why the app crash.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/* Initialise Azure Service Adapter */
AzureServiceAdapter.Initialize(this)
hasInternetConnection().subscribe{hasInternet->
/*Call database and check phone number*/
Log.i("Logger", "Connected")}
/* Authentication */
authUser()
}
}
This is my implementations
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
Is there anything I'm lacking or I shouldn't add to my MainActivity File? Or a clue as to why my kotlin app crash ?
That's because you cant call this on main Thread.
Check if you added Internet permission in Manifest.
hasInternetConnection()
.subscribeOn(Schedulars.io())
.observeOn(AndroidSchedulars.mainThread()).subscribe{hasInternet->
/*Call database and check phone number*/
Log.i("Logger", "Connected")}
I have a TCP Server on Windows, and I want to send and receive text strings between the server and my Android device.
I spent alot of time searching for an example using Kotlin but I didn't find any useful code, so I'm now only able to create the socket and connect.
fun connect() {
try{
val soc = Socket("192.168.1.5", 1419)
val dout = DataOutputStream(soc.getOutputStream())
dout.writeUTF("1")
dout.flush()
dout.close()
soc.close()
}
catch (e:Exception){
e.printStackTrace()
}
}
You can check this simple example. Hope it'll help you!
Server:
fun main() {
val server = ServerSocket(9999)
println("Server running on port ${server.localPort}")
val client = server.accept()
println("Client connected : ${client.inetAddress.hostAddress}")
val scanner = Scanner(client.inputStream)
while (scanner.hasNextLine()) {
println(scanner.nextLine())
break
}
server.close()
}
Client:
fun main() {
val client = Socket("127.0.0.1", 9999)
client.outputStream.write("Hello from the client!".toByteArray())
client.close()
}
You can also do it with ktor, it's a kotlin based asynchronous framework. It uses coroutines natively which allow concurrency.
Use Kotlin 1.4 and ktor 1.6.0, add it to your build.gradle.kts:
plugins {
kotlin("jvm") version "1.4.32"
}
dependencies {
implementation("io.ktor:ktor-server-netty:1.6.0")
implementation("io.ktor:ktor-network:1.6.0")
}
Then you can use the sockets, it's still a bit experimental but it's getting there, with newer version ktor-network is now necessary.
Here is the code:
Server:
suspend fun server() {
val server = aSocket(ActorSelectorManager(Executors.newCachedThreadPool().asCoroutineDispatcher())).tcp()
.bind(InetSocketAddress("127.0.0.1", 2323))
println("Server running: ${server.localAddress}")
val socket = server.accept()
println("Socket accepted: ${socket.remoteAddress}")
val input = socket.openReadChannel()
val output = socket.openWriteChannel(autoFlush = true)
val line = input.readUTF8Line()
println("received '$line' from ${socket.remoteAddress}")
output.writeFully("$line back\r\n".toByteArray())
}
Client:
suspend fun client() {
val socket = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp()
.connect(InetSocketAddress("127.0.0.1", 2323))
val input = socket.openReadChannel()
val output = socket.openWriteChannel(autoFlush = true)
output.writeFully("hello\r\n".toByteArray())
println("Server said: '${input.readUTF8Line()}'")
}
Run them both:
fun main() {
CoroutineScope(Dispatchers.Default).launch { server() }
runBlocking { client() }
}
When you run them, the client will send a message, the server will respond and you should see something like this:
Server running: /127.0.0.1:2323
Socket accepted: /127.0.0.1:56215
received 'hello' from /127.0.0.1:56215
Server said: 'hello back'
Find more example on their documentation simple echo server
There are 2 important things based on my experiment:
get permission in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
create the socket from a background thread, the following works for me:
Executors.newSingleThreadExecutor().execute {
val socket = Socket("192.168.0.15", 50000)
val scanner = Scanner(socket.getInputStream())
val printWriter = PrintWriter(socket.getOutputStream())
while (scanner.hasNextLine()) {
Log.d(TAG, "${ scanner.nextLine() }")
}
}
This is the source code in GitHub.
There is a video of my experiment.
I am trying to implement RabbitMQ into my android App, but having an issue that inside the handleDelivery method when i am trying to call an outer function the connection getting lost.
private fun initRabbitmq () {
factory.setUri("someURI")
subscribeThread = Thread(object : Runnable {
override fun run() {
val connection: Connection = factory.newConnection()
val channel: Channel = connection.createChannel()
val consumer: DefaultConsumer
consumer = object : DefaultConsumer(channel) {
override fun handleDelivery(consumerTag: String?, envelope: Envelope?, properties: AMQP.BasicProperties?, body: ByteArray?) {
super.handleDelivery(consumerTag, envelope, properties, body)
val msg = String(body!!, Charsets.UTF_8)
Log.e(TAG, "RabbitMQ - $msg")
showRabbitMessage(msg)
}
}
channel.basicConsume("defenders_test", true, consumer)
}
})
subscribeThread.start()
}
When the function showRabbitMessage() being executed the connection being lost, but if i am removing it and watching the logs, the messages being displayed in the console.
Any idea how to get the message out of the Thread?
Thx in advance!
The problem was that i had to transfer the object from the thread -> out, and in android it can be done by using the Handle object and handleMessage() method.
What I am trying to make is a local chat app (i.e, over local network, i.e. without internet only i.e. hotspot wifi based on android).I studied about sockets and tried to implement using https://github.com/socketio/socket.io-client-java I tried to make use of mainly socket.emit and socket.on. Both of my devices are connected on local network so can I do this
class MainActivity : AppCompatActivity()
{
var TAG = "TCPClient"; //For debugging, always a good idea to have defined
var serverIp = "192.168.0.102";
var startTime = 0L;
var serverPort = 5000;
lateinit var socket:Socket
var onMessageReceived=object:Emitter.Listener
{
override fun call(vararg args: Any?)
{
runOnUiThread {
editText2.setText(args[0].toString())
Toast.makeText(this#MainActivity,"called",Toast.LENGTH_SHORT).show()
}
}
}
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var SOCKET_URL="http://192.168.0.102"
socket= IO.socket(SOCKET_URL)
button.setOnClickListener {
socket.emit("messageSent",editText.text.toString())
Toast.makeText(this#MainActivity,"button",Toast.LENGTH_SHORT).show()
}
socket.on("messageSent",onMessageReceived)
socket.connect()
}
override fun onDestroy()
{
socket.disconnect()
super.onDestroy()
}
}
What I was trying whatever is the text written in editext1(in one phone with ip 192.68.0.102) is displayed in edittex2 (of both devices (one with ip 192.168.0.102 and the other devices on local network(192.168.0.100) since I ran the same app on both devices)) when button is pressed.What I am doing wrong? I would have made this app by hosting rest service on one of the devices and accessing it from all the connected devices in the network but the main problem I was facing is that if I do so I would have to request the rest api again and again in a loop in a thread to check for a new message.
Don't all the connected devices listen when we use socket.on?