News

Migrating v3 Android Apps to the New PubNub Android SDK v4

7 min read Michael Carroll on Jan 13, 2017

Earlier this year, we released our new v4 Android SDK to GA, and we’re already seeing some awesome new implementations with our customers! In Part One of our series, we covered some of the major changes to the SDK. In this post, we’ll cover migration, showing you how to upgrade apps from the Android v3 to the Android v4 SDK. For more on the SDK improvements, we’ve got a writeup on that as well.

PubNub Android SDK V3 and V4 Sample Applications

In our experience, we’ve found that the best help for migrating code is a solid foundation of sample code that actually works. It’s especially helpful if that code is streamlined so that there isn’t a ton of business logic to wade through.

Along those lines, we’ve collected a bunch of sample Android applications together that you can refer to when migrating between PubNub API v3 and v4. If you use these codebases, make sure to substitute in your own publish and subscribe keys from the last section – otherwise, they won’t work!

Ok, now we’re ready to go! Let’s dive into those first 2 codebases listed above and see exactly how to migrate between the API versions.

Preamble: Running the code

If you downloaded the code from our sample chat applications above into Android Studio, then running the code should be as easy as clicking the play button in the Android Studio toolbar. You can use a connected device or an AVD in the emulator to run the application.

As you sign into the application from multiple devices, you can exchange chat messages in the Pub/Sub tab, the Presence tab will show an updated member list, and the Multi-tab will show the latest message sent by each device to a random channel.

Here’s what you’ll find:

android-app-all

Just in case you need it, here’s the link for how to enable USB debugging on an Android device.

Step 1: Migrating Initialization Code

As we said before, the v4 SDK improves upon the v3 API tremendously with its Fluent API.

In v3, initialization looked like this:

// OLD v3 CODE
this.mPubnub = new Pubnub(Constants.PUBLISH_KEY, Constants.SUBSCRIBE_KEY);
this.mPubnub.setUUID(this.mUsername);

That doesn’t look too bad, but what if you need to override options?

// OLD v3 CODE
this.mPubnub = new Pubnub(publish_key, subscribe_key, secret_key, cipher_key, ssl, iv);

At first glance, the constructor scheme seems pretty sweet. That is, until you realize you need to remember the proper ordering and data types, and look up the right constructor every time you add an override.

In contrast, here’s how it’s done in v4:

// NEW v4 CODE
PNConfiguration config = new PNConfiguration()
  .setPublishKey(Constants.PUBNUB_PUBLISH_KEY)
  .setSubscribeKey(Constants.PUBNUB_SUBSCRIBE_KEY)
  .setUuid(this.mUsername)
  .setSecure(true);
this.mPubnub = new PubNub(config);

Even though it looks like more code, the code is much more understandable and self-documenting. It also separates the configuration from the instantiation, enabling the configuration to be contained in its own method.

One other note – it’s PubNub now in v4, in contrast to Pubnub in v3. Much better!

Step 2: Migrating Publish/Subscribe Code

Once your initialization is all set, you’ll want to make sure all of your Publish/Subscribe code and callbacks are wired up correctly. In the old API version, all of the callback binding happened in the subscribe call. This was fine, but it meant that we had to also subscribe to the presence channel as well to receive presence updates (we’ll cover that shortly).

// OLD v3 CODE
this.mPubnub.subscribe(Constants.CHANNEL_NAME, this.mChatCallback);
this.mPubnub.subscribe(Constants.PRESENCE_CHANNEL_NAME, this.mPresenceCallback);

The key thing to remember about the v3 API is that it’s a very thin binding around the publish/subscribe channel API. It’s not difficult, but always remembering that the presence channel ends in “-pnpres” and tracking the channels independently was one more implementation detail to worry about.

In the new v4 API, there are two steps, corresponding to the richer bindings around channels and presence. The first step involves adding a listener for events – this makes the callback eligible for receiving channel and presence messages. The second step involves the subscription call itself.

// NEW v4 CODE
this.mPubnub.addListener(this.mPubSubPnCallback);
this.mPubnub.subscribe().channels(PUBSUB_CHANNEL).withPresence().execute();

You might be wondering why this actually matters. In practice, when subscribing and unsubscribing channels regularly in an application, it makes much more sense to call unsubscribe() on the channel name (which is just a simple string) and not have to provide the listener object (which might be in a much different part of the code).

Speaking of callbacks, let’s take a look at those.

In the v3 API, Callback is a generic object that handles any inbound message or event coming from a channel. It might be a message event, a presence event, or an error or status case. The painful part is that when subscribing to many channels, all the error and reconnection code gets duplicated. Another painful part is that the inbound message object is an org.json object that requires typecasting and inspection to process. Not horrible, but not really awesome either.

