InputFilter used on Android EditText to limit to a number range

In my Android app, I had a need to limit a number in an EditText widget between a certain range. Namely, 0-59, for time entry pertaining to minutes and seconds. Enter Android’s InputFilters, which are an easy and useful way to limit input in an EditText.

First of all, the EditText is defined in the layout XML as follows:

This ensures that the EditText should be a number, of 2 digit length, with initial value “0”.

Then in your code, you’ll need to define an InputFilter as follows:

public class InputFilterMinMax implements InputFilter {
   private int minimumValue;
   private int maximumValue;

   public InputFilterMinMax(int minimumValue, int maximumValue) {
      this.minimumValue = minimumValue;
      this.maximumValue = maximumValue;
   }

   @Override
   public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
      try {
         int input = Integer.parseInt(dest.subSequence(0, dstart).toString() + source + dest.subSequence(dend, dest.length()));
         if (isInRange(minimumValue, maximumValue, input))
            return null;
      }
      catch (NumberFormatException nfe) {
      }
      return "";
   }

   private boolean isInRange(int a, int b, int c) {
      return b > a ? c >= a && c <= b : c >= b && c <= a;
   }

}

So now essentially you can define an InputFilter, that initializes with your desired minimum and maximum integer values. It can then be applied to an EditText to limit the entry to a certain range of integer values. So if you have a reference to your EditText in code, for this example it would be initialized in this way:

minsEditText.setFilters(new InputFilter[]{new InputFilterMinMax(0, 59)});

This will limit the entry from 0-59. Of course you can use any number range that you’d like.

Getting the number of active sessions in Vaadin

Last week I explored how to get the number of active sessions that Tomcat reports: https://adeelscorner.wordpress.com/2016/03/13/getting-the-number-of-active-sessions-in-tomcat/

The problem with that metric is that some of those sessions, or all, may not actually be active users. What if someone is connected to your java web application (Tomcat in this case), but has just been sitting idle, for hours or even days. They’re not really using your application per se. However, Tomcat will report them as active users, especially if your application has a heartbeat, or a long polling push connection established.

So an additional metric that is useful in determining if your java application is actually in use is to track the number of active sessions within your java application. In our case we’re using Vaadin, so that’s what this post is geared towards. However, you’ll see the general idea here and can apply this to any user based application.

Before I continue, I want to point out a useful Vaadin add-on to measure idle time: https://vaadin.com/directory#!addon/idle. This is pretty handy in checking the actual idle time for a user.

The other important thing to explore first is as follows. Each Vaadin Session is based on a cookie, so if a browser has multiple tabs open to the same application server running Vaadin, the Vaadin Session will be shared among those tabs, because the cookie is shared. Hence, when a Vaadin session ends (perhaps when the user logs out, or times out), all user browser tabs open corresponding to that session are disconnected.

Let’s get started. At the core of how this will work is a public static HashMap which we can use to track a browser tab that belongs to a particular Vaadin session, and how long it’s been active or idle. Since this is a static data structure, it will be shared among all sessions at the Tomcat level. So it’s pretty handy in tracking all sessions on that particular Tomcat server. We’ll be able to track not only how many browser tabs a user has open to your application, but how long they’ve been idle in each tab.

I created a class called ApplicationLevelTracker to assist, which is pretty simple really. It’s as follows:

public class ApplicationLevelTracker {
 public static HashMap < String, Pair < Boolean, Long >> browserTabUniqueIDToIdleTimeHashMap = new HashMap < String, Pair < Boolean, Long >> ();

 private String thisBrowserTabUniqueID;

 public ApplicationLevelTracker(int userID, String vaadinSessionID) {
  thisBrowserTabUniqueID = userID + ":" + vaadinSessionID + ":" + UUID.randomUUID().toString();
  registerIdle(false);
 }

 public void registerIdle(boolean idle) {
  Date date = new Date();
  browserTabUniqueIDToIdleTimeHashMap.put(thisBrowserTabUniqueID, new Pair < Boolean, Long > (idle, date.getTime()));
 }

 public void deRegisterThisTab() {
  browserTabUniqueIDToIdleTimeHashMap.remove(thisBrowserTabUniqueID);
 }

