Author: David Rager
Date: February 24, 2016
When I first created Baby’s First Game for Android I gave away a free promotional version. This promotional version was basically to get feedback from people before the real release. I wanted the app to only work for a limited time after which it would disable itself. I suppose I could have just released the full version without any limitations but I didn’t know how well (or poorly as it turns out) my app would do or how a free version floating around would affect it. Plus I wanted to see how one might create a time limited app anyway.
I created a single method called doPromoCheck()
that stores the current install date in the app settings and checks them on every start up. I also added a check to alert the user once a day that the application was a promotional version and would expire in x
number of days. This message I wanted shown only once a day as to not annoy the users. Here’s the method with some static class variables for configuration:
...
private static final String PROMO_DATE = "promoDate";
private static final String PROMO_DISPLAYED = "promoDisplayed";
private static final long DAYS_MILLIS = 24 * 60 * 60 * 1000;
private static final long PROMO_DURATION = DAYS_MILLIS * 30; // 30 days
private void doPromoCheck() {
SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
long now = System.currentTimeMillis();
long exp = prefs.getLong(PROMO_DATE, now + PROMO_DURATION);
editor.putLong(PROMO_DATE, exp);
// check if the promo period has ended
if(now > exp) {
AlertDialog alertDialog;
String ok = getResources().getString(R.string.label_ok);
alertDialog = new AlertDialog.Builder(this)
.setCancelable(false)
.setPositiveButton(ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish(); // stops the app as soon as the dialog is dismissed.
}
}).create();
String title = "Promo Version";
alertDialog.setTitle(title);
String msg = "This promotional version has expired. Please purchase the official version from Google Play.";
alertDialog.setMessage(msg);
alertDialog.show();
} else {
long disp = prefs.getLong(PROMO_DISPLAYED, now);
// only display the dialog if it's been one day since the last time it was displayed
if(now >= disp) {
// save the next display time for one day from now.
editor.putLong(PROMO_DISPLAYED, now + DAYS_MILLIS);
AlertDialog alertDialog;
String ok = getResources().getString(R.string.label_ok);
alertDialog = new AlertDialog.Builder(this)
.setCancelable(false)
.setPositiveButton(ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// do nothing
}
}).create();
String title = "Promo Version";
alertDialog.setTitle(title);
long days = (exp - now) / DAYS_MILLIS;
String msg = "This promotional version will expire in " + days + " days. Please consider purchasing the official version from Google Play.";
alertDialog.setMessage(msg);
alertDialog.show();
}
}
editor.commit();
}
The first time this is run it calculates the expiration date and stores it in the private app settings. Each time it is run after, it pulls the expiration out of the app settings. To use this method in your app, put the call as the first thing in your main Activity onCreate()
method:
protected void onCreate(Bundle savedInstanceState) {
doPromoCheck();
...
}
That’s it. Your application will now only last for 30 days and will simply show the promotional period ended dialog after. Of course, the app can be uninstalled and reinstalled to reset the expiration but it’s annoying and probably not worth the hassle to most people.
Author: David Rager
Date: December 10, 2013
I needed to replace the non-alphanumeric characters in a std::string
. While the Java String
class has the replace()
and replaceAll()
methods for doing this, the std::string
class has no such utility methods. Instead you can use the std::replace_if
function from the Standard Template Library. Here’s some example code:
#include <iostream>
#include <string>
#include <algorithm>
int isNotAlphaNum(char c)
{
return !std::isalnum(c);
}
int main(int argc, char* argv[])
{
std::string s1 = "some/string/with*/nonalpha/characters+1";
std::cout << s1 << " : ";
std::replace_if(s1.begin(), s1.end(), isNotAlphaNum, ' ');
std::cout << s1 << std::endl;
return 0;
}
The third parameter of the replace_if()
function is a pointer to a function that performs the desired check and returns either true
or false
if the input satisfies the condition. The last parameter is the character to replace the matched character, in this case a space. This program produces the following:
$ ./replace.exe
some/string/with*/nonalpha/characters+1
some string with nonalpha characters 1
Author: David Rager
Date: December 10, 2013
I don’t usually need to convert string case in C++ so when the need comes up I’ve usually forgotten how to do it and have to Google.
While the Java String class has toLowerCase()
and toUpperCase()
, C++ std::string
does not have such a utility method. Instead, you need to use the std::transform()
function. Here’s some example code:
#include <iostream>
#include <string>
#include <utility>
int main(int argc, char* argv[])
{
std::string s1 = "lowertoupper";
std::string s2 = "UPPERTOLOWER";
std::cout << s1 << " : ";
std::transform(s1.begin(), s1.end(), s1.begin(), ::toupper);
std::cout << s1 << std::endl;
std::cout << s2 << " : ";
std::transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
std::cout << s2 << std::endl;
return 0;
}
Produces the following:
$ ./case.exe
lowertoupper : LOWERTOUPPER
UPPERTOLOWER : uppertolower
Note that while the Java toUpperCase()
and toLowerCase()
methods do not modify the original string, the std::transform
function does.
Author: David Rager
Date: April 16, 2013
In light of the latest attacks on WordPress sites everywhere I thought I should probably step up security a bit here. Not that I thought I had a bad password or anything but I still had the default admin
account enabled. This attack is being conducted by a huge botnet of about 90,000 computers trying a large dictionary of passwords against the admin
account. I wasn’t too concerned but the fact that it was targeting the admin
account and seeing a huge spike in access to wp-login.php
I still had an uneasy feeling in my gut.
First, the admin
account is now disabled. They can target it all they want! Second, no one should need to access wp-login.php
from anywhere in the world. So I updated .htaccess
to only allow access from my IP address.
<Files "wp-login.php">
Order Deny,Allow
Deny from all
Allow from xxx.xxx.xxx.xxx/32
ErrorDocument 403 "https://www.google.com"
</Files>
Third, installed the Limit Login Attempts plugin for WordPress which will automatically block an IP after so many failed login attempts.
Author: David Rager
Date: January 22, 2013
So, every time I try to start Cygwin (actually, the cygwin XWin server) I get that ugly UAC prompt. Very annoying since this is an application I use quite frequently. Unfortunately, changing the properties to always “Run As Administrator” does not fix it.
The only way I’ve successfully managed to get it to work is through the Application Compatibility Toolkit from the Microsoft Download center. Download and install the Application Compatibility Toolkit. Once installed, run ACT as administrator. Right click on its menu entry while holding the Shift key and select Run as Administrator. Note that you have to run the correct version for the architecture of the target program. For instance, Cygwin is 32-bit so the 32-bit version of ACT must be used.

