WordPress Hybrid Client: v1.3.0 released

WordPress Hybrid Client (WPHC) is an Open Source project available on GitHub.

You can refer to the online documentation to properly build your applications. A Computer science background is required but the explanations should be clear enough.

v1.3.0 ChangeLog

milestone

iOS / Android push notifications 100% free and self hosted for WordPress using Cordova and Ionic

Push notification is always a pain when it comes to find the perfect free service, there are several possibilities like pushwoosh, pushapps, pushover etc.

If you are hosting your WordPress website there is no need to subscribe any of those services. With your server you have already what it takes to send push notifications to your subscriber.

No third party service involved, just your WordPress server and your application.

It all start with installing Push Notifications for WordPress (Lite) plugin to your WordPress.

Send push notifications to iOS, Android, and Fire OS devices when you publish a new post. Straight from your WordPress site, in real-time.

Installation

  1. Search and install “Push Notifications for WordPress (Lite)” from the Plugins WordPress page
  2. Activate “Push Notifications for WordPress (Lite)” through the ‘Plugins’ menu in WordPress
  3. Configure the plugin by going to the Push Notifications menu that appears in your admin menu

Android

If you have not already done so, you’ll need to set up a Google API project, to generate your senderID. Follow these steps to do so.

Get the SenderID

Signing into https://developers.google.com/mobile/add and follow the steps to get Cloud messaging senderID and apiKey.

Tip: The senderID is a 12 digit number

Configure the WordPress plugin

Go to Push Notifications > Settings and check the following checkboxes:

  • Basic Options > Send push notifications when a new post is published
  • Basic Options > Android devices
  • Send Push Notifications for > Posts
  • Misc > In the Android notification payload add the message field

Then go to “Android Push Notifications (via GMC)” section and enter you Google Api key.

Do not forget to save.


iOS

Configure the WordPress plugin

Go to Push Notifications > Settings and check the following checkboxes:

  • Basic Options > Send push notifications when a new post is published
  • Basic Options > iOS devices
  • Send Push Notifications for > Posts

Do not forget to save.

Certificates and Provisioning profiles

This part is really painful (Generally when you have to use Apple’s service it is…). It is all well explained there: http://strangemilk.com/ionic-push-notifications-with-ios/

Create .pem

Get .perm files

Once you have got your .pem files upload them in the iOS Push Notifications section

Setup Ionic / Cordova

I recommend using NgCordova and the NgCordova pushNotifications plugin

Installation

cordova plugin add https://github.com/phonegap-build/PushPlugin.git

# Or if you are using Ionic CLI
ionic plugin add https://github.com/phonegap-build/PushPlugin.git

Register to “Push Notifications for WordPress (Lite)”

“Push Notifications for WordPress (Lite)” exposes a Web service API that you can access over HTTP.

It only takes the OS (iOS | Android) and the device token.

function register(os, token) {
        var baseUrl;
        baseUrl = 'http://yourDomainName.com/pnfw';
        if (!baseUrl) {
            return $q.reject();
        }
        return $http({
            method: 'POST',
            url: baseUrl + '/register',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            transformRequest: function(obj) {
                var p, str;
                str = [];
                for (p in obj) {
                    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
                }
                return str.join('&');
            },
            data: {
                os: os,
                token: token
            }
        });
    };

iOS

$cordovaPush.register(iosConfig).then(function(deviceToken) {
    register('iOS', deviceToken).success(function() {
        return $log.info('Push notif Token stored');
    });
    $log.debug('iOS push notification registration success', deviceToken);
}, function(err) {
    $log.error('iOS push notification registration error', err);
});

$rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
    $log.debug('Push notif message', notification);
    if (notification.alert) {
        if (notification.foreground) { // If your user is using the app
            // Do something like opening the Post within the app
            // You have access to
            // notification.id which is the new Post ID
            // notification.alert which is the new Post Title
        } else { // If your user has clicked on the notification
            // Do something like opening the Post within the app
            // You have access to
            // notification.id which is the new Post ID
            // notification.alert which is the new Post Title
        }
    }
    if (notification.badge) {
        return $cordovaPush.setBadgeNumber(notification.badge).then(function(result) {
            $log.debug('Push notif badge ok', result);
        }, function(err) {
            $log.debug('Push notif badge error', err);
        });
    }
});

