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.
Related
I am a beginner in android application development(Kotlin) and recently I was handover a project on NFT which involves walletConnect integration & for that I am using the walletConnectV1 library.
Fetching the public key and Connecting with metamask was not so hard but I am struggling when it comes to signing methods.
if anyone can help me with, how to sign messages and transactions or what I was doing wrong all this time that would really help me.
Thank you
Connect Button Click Listener
screen_main_connect_button.setOnClickListener {
try {
ExampleApplication.resetSession()
ExampleApplication.session.addCallback(this)
val i = Intent(Intent.ACTION_VIEW, Uri.parse(ExampleApplication.config.toWCUri()))
startActivity(i)
} catch (e: ActivityNotFoundException) {
// open play store
} catch (e: Exception) {
//handle exceptions
}
}
Response after the session was approved
private fun sessionApproved() {
uiScope.launch {
val account = session.approvedAccounts()?.get(0)?:""
screen_main_status.text = "Connected: $account"
screen_main_connect_button.visibility = View.GONE
screen_main_disconnect_button.visibility = View.VISIBLE
screen_main_tx_button.visibility = View.VISIBLE
val job = async {
personalSign(
"Sign this message of mine to this address",
account) {
Log.d(TAG, "sessionApproved: ${it.result}")
}
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("wc:")
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
}
}
private fun personalSign(
message: String,
address: String,
response: (Session.MethodCall.Response) -> Unit
) {
val id = System.currentTimeMillis()
val messageParam = if (message.hasHexPrefix()) message else message.toHex()
session.performMethodCall(
Session.MethodCall.Custom(
id, "personal_sign", listOf(messageParam, address)
)
) { response(it) }
}
When i try to connect my android app with socket.io, it saying invalid namespace. There is no issue with socket url , but having problem in connection, please help if you faced this issue ever. Thanks!
val options = io.socket.client.IO.Options().apply {
forceNew = false
reconnection = true
}
private val socket: Socket = io.socket.client.IO.socket(socket_url,options)
val socket = applicationAccessorImpl.socket
socket.connect()
socket.once(Socket.EVENT_CONNECT) {
try {
Log.d(TAG, "connect")
} catch (e: Exception) {
Log.d(TAG, e.message!!)
}
}.on(Socket.EVENT_CONNECT_ERROR) {
val e = it[0]
Log.e(TAG, "error $e")
}.on(Socket.EVENT_DISCONNECT) {
val e = it[0]
Log.e(TAG, "Transport error $e")
}
Sorry , it was my mistake , i was passing the wrong url 😋
Razorpay callbacks is not working in fragment instead of activity using fragment please give a solution If anyone aware thanks in advance.
private fun startPayment() {
val activity: Activity = requireActivity()
val co = Checkout()
try {
val options = JSONObject()
options.put("name", "Vendor")
options.put("description", " for Order")
//You can omit the image option to fetch the image from dashboard
options.put("image", "https://rzp-mobile.s3.amazonaws.com/images/rzp.png")
options.put("currency", "INR")
val payment: String = "1"//getcart?.CartTotal.toString()
// amount is in paise so please multiple it by 100
//Payment failed Invalid amount (should be passed in integer paise. Minimum value is 100 paise, i.e. ₹ 1)
var total = payment.toDouble()
total = total * 100
options.put("amount", total)
val preFill = JSONObject()
preFill.put("email", "hell#gmail.com")
preFill.put("contact", "9898989898")
options.put("prefill", preFill)
co.open(requireActivity(), options)
} catch (e: Exception) {
Toast.makeText(activity, "Error in payment: " + e.message, Toast.LENGTH_SHORT).show()
e.printStackTrace()
}
}
override fun onPaymentSuccess(s: String?) {
toast("onPaymentSuccess")
Log.i(TAG, "onPaymentSuccess: $s")
}
override fun onPaymentError(i: Int, s: String?) {
Log.e(TAG, "error code "+i.toString()+" -- Payment failed "+s.toString())
try {
toast("Payment error please try again")
} catch (e : Exception) {
Log.e("OnPaymentError", "Exception in onPaymentError", e);
}
}
Amount should be in Integer and in paise.
implement result listener to the fragment host activity and override error and success function there.
in fragment you won't get Razorpay callback function, so you should implement PaymentResultListener or PaymentResultWithDataListener in activity and from activity you have call your fragment and do your api call for razor pay response.
in your Activity:
#Override
public void onPaymentSuccess(String s, PaymentData paymentData) {
try {
FeeFragment feeList = (FeeFragment) mViewPager.getAdapter().instantiateItem(mViewPager, mViewPager.getCurrentItem());
feeList.checkRazorResponse(paymentData, true);
} catch (Exception e) {
Log.e("Exception in success", e.toString());
e.printStackTrace();
}
}
in your Fragment:
public void checkRazorResponse(PaymentData paymentData, boolean success) {
if (success) {
updatePaymentStatus(paymentData);
//do your api call
} else {
//handle error message
}
}
Razorpay payment integration is not supported on the fragment. You have to implement it on Activity.
Like this way
This code is for fragment:
binding.tvPlaceOrder.setOnClickListener(view -> {
startActivity(new Intent(getActivity(), PaymentActivity.class));
}
}
});
This code is for Activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityPaymentBinding.inflate(layoutInflater)
setContentView(binding.root)
payOnline()
}
private fun payOnline() {
val checkout = Checkout()
checkout.setKeyID(getString(R.string.razorpay_api_key))
checkout.setImage(R.mipmap.ic_launcher)
try {
val options = JSONObject()
options.put("name", "mName")
options.put("currency", "INR")
options.put("image", R.mipmap.ic_launcher)
options.put("amount", 10000) //pass amount in currency subunits
options.put("prefill.email", "roydeveloper01#gmail.com")
options.put("prefill.contact", "8620828385")
checkout.open(this, options)
} catch (e: Exception) {
Toast.makeText(this, "Error in starting Razorpay Checkout: $e", Toast.LENGTH_LONG).show()
}
}
override fun onPaymentSuccess(p0: String?) {
try {
binding.tvId.text = "Payment Successful \n Transaction ID $p0"
} catch (e: NoSuchAlgorithmException) {
binding.tvId.text ="Exception"
}
}
override fun onPaymentError(p0: Int, p1: String?) {
try {
binding.tvId.text ="Exception: $p1"
} catch (e: NoSuchAlgorithmException) {
e.printStackTrace()
}
binding.tvId.text ="Error: $p1"
}
My problem is solved this way. I think your problem will also solve . Best of luck.
viewModelScope.launch {
val req = RequestCodeMutation(phoneNumber)
val response = try {
ApolloClientManager
.apolloClient
.suspendMutate(req)
}
catch (e: ApolloException) {
println(e.message)
isError.value = true
null
}
finally {
loading.value = false
}
val requestCode = response?.data?.requestCode
println(response?.errors)
}
suspend fun <D : Operation.Data, T, V : Operation.Variables> ApolloClient.suspendMutate(mutation: Mutation<D, T, V>): Response<T> =
mutate(mutation).toDeferred().await()
This is my validator on server side. It is shown correctly on Graphiql, however, I am unable to receive this message on client side.
requestCode = async (resolve, source, args, context, info) => {
let { phoneNumber } = args;
phoneNumber = validator.trim(phoneNumber);
Object.assign(args, { phoneNumber });
if (!validator.isMobilePhone(phoneNumber)) {
throw new UserInputError('Invalid phone number provided!');
}
return resolve(source, args, context, info);
}
ApolloException.message is showing Internal Server Error and response?.errors is null.
response?.errors is not supposed to be null and show the proper error message that is being shown on GraphiQL.
In your catch block, you can build a new Response, based on the ApolloCall.
So consider the following:
import com.apollographql.apollo.api.Response
import com.apollographql.apollo.api.Error
fun <T> executeCall(call: ApolloCall<T>): Response<T> = try {
apolloCall.toDeferred().await()
} catch (apolloException: ApolloException) {
val error = Error(apolloException.message ?: "Unknown Error")
Response.builder(apolloCall.operation()).errors(listOf(error)).build()
}
Note: I assume that ApolloClientManager.apolloClient.suspendMutate(req) returns an instance of ApolloCall<T>.
You can then use this function like:
val call = ApolloClientManager.apolloClient.suspendMutate(RequestCodeMutation(phoneNumber))
val response = executeCall(call)
// check the response status code
I'm trying to subscribe to a topic via my Android application. Even though it connects successfully subscription fails. As soon as I perform subscription call, IOT connectivity fails and gives an error log as stated below. Want to Know where have I done any wrong coding ?
All the resources of IOT policy is given due to testing purposes to find a clue.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "iot:*",
"Resource": "*"
}
]
}
I referred AWS-amplify for my development.
https://aws-amplify.github.io/docs/android/pubsub
1 .Connecting to IOT
private var mAWSMobileClient : AWSMobileClient = AWSMobileClient.getInstance()
private lateinit var mIotDataManager: AWSIotMqttManager
private lateinit var mAttachedPolicyReq: AttachPolicyRequest
private lateinit var mAwsIOTClient: AWSIotClient
private lateinit var mAwsCredentials: AWSCredentials
private fun connectToIOT() {
Thread(Runnable {
var mDeviceIdentity = Settings.Secure.getString(this.contentResolver, Settings.Secure.ANDROID_ID)
mIotDataManager = AWSIotMqttManager(mDeviceIdentity, <iot endpoint>)
mIotDataManager.keepAlive = 50
mIotDataManager.isAutoReconnect = false
mIotDataManager.connectionStabilityTime = 100
mAwsCredentials = mAWSMobileClient.awsCredentials
mAwsIOTClient = AWSIotClient(mAWSMobileClient)
mAwsIOTClient.setRegion(Region.getRegion(Regions.AP_SOUTHEAST_2))
mAttachedPolicyReq = AttachPolicyRequest()
mAttachedPolicyReq.policyName = "test_policy"
mAttachedPolicyReq.target = mAWSMobileClient.identityId
mAwsIOTClient.attachPolicy(mAttachedPolicyReq)
try {
mIotDataManager.connect(mAWSMobileClient, object : AWSIotMqttClientStatusCallback {
override fun onStatusChanged(
status: AWSIotMqttClientStatusCallback.AWSIotMqttClientStatus?,
throwable: Throwable?
) {
when (status) {
AWSIotMqttClientStatusCallback.AWSIotMqttClientStatus.ConnectionLost -> {}
AWSIotMqttClientStatusCallback.AWSIotMqttClientStatus.Connected -> {}
AWSIotMqttClientStatusCallback.AWSIotMqttClientStatus.Connecting -> {}
AWSIotMqttClientStatusCallback.AWSIotMqttClientStatus.Reconnecting -> {}
else -> {
}
}
}
})
} catch (e: Exception) {
Log.d("IOT Data Manager Connection Errror : $e")
}
}).start()
}
Subscription Method
fun subscribeToThing() {
if(mConnected) {
Thread(Runnable {
mThingsName = "$mThingsName/shadow/get/accepted"
var message: String? = null
try {
mIotDataManager.subscribeToTopic(
mThingsName,
AWSIotMqttQos.QOS1,
object : AWSIotMqttNewMessageCallback {
override fun onMessageArrived(topic: String?, data: ByteArray?) {
try {
message = String(data!!, Charsets.UTF_8)
} catch (e: UnsupportedEncodingException) {
Log.d("Unsupported Encoding error :$e")
}
}
})
} catch (e: Exception) {
Log.d("Subscription error :$e")
}
}).start()
} else {
Log.d("IOT Not Connected")
}
}
Result Log :
W/AWSIotMqttManager: connection is Lost
Subscription error :com.amazonaws.AmazonClientException: Client error
when subscribing.
I see that you are using AWSMobileClient. Perhaps you did not initialize the mobile client instance prior to using the IOT client? The details are outlined in the following documentation.