i am implementing SignalR on client side with android using kotlin. I can connect and can get connection id its mean connection established succeeded after that invoke and subscribed it, when i call hubConnection.on() it could not move inside any log or nor catch any exception. where i have done mistake any help is appreciated
lifecycle.coroutineScope.launchWhenCreated {
hubConnection =
HubConnectionBuilder.create("baseurl",)
.build()
hubConnection.start().blockingAwait()
Log.e("123**** ", "Established connection......" + hubConnection.connectionId)
val userID = "Model.user_id"
try {
hubConnection.invoke(
"Subscribe",
hubConnection.connectionId,
arrayListOf(
userID,
"$userID+_messaging",
"$userID+_notification",
"$userID+_setting",
"$userID+_plan",
"$userID+_refresh"
)
).subscribe()
} catch (e: Exception) {
Log.e("ExceptionDone: ", e.toString())
}
try {
hubConnection.on("ReceiveSimplifiedRealTime", { response: String ->
// runOnUiThread {
Log.e("Receive123**** ", response)
//}
}, String::class.java)
} catch (e: Exception) {
Log.e("Receive123**** ", e.toString())
} catch (e: ExecutionException) {
Log.e("Receive123**** ", e.toString())
}
}
Related
I'm using ktor client to make a simple REST request, when a network exception error occurs inside the client.get() call, I cannot catch this error no matter what I do and it causes the app to crash.
Keep in mind, I'm NOT trying to find the cause/solution of the crash, I'm trying to figure out how I can catch the Exception so the app doesnt crash.
here are all things I've tried:
try {
val response = runCatching {
client.post("$BASE_URL/api/users/login")
}.getOrElse {
throw it
}
return Result.Success(response.body())
} catch (e: RedirectResponseException) { // 3xx
Result.Error(e, e.response.status.description)
} catch (e: ClientRequestException) { // 4xx
Result.Error(e, e.response.status.description)
} catch (e: ServerResponseException) { // 5xx
Result.Error(e, e.response.status.description)
} catch (e: java.net.ConnectException) {
Result.Error(e, e.message.orEmpty())
} catch (e: Exception) {
Result.Error(e, e.message.orEmpty())
} catch (e: Throwable) {
Result.Error(java.lang.Exception(), e.message.orEmpty())
}
None of these is able to catch the crash.
I'm assuming the crash is happening on another thread or process and that's why I cant catch it, and that I need to add some sort of error handler to the httpClient during initialization, However I cant figure out how to do this. This is what I have so far in my httpClient Initialization:
val client = HttpClient(Android) {
install(Logging) {
level = LogLevel.ALL
}
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
})
}
}
The actauly exception that's causing my app to crash is this:
java.net.ConnectException: Failed to connect to localhost/127.0.0.1:8090
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:147)
this is my first time creating a chat using socket in Android app. I have a nodejs back-end. I also a have a front-end app written with Reactjs and it's working as expected. However, it's not the case for my Android app. Please see below code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chatroom)
send.setOnClickListener(this)
leave.setOnClickListener(this)
// Get the nickname and roomName from entrance activity.
try {
userName = intent.getStringExtra("username")!!
roomName = intent.getStringExtra("room")!!
} catch (e: Exception) {
e.printStackTrace()
}
// Set ChatRoom RecyclerView adapter
chatRoomAdapter = ChatRoomAdapter(this, chatList)
recyclerView.adapter = chatRoomAdapter
val layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = layoutManager
// Let's connect to our Chat room! :D
try {
val opts = IO.Options()
opts.forceNew = true;
opts.reconnection = false
opts.transports = arrayOf(Polling.NAME, PollingXHR.NAME, WebSocket.NAME)
// This address is the way you can connect to localhost with AVD (Android Virtual Device)
mSocket = IO.socket(URL, opts)
Log.d(TAG, "Name $URL")
Log.d(TAG, "Opts $opts")
} catch (e: Exception) {
e.printStackTrace()
Log.d("Fail", "" + "Failed to connect")
}
mSocket.connect()
mSocket.on(Socket.EVENT_CONNECT, Emitter.Listener {
val data = initialData(userName, roomName)
val jsonData = gson.toJson(data) // Gson changes data object to Json type.
Log.d(TAG, "json >> $jsonData")
Handler(Looper.getMainLooper()).postDelayed(object : Runnable {
override fun run() {
mSocket.emit("join", jsonData)
}
},200)
Log.d("Success", "" + mSocket.id())
mSocket.on("message", onUpdateChat)
});
mSocket.on(Socket.EVENT_CONNECT_ERROR, Emitter.Listener { args ->
Log.e(TAG, "Andito na ba ko? ${args[0]} size: ${args.size}")
});
mSocket.on(Socket.EVENT_ERROR, Emitter.Listener {
Log.e(TAG, "Error")
});
}
But I keep getting io.socket.engineio.client.EngineIOException: server error
Anyone encountered this error? I would gladly appreciate any kind of help. Thanks.
I decided to wrap getting device location (once, without updating) using kotlin coriutines, so finally i got this code:
#SuppressLint("MissingPermission")
suspend fun LocationManager.getCurrentLocationOnce(): Location {
return suspendCancellableCoroutine { continuation ->
try {
val locationListener = object : SimpleLocationListener {
override fun onLocationChanged(location: Location?) {
if (location == null) {
this#getCurrentLocationOnce.removeUpdates(this)
continuation.resumeWithException(FailedToRetrieveLocationException("Location is NULL"))
} else {
this#getCurrentLocationOnce.removeUpdates(this)
continuation.resume(location)
}
}
override fun onProviderEnabled(provider: String?) {}
override fun onProviderDisabled(provider: String?) {
this#getCurrentLocationOnce.removeUpdates(this)
continuation.resumeWithException(ProviderDisabledException(provider ?: ""))
}
}
this.requestSingleUpdate(
LocationManager.GPS_PROVIDER,
locationListener,
null
)
} catch (e : Exception) {
continuation.resumeWithException(e)
}
}
}
When GPS is ON all works fine, but when GPS is OFF program fails with exception ProviderDisabledException, thats because of:
override fun onProviderDisabled(provider: String?) {
this#getCurrentLocationOnce.removeUpdates(this)
continuation.resumeWithException(ProviderDisabledException(provider ?: ""))
}
But i don't know why it's fails, because in place where i'm using this function i've got:
try {
val locationManager = (requireActivity().getSystemService(Context.LOCATION_SERVICE) as? LocationManager)
?: throw FailedToRetrieveLocationException("Location Service is null")
val location = locationManager.getCurrentLocationOnce()
log("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle",
"Successfully got location={lat:${location.latitude}, long:${location.longitude}}")
downloadRestaurantsWithLocation(location)
} catch (ex : FailedToRetrieveLocationException) {
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", ex)
throw ex
} catch (providerException : ProviderDisabledException) {
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", providerException)
throw providerException
} catch (e : Exception) {
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", e)
throw e
}
So i'm logging exception and rethrow it to caller function and in caller function i'm catching this exception:
try {
log("[GOOGLE] downloadRestaurants", "Starting donwload restaurants for GOOGLE")
downloadRestaurantsWithGPSLocationGoogle()
} catch (e : Exception) {
logError("[GOOGLE] error happened while getting location", e)
downloadRestaurantsWithFusedLocationGoogle()
}
And in error stacktrace i've got only this:
E/[GOOGLE] downloadRestaurantsWithGPSLocationGoogle: my.package.location.exceptions.ProviderDisabledException: Provider gps disabled
at my.package.common.location.LocationUtilsKt$getCurrentLocationOnce$$inlined$suspendCancellableCoroutine$lambda$1.onProviderDisabled(LocationUtils.kt:45)
at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:384)
at android.location.LocationManager$ListenerTransport.access$000(LocationManager.java:300)
at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:316)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:6878)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
I don't know why app fails, because code like this works perfect:
lifecycleScope.launch {
try {
throwError()
} catch (e : Exception) {
e.printStackTrace()
}
}
private suspend fun throwError() {
return suspendCancellableCoroutine { continuation ->
continuation.resumeWithException(ProviderDisabledException("TEST"))
}
}
So, finally i realized why it's crash the app =). All ok with coroutines.
Problem is in this method:
#Throws(ProviderDisabledException::class, FailedToRetrieveLocationException::class)
private fun downloadRestaurantsWithGPSLocationGoogle() = lifecycleScope.launch {
log("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", "Trying to get location via GPS")
try {
val locationManager = (requireActivity().getSystemService(Context.LOCATION_SERVICE) as? LocationManager)
?: throw FailedToRetrieveLocationException("Location Service is null")
val location = locationManager.getCurrentLocationOnce()
log("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle",
"Successfully got location={lat:${location.latitude}, long:${location.longitude}}")
downloadRestaurantsWithLocation(location)
} catch (ex : FailedToRetrieveLocationException) {
ex.printStackTrace()
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", ex)
throw ex
} catch (providerException : ProviderDisabledException) {
providerException.printStackTrace()
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", providerException)
throw providerException
} catch (e : Exception) {
e.printStackTrace()
logError("[GOOGLE] downloadRestaurantsWithGPSLocationGoogle", e)
throw e
}
}
And the problem is that i'm throwing exception from coroutine and handle this exception not in coroutine, so i'm launched my coroutine and all try-cathces are skipped, because here i'm using fire and forget style. So to fix this i need to do this method suspend and throw exceptions.
Place where trying to catch errors:
private fun downloadRestaurants() = lifecycleScope.launch {
log("downloadRestaurantsWithLocationSort",
"Requesting Manifest.permission.ACCESS_COARSE_LOCATION & Manifest.permission.ACCESS_FINE_LOCATION permissions")
val user = requestPermissions(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
if (!user.any { !it.second }) {
// permission is granted, can download restaurants and sort by nearest
log("downloadRestaurantsWithLocationSort", "Permissions is granted")
log("MANUFACTURER", Build.MANUFACTURER)
if (Build.MANUFACTURER == "Huawei" || Build.MANUFACTURER == "HUAWEI") {
showToast("HUAWEI")
try {
log("[HUAWEI] downloadRestaurants", "Starting donwload restaurants for HUAWEI")
downloadRestaurantsWithGPSLocationHuawei()
} catch (e : Exception) { // this will not work, because FIRE and FORGET
e.printStackTrace()
logError("[HUAWEI] error happened while getting location", e)
mainViewModel.downloadRestaurantsHeaders(null)
}
} else {
showToast("NOT A HUAWEI")
try {
log("[GOOGLE] downloadRestaurants", "Starting donwload restaurants for GOOGLE")
downloadRestaurantsWithGPSLocationGoogle()
} catch (e : Exception) { // this will not work, because FIRE and FORGET
e.printStackTrace()
logError("[GOOGLE] error happened while getting location", e)
downloadRestaurantsWithFusedLocationGoogle()
}
}
} else {
// permission is not granted, just download the restaurants
log("downloadRestaurantsWithLocationSort", "Permissions is NOT granted")
mainViewModel.downloadRestaurantsHeaders(null)
}
}
So the answer make functions downloadRestaurantsWithGPSLocationGoogle and downloadRestaurantsWithFusedLocationGoogle suspend and don't launch separate coroutine inside them. (remove lifecycleScope.launch)
I need to print a image using thermal printer. Now I am able to print text using below code,
private fun printBill() {
Thread {
try {
val sock = Socket("192.168.100.99", 9100)
val oStream = PrintWriter(sock.getOutputStream())
oStream.printf("%-35s %-5s %5s\n", "Jihin Raju", 10.00, 100.00)
oStream.println(charArrayOf(0x1D.toChar(), 0x56.toChar(), 0x41.toChar(), 0x10.toChar()))
oStream.close()
sock.close()
} catch (e: UnknownHostException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
runOnUiThread {
Toast.makeText(this#MainActivity, "Printed ", Toast.LENGTH_SHORT).show()
}
}.start()
}
Is there any way to print image
Making Chat App using Smack ,
Try to get the Last Seen time of user but getting following Exception
org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: subscription-required - auth
Code :
public void getLastSeen(String JID) {
LastActivityManager mLastActivity = LastActivityManager.getInstanceFor (connection);
try {
try {
mLastActivity.getLastActivity (JID);
Log.e (TAG, "" + mLastActivity.getLastActivity (JID));
} catch (SmackException.NoResponseException e) {
e.printStackTrace ( );
}
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace ( );
} catch (SmackException.NotConnectedException e) {
e.printStackTrace ( );
}
}
getting above Exception on following line
mLastActivity.getLastActivity (JID);
Anybody know why getting this exception ?
Likely because you need to be subscribed to the contact's presence in order to retrieve the last activity.
First you need to setup roster once xmpp connection established :
private fun setupRoaster() {
if (conn1 == null) {
Timber.d("setupRoaster failed , due to connection is null $conn1")
} else {
conn1?.let {
roster = Roster.getInstanceFor(conn1)
roster?.subscriptionMode = Roster.SubscriptionMode.manual
roster?.addRosterListener(this)
Timber.d("setupRoaster roster?.entryCount : ${roster?.entryCount}")
roster?.addSubscribeListener(object:SubscribeListener{
override fun processSubscribe(
from: Jid?,
subscribeRequest: Presence?
): SubscribeListener.SubscribeAnswer {
Timber.d("setupRoaster SubscribeListener calledback Approved")
return SubscribeListener.SubscribeAnswer.Approve
}
})
if(BuildConfig.DEBUG){
//Here we are observed all the roster contacts and status
roster?.let {
for(ros in it.entries){
Timber.d("setupRoaster Info isSubscriptionPending :: ${ros.isSubscriptionPending} isApproved :: ${ros.isApproved} type :: ${ros.type} isSubscribedToMyPresence : ${roster?.isSubscribedToMyPresence(ros.jid)} ros.jid : ${ros.jid}")
//ros.isSubscriptionPending
}
}
}
Timber.d("setupRoaster success")
}
Timber.d("setupRoaster failed $conn1")
}
}
To add any user into your roster use below code :
override suspend fun addContactToRoster(toUserId: String, name: String) {
Coroutines.io {
Timber.d("addContactToRoster 1 $toUserId")
if(roster == null){
setupRoaster()
}
if (roster != null) {
Timber.d("addContactToRoster 2 roster?.isLoaded : ${roster?.isLoaded} ")
try {
roster?.let {
if(it.isLoaded && !it.isSubscribedToMyPresence(getJabberId(toUserId))){
val presence = Presence(Presence.Type.subscribe)
presence.setTo(getJabberId(toUserId))
presence.setType(Presence.Type.subscribed)
conn1?.sendStanza(presence)
roster?.createEntry(getJabberId(toUserId), name, null)
}
}
Timber.d("addContactToRoster Contact added to roster successfully")
} catch (e: SmackException.NotLoggedInException) {
Timber.d("addContactToRoster SmackException.NotLoggedInException called ${e.message} conn1?.isConnected ${conn1?.isConnected} conn1.isAuthenticated : ${conn1?.isAuthenticated}")
login()
} catch (e: SmackException.NoResponseException) {
Timber.d("addContactToRoster SmackException.NoResponseException called ${e.message} conn1?.isConnected ${conn1?.isConnected} conn1.isAuthenticated : ${conn1?.isAuthenticated}")
} catch (e: SmackException.NotConnectedException) {
Timber.d("addContactToRoster SmackException.NotConnectedException called ${e.message} conn1?.isConnected ${conn1?.isConnected} conn1.isAuthenticated : ${conn1?.isAuthenticated}")
}
} else {
Timber.d("addContactToRoster Roster not initilized,")
Timber.d("addContactToRoster May when user comes first time at that time internet not available so connection not established")
}
}
}
Once user successfully added to roster and receiver accept your subscription than you can last get activity/last seen by using below method :
fun getLastActivity(userId: String): String? {
Timber.d("XMPP :: getLastActivity $userId called conn1 : $conn1")
val jabberId = getJabberId(userId)
jabberId?.let {
Timber.d("XMPP :: getLastActivity 1 ${jabberId}")
conn1?.let {
Timber.d("XMPP :: getLastActivity 2")
if (it.isConnected && it.isAuthenticated) {
Timber.d("XMPP :: getLastActivity 3")
try {
val lastActivityManager: LastActivityManager =
LastActivityManager.getInstanceFor(conn1)
//val jid : Jid = JidCreate.from("u1304#quantumpigeon.com");
val status = lastActivityManager.isLastActivitySupported(jabberId)
val lastStatus = lastActivityManager.getLastActivity(jabberId)
Timber.d(
"XMPP :: lastStatus.toString $lastStatus \n lastStatus.lastActivity ${lastStatus.lastActivity} " +
"\n lastStatus.idleTime : ${lastStatus.idleTime} \n lastStatus.message : ${lastStatus.message} \n lastStatus.statusMessage : ${lastStatus.statusMessage}"
)
val milliSeconds =
applicationContext.getTrueTimeNow().time - (lastStatus.lastActivity * 1000)
//val lastSeen = getDate(milliSeconds, "dd/MM/yyyy hh:mm:ss.SSS")
val lastSeen = getLastSeen(milliSeconds)
Timber.d("XMPP :: isLastActivitySupported : $status lastStatus : $lastStatus LastSeen : $lastSeen")
return lastSeen
} catch (e: XMPPException.XMPPErrorException) {
Timber.d("XMPP :: Error in get last activity : ${e.message}")
} catch (e: SmackException.NoResponseException) {
Timber.d("XMPP :: SmackException.NoResponseException. : ${e.message}")
} catch (e: SmackException.NotConnectedException) {
Timber.d("XMPP :: SmackException.NotConnectedException. : ${e.message}")
}
} else {
Timber.d("XMPP :: handleNotConnectedException : ${it.isConnected} or authenticated ${it.isAuthenticated}")
// handleNotConnectedException()
}
Timber.d("XMPP :: Connection not connected : ${it.isConnected} or authenticated ${it.isAuthenticated}")
}
Timber.d("XMPP :: Connection not established $conn1")
}
return null
}