Android

$cordovaPush.register(androidConfig).then(function(result) {
    $log.debug('android push notification registration success', result);
}, function(err) {
    $log.error('android push notification registration error', err);
});
return $rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
    switch (notification.event) {
        case 'registered':
            if (!notification.regid.length) {
                return;
            }
            $log.debug('registration ID', notification.regid);
            register('Android', notification.regid).success(function() {
                return $log.info('Push notif Token stored');
            });
            break;
        case 'message':
            $log.debug('Push notif message', notification);
            if (notification.foreground) { // If your user is using the app
                // Do something like opening the Post within the app
                // You have access to
                // notification.payload.id which is the new Post ID
                // notification.payload.message which is the new Post Title
            } else { // If your user has clicked on the notification
                // Do something like opening the Post within the app
                // You have access to
                // notification.payload.id which is the new Post ID
                // notification.payload.message which is the new Post Title
            }
            break;
        case 'error':
            $log.debug('Push notif error', notification);
            break;
    }
});

All in one

angular.module('yourModuleName').run(function($log, $cordovaPush, $rootScope, $http, $ionicPlatform) {
    var androidConfig, iosConfig, register;

    androidConfig = {
        "senderID": ""
    };
    iosConfig = {
        "badge": true,
        "sound": true,
        "alert": true
    };

    register = function(os, token) {
        var baseUrl;
        baseUrl = 'http://yourDomainName.com/pnfw';
        if (!baseUrl) {
            return $q.reject();
        }
        return $http({
            method: 'POST',
            url: baseUrl + '/register',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            transformRequest: function(obj) {
                var p, str;
                str = [];
                for (p in obj) {
                    str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
                }
                return str.join('&');
            },
            data: {
                os: os,
                token: token
            }
        });
    };
    return $ionicPlatform.ready(function() {
        if (ionic.Platform.isAndroid()) {
            $cordovaPush.register(androidConfig).then(function(result) {
                $log.debug('android push notification registration success', result);
            }, function(err) {
                $log.error('android push notification registration error', err);
            });
            return $rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
                switch (notification.event) {
                    case 'registered':
                        if (!notification.regid.length) {
                            return;
                        }
                        $log.debug('registration ID', notification.regid);
                        register('Android', notification.regid).success(function() {
                            return $log.info('Push notif Token stored');
                        });
                        break;
                    case 'message':
                        $log.debug('Push notif message', notification);
                        if (notification.foreground) { // If your user is using the app
                            // Do something like opening the Post within the app
                            // You have access to
                            // notification.payload.id which is the new Post ID
                            // notification.payload.message which is the new Post Title
                        } else { // If your user has clicked on the notification
                            // Do something like opening the Post within the app
                            // You have access to
                            // notification.payload.id which is the new Post ID
                            // notification.payload.message which is the new Post Title
                        }
                        break;
                    case 'error':
                        $log.debug('Push notif error', notification);
                        break;
                }
            });
        } else if (ionic.Platform.isIOS()) {
            $cordovaPush.register(iosConfig).then(function(deviceToken) {
                register('iOS', deviceToken).success(function() {
                    return $log.info('Push notif Token stored');
                });
                $log.debug('iOS push notification registration success', deviceToken);
            }, function(err) {
                $log.error('iOS push notification registration error', err);
            });
            return $rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
                $log.debug('Push notif message', notification);
                if (notification.alert) {
                    if (notification.foreground) { // If your user is using the app
                        // Do something like opening the Post within the app
                        // You have access to
                        // notification.id which is the new Post ID
                        // notification.alert which is the new Post Title
                    } else { // If your user has clicked on the notification
                        // Do something like opening the Post within the app
                        // You have access to
                        // notification.id which is the new Post ID
                        // notification.alert which is the new Post Title
                    }
                }
                if (notification.badge) {
                    return $cordovaPush.setBadgeNumber(notification.badge).then(function(result) {
                        $log.debug('Push notif badge ok', result);
                    }, function(err) {
                        $log.debug('Push notif badge error', err);
                    });
                }
            });
        }
    }, false);
});

