PHP: fwrite() wrapper

I recently ran into an issue on one of my Drupal projects.  While tracking down the problem, I wrote a wrapper for PHP’s fwrite() function since it should be wrapped inside a loop in case there was a network issue while writing out the data.  In the process, I also handled a Windows quirk that may also cause problems.  This function was the result:

/**
 * Writing to a network stream may end before the whole string is written. 
 * Return value of fwrite() may be checked. Windows quirk handled as well.
 * @param file_stream $aFileStream - the file stream instance.
 * @param string $aText - the string data to write out.
 * @param number $aRetryCount - number of attempts before giving up.
 * @return number - Returns the # of bytes written out.
 */
function fstream_write($aFileStream, $aText, $aRetryCount=3) {
	$ts = microtime(true);
	$num_queued = strlen($aText); //returns num bytes, which is what we want
	$num_wrote = 0;
	$num_retries = $aRetryCount + 0; // in case NULL is passed in
	$isWindows = (strtoupper(substr(php_uname('s'), 0, 3)) === 'WIN');
	while (($num_queued > $num_wrote) && ($num_retries > 0)) {
	    // handle Windows quirk since we are already going through all the trouble of while loop
		$theText = (!$isWindows) ? substr($aText, $num_wrote) : substr($aText, $num_wrote, 8100);
		// only care about warnings if on last retry
		$fwResult = ($num_retries > 1) 
				? @fwrite($aFileStream, $theText, strlen($theText)) 
				: fwrite($aFileStream, $theText, strlen($theText));
		if (!empty($fwResult)) {
			$num_wrote += $fwResult;
		}
		else { //cover the case of FALSE and 0 being returned
			//0 result may mean the socket/connection was severed, prevent infinite loop
			$num_retries -= 1;
			if ($num_retries > 0) {
				sleep(1); //give the target time to recover
			}
			else {
				$tl = microtime(true);
				watchdog('PHP', 'fstream_write> wrote: @num duration: @dur text: @out', 
						array('@num'=>$num_wrote, '@dur'=>number_format($tl-$ts), '@out'=>$aText));
			}
		}
	}
	return $num_wrote;
}

In the end, it turns out my issue was fixed with a few configuration setting changes rather than any code changes, but this seemed useful enough to remember for later.

GDG-DC Sept 6th

I had the privilege of being one of the 200 or so attending a Google Dev Group meeting in which a few of Google’s Android Developer Advocates gave a couple of talks as well as had the AOL development team present a demo of their work which will soon be published in the market.  The meeting was held in an auditorium of AOL’s campus which was pretty nice and could hold easily hold the 200 attendees. The Google guys bought tons of pizza for everyone.  A big thanks to both AOL for the room and Google for the food. =D  If you follow the meeting link, you can see the pictures taken at that event.

The first speaker was David Chandler who is the primary developer behind the WebView widget and is the primary force behind GWT. He was in town for the FCC’s meeting on Accessibility in Mobile Apps and the Mobile Web and agreed to be one of the speakers for this little shindig.  He talked about WebView apps and how many of them are designed on-the-cheap as a way to target several different mobile ecosystems with one app.  He pointed out how many of them are also designed to look like an iOS app… which is incongruous and confusing for an Android user and basically to “don’t do that”.  I learned that AsyncTasks are great for background tasks, but not for a task that may get killed mid-run if the device orientation changes as they will get cancelled (use a Service instead).  Spring Android is an open source project with a REST encapsulation set of classes to make those kinds of calls easy inside Android.  Building a service around Spring Android would be the best practice, but you can put it anywhere you like, even inside an AsyncTask.

Android 4.1 (JellyBean) introduced a new set of notifications, with a much larger size and buttons and even a short list.  One of the problems with this new set was a fairly hidden feature of the expandable notification (hidden because it isn’t really discoverable):  some notifications can be expanded if you use two fingers to “pull down” which would expand it.  Not really something hinted at visually and, for people like me, impossible to discover because I am usually using the phone one handed, preventing the use of two finger gestures most times.

