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.

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...
}

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 is, not the world of should. 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:

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.

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);
            }
        });
    }

Android ListView and setSelection

Android’s ListView is a powerful class that is capable of presenting a list of whatever you wish fairly easily. One of the issues that has vexed me has been scrolling the ListView to a particular entry. While newer Android versions have provided better support in this area, trying to maintain backward compatibility with Android 1.5 presents some challenges. In light of this Google issue and it’s comments, I have come up with a decent method of scrolling a ListView to a particular position if it is not already visible. I clear the focus after setting the selection because users became confused at why an “orange box suddenly appeared” when they did not expressly tap a selection with their finger or scroll with the trackball.

//this method would be part of a ListView class
    @Override
    public void scrollToPosition(final int anItemPos) {
        if (anItemPos!=AdapterView.INVALID_POSITION) {
            int theFirstItemPos = getFirstVisibleItemPos();
            int theLastItemPos = getLastVisibleItemPos();
            if (anItemPos<theFirstItemPos || theLastItemPos<anItemPos) {
                getListView().post(new Runnable() {
                    @Override
                    public void run() {
                        getListView().setSelection(anItemPos);
                        getListView().clearFocus();
                    }    
                });
            }
        }
    }

Picking a Contact photo with Motorola Cliq

Some Motorola Cliq phones are having issues trying to pick a contact photo using something other than the Gallery app that comes with the phone. Motorola is aware of the issue, but I am trying out a workaround for it in my File Browser app. Basically, the problem is that an OutOfMemoryError could result from attempting to pick a large photo because the Intent being used does not specify the size to be returned. Normally, I would just use getIntExtra(“outputX”,defX) and getIntExtra(“outputY”,defY) in order to get what the caller wanted as a size, but since Motorola’s contact app does not provide those Intent Extras, it would return the full sized photo.

Instead of waiting for Motorola to modify their app, I decided to check the name of the caller and provide a default size for that particular app.

if (myActivity.getCallingPackage().equals("com.motorola.blur.contacts")) {
    outputX = outputY = 48;
}

Android Dialog Button onClicks

One practice I’ve come to standardize in my apps has been to take dialogs with buttons that perform some kind of action or processing and then dismiss the dialog and instead place that dismiss() call as the very first line within the onClick handler.

new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        my_final_dialog_var.dismiss();
        Thread.yield(); //optional
        /* do my action here */
    };
}

On some of the more sensitive operations (like file delete), I even put a Thread.yield(); after the dismiss so that the dialog will be sure to go away before any more processing is done. The reason you want to dismiss the dialog right away is so that you avoid getting occasional double presses in case the phone is slow to perform your process or action. Nothing is worse from a user’s perspective than to have the phone not react fast enough and so will keep pressing buttons in the hopes that it will finally do something. If you code your buttons to do something each time a button is clicked, then you can have potentially disastrous results. In my case, having multiple file deletes would be a disaster when the user only wanted to delete one file and the phone just hiccuped on the confirmation dialog. Immediately dismissing the dialog gets rid of the temptation to hit the button multiple times while it is doing it’s job.