WordPress Hybrid Client

If you want your WordPress website available on iOS and Android there is a simple free and Open Sourced solution: WordPress Hybrid Client

With WPHC (WordPress Hybrid Client), your WordPress website application (iOS and Android) is just a build away.

Here is the features already available and a lot more is coming:

  1. Push Notifications
  2. Social buttons
  3. About Page
  4. Params Page
  5. Language switch [French|English|Chinese]
  6. Accessibility (Post font size)
  7. App rate
  8. Docker support for easier installation
  9. Syntax highlighter for tech blogs

MISC: Test Push Notifications on Android

If you want to test that GMC is correctly setup and that your device receive notifications you can follow this tutorial: Sending push notifications to Android via Gulp

WordPress Hybrid Client: v1.2.0 released

WordPress Hybrid Client (WPHC) is an Open Source project available on GitHub.

With WPHC you will be able to generate iOS and Android applications in a blink of an eye. Before anything you will need to install WP-API plugin which basically will turn your Website into a REST API.

Then you can refer to the documentation to properly build your applications. A Computer science background is required but the explanations should be clear enough.

v1.2.0 ChangeLog

milestone

Sending push notifications to Android via Gulp

If you ever wondered how to test that your push notifications work on Android without setting up any server here is how to do.

Install

npm install gulp node-gcm

Get Api key, Sender ID and Device ID

In order to be able to send push notifications we need only need the Google Cloud Api key, and the device ID(s).

To get the Api key and the senderID you can register there: https://developers.google.com/mobile/add

As for the device ID it can be found once your device is registered.

If you are using this Cordova plugin https://github.com/phonegap-build/PushPlugin you can get it like this (note that the senderID is used here):

document.addEventListener("deviceready", function() {
    var pushNotification = window.plugins.pushNotification;
    pushNotification.register(
        successHandler,
        errorHandler, {
            "senderID": "replace_with_sender_id (12 digits number)",
            "ecb": "onNotification"
        });

    function onNotification(e) {
        switch (e.event) {
            case 'registered':
                if (e.regid.length > 0) {
                    // Your GCM push server needs to know the regID before it can push to this device
                    // here is where you might want to send it the regID for later use.
                    console.log('Device id', e.regid);
                }
                break;
        }
    }

    function successHandler() {}

    function errorHandler() {}
});

Script

Now that you have both Device ID and Api key let’s create a script that send push notifications.

gulp.task('push:android', function() {
    if (!gutil.env.apiKey || gutil.env.apiKey === true) {
        throw new Error('You must specify the android Api key, refer to the documentation');
    }
    if (!gutil.env.deviceId || gutil.env.deviceId === true) {
        throw new Error('You must specify the android ID, refer to the documentation');
    }

    console.log('apiKey', gutil.env.apiKey);
    console.log('deviceId', gutil.env.deviceId);

    var gcm = require('node-gcm')

    var message = new gcm.Message({
        collapseKey: 'demo',
        delayWhileIdle: true,
        timeToLive: 3,
        data: {
            key1: 'message1',
            key2: 'message2'
        }
    });

    var sender = new gcm.Sender(gutil.env.apiKey);

    sender.send(message, (gutil.env.deviceId instanceof Array) ? gutil.env.deviceId : [gutil.env.deviceId], 5, function(err, result) {
        if (err) {
            console.error('Failed, status code', err);
        } else {
            console.log('Success', result);
        }
    });
})

Run

You can run the script like like this on one or several devices:

# One device
gulp push:android --apiKey YOUR_API_KEY --deviceId YOUR_DEVICE_ID

# Two devices
gulp push:android --apiKey YOUR_API_KEY --deviceId YOUR_DEVICE_ID --deviceId YOUR_DEVICE_ID

If everything is fine you should have your push notifications working.

Commun error

If your api key and senderId are not ok you will get this error message:

Success { multicast_id: 7412383159195664000,
  success: 0,
  failure: 1,
  canonical_ids: 0,
  results: [ { error: 'MismatchSenderId' } ] }

If so regenerate a api key using this link https://github.com/phonegap-build/PushPlugin.

Toptal interview process explained