The Google I/O 2012 App demonstrating many of the new features is still available on Google Play, but not for much longer. Source code for the app will be available for a long time to come and can be seen/downloaded from here. Demonstrated features include: the new notifications, ICS calendar integration, GCM (successor to C2DM – push notification from web server), Android Beam (using the NFC), and more.

David then went on to discuss the FCC meeting on Accessibility and proceeded to talk about various quick and easy ways to vastly improve accessibility of an app for the visually impaired.  He gave a short example of a slider bar and how, even with text to speech enabled with various text being read as you operated it, the UX is quite cumbersome.  Supplementing the slider bar with simple + and – buttons to move the slider up and down did not add much complexity, but made the task of properly setting the value of the slider so much easier by just using those simple buttons instead.

The AOL Android development team gave their demonstration next and they showed off their fairly sophisticated magazine reader app that had multiple call outs, gesture actions, vertical page scrolling, and even content drill down based on hot spots defined in the xml content.  The thing I found most fascinating was their ability to hook up a device directly to the screen projector and show off the app that way (at least for the tablet, their phone could not hook up).  When I inquired about that ability after the event, they said it was a Motorola Xoom with an HDMI port.  After I got home, I immediately checked my ASUS tablet for such a port and found it has a microHDMI output.  The Samsung Galaxy S III handset also has one, so I may need to get one of those kinds of phones the next time I need to do a presentation with a handset.  AOL On is a new Google TV app that will add feature rich content from AOL as a set of new channels for you to watch on your Google TV, including HuffLive.  While I technically found the apps presented impressive, I don’t typically read the magazines they would be delivering nor do I have a Google TV.  Others will have to comment about them once they get published (which should be soon, this was the first time anyone outside AOL got to see anything about them).

Adam Koch and Roman Nurik came down from Google’s NYC office to give a micro version of their Google IO presentation about the features of JellyBean (4.1), best practices for UI design, and how best to design and develop with the Nexus 7… which is quirky because of it’s default portrait mode instead of landscape, being 7″ with a “tvdpi” of 213dpi, and only a front facing camera. They talked about UI design, UX should be “butter” (smooth — opposite of “janky”), making sure we have “hardware acceleration” option turned on in our apps and that we should all review the design guidelines with regards to how the new Up button behaves (which is the app icon) vs. the Back button which has been around forever. A special note was said to pay attention to the new activity attribute parentActivityName and the TaskStackBuilder class.

Adam asked at one point during his talk if anyone created a “universal app” which targeted any and all screen sizes. As far as I know, I was the only one to raise my hand.  He asked me about the challenges I faced and I mentioned all the different layout folders and value folders necessary to create such apps.  During Roman’s talk about best practices for UI design in helping to support “universal screen apps”, he asked the audience to see how many were using the “smallest width” layout filter (i.e. layout-sw600 folder for 7″ tablet layouts as apposed to “layout” for handsets and “layout-sw720″ for 10” tablets).  When Roman saw that I was the only one with my hand up, he commented “Only one? That’s very disappointing. You all should be using it”. It made me realize that my development process and experience is not only valuable, but rare, too (around here, at least).

All in all, it was a very informative 2 hour set of talks and demonstrations and I appreciated every minute of it.  Thanks again to Google and AOL for sponsoring the event and presenting something like that. Very cool. =)

As I left the parking garage at AOL’s campus, I was greeting with this warning sign.

Crosswalk warning sign at AOL

Android 4.1 change to setTextSize

Android 4.1 changed standard behavior for setTextSize.

It used to be that you could use setTextSize(0) and the size would default to whatever was appropriate for the device.  Very handy!  Unfortunately, it now literally sets the font size to 0.  Effectively rendering your TextView invisible. Bad Google! Changes like this make it harder and harder to write code that works on the majority of devices.

I guess that’s why we make the “big bucks”, right?  /sarcasm 😉

Android Custom Permissions

Google encourages developers to define custom permissions to protect our publicly available activities and custom data providers.  The first step is to define such permissions in your manifest so that your app as well as all other apps can display pretty text for the permissions.  Apps that merely use your custom permissions will display the text you defined in your app for each permission. One issue I discovered is that you should never define the permission group as an empty string (android:permissionGroup=””) or else the permission definition becomes invalid and no other app will be able to use it.