This will open up a new custom database that we will edit. From here click the Fix icon in the toolbar.

In the Create new Application Fix dialog, give it a name, the vendor is optional, and select the path to the executable. The executable we want is run.exe on my machine at C:\cygwin\bin\run.exe.

Click next, and next again. From the Compatibility Fixes list, select “RunAsInvoker” and click Finish.

Next save the database by clicking the save icon. You will be prompted to provide a name.

Once it is saved we have to install it. Right click on the database in the tree and select Install.

Now you should be able to click the Cygwin XWin Server icon and it will start without prompting you. One additional issue I had was that before any of this I had created a Quick Launch icon for the XWin Server. For some reason, these changes do not take affect right away for the Quick Launch icon only. I had to delete and recreate the Quick Launch icon before I could start it that way without being prompted.
Author: David Rager
Date: January 4, 2013
This isn’t meant to be a comprehensive tutorial on everything you can do with mingw-get but rather a place for me to document some tips that I found Googling and felt I should consolidate here. If something here does not work for you or if you have some other useful pointers let me know and I’ll update this post.
MinGW is standard equipment on any new Windows computer I need to use which includes most of the tools I use regularly. I had a need to create zip
files recently however zip
and unzip
are not included in the base MinGW installation. The easiest way to install these utilities is through mingw-get
.
$ mingw-get install msys-zip
$ mingw-get install msys-unzip
This lead me to the question, what additional packages are actually available this way? Cygwin provides a nice GUI to pick and choose packages and of course there are the various package managers available for the many Linux distros. There doesn’t seem to be an easy way to list packages that can be installed with mingw-get
. One method I found is to look in the catalog file.
$ grep "package name" /mingw/var/lib/mingw-get/data/*.xml
Or to make the output a little nicer:
$ grep "package name=" /mingw/var/lib/mingw-get/data/*.xml |
sed 's/.*package name="\([^"]*\)".*/\1/'
These commands will show you all the packages available whether they are already installed or not. To list packages that are already installed there is a nifty little script that can be found here. Download mingw-get-info
and copy it to /mingw/bin
.
$ mingw-get-info installed
This script is not an official MinGW tool and seems to only exist as an attachment to the linked bug report. From the comments on that page the script will generate a number of reports:
$ mingw-get-info all
to see current status for all available packages,
$ mingw-get-info installed
to filter on only those packages which are installed locally, or
$ mingw-get-info index
to see an index for the repository catalogue.
Author: David Rager
Date: December 6, 2012
I’ve been running this OpenGL Globe screensaver I wrote for several years now on various machines without any issues. Until the other night when I installed it on my new laptop. So I did a little digging and figured out what was going on. After I installed the screensaver and tried to activate it I got the following error:

Googling for information brought me to this site. Further down in the discussion they start talking about switchable graphics with the AMD drivers (which I have) and the Catalyst control center. It seems that by default screensavers are run in “Power Saving” mode with hardware acceleration disabled. Well, since this is an OpenGL screensaver that just will not do! I open up the Catalyst control center and it’s not listed in the recent applications. I guess since it hadn’t run yet it wouldn’t show up. Of course, the Browse… button on the Other Applications box below won’t allow you to select a .scr file. So I try right clicking the .scr file to try to test it that way:

Hey, it starts! So I jump back into the Control Center and there it is!

I set it to “High Performance” and go back to the screensaver control panel and it starts right up! Interesting. I’m not sure if or how I could update the installer to detect and adjust these settings automatically. I’ve been running this screensaver (or previous builds of it) on various computers for several years now and this is the first time I’ve encountered an issue with it. I’m not sure if I can even consider it an issue with the screensaver or not though I’d argue either the screensaver or the installer need to be updated since I can’t really expect end users to have to jump through hoops to get my software to work. I’m probably not going to do it any time soon however. If you have an idea for fixing this problem in an automated fashion I’d be interested in hearing it. If you’d like to play around with the installer code let me know and I’ll give it to you. In the mean time, if you see this issue, let me know if this fixes it.
Update 3/12/2013
So, I’ve been playing around with the drivers and mucked things up enough that I had to revert. However, when I installed the original version and encountered the same problem with the screensaver described above, the above fix did not work this time! Grrr… To get around it I had to go in and manually add it in the registry. One of the existing screensavers that actually ran without issues was listed in the Switchable Graphics dialog as shown above. I picked ribbons.scr. I opened regedit32.exe and searched for “ribbons.scr”.

I edited this string value and changed the path to specify “ssglobe.scr” instead of “ribbons.scr”. When I reopened the Switchable Graphics dialog it was listed though it was marked as “Not Assigned”. I’m sure there are other registry settings that can be updated to add it and give it the proper settings all in one shot. However, getting it to show up in the dialog is sufficient for now as the settings can then be changed from there. I set it back to “High Performance” and all is again working.
Author: David Rager
Date: October 21, 2012
Some genius at HP decided the function keys F1 through F12
aren’t important enough and demoted them to second level functions. To access them you now need to pres the Fn + Function key
combination to get the normal behavior.
The default behavior for those keys now is what you would normally have had to hold the Fn
key to access. Like turning your wireless card on and off, adjusting the display brightness, etc… F5
it looks like enables/disables the backlight on my keyboard. Um no. Setting the display brightness does NOT need to be a top level function, idiot! I’ll set it once and never touch it again.
In the mean time, F3
is used all the time for opening Find/Replace dialogs. I use F5
all the time to refresh web pages, folders, my IDE, etc. I can handle holding the Fn
key to toggle my wireless on and off or changing display outputs. In the mean time I want my function keys back.
The fix isn’t a simple control panel setting either. You actually have to go into the computer BIOS to change it. When the computer boots you have to hit F10
to enter the BIOS settings. (Remember to hold the Fn
key or you might just be trying to eject your CD-ROM).
Once at the BIOS menu navigate to the “System Configuration” settings. Select “Action Keys Mode” and turn that crap off. Reboot and your sanity and balance in the universe will have been restored.
Author: David Rager
Date: September 11, 2012
Oracle, you’ve outdone yourself! Still not getting this consumer level software thing are you? I got a call at work that my daughter’s laptop was acting funny. Turns out she got hit by a virus. I have her user account set up to run with limited permissions so there wasn’t any real damage and was fairly easy to clean up.
I spent some time trying to figure out how she got infected in the first place since she doesn’t usually venture too far from her game sites, doesn’t have email or facebook, and is pretty closely monitored by us. Her internet history didn’t show anything I didn’t expect, the typical game sites, Google searches for Justin Bieber, etc…
Nothing was out of the ordinary however, some of her game sites make heavy use of Java. Maybe a rogue ad took advantage of the recent Java exploit or something. No, she has Java 6 installed so it wasn’t that particular exploit. I’m not entirely sure it was a Java vulnerability, just covering bases here. Maybe something else?
I figure I’d make sure it was updated anyway and started the Java control panel. Went to the Update
tab and clicked Update Now
. A new version was available so I clicked Install
. The prompt for my administrator password came up (of course, she’s running a limited user account). I enter it and the following error pops up:
Failed to download required installation files.
Hmmm… ok. Not sure why. I check the network settings and tell it to use a direct connection instead of my default browser settings. Same issue. Maybe it’s a permission issue. So I navigate in Explorer to the Java directory, find the javacpl.exe file, right-click and select Run as administrator...
Enter my password and try again. Same issue.
I switch user and log into my administrator account. Open the Java control panel and try again. Voila! It works! Looking around the internet, this bug has been around for quite a while and still isn’t fixed. It seems the Java updater won’t work at all unless you are logged into the administrator account. Being a general user and running it as administrator is NOT sufficient. Grrrr…
Author: David Rager
Date: July 10, 2012
Here’s one I forget every so often. What hot key combination will let you create a new folder in Windows Explorer?
In all versions of Windows, with a folder opened in Windows Explorer use Alt + F, W, F. This basically walks you through keyboard navigation of the Explorer menu. Windows 7 has added a hot key combination specifically for this task. Ctrl + Shift + N Thanks to How-To Geek for the tip!