 public void deRegisterAllTabsForThisVaadinSession() {
  String userID = thisBrowserTabUniqueID.split(":")[0];
  String vaadinSessionID = thisBrowserTabUniqueID.split(":")[1];
  Set < String > keySet = ApplicationLevelTracker.browserTabUniqueIDToIdleTimeHashMap.keySet();
  List < String > browserTabUniqueIDsToRemove = new ArrayList < String > ();
  for (String key: keySet) {
   String _userID = key.split(":")[0];
   String _vaadinSessionID = key.split(":")[1];
   if (_userID.equals(userID) && _vaadinSessionID.equals(vaadinSessionID))
    browserTabUniqueIDsToRemove.add(key);
  }
  for (String browserTabUniqueID: browserTabUniqueIDsToRemove) {
   browserTabUniqueIDToIdleTimeHashMap.remove(browserTabUniqueID);
  }
 }
}

Here’s a breakdown of the class, and the methods: The constructor takes the user’s ID (any identifier you have for your user, in our case an integer), and the Vaadin Session ID. Using these keys, and a random ID, each browser tab that a user opens to your application will get its own unique ID created in the constructor.

When a user goes idle, registerIdle(true) is called. When a user is active, registerIdle(false) is called. This way we can track whether they are active or idle in the corresponding browser tab. These methods will be used by the Vaadin Idle add-on (more on that soon).

When a browser tab is closed, deRegisterThisTab() is called. When the Vaadin session is being ended (for example, you may do that when a user logs out from your application, or when Vaadin determines the user has timed out), deRegisterAllTabsForThisVaadinSession() is meant to be called, to clean them out of the tracking HashMap.

Next, to actually make use of the ApplicationLevelTracker, you’ll have to set it up and use it properly in your Vaadin UI class, where your application is created and each user’s instance is initiated. So in your UI class that creates your Vaadin application (the class usually extends Vaadin’s “UI”), you’ll need to set up the following code for all this to come together:

First, define this variable in your UI class:

private ApplicationLevelTracker applicationLevelTracker = null;

Next, when the views are being created, after the User is logged in (note: you should set it up so this code is called on every new creation of the UI class, and not just the creation of a new Vaadin Session (the same Vaadin session can have multiple UIs attached to it)), you’ll want to set up ApplicationLevelTracker:

applicationLevelTracker = new ApplicationLevelTracker(user.USER_ID, VaadinSession.getCurrent().getSession().getId());
Idle.track(UI.getCurrent(), 120000, new Idle.Listener() {
 @Override
 public void userInactive() {
  applicationLevelTracker.registerIdle(true);
 }
 @Override
 public void userActive() {
  applicationLevelTracker.registerIdle(false);
 }
});

Notice that the Vaadin Idle add-on is used here. We create an instance of ApplicationLevelTracker with the user’s ID, and the Vaadin session ID, which registers this browser tab in static (shared) memory. And then when the user goes idle, or when the user goes active, as reported by the Idle add-on, we register that with ApplicationLevelTracker.

Now that things are setup, we need to be sure they are cleaned up when the user goes away.

You can use this neat trick to register whenever that particular browser tab is closed, or when the user navigates away from your application. This is where you’ll want to call applicationLevelTracker.deRegisterThisTab():

JavaScript.getCurrent().addFunction("browserIsLeaving", new JavaScriptFunction() {
 @Override
 public void call(JsonArray arguments) {
  if (applicationLevelTracker != null)
   applicationLevelTracker.deRegisterThisTab();
 }
});
Page.getCurrent().getJavaScript().execute("window.onbeforeunload = function (e) { var e = e || window.event; browserIsLeaving(); return; };");

You’ll also want to use applicationLevelTracker.deRegisterThisTab() when the Vaadin detach listener is fired. A detach listener corresponds to the UI, and not the whole Vaadin session. So it will be fired when one particular instance of UI belonging to a singular browser tab (which may one of several tabs belonging to the same Vaadin session) is detected to have gone away, this code will be called to clean up that particular browser tab. You can add the following block of code in the init() method in your Vaadin UI class:

addDetachListener(new DetachListener() {
 @Override
 public void detach(DetachEvent event) {
  if (applicationLevelTracker != null)
   applicationLevelTracker.deRegisterThisTab();
 }
});

Lastly, wherever in your code the user logs out, and you end the Vaadin session, you’ll want to call applicationLevelTracker.deRegisterAllTabsForThisVaadinSession():

