I have a socket.io project and my client is using android. Connection event is fired on the server-side but join match is not. any ideas why?
socket.connect();
on the client-side, fires the below code on server-side:
io.on('connection', (socket) => {
try {
console.log("connected!");
self.handleJoinMatch(io, socket);
})
} catch (ex) {
console.log(ex.toString());
}
});
connected is logged on the console. handleJoinMatch function is:
handleJoinMatch(io, socket) {
console.log("handle join match is called!");
socket.on('join match', (params) => {
console.log("join matched is recieved!");
.........
handle join match is called! is logged on the console as well, but the below code does nothing:
socket.emit("join match");
update1:
I should mention the even after 10 minutes if I close the android app, the below code is called:
socket.on('disconnect', (reason) => {
console.log("disconnected");
......
update2:
I just realized that in my client, after socket.connect(), socket.connected() returns false and socket.on("connect", connectHandler); is not being called at all.
Related
I have developed screen casting app. I am making connection using twilio but I want to share touch events from receiver(participant) to sender(host) as a live data. Is there any possible solution to simplify this?
If you are using Twilio Video for this connection then you can use the DataTrack API to send arbitrary data over your connection.
You can create a LocalDataTrack object:
const { LocalDataTrack } = require(`twilio-video`);
const dataTrack = new LocalDataTrack();
Connect it to a room, either by sending it as part of the tracks option when connecting, or by publishing it to the room after a connection has been made.
const { connect } = require('twilio-video');
const room = await connect('$TOKEN', {
name: 'my-chat-room',
tracks: [dataTrack]
});
You can send a message down the data track once it is published:
dataTrack.send(message)
And you can receive data track messages by subscribing to the track and listening for the message event:
participant.on('trackSubscribed', track => {
console.log(`Participant "${participant.identity}" added ${track.kind} Track ${track.sid}`);
if (track.kind === 'data') {
track.on('message', data => {
console.log(data);
});
}
});
See the documentation for more detail.
I'm using pusher in my app to get some live values in-app from the server.
I'm subscribing to static channelName but somehow the user can't get data from the server if he keeps the app for a long time open, if the user restarts the app it works fine.
in the pusher dashboard it works well and shows data go to users but, it's not.
when I read on pusher I found that there is ping-pong but, even if I increased pong time it fails too
here is my code:
1- for pusher & channel create ( called in on create ):
options = new PusherOptions();
String APP_CLUSTER = "APP_CLUSTER ";
options.setCluster(APP_CLUSTER);
String APP_KEY = "APP_KEY ";
pusher = new Pusher(APP_KEY, options);
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
Log.e("PUSHER SUCCESS => ", change.getCurrentState().name());
}
#Override
public void onError(String message, String code, Exception e) {
Log.e("PUSHER FAILED => ", message);
}
}, ConnectionState.ALL);
2- channel bind & subscribe ( called in onResume ):
channel = pusher.subscribe("xxx");
channel.bind("MessageCreated", event -> {
Log.e("PUSHER DATA => ", event.getData());
});
3- channel un-subscribe ( called in onPause):
pusher.unsubscribe("xxx");
4- disconnect pusher ( called in onDestroy ):
pusher.disconnect();
I hope if anyone can give me the reason for disconnecting for some users, can someone tell me
Structure of my app:
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MdpMainPage();
}
MdpMainPage is a MasterDetailPage:
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<pages:HomePage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
My HomePage is a CarouselPage and it contains three pages of type ContentPage.
<CarouselPage>
...some namespaces...
<CarouselPage.Children>
<pages:HomePageA />
<pages:HomePageB />
<pages:HomePageC />
</CarouselPage.Children>
</CarouselPage>
I would like to use JamesMontemagno's ConnectivityPlugin to WATCH for internet connection CHANGES.
DisplayAlert box should pop up when the application starts and it should tell us either:
DisplayAlert("Internet connection found.", "Wait for the application data to update.", "OK");
...or...
DisplayAlert("No internet connection found.", "Application data may not be up to date. Connect to a working network.", "OK");
If there was internet connection at the start of the application and it gets lost during the using of the app, another message box should pop up saying:
DisplayAlert("Internet connection lost.", "Application data may not be up to date. Connect to a working network.", "OK");
If there was no internet connection at the start of the application and somehow later the device connects successfully, the firstly mentioned message box should appear:
DisplayAlert("Internet connection found.", "Wait for the application data to update.", "OK");
I've tried to figure out the correct implementation with the help of the provided Documentation.
Unfortunately, James Montemagno doesn't bother to explain in detail how to use the ConnectivityPlugin, so beginners like myself tend to end up confused.
I know I should use the following code snippets:
/// <summary>
/// Event handler when connection changes
/// </summary>
event ConnectivityChangedEventHandler ConnectivityChanged;
public class ConnectivityChangedEventArgs : EventArgs
{
public bool IsConnected { get; set; }
}
public delegate void ConnectivityChangedEventHandler(object sender, ConnectivityChangedEventArgs e);
CrossConnectivity.Current.ConnectivityChanged += async (sender, args) =>
{
Debug.WriteLine($"Connectivity changed to {args.IsConnected}");
};
...but I don't know where to put them.
I've tried a couple of combinations, but to no avail so far.
Do I put some in the App.xaml and some in the MasterDetailPage?
Or rather one of the Detail pages?
Or in each of the detail pages?
Please don't think I didn't google around. Because I did and everybody seems to have a different opinion on how to flavor the basic Montemagno recipe, which is very confusing.
Could somebody provide the simplest, cleanest way to implement this? Nothing fancy really, just message boxes that inform the user about changes in connectivity.
Help would be much appreciated.
Thank you all.
Let's say you have a dozen pages in your application. It wouldn't make sense to have connectivity code in all of them. A better place to subscribe to the events would be your App.xaml.cs inside the OnStart method (could also be inside the constructor). This is what I have in one of the projects:
protected override void OnStart()
{
CrossConnectivity.Current.ConnectivityChanged += (sender, args) =>
{
MessagingService.Current.SendMessage("connectivityChanged", args.IsConnected);
};
}
MessagingService is from James Montemagno's Xamarin.Forms Toolkit but you can also use Xamarin's Messaging Center.
Then, on each ViewModel of those pages that want to subscribe to this message of a connection change will subscribe to it like this:
MessagingService.Current.Subscribe ("connectivityChanged", async (e) =>
{
//Show a dialog or something to inform about the connectivity change.
});
This way you'll have everything decoupled.
Edit: I just noticed you're probably looking to show the alert from a code behind of the page. You could simply subscribe to the event on your MasterDetailPage like this:
public class MainPageCS : MasterDetailPage
{
public MainPageCS()
{
MessagingService.Current.Subscribe<bool>("connectivityChanged", (args, connected) =>
{
if (connected)
DisplayAlert("Internet connection found.", "Wait for the application data to update.", "OK");
else
DisplayAlert("Internet connection lost.", "Application data may not be up to date. Connect to a working network.", "OK");
});
}
}
Any time the connectivity changes, your App.xaml.cs handles the event and sends a message to the MessagingService which is received by the MasterDetailPage that reacts to it.
Edit 2: Put this into your App.xaml.cs so the connection gets checked only when the app starts.
protected override void OnStart()
{
Device.BeginInvokeOnMainThread(async () =>
{
var isConnected = CrossConnectivity.Current.IsConnected;
await MainPage.DisplayAlert("Connection", $"Connected {isConnected}", "OK");
});
}
I'm trying to set up a Websocket client that communicates with a websever via JSON. I don't find any good examples online.
I only found this code online :
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
// connection opened
ws.send('something'); // send a message
};
ws.onmessage = (e) => {
// a message was received
console.log(e.data);
};
ws.onerror = (e) => {
// an error occurred
console.log(e.message);
};
ws.onclose = (e) => {
// connection closed
console.log(e.code, e.reason);
};
I don't know how to integrate this code into my app-code to function.
Do I need to install some packages for it?
I'm doing a project for my studies, and at the end I should have a Quiz-App which connects to a server to get the questions and answers for the game.
Thanks for anny help!
You do not need anything else to work with a WebSocket in react-native (or any relatively new JS environment for that matter). The example that you found covers pretty much anything that you need to get started. The next step is to bind that to your React logic. For instance, you can create a WebSocketController component that would look (details omitted) like this
class WebSocketController extends React.Component {
componentDidMount(){
this.ws = new WebSocket('ws://host.com/path');
this.ws.onmessage = this.handleMessage.bind(this);
this.ws.onerror = //...
}
handleMessage(e){
// dispatch event (รก la redux, flux), or do something else
}
componentWillUnmount(){
// close WS
}
}
Render this within your React hierarchy and it will be started along the rest of your components. If you need something more specific, let us know.
i am building my app on android repository by Fernando Cejas and i have a problem with subscribing to observable after calling dispose.
When i come to dashboard, i call method subscribeOnUserMessages.execute(new Subscriber(), new Params(token)), which is method in UseCase class
public void execute(DisposableObserver<T> observer, Params params) {
Preconditions.checkNotNull(observer);
final Observable<T> observable = this.buildUseCaseObservable(params)
.subscribeOn(Schedulers.from(threadExecutor))
.observeOn(postExecutionThread.getScheduler());
addDisposable(observable.subscribeWith(observer));
}
In child class SubscribeOnUserMessages i simply call repository like this
return messageRepository.subscribeOnUserMessages(params);
In my socket implementation i create like this
return Observable.create(emitter -> {
if (!isThereInternetConnection()) {
Timber.w("Network connection exception");
emitter.onError(new NetworkConnectionException());
return;
}
/*
* Open socket if not opened
*/
openSocket(params.getToken());
String channelName = CHANNEL_PRIVATE_USER + params.getAuthenticated().getUuid();
if (subscribedChannels.contains(channelName)) {
Timber.d("Channel %s is already subscribed", channelName);
return;
}
JSONObject auth;
try {
auth = createAuthJson(CHANNEL, channelName, params.getToken());
} catch (JSONException e) {
Timber.e("Couldn't create auth json");
emitter.onError(e);
return;
}
mSocket.emit(SUBSCRIBE, auth);
Timber.d("Emitted subscribe with channel: %s ", CHANNEL_PRIVATE_USER + params.getAuthenticated().getUuid());
subscribedChannels.add(CHANNEL_PRIVATE_USER + params.getAuthenticated().getUuid());
Timber.d("Subscribing on event: %s\n with user: %s", EVENT_USER_NEW_MESSAGE, params.getAuthenticated().getUuid());
if (mSocket.hasListeners(EVENT_USER_NEW_MESSAGE)) {
Timber.v("Socket already has listener on event: %s", EVENT_USER_NEW_MESSAGE);
return;
}
mSocket.on(EVENT_USER_NEW_MESSAGE, args -> {
if (args[1] == null) {
emitter.onError(new EmptyResponseException());
}
Timber.d("Event - %s %s", EVENT_USER_NEW_MESSAGE, args[1].toString());
try {
MessageEntity messageEntity = messageEntityJsonMapper.transform(args[1]);
emitter.onNext(messageEntity);
} catch (JSONException e) {
Timber.e(e, "Could not parse message json");
emitter.onError(e);
}
});
});
Symptoms are that first time i subscribe everything is going through to presentation layer. When i dispose after going to second screen and come back i only see logs coming to socket implementation, but not going through.
My question is: Is there a method for subscribing to same observable again? I've already tried to save that observable in my use case in singleton and subscribe to that observable, didn't help.
Without additional info and details regrading socket implementation it is hard to spot the problem exactly, but, from the code you've posted, you don't have dispose logic, so while you might properly call dispose() to the Observable at the correct lifecycle event, your socket will actually stay open, and it might not got disconnected/closed properly ever.
That might lead to a problems opening and connecting to the socket at the 2nd time, as you might try to reopen already open socket and depends on your internal socket impl that might be a problem.
(I can see in the comment that openSocket if not already opened, but still there might be problem elsewhere calling some method on the socket multiple times or setting listeners, again depends on the socket impl)
As a general guidelines, you should add dispose logic using emitter.setCancellable()/emitter.setDisposable() in order to dispose properly the socket resources when you no longer need them, thus - when applying subscribe again (whether the same object or not) will invoke your subscription logic again that will reopen the socket and listen to it.
It is not clear to me if you like to keep the socket open when you moving to a different screen (I don't think it is a good practice, as you will keep this resource open and might never get back to the screen again to use it), but if that's the case as #Phoenix Wang mentioned, you can use publish kind operators to multicast the Observable, so every new Subscriber will not try to reopen the socket (i.e. invoking the subscription logic) but will just get notify about messages running in the already opened socket.