Custom permissions should also define a custom Permission Group if they are not part of one of the Android built-in groups, otherwise they will be displayed as part of a permission called “Default” and all your custom permissions will be shown as a comma separated list underneath it. For example:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mydomain.myapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <permission-group android:name="com.mydomain.provider.permissions" 
        android:label="@string/perm_text_group_mydomain_provider" />

    <permission android:name="com.mydomain.provider.permission.ACCESS_DATA"
        android:permissionGroup="com.mydomain.provider.permissions" 
        android:label="@string/perm_text_access_mydomain_provider" />

    <permission android:name="com.mydomain.provider.permission.WRITE_DATA"
        android:permissionGroup="com.mydomain.provider.permissions" 
        android:label="@string/perm_text_modify_mydomain_provider" />

    <uses-permission android:name="com.mydomain.provider.permission.ACCESS_DATA" />
    <uses-permission android:name="com.mydomain.provider.permission.WRITE_DATA" />

    <application
      android:label="@string/app_name"
      android:description="@string/app_desc" 
      android:icon="@drawable/app_icon" >

        <provider android:name="com.mydomain.MyProvider" 
            android:authorities="com.mydomain.provider.myprovider" 
            android:readPermission="com.mydomain.provider.permission.ACCESS_DATA" 
            android:writePermission="com.mydomain.provider.permission.WRITE_DATA" 
            android:exported="true" >
        </provider>

    </application>

</manifest>

Once you have defined all your permissions, other apps can simply use them with <uses-permission> and their apps will use your string definitions when displaying them in Settings as part of managing the device’s apps.

Android’s PreferenceActivity for all API versions

I have spent the last few days learning about how to use the new Android PreferenceFragment which requires PreferenceActivity to override a new v11 (Honeycomb) method called onBuildHeaders().  Unfortunately, the documentation is not very clear how one would create a single PreferenceActivity that could play well in all versions, utilizing the newest features if you have it and avoiding an app crash on older Android versions. I encountered several solutions to this issue by creating two different activities for the two different mechanisms requiring two entries in your AndroidManifest.xml file.  Having two different PreferenceActivities means if you have library code that extends that class, you now have to duplicate it.  Then, if your app descends your library class, now has to be duplicated yet again.  The end result is … less than ideal. Continue reading

Android’s onCreateContextMenu() called with no ContextMenuInfo

I recently had an exception report from an eeePC using a mouse which caused the following code to give a NullPointerException:

public void onCreateContextMenu(ContextMenu aMenu, View aView, ContextMenuInfo aMenuInfo) {
	AdapterView.AdapterContextMenuInfo theMenuInfo = null;
	try {
		theMenuInfo = (AdapterView.AdapterContextMenuInfo) aMenuInfo;
	} catch (ClassCastException e) {
		return;
	}
	File theFile = myActivity.getListItem(theMenuInfo.position);
	//...snip rest of code...
}{/java]
The only way that theMenuInfo would be NULL in order to cause the NullPointerException is that the passed in aMenuInfo was NULL -- and that is not supposed to be the case.

I am not quite sure how such an event occurred. It could be a result of "right-clicking" on a spot where there is no list item shown, except that the behavior in that case should have not resulted in a context menu since there is no item there at all. While I should not have to protect my code against a NULL being passed in for the required ContextMenuInfo parameter, I have to live in the world that <em>is</em>, not the world of <em>should</em>. Who knows, maybe this is the start of a trend where "right clicking" on the "white space" of a list will pass in NULL for that parameter and cause a completely different menu to popup for quick actions that provide the same functionality as clicking on the Menu button and choosing some deeper submenu from that list. Then again, it is probably just a bug in the OS and will be fixed at a later point in time. Either way, it's best to protect against NULL parameters even if they should never be NULL.

My new code:
[java]public void onCreateContextMenu(ContextMenu aMenu, View aView, ContextMenuInfo aMenuInfo) {
	AdapterView.AdapterContextMenuInfo theMenuInfo = null;
	File theFile = null;
	try {
		theMenuInfo = (AdapterView.AdapterContextMenuInfo) aMenuInfo;
		theFile = myActivity.getListItem(theMenuInfo.position);
	} catch (ClassCastException cce) {
		return;
	} catch (NullPointerException npe) {
		return;
	}
	//...snip rest of code...
}