// OLD v3 CODE
public class ChatPnCallback extends Callback {
    @Override
    public void successCallback(String channel, Object messageObject) {
        // message handling
    }
    @Override
    public void errorCallback(String channel, PubnubError error) {
        // case handling
    }
    @Override
    public void connectCallback(String channel, Object message) {
        // case handling
    }
    @Override
    public void reconnectCallback(String channel, Object message) {
        // case handling
    }
    @Override
    public void disconnectCallback(String channel, Object message) {
        // case handling
    }
}

In v4, things get much better in our opinion. There are fewer events to worry about – all of the connect/disconnect/reconnect events are handled in the status handler. Also, message and presence events are separate, strongly typed, and include much more context about the message.

// NEW v4 CODE
public class PubSubPnCallback extends SubscribeCallback {
    @Override
    public void status(PubNub pubnub, PNStatus status) {
        // status handling
    }
    @Override
    public void message(PubNub pubnub, PNMessageResult message) {
        // message handling
    }
    @Override
    public void presence(PubNub pubnub, PNPresenceEventResult presence) {
        // presence handling
    }
}

For more details on Publish/Subscribe code, check out the pubsub package in the v4 sample code and the chat package in the v3 sample code.

Altogether, we found that this is much easier and cleaner to work with than the old style. Hopefully, you like it too!

Step 3: Migrating Presence Code

Previously, using presence was just a thinly veiled operation around channel subscription to the presence channel.

// OLD v3 API
this.mPubnub.subscribe(Constants.CHANNEL_NAME, this.mChatCallback);
this.mPubnub.subscribe(Constants.PRESENCE_CHANNEL_NAME, this.mPresenceCallback);

The Presence callback usually had to be a totally different specialized object (since presence events are a message event coming from the presence channel), which was a bit of a restrictive requirement.

In the v4 API, there are separate events in the SubscribeCallback for message and presence events. If presence events are desired, the developer just needs to specify withPresence() in the subscribe call. Goodbye, “-pnpres”!

// NEW v4 CODE
this.mPubnub.addListener(this.mPubSubPnCallback);
this.mPubnub.subscribe().channels(PUBSUB_CHANNEL).withPresence().execute();

Also, Presence events in v4 are more strongly typed and include the UUID and event data. This makes it a lot easier to build the code for presence handling. In v3, it took a lot of debugging to figure out JSON message structures for all of the different presence events.

For more details on Presence code, check out the presence package in the v4 sample code and the presence package in the v3 sample code.

Step 4: Migrating Multiplexing & Channel Groups Code

If you’re not already familiar with it, Multiplexing allows more efficient connection usage when subscribing to multiple channels. In v3, the user could either specify a comma-separated list or an array of String channel names.

// OLD v3 CODE
this.mPubnub.subscribe("my_channel_1,my_channel_2", this.mChatCallback);
this.mPubnub.subscribe(new String[]{"my_channel_1","my_channel_2"}, this.mChatCallback);

In v4, it is much java-friendlier to pass an Array object instead of a primitive String array or comma-separated list. The other primary simplification is that you don’t need to remember separately which callbacks are bound for which channels when unsubscribing and resubscribing.

// NEW v4 CODE
pubnub.subscribe().channels(Arrays.asList("my_channel1","my_channel2")).execute();

In the v4 model, the listeners are bound separately and message events have additional context so that callbacks don’t need to contain as much state.

Channel Groups are a first-class citizen in v4. Subscribing to a channel group in v4 is as easy as:

// NEW v4 CODE
pubnub.subscribe().channelGroups(Arrays.asList("channelgroup1","channelgroup2")).execute();

You can check out the full API Clicking here for adding channels to and managing channel groups. Previously in v3, there were separate methods for channel group subscribe and unsubscribe which weren’t unified with the subscribe call like in v4.

For more details on Multiplexing code, check out the multi package in the v4 sample code.

Next Steps: Migrating Mobile Push Notifications, History, and Access Manager

We’ve covered a lot of ground in this article! In the interest of keeping it brief, we’ve omitted a few advanced topics which may be relevant to your application. Stay tuned for future articles – we’d love to cover these topics if there is enough interest. In the meantime, please refer to these v4 API and tutorials for guidance.

Hope this helps, and give us a yell if there’s any further info we can provide!

Wrapping Up

Thanks so much for stopping by and checking out our migration guide for Android v4 SDK updates. Hopefully, this gives you an idea of the latest and greatest features and how to use them! In the future articles, we’ll dive deeper into some advanced applications of the Android SDK for location-aware applications. Stay tuned, and please reach out anytime if you feel especially inspired or need any help!

0