Introduction to toptal

Toptal is platform for Freelancers to meet clients from all over the world. It is similar to freelancer.com, elance.com or upwork.com but with a big difference, Toptal claims to have the best freelancers there are thanks to a high level interview process. Here is a video that will help you better understand Toptal.

It took me two months to go through all the interview steps to become a Toptal Engineer, part of the so called The Top 3%! Here is how things went:

Interview process

Language & Personality (26.4% pass)

The first step in the screening process is a comprehensive language, personality, and communication interview. Candidates must be able to read, write, and speak English extremely well.

You need to show them that you are invested and passionated about your work (maybe you have a blog or you commit on famous open source projects etc.). Find something that makes you an above average developer and start from there.

Be yourself, do not be stressed and everything will be alright.


Timed Algorithm Testing (7.4% pass)

This step checks for computer science fundamentals, problem solving ability, and intellect. I spent days going through old algorithm books and refreshing my memory about famous algorithms time complexity. If you do not have at least the background listed in this article: JavaScript background to have before any job interview with top companies do not even try.

You will have 90 minutes to solve three algorithms on https://codility.com/. To be honest you cannot do all of them in the given time, focus only on two but make them great! Obviously I cannot disclose the content of those tests but let just say that they were really different from each other and therefore required a large algorithm knowledge.

This is the most difficult part of the interview process. If you do not spend some time learning algorithm basics you will fail. My advice is to get back to your university books and train as much as you can. Open Codility and start coding! If you need a little help my solutions are available on this post: Codility efficient algorithm solutions in JavaScript


Technical Screenings (3.6% pass)

Each candidate is screened by at least two certified Toptal engineers. Each screener will provide specific live coding exercises that cover core topics within the candidate’s primary tech stack.

You will have the choice between a back end or a front end test. I obviously selected the front end test. You will have real life problems to solve using a specific technology. For me it was jQuery, and to be honest at the beginning I was a little bit skeptical on my ability to succeed as I did not used jQuery for a while but I sorted things out pretty easily.

If you have the experience you claim to have, you should not have any difficulty with this step.


Test Projects (3.2% pass)

Ok now we are talking! If you arrive here, it means that you are pretty good at what you do but this step is somehow special. It tests your ability to commit to a project and your willingness to become a Toptal engineer! It is a great way to demonstrate technical competence, thoroughness, professionalism, and integrity.

I have heard there are several projects that you can end up with. One of them is a classic Todo list but the one I got was the creation of a Web page form that creates new users dynamically. I received around 20 wireframes that I had to bring to life in two weeks time using the technology that I wanted.

It had to be pixel perfect and fully functional. I am more of a mobile (cordova), single page application kind of guy so I actually learnt stuff doing this project. For example to help you doing pixel perfect pages you can use the Perfect pixel Chrome extension.

What I believe is that they are trying to give you a project that is a little bit far from your comfort zone to test your ability to learn/discover new stuff while delivering high quality projects.

I chose to use Webpack, Bootstrap 3 and jQuery and I spent around 20 hours to finish this project.

Once it is done you will review the project and the code with a recruiter and that’s it, the interview process is now over and if you are lucky enough you will be part of Toptal đŸ™‚

Select only technologies that are mature enough, you do not want to waste time on bugs that are not part of your code.


Acknowledgment

I personally wanted to thank recruiters and engineers that I talked to. They are really professional and are here to help you succeed.

Conclusion

Overall this experience was really good to me, during the process I wrote greats articles JavaScript background to have before any job interview with top companies and Codility efficient algorithm solutions in JavaScript that really helped me reviewing my basics and taught me that in life nothing is impossible as long as your are brave enough.

In case your are interested in my profile: http://www.toptal.com/resume/julien-renaux

WordPress Hybrid Client: v1.1.0 released

WordPress Hybrid Client (WPHC) is an Open Source project available on GitHub.

With WPHC you will be able to generate iOS and Android applications in a blink of an eye. Before anything you will need to install WP-API plugin which basically will turn your Website into a REST API.

Then you can refer to the documentation to properly build your applications. A Computer science background is required but the explanations should be clear enough.

v1.1.0 ChangeLog

milestone