If you know why the ContextMenuInfo parameter is sometimes NULL, please feel free to share the reason as I know several developers that would be interested in it besides myself.

Android: Notification Icons

The Android notification bar has been white for a very long time. A great many apps that put up icons inside this bar create black icons with transparencies so they appear black on white when viewed against this white notification bar. Unfortunately, with Android 2.3.3+ and 3.0+, the notification bar is now black. Black icons on black bars do not show up well at all.

I highly advise against creating separate icons for the different versions and instead offer the tip of creating a white background for your black icons. In my apps that require a notification icon, I gave the icons a round, white background that used the alpha channel to fade the white from the center to the edge. The effect is that on the older, white notification bars, no difference is detected since white fading into white is the same thing as nothing at all. On a black background, however, the effect is that my black icon is visible within a white circle that fades to black, making it look like a modern, 3D rounded icon.

Example Notification Icon

Personally, I detest the current state of my 2.3.4 phone’s notification colors since most of the apps currently use black or dark grey notification icons (including stock apps) and as such makes it nearly impossible to see them at a glance when checking my phone for messages out in bright daylight. Whomever’s bright idea it was to push this change out to phones that have been using and expecting white notification bars for years now should be given a painful wedgie!

PHP: Query Result Loops

Pro Tip: when you loop through the results of a query like this:

$theDatabase->getSqlData($theSQLtext);
while ( $theDatabase->getNextRow() ) {
    //... do a ton of stuff ...
}

I would like to point out that it will fail eventually. Why? Oh there’s nothing wrong with it, per se…

But if somewhere in all of that ton of stuff inside the while loop you ask the database for something else (like a small list of items for a drop down control), then when you get back to the “while” line, it will now either return the wrong data row or most likely just end prematurely — because of lazy coding!

All that is needed to avoid this hard to detect bug, is to save off the query result given in the first line and use it in the “while” line. No question now which row will be returned and everything will be correct no matter how many nested database calls you put inside the while loop.

$theQueryResult = $theDatabase->getSqlData($theSQLtext);
while ( $theDatabase->getNextRow($theQueryResult) ) {
    //... do a ton of stuff...
}

Android Dialogs and onContextItemSelected()

ListViews and GridViews are great widgets to use in an Activity for your app. Sometimes it is useful to also create smaller versions of them for dialogs within your app. There’s only one problem: Context Menus. If you have tried to put a context menu on a ListView inside a dialog, you may have found out that while onCreateContextMenu() is called, onContextItemSelected() is not. There is a workaround, though, because onContextItemSelected() is actually a convenience method called from onMenuItemSelected(int, MenuItem). If you add the following method to your dialog containing the ListView (or GridView), you will find that onContextItemSelected() is working again.

@Override
public boolean onMenuItemSelected(int aFeatureId, MenuItem aMenuItem) {
    if (aFeatureId==Window.FEATURE_CONTEXT_MENU)
        return onContextItemSelected(aMenuItem);
    else
        return super.onMenuItemSelected(aFeatureId, aMenuItem);
}

 

Android: Programmatically Show the Soft Keyboard, If Needed

If you are expecting user input, a polite app will check to see if there is a hardware keyboard and if one is not present, then automatically display one so the user does not have to click the edit box first in order to pop one up. This kind of behavior is especially nice if there is only one input box being presented. While there are a few methods available out on the net in various places, I wrote my own to be compatible with Android 1.5+ and works in all cases where a keyboard is not part of the physical device as well as does nothing if a physical device has a keyboard.

The source code provided is written from the perspective of a static utility class.

    /**
     * Show soft keyboard if device does not already have a hardware one available.
     * @param aView - the View that will receive the keyboard input
     */
    public static void popKeyboard(final View aView) {
        aView.post(new Runnable() {
            @Override
            public void run() {
                ((InputMethodManager)aView.getContext().getSystemService(
                        Context.INPUT_METHOD_SERVICE)).showSoftInput(aView,
                        InputMethodManager.SHOW_IMPLICIT);
            }
        });
    }