Jiffy – The JavaScript File Editor

Jiffy - JavaScript File Editor

You’ve got flat files?  That’s understandable.

In the beginning was the flat file: that simple but effective means of data interchange. Long before there were web services, systems shared data through files having custom record and field layouts.

Yet these things are alive, well, and growing today; for example, nearly all payments travel in some sort of standard flat file format. And since “the wonderful thing about standards is that there are so many to choose from,” hundreds of proprietary file formats support these industry-standard ones.

So, not surprisingly, I’ve found myself over time building custom viewers and editors for various file formats that we use. These are mostly fat-client Windows apps that must be installed to use. I promised myself that the next time I needed a new custom flat file viewer/editor, I would create it as a single-page app.

That time has come, and since I’ve been working with AngularJS and Bootstrap, I decided to use that stack. Hence, Jiffy – the JavaScript File Editor. It’s simple but easily extended: it can support a new file format just by adding a JSON file definition for it. It keeps everything local (in the browser) so no private data is ever sent to a server.

The initial version is now on GitHub, npm, and bower. If you’re also surrounded by flat files, give Jiffy a try. And if you create custom file definitions that others might like, please send me a pull request to add it to the collection.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

JavaScript Tools

bracketsOne of my current projects is a single-page responsive app with several JavaScript / HTML5 frameworks: AngularJS, Bootstrap, jQuery, Underscore, RequireJS, etc. These are awesome, but my usual server-side editors (Eclipse, IntelliJ, Vim) are not a great fit.

Perhaps not surprisingly, many new web-dev editors are built in JavaScript. Here are two that I now use regularly and highly recommend:

  • Brackets.io. This open-source editor is still being cooked by Adobe, but it’s already awesome. It’s fast and featured, with some good extensions like Vim bindings.
  • Draw.io. Yes, Visio is terrible and getting worse, as are many “enterprise architect” drawing tools. Meanwhile, the web-based draw.io is free, lightweight, easy to use, and often exactly what you need.

Perhaps if it ends with “io,” it must be good.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Please Just Work

Apple Cracked LogoLet me add my voice to the chorus of those calling on Apple to refocus on software quality. Today’s surprise was that Xcode now breaks IPA packaging in the silliest way possible. Sure, it’s a quick work-around to unzip, repair, and re-zip an IPA, but, please, stop the regression. I’m at the point that I wince at every new (frequent) fix update. The rush to innovate is great, but let’s not do it at the expense of “It Just Works.”

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

DevNexus

devnexusTaking in a good tech conference like JavaOne, Google I/O, or the WWDC usually means hopping a plane to the Valley for a week.  So it’s nice to know there are a couple of good local (Atlanta) and shorter conferences like DevNexus and GASS / NoFluffJustStuff

A colleague talked me into DevNexus this year, and I’m glad he did. This AJUG-sponsored conference has grown to the caliber and content of much larger conferences, includes tracks much broader than Java, and is well worth the low cost. So if, like me, you can’t usually break away for a week of JavaOne, take in DevNexus or NoFluff instead.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

XRebel

xrebelMy colleagues and I have plenty of Java profilers at our disposal, from the free ones included with every JDK to commercial suites. But while the best tool is the one you’ll use, heavyweight profiling tools often get shoved to the late stages of a project when tuning time is short.

XRebel is a lightweight profiler from our JRebel friends for ongoing use during code development. It doesn’t try to be an end-all monitor; rather, it targets a few of the most common trouble spots in Java web apps: SQL performance, session memory, and exceptions.  Installation is trivial: just add -javaagent to your container’s VM arguments. It injects an iframe to each of your served pages with a dashboard that flags any problems. From there, you can drill into stack traces and SQLs, and view execution counts and times.

I’ve used XRebel with several web apps, and have demo’ed it to others who have become fans. The new 2.0 Beta adds application code profiling, but I’ve encountered some UI hiccups with the initial beta version.  I’m sure those will be fixed fast, and I look forward to the upgrade.

If you haven’t yet tried XRebel, give it a run.  It’s so easy to download and enable, there’s no excuse not to try it.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Meap, Meap