if (applicationLevelTracker != null)
 applicationLevelTracker.deRegisterAllTabsForThisVaadinSession();

And that’s it! Now you have an application wide HashMap which fully tracks all individual browser tabs open to your application, and information on how long the user has been active or idle in each tab. In my next blog post I’ll cover how to actually pull this information and use it in a meaningful way to make a determination of how many users are using your application at any given moment.

Before wrapping up I want to point out one final thing on how to interpret this tracking information after you’ve started collecting it. If a user is connected, and is idle for too long (say 2 hours, or several days), you can reliably know that they are not using the application. They are either connected and left their machine running and browser open, just sitting idle. Or they’re gone (no longer connected) and their session was never cleaned up for whatever reason. If the user has been active for a long time (say, several days), that means something is wrong too, unless they really have been working every minute in your application for the last several days without a break. In this case you can assume the user is not really there, that their browser connection went away and their tracking didn’t get cleaned up for whatever reason (for example, Vaadin didn’t fire the detach listener reliably, which I’ve noticed happens sometimes though it may be fixed in new Vaadin versions). The only case you can be pretty certain that a user is using your application at the present moment is if they’ve just been idle for a short period (say within a 30 minute window), or if they’ve been active within a short period (say 30 minutes again).

Giving the user a message before resizing images through ng-file-upload

This had been bothering me for a while until I stumbled upon an answer that led me to a solution.

With ng-file-upload (https://github.com/danialfarid/ng-file-upload) for AngularJS, you have the capability to resize images using the ngf-resize directive. It’s very handy since you can put some of the CPU processing burden resizing giant images to smaller sizes on the user, rather than to put it on your own server (if you resize the images after the files are uploaded).

HOWEVER, the problem with ngf-resize is when resizing starts, and especially if the user selects multiple images at once, the user’s browser hangs while the images resize. The bigger the image, the longer it takes. This is irritating, and also confusing, causing the user to wonder what is going on. For the longest time I was trying to figure out how to give the user a message before the resizing actually starts.

I eventually stumbled upon the ngf-before-model-change directive part of ng-file-upload. This allows you to define a function that is called before the model changes (and the images start resizing). This is a perfect place to put up a message to the user that their images are about to be resized, and for them to sit tight for the next few seconds.

Then the ngf-select directive can be used to define a function which is called AFTER the resizing is complete, and this is where you can remove the message to the user.

Full example follows like this. In your JavaScript side of things (in your AngularJS controller) you would do:

$scope.beforeResizingImages = function(images)
{
  blockUI.start($translate.instant('FORMATTING_IMAGES')+"...");
  $scope.$apply();
}

$scope.afterResizingImages = function(images)
{
  blockUI.stop();
}

And then in HTML:

<div ngf-before-model-change="beforeResizingImages($files)" ngf-select="afterResizingImages($files)" />

And that’s it! beforeResizingImages() and afterResizingImages() will be called in the correct order, putting the message up before resizing images (and before the browser hangs for a few seconds for the CPU intensive process), and taking it off after resizing. Note that I use angular-block-ui (https://github.com/McNull/angular-block-ui) to block the UI and put the message up, and of course angular-translate to translate the text for the block message.

Making a Vaadin window transparent/translucent

We had a need to do this recently, and it wasn’t obvious, so I thought I’d share.

One thing to note is that if the window is modal, this trick won’t work. Since for modal windows, Vaadin adds some more styling around the window to the back the background “dimmed”, thus giving a stronger visual focus on the modal window. For regular (non-modal) windows, this trick works great, especially if you just want to overlay some information on content behind the window.

In your java code, add the following style to your Vaadin Window:

myWindow.addStyleName("translucent");

In your theme stylesheet for your application (most likely a “.scss” file), add the following styles:

.v-window-translucent
{
  background-color: rgba(255,255,255,0.6) !important;
}
div.v-window-translucent .v-window-contents {
  background: rgba(255,255,255,0.6);
}

Then compile your theme, and refresh your page. Viola! Your window will now be translucent.

To tweak the translucency, modify the “a” (alpha) value in the rgba inside the theme style. 0.6 worked well for us, making it a bit translucent. To make it less translucent, try a value greater than 0.6. And to make it completely transparent, try 0.

Enjoy!