Firebase - Count online users - javascript

I tried using presence to make it display the total connected users in an element. I can't really figure out how to make it work.
I also tried doing the following:
var dataUlist = new Firebase('https://<url>.firebaseio.com/.info/connected');
dataUlist.on('value', function(snap) {
console.log(snap);
});
To tried to see if I could find anything useful in there, but I couldn't figure out how the data works.
Is there any way to accomplice what I am after? Fetch the total number of connected users and then echo it out in the console or to an element?

.info/connected will only return information about whether the current client is connected or not. In order to maintain a presence count, you'll need to create a counter by storing presence information for each user and utilizing setOnDisconnect(). For example:
var listRef = new Firebase("https://<url>.firebaseio.com/presence/");
var userRef = listRef.push();
// Add ourselves to presence list when online.
var presenceRef = new Firebase("https://<url>.firebaseio.com/.info/connected");
presenceRef.on("value", function(snap) {
if (snap.val()) {
// Remove ourselves when we disconnect.
userRef.onDisconnect().remove();
userRef.set(true);
}
});
// Number of online users is the number of objects in the presence list.
listRef.on("value", function(snap) {
console.log("# of online users = " + snap.numChildren());
});

Here is the the code from Anant formatted for Android
public void getDbCount() {
Firebase listRef = new Firebase("https://<your-firebase-database>.firebaseio.com/presence/");
final Firebase userRef = listRef.push();
// Add ourselves to presence list when online.
Firebase presenceRef = new Firebase("https://<your-firebase-database>.firebaseio.com/.info/connected");
ValueEventListener myPresence = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// Remove ourselves when we disconnect.
userRef.onDisconnect().removeValue();
userRef.setValue(true);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("DBCount", "The read failed: " + firebaseError.getMessage());
}
};
presenceRef.addValueEventListener(myPresence);
// Number of online users is the number of objects in the presence list.
ValueEventListener myList = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// Remove ourselves when we disconnect.
Log.i("DBCount", "# of online users = " + String.valueOf(snapshot.getChildrenCount()));
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("DBCount", "The read failed: " + firebaseError.getMessage());
}
};
listRef.addValueEventListener(myList);
}

Related

How to add Logout from all other session

My scenario is there are two different users login with same user id and password.mean time one of the person change the password by giving the current password. And changed the password at same time the another user gives current password what he logged in was incorrect. So i wants to add logout from all other devices in my web application.how can i do that
There is of course more than one approach, my first idea would be to hook the sessions to the ServletContext. Something like
// this can be in some util class, let's call it SessionUtil
static final String SESSION_REGISTER = "session.register";
public static synchronized void registerSession(ServletRequest req, HttpSession ses, String userName) {
ServletContext ctx = req.getServletContext();
Map<String, List<HttpSession>> register = (Map<String, List<HttpSession>>) ctx.getAttribute(SESSION_REGISTER);
if (register == null) {
register = new HashMap<>();
ctx.setAttribute(SESSION_REGISTER, register);
}
List<HttpSession> sessions = register.computeIfAbsent(userName, k -> new ArrayList<>());
sessions.add(ses);
}
Then, in your code, you need to register the user's session after login:
HttpSession ss = request.getSession();
if (isUser(name,password)) {
ss.setAttribute("user",name)
SessionUtil.registerSession(request, ss, name);
}
Finally, you need a method (again in SessionUtil class) to invalidate all the user's sessions (except the current one):
public static synchronized void invalidateSessions(ServletRequest req, HttpSession current, String userName) {
ServletContext ctx = req.getServletContext();
Map<String, List<HttpSession>> register = (Map<String, List<HttpSession>>) ctx.getAttribute(SESSION_REGISTER);
if (register != null) {
List<HttpSession> sessions = register.get(userName);
if (sessions != null) {
for (HttpSession ses : sessions) {
if (!ses.equals(current)) {
ses.invalidate();
}
}
}
}
}
Then you can call this method e.g. when the user changes his/her password.
Note #1: Not a very nice code, it misses some sanity checks and synchronized can be smaller chunks of code. It's just to give you an idea.
Note #2: The functionality of the registerSession(...) method can be done using the HttpSessionAttributeListener, but I've never used it yet, so cannot give an example.