MEAPAfter several runs of building native mobile apps for Android and iOS, I’m again using cross-platform (hybrid) solutions for those apps that don’t need heavy native capabilities. Mobile Enterprise App Platforms (MEAPs) based on Cordova are common, and a good place to start for corp-rat work.

IBM’s MEAP is Worklight (now called the MobileFirst Platform), and I’ve been running it through the paces. The Eclipse-based Studio is a free download from the Eclipse Marketplace, the online tutorials are quick, and the documentation is complete.

MobileFirst’s frameworks and structure are well-designed, helping keep as much apps code as possible in common JavaScript/HTML5/CSS, and pushing customization to platform-specific environments and device-specific skins. It has jQuery included, and convenience support for jQuery Mobile, Dojo, and Sencha Touch. But it’s possible to use just about any JavaScript framework. It provides good client-side (WL) support classes for JavaScript as well as native Android and iOS.

Server-side adapters can also be coded in JavaScript, with good libraries and tooling. I ran into a few adapter issues, such as exceptions using default data sources with z/OS DB2 connections, and namespace errors for SOAP adapters generated from WSDL. But these were easy enough to fix, and the benefits were worth the trouble.

The suite includes libraries and server apps for app management and updates, analytics, authentication, push notifications, and other “back end” responsibilities. It takes awhile to learn how to correctly package apps and then production-deploy everything, but I got by with help from the doc and StackOverflow.

Worklight is a mature product that’s continually being improved. And with IBM’s backing and focus, it’s a good choice for all your MEAPing.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Mule Ride

MuleESBMy prior experiences with heavyweight Enterprise Service Buses (ESBs) had me running away screaming, and ready to join the nascent NoESB movement. But I recently started a new project with broad integration requirements, and point-to-point solutions wouldn’t cut it.

This time, I went after a lightweight, embeddable solution. After ruling out lesser alternatives, I settled on Mule ESB (aka, Anypoint Platform). I downloaded Anypoint Studio and runtimes, worked through Mule in Action, and started building my adapter platform. I found it easy to integrate Mule with my other Java EE stuff and extend it as needed. Mule flows and Mule Expression Language (MEL) took a little getting used to, but I found them rich enough for much of what I needed, with supporting services and Java components filling the gaps. The GUI flow editors are nice, but direct XML editing was faster.

I ran into some problems with new message processors introduced with 3.5, such as the Web Service Consumer and generic Database connector, but their predecessors (HTTPS and JDBC connectors) worked fine. The new DataMapper is nice, but I avoided components that require the enterprise (vs community) edition. Through various flows, I was able to quickly integrate services (SOAP and REST), databases (mostly DB2), queues (WebSphere MQ and ActiveMQ), files, and various other endpoints on servers and mainframes.

If you need to quickly implement many decoupled enterprise integration patterns with SEDA benefits, I recommend MuleESB.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

May I?

Camera PrivacyiOS 8‘s broader camera privacy enforcement has caught many photo apps off guard. For too long, apps have just grabbed a UIImagePickerController and hoped for the best. After all, if isSourceTypeAvailable: or isCameraDeviceAvailable: answers YES, what could possibly go wrong?

Well, a lot. Now, if the user dismisses the first “Would Like to Access the Camera” prompt, bad things happen until the user changes the camera privacy settings. Without access, various apps (including my own) running under the iOS 8 betas have responded with black capture screens, crashes, and other ugliness.

The fix, of course, is to check further for access and gracefully handle denials: disable camera buttons and display a message. Here’s one way to check:

    AVAuthorizationStatus authStatus = [AVCaptureDevice 
                               authorizationStatusForMediaType:AVMediaTypeVideo];

And this:

    AVCaptureDevice *cameraDevice = [AVCaptureDevice 
                                          defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput 
                                          deviceInputWithDevice:cameraDevice error:&error];

…will give a more helpful error message in the NSError’s localizedFailureReason, such as “This app is not authorized to use the Back Camera.”

Who knows; maybe we’ll start getting failure reasons of “excessive selfies.” We can hope.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

The Other One