WCF service hosed in application can't be accessed from javascript?

I have an console application which starts a WCF service, and I want to access it in an html file using javascript.
Don't want to use web.config because it seems too complicated. and I want to host the service in an addon of an application later. (but if web.config meets my requirement, it is ok to use it too).
Following is the service code:
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080");
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.AddServiceEndpoint(typeof(IHelloWorldService), new BasicHttpBinding(), "bh");
host.AddServiceEndpoint(typeof(IHelloWorldService), new WebHttpBinding(WebHttpSecurityMode.None), "wb");
host.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
[WebGet(UriTemplate = "/SayHello?name={name}", ResponseFormat = WebMessageFormat.Json)]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
public string SayHello(string name)
{
Console.WriteLine("called SayHello");
return string.Format("Hello, {0}", name);
}
}
And I want to access the service using javascript from a single html file, e.g. index.html like this:
jQuery.post("http://localhost:8080/HelloWorldService.svc/wb/SayHello", {name:"kii"}, function(ret){alert(ret);}});
Or like this:
jQuery.get("http://localhost:8080/HelloWorldService.svc/wb/SayHello?name=kii", function(ret){alert(ret);}});
But they don't work.
"POST" method got "404 Not Found"
and
"GET" method got "405 Method Not Allowed"
Any suggestion?
thanks very much~~
here is the modified program for your reference.
class Program {
static void Main(string[] args) {
Uri baseAddress = new Uri("http://localhost:8080");
using (ServiceHost host = new ServiceHost(
typeof(HelloWorldService), baseAddress)) {
host.Description.Behaviors.Add(
new ServiceMetadataBehavior { HttpGetEnabled = true });
host.AddServiceEndpoint(
typeof(IHelloWorldService), new BasicHttpBinding(), "bh");
var webEndPoint = host.AddServiceEndpoint(
typeof(IHelloWorldService),
new WebHttpBinding(WebHttpSecurityMode.None), "wb");
webEndPoint.Behaviors.Add(new WebHttpBehavior());
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
host.Open();
var n = 0;
foreach (var endPoint in host.Description.Endpoints) {
Console.WriteLine("endpoint " + n);
Console.WriteLine(" address: " + endPoint.Address);
Console.WriteLine(" absolute path: " + endPoint.ListenUri.AbsolutePath);
Console.WriteLine(" absolute uri: " + endPoint.ListenUri.AbsoluteUri);
n++;
}
Console.WriteLine();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
}
}
}
The only actual difference is to add WebHttpBehavior into the web endpoint.
running this program, and open brower to test address localhost:8080/wb/sayhello?name=abc
if the brower returns "abc", that means the web end point is working.
if calling this address by jQuery is still not working, then trouble-shooting on jQuery side.

Sorting List alphabetically from JSON source

I've looked in a variety of places for an answer to my query, but nothing has helped me thus far. I'm currently trying to learn Android development, and i'm stuck on how to sort a list alphabetically. I am using this tutorial on how to create the list and have modified parts of the "Albums" page to suit my needs, from albums to artists (i'm still working on this, just wanting the sorting finished before changing it fully). This particular list calls on a file from a HTTP address when the app is accessed to check it for updates.
Here is the code from that particular page, minus all the imports:
public class AlbumsActivity extends ListActivity {
// Connection detector
ConnectionDetector cd;
// Alert dialog manager
AlertDialogManager alert = new AlertDialogManager();
// Progress Dialog
private ProgressDialog pDialog;
// Creating JSON Parser object
JSONParser jsonParser = new JSONParser();
ArrayList<HashMap<String, String>> albumsList;
// albums JSONArray
JSONArray albums = null;
// albums JSON url
private static final String URL_ALBUMS = "http://api.androidhive.info/songs/albums.php";
// ALL JSON node names
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_SONGS_COUNT = "songs_count";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_albums);
cd = new ConnectionDetector(getApplicationContext());
// Check for internet connection
if (!cd.isConnectingToInternet()) {
// Internet Connection is not present
alert.showAlertDialog(AlbumsActivity.this, "Internet Connection Error",
"Please connect to working Internet connection", false);
// stop executing code by return
return;
}
// Hashmap for ListView
albumsList = new ArrayList<HashMap<String, String>>();
// Loading Albums JSON in Background Thread
new LoadAlbums().execute();
// get listview
ListView lv = getListView();
/**
* Listview item click listener
* TrackListActivity will be lauched by passing album id
* */
lv.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view, int arg2,
long arg3) {
// on selecting a single album
// TrackListActivity will be launched to show tracks inside the album
Intent i = new Intent(getApplicationContext(), TrackListActivity.class);
// send album id to tracklist activity to get list of songs under that album
String album_id = ((TextView) view.findViewById(R.id.album_id)).getText().toString();
i.putExtra("album_id", album_id);
startActivity(i);
}
});
}
/**
* Background Async Task to Load all Albums by making http request
* */
class LoadAlbums extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(AlbumsActivity.this);
pDialog.setMessage("Listing Artists...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
/**
* getting Albums JSON
* */
protected String doInBackground(String... args) {
// Building Parameters
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
String json = jsonParser.makeHttpRequest(URL_ALBUMS, "GET",
params);
// Check your log cat for JSON reponse
Log.d("Albums JSON: ", "> " + json);
try {
albums = new JSONArray(json);
if (albums != null) {
// looping through All albums
for (int i = 0; i < albums.length(); i++) {
JSONObject c = albums.getJSONObject(i);
// Storing each json item values in variable
String id = c.getString(TAG_ID);
String name = c.getString(TAG_NAME);
String songs_count = c.getString(TAG_SONGS_COUNT);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_NAME, name);
map.put(TAG_SONGS_COUNT, songs_count);
// adding HashList to ArrayList
albumsList.add(map);
}
}else{
Log.d("Albums: ", "null");
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
/**
* After completing background task Dismiss the progress dialog
* **/
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all albums
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
AlbumsActivity.this, albumsList,
R.layout.list_item_albums, new String[] { TAG_ID,
TAG_NAME, TAG_SONGS_COUNT }, new int[] {
R.id.album_id, R.id.album_name, R.id.songs_count });
// updating listview
setListAdapter(adapter);
}
});
}
}
}
My problem is that I have no real idea where I need to put the Collections.sort command. I have tried in so many places, but cannot get it working. No matter where I put the command, it always sorts in order of ID. This is the full code I have for that:
Collections.sort(params, new Comparator<NameValuePair>() {
#Override
public int compare(NameValuePair art1, NameValuePair art2) {
//here getTitle() method return app name...
return art1.getName().compareToIgnoreCase(art2.getName());
}
});
If I try to have return art1.name.compareToIgnoreCase(art2.name); it comes back with an error that says name cannot be resolved or is not a field. I'm really stumped. I thought a list might be a good way to start learning to develop for Android, but now i'm finding this incredibly hard.
Any help would be greatly appreciated.

Using javascript timers with signalR events to check for new data

I have this table, with a set of rows, each using a unique connection to signalR. This allows me to update several rows at the same time with unique content.
The way it works is that a service bus provides the messagehub with new values and a uniqe id to go with that value, every time a remote unit transmits a new message.
At this point i'd like to run a check every 10 seconds to see if the webserver still gets a message from the unit, which transmits this as long as it is alive. In other words, if there's more than 10 seconds since the last time SignalR gave me a value, this would indicate that the connection to the remote unit is lost. (Not to be mistaken with SignalR losing its connection)
As I have a lot of units (rows) in my table, I was wondering if a javascript timer for each row would be sufficient for this check, or is there a better way of doing this? If so, do I do this in my connector script or in my html?
A single timer firing every 10 seconds and scanning all your signalr connections should work fine.
Ok, so I figured this out in another way, letting my messagehandler take care of the task of distributing messages at the correct time:
public class AsxActivityAliveEventMessageHandler : IHandleMessages<AsxActivityAliveEvent>
{
private const double INTERVAL = 10000;
public static bool AsxConnected { get; set; }
private static Dictionary<String, TagTimer> _connectionTimers = new Dictionary<string, TagTimer>();
public void Handle(AsxActivityAliveEvent message)
{
AsxConnected = true;
NotifyClients(message);
TagTimer timer;
if (_connectionTimers.ContainsKey(message.ConveyanceId))
{
timer = _connectionTimers[message.ConveyanceId];
if (timer != null)
{
timer.Stop();
timer.Elapsed -= timer_Elapsed;
_connectionTimers.Remove(message.ConveyanceId);
}
}
timer = new TagTimer
{
Interval = INTERVAL,
Tag = message
};
timer.Elapsed += timer_Elapsed;
_connectionTimers.Add(message.ConveyanceId, timer);
timer.Start();
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
var timer = sender as TagTimer;
if (timer != null)
{
timer.Stop();
timer.Elapsed -= timer_Elapsed;
}
AsxConnected = false;
if (timer != null)
{
NotifyClients(timer.Tag as AsxActivityAliveEvent);
}
}
static void NotifyClients(AsxActivityAliveEvent message)
{
var messageHub = GlobalHost.ConnectionManager.GetHubContext<MessageHub>();
var conveyanceId = message.ConveyanceId;
// Removed some vars and notify's as they're not relevant to this example
messageHub.Clients.Group(message.ConveyanceId).notifyAlive(AsxConnected, conveyanceId);
}
}
internal class TagTimer : Timer
{
public object Tag { get; set; }
}
}

Function to add and remove a username

In my chat application project, I am trying to broadcast usernames to all the users whenever a new user is connected to a server. and remove a username whenever the user leaves the server. The below is the code which I have tried by going through tutorials. (please check the file.js file which is not showing the desired output)
Chat.cs (Working) --> Implements "Hub" class of SignalR
public class Chat : Hub
{
/* showing only related content */
static ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>();
public override Task OnDisconnected()
{
var user = _users[Context.ConnectionId]; //user as ConnectionId
User removedUser; //new class object
_users.TryRemove(Context.ConnectionId, out removedUser);
return Clients.All.leave(user, DateTime.Now.ToString()); //dynamic expression
}
public void Joined()
{
User user = new User(Context.ConnectionId, Clients.Caller.username);
_users.TryAdd(user.ConnectionID, user);
Clients.All.joins(user.ConnectionID, user.Name, DateTime.Now); //dynamic expression
}
}
User.cs (Working)
public class User
{
public User(string ConnID, string Username)
{
Name = Username;
ConnectionID = ConnID;
}
public string Name { get; set; }
public string ConnectionID { get; set; }
}
file.js (not working)
var chatUsername = window.prompt("Enter Username:", ""); //username
var chat = $.connection.chat; //connection
//
chat.client.joins = function (ConnectionId, name, Date) {
ConnectionId = 1; /* given value to just test */
name = chatUsername;
};
chat.client.leave = function (user, date) {
user = ""; //making the string empty so that the disconnected user value will be lost.
};
//Here is the connection which calls the "Joined" function of the server (Chat.cs)
What should I write in file.js functions (joins and leave) so that I will get the desired result as I mentioned above. Before asking here, I have gone through this site which is doing the same but including additional javascript files(knockout.js and json) which I dont want to include.(bcos I am new to jquery).
In order to pass UserNames to the client you can take your dictionary and in your joined server side method you could change the SignalR line to be:
Clients.All.joins(_users.Values); //dynamic expression
Then the client version of joins would be:
chat.client.joins = function (users) {
for(var i = users.length - 1; i >= 0; i--) {
alert("User Name: " + users[i].Name + "\nUser Connection ID: " + users[i].ConnectionID);
}
};
Of course you can handle the user information differently than alerting it, but that's the gist of how to handle the data. Lastly, I'd recommend against passing down the connection ID to everyone because a third party could then easily hijack it.

Categories