As JAX-RS implementations go, I suppose Apache CXF is as good as any. But among all the conveniences, it certainly has its share of surprises. For example, although I follow a typical REST resource URI scheme, I had to write a custom ResourceComparator to get certain lookups to work across multiple service beans. I’m over that now, but today’s bug was really weird.

In this case, I’m handling basic authentication in an upstream inInterceptor, pulling credentials from the message. This has several benefits, including simpler service beans. If credentials are missing or invalid, I do the usual 401 / 403 thing, but if authenticated, I inject a SecurityPolicy containing my Principal, like so:

        message.put(SecurityContext.class, new BasicSecurityContext(userProfile));

.. with the hopes of my service bean having access via:

        @Context SecurityContext securityContext

Trouble is, that came out null. Turns out, this is a known issue with CXF, and the work-around (barring unwanted extra plumbing) is to use javax.ws.rs.core.SecurityContext, not org.apache.cxf.security.SecurityContext. So much for polymorphism.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Que penser de ces Pommes?

iOS AirPlay icons are infamous for disappearing when you need them most, but the usual work-arounds weren’t working under iOS 8 Beta 4.  So I went googling and found this gem:

On your iPad, iPhone or iPod touch, navigate to Settings > General > International > Language and change to a different language… The device will go through a language switch/reset process, and your AirPlay icon should be restored.

Next navigate back to Settings > General > International > Language (translated into the new language, of course) and switch back to your original language.

Change languages: love it! Fortunately, I remembered enough high school French to try it, but it seemed silly and didn’t work. But since it has worked for many others, it gets my vote for the most interesting work-around ever.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Smackdown

In today’s action, I wrote a new Google Cloud Messaging (GCM) server interface to the GCM Cloud Connection Server (CCS) via XMPP. GCM CCS offers several benefits over GCM HTTP including one of my key requirements, bidirectional messaging.

My app server didn’t yet have a XMPP interface, so I followed Google’s sample and plugged in Smack. Then the fun began. I immediately started getting exceptions (see Smackdowns below). These varied based on state and configuration, but basically the result was the same: the GCM CCS server was abruptly closing the connection during authentication. How rude; Smack was getting smacked down.

I dug in but ran into several red herrings. For example, Smack’s stream headers didn’t match Google’s doc (no tag close); Google’s doc is wrong. I debugged Smack, tried different Smack versions, tried other XMPP clients, tweaked configurations, studied XMPP protocols and SASL authentication, and updated authentication parameters and allowed IPs. Ultimately, I had a minor error in one of the authentication parms. I found it by Base64-decoding the auth value in Google’s example and comparing it to my own traces.

This would have been a quick fix if CCS had just given an authentication error message rather than just slamming the door. It must be a security thing. Oh well, on to the next adventure.

Smackdowns 

No response from the server.: 
	at org.jivesoftware.smack.NonSASLAuthentication.authenticate(NonSASLAuthentication.java:73)
	at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:357)
	at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:221)
java.net.SocketException: Connection closed by remote host
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkWrite(Unknown Source)
	at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
	at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
	at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
	at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
	at sun.nio.cs.StreamEncoder.flush(Unknown Source)
	at java.io.OutputStreamWriter.flush(Unknown Source)
	at java.io.BufferedWriter.flush(Unknown Source)
	at org.jivesoftware.smack.util.ObservableWriter.flush(ObservableWriter.java:48)
	at org.jivesoftware.smack.PacketWriter.writePackets(PacketWriter.java:168)
java.io.EOFException: no more data available - expected end tag  to close start tag  from 
                                      line 1, parser stopped on END_TAG seen ...... @1:344
	at org.xmlpull.mxp1.MXParser.fillBuf(MXParser.java:3035)
	at org.xmlpull.mxp1.MXParser.more(MXParser.java:3046)
	at org.xmlpull.mxp1.MXParser.nextImpl(MXParser.java:1144)
	at org.xmlpull.mxp1.MXParser.next(MXParser.java:1093)
	at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:279)
Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Android Studio

I’ve been waiting months for a “ready for prime time” version of Android Studio. Its move from “Preview” to “Beta” (version 0.8) on June 26 became my signal to dive in deep and use it for real work. After all “beta” in Google terms usually means a level of quality some products don’t achieve with years of “GA” releases.

Android Studio inherits many of its benefits from IntelliJ. I like the speed and stability, the quality of the development and rendering tools, the productivity, the rich static code analysis, and all the other benefits that come from its IntelliJ underpinnings.  I’ve bounced back and forth between Eclipse keymaps and IntelliJ defaults, but settled on the IntelliJ’s, with the cheat sheet on hand. “When in Rome,” don’tchaknow, although I haven’t yet joined the Darcula side. Even from a few days’ use, I’m sold on IntelliJ and certainly don’t miss Eclipse’s crashes and stalls.

I’m also pleased with the Gradle-based build system and AAR support. After fighting with Maven plugin bugs, apklib hacks, and other Eclipse-Maven clashes, it’s refreshing to have a build system that is elegant, is backed by Google, and just works. The factoring of content across build.gradle files, manifests, etc., is clean and DRY, and the Android-specific checks guide you toward best practices.

The main downside is that there is no automatic nor incremental build as with Eclipse, so builds are slower and many errors aren’t discovered during editing. Build speed will likely improve as it exits beta (perhaps with the help of parallel builds), but the rest is just the IntelliJ way.

Still, I’m happy with both IntelliJ and the Android Studio so far. Now if I could only switch from MyEclipse to IntelliJ for server-side code…

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Time’s Up

I recently needed to add an inactivity timer to a pair of new apps. If the user was logged in but inactive past a configurable period, the app should display an error when resumed and return to the login screen. It must be non-intrusive and not interrupt any foreground apps. It could not require a background service.

For Android, this fit well into the standard activity architecture. In particular, well-behaved activities should normally remain quiet when paused and should finish themselves rather than be killed by some other activity.  So I created the following simple utility class to enable this.  The primary hooks are:

  • initialize – Called when the first (main) activity starts.
  • startMonitoring – Called when the user logs in.
  • monitor – Called from each activity’s onResume.  I added it to my common fragment superclass.

It also has an optional requestExit to request an immediate exit based on some other criteria.

The deus ex machina is the simple activity.finish().  This ripples through all active activities so that they politely exit whenever the sShouldExitNow flag is set.

public class UserActivityMonitor {
 
    private static long sUserTimeoutMillisecs = 5 * 60 * 1000;	// Default to 5 minutes
    private static boolean sIsMonitoring = false;
    private static boolean sShouldExitNow = false;
    private static long sLastActionMillisecs = 0;
 
    /**
     * Initialize monitoring. Called at app startup.
     */
    public static void initialize(long timeoutMillisecs) {
        sUserTimeoutMillisecs = timeoutMillisecs;
        sIsMonitoring = false;
        sShouldExitNow = false;
        sLastActionMillisecs = 0;
    }
 
    /**
     * Start monitoring user activity for idle timeout.
     */
    public static void startMonitoring() {
        sIsMonitoring = true;
        sLastActionMillisecs = System.currentTimeMillis();
    }
 
    /**
     * The given activity is at the foreground.
     * Record the user's activity and, if necessary, handle an exit or timeout request.
     * If timed out, start the postTimeoutActivity (if provided) on a new task.
     */
    public static void monitor(Activity currentActivity, Intent postTimeoutActivity) {
        if (sShouldExitNow) {
            // Calls here will ripple through and finish all activities
            currentActivity.finish();
        } else {
            if (sIsMonitoring) {
                checkForIdleTimeout(currentActivity, postTimeoutActivity);
            }
        }
        sLastActionMillisecs = System.currentTimeMillis();
    }
 
    /**
     * Request to exit the app by triggering all activities to finish.
     */
    public static void requestExit() {
        sShouldExitNow = true;
    }
 
    /**
     * Check for an inactivity timeout.
     * If we have timed out, display a message, finish the activity,
     * and set the "should exit now" flag so that other activities quit.
     * If timed out, start the postTimeoutIntent (if provided) on a new task.
     */
    private static void checkForIdleTimeout(final Activity activity,
                                            final Intent postTimeoutIntent) {
        if (User.getCurrentUser().isLoggedIn() && sLastActionMillisecs > 0) {
            long idleMillisecs = System.currentTimeMillis() - sLastActionMillisecs;
            if (idleMillisecs > sUserTimeoutMillisecs) {
                // The first time we detect a timeout, display a popup message
                UiUtils.showError(activity.getString(R.string.msg_timeout),
                        activity.getString(R.string.msg_timeout_title), activity, 
                         new IErrorDisplayListener() {
                            @Override
                            public void onResponse(int buttonClicked) {
                                sShouldExitNow = true;
                                activity.finish();
                                if (postTimeoutIntent != null) {
                                    postTimeoutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                                            Intent.FLAG_ACTIVITY_CLEAR_TASK);
                                    activity.startActivity(postTimeoutIntent);
                                }
                            }
                        });
            }
        }
    }
}
Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

In a Heartbeat

Although the Heartbleed data leak vulnerability is as old as OpenSSL 1.0.1‘s heartbeats (over two years), it has just now risen to instant infamy. First, it has taken us all a while to upgrade OpenSSL to 1.x and, second, it wasn’t publicized until this week. So now that we have a perfect storm of ubiquity and fame, the internet will be flooded with hackers scanning sites and running off with all the data they can grab.

So Filippo Valsorda‘s Heartbleed tester has arrived just in time. I found the online version to be too slow for my needs, so I grabbed the golang source and used it. It contains the simple magic:

     err = binary.Write(&buf, binary.BigEndian, uint16(len(payload)+100))

… which can get you back more than you gave and everything you asked for:

00000000 02 00 79 68 65 61 72 74 62 6c 65 65 64 2e 66 69 |..yheartbleed.fi|
00000010 6c 69 70 70 6f 2e 69 6f 59 45 4c 4c 4f 57 20 53 |lippo.ioYELLOW S|
00000020 55 42 4d 41 52 49 4e 45 3f e5 bc eb c8 a6 ba e0 |UBMARINE?.......|
00000030 c3 a2 3f f4 27 a1 66 00 4d 6b ca 79 ed 24 8b 2c |..?.'.f.Mk.y.$.,|
00000040 ab ff 3a 31 25 8d c5 c2 6c ea 04 bb 2c e3 53 41 |..:1%...l...,.SA|
00000050 4f 2e 56 09 de e5 99 98 dc ef f8 42 67 41 9f 21 |O.V........BgA.!|
00000060 6c 73 e7 6f f5 4a 54 90 a5 fc bb 5b c1 2c aa 78 |ls.o.JT....[.,.x|
00000070 d8 1c c4 ea 5f 99 f5 09 69 bb b7 46 76 0d 8a 2b |...._...i..Fv..+|
00000080 1c 48 f3 c5 1c 9f d8 47 e7 b1 b6 15             |.H.....G....|

That’s right: OpenSSL versions between 1.0.1 and 1.0.1f will use your payload length for its return data, up to nearly 64K of goodies.

Kudos to Filippo for putting together such a handy tester so quickly.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Such Little Things

After many Android app versions with perfectly-good icons, it came time to replace them: new launcher icons, new store listing graphic, new action bar icons, and in some cases, removing the icon from the action bar altogether.

For the latter, I preferred an easily-customized manifest entry:

android:icon=”@color/transparent”

This worked nicely for local and ad-hoc installs. So I was surprised when publishing to the Google Play store failed with the obscure yet common error:

Your APK cannot be analyzed using ‘aapt dump badging’.  Error output:

Failed to run aapt dump badging: Error getting ‘android:icon’ attribute: attribute is not a string value

You wouldn’t know it from the message nor from any online suggestions, but that @color/transparent trick was the root cause. So instead I created a 1×1 transparent PNG (ic_empty.png) and used it instead:

android:icon=”@drawable/ic_empty”

BTW, when it’s “icon update” time, I’ve found the quickest way to get scaled icons is to create the 512×512 web version, and point the New Android Application wizard at it.  It’ll create the mdpi, hdpi, xdpi, and xxhdpi sizes for you.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

22.6.2, Maybe?

The recent 22.6 Android Developer Tools (ADT) update broke quite a few things: AVD creation and editing, ProGuard, performance, etc.  Rather than revert to 22.3 like many folks, I decided to muddle through with some work-arounds and hold out for the fixes in 22.6.1.

Well, 22.6.1 has arrived and at least fixed the AVD issues, but ProGuard still fails with:

Error: Unable to access jarfile ..\lib\proguard.jar

Fortunately, working around that bug is easy: simply edit proguard.bat and provide an absolute path to the JAR.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Surprise!

Like others before it, this week’s final release of iOS 7.1 brought the rush to grab the latest and greatest. Time to upgrade Xcode (5.1) and the SDK (7.1). Time to load the final iOS 7.1 on devices. Time to repackage and test.

Also like recent updates, this one carried an unwelcome surprise: for over-the-air (OTA) distribution, the plist must now be served over https with a valid (and CA-signed) SSL certificate. I discovered this one the hard way, when ad-hoc OTA installs of my apps failed with “Cannot install applications because the certificate for … is not valid.”  This change was in the 7.1 betas, but I didn’t use OTA distribution for betas.

While I’m sure Apple meant well, this change has real impacts on those of us in the real world who use test servers for deployment, and yet don’t want the security risks that come with proliferating SSL certs. Fortunately, the work-around is easy: serve the plist (and only the plist) via SSL and serve the link and IPA over vanilla http.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Goto Fail

Now that the media frenzy over Apple’s SSL (goto fail) MitM vulnerability has calmed and our iPhones and Macs have been updated, folks are starting to reflect. That’s a good thing. Among other things, this event has pushed issues of code quality, review, testing, patching/updates, version blocking and user notification up the management chain to, hopefully, get more focus and funding.

This had something for everyone and the net is now flooded with commentary on it. I’m certainly not going to repeat that, but consider:

  • Some static analyzers (like Coverity and clang with -Wunreachable-code) would have caught this.
  • Peer code review likely would have caught this.
  • The bug was in the open source community for anyone to find.
  • Vendors everywhere were asking how they could help notify their users and ensure they upgrade.

This one-liner joins the ranks of the most apt and pithy software bugs. It’s right up there with the misplaced break that broke the AT&T network on my 25th birthday. BTW, if your birthday call to me didn’t get through that day, there’s still time; call or message me. But please upgrade your iPhone first.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Back Up

Enabling Up (ancestral) navigation in Android apps is straightforward for the typical case: just specify parent activities in the manifest and send setDisplayHomeAsUpEnabled(true). But non-typical cases (like dynamic parents) require extra steps.

Today I implemented some non-typical cases and experimented with overriding action bar callbacks, tweaking the back stack, etc. But in most cases I simply wanted up navigation to behave like back navigation whenever there was no fixed parent defined. For that, I developed a simple recipe:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
	switch (item.getItemId()) {
		case android.R.id.home:
			if (NavUtils.getParentActivityName(getActivity()) != null) {
				NavUtils.navigateUpFromSameTask(getActivity());
			} else {
				getActivity().onBackPressed();
			}
			return true;
		default:
			return super.onOptionsItemSelected(item);
	}
}
Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS

Easy Choice

By managing two different teams at the Apple developer site, I’ve been able to compare iOS developer programs over time.  The $99 individual and company programs are an OK first step, but you get what you pay for. With these programs, ad-hoc (pre-store) distributions are limited to 100 devices, each of which must be registered. And every new device registration requires updating provisioning profiles, refreshing, and repackaging. This also makes testing at cloud services like DeviceAnywhere a major hassle.

With the $299 enterprise program, you can get that magical ProvisionsAllDevices in your embedded.mobileprovision and get out of the device registration business. Unless you’re only distributing internally to a very small team, the $200 shakedown is well worth paying for.

Of course, when it’s time to submit to the store, you must use the non-enterprise membership, so that $99 company membership isn’t wasted.

Share This:
  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks
  • Google Buzz
  • RSS