What I love and hate about AirPods after a month of use.

I have been using wireless headphones for five years now

Motorola S305 Bluetooth Stereo Headset

This Motorola Headset was the first wireless headset I have purchased. They were pretty bad. The sound quality was below average, the battery life was not impressive, they were extremely uncomfortable to wear, but they were affordable.

Despite all of the highlighted issues I fell in love with the idea of having wireless headphones and ever since then I’m using wireless headsets almost all of the time.

BackBeat GO

A massive step up from my Motorola headset. A lot more comfortable, longer battery life and better sound quality.

Unfortunately, they didn’t live for very long. After about a year and half of use, they stopped turning on. The fact that Plantronics didn’t have an office in Auckland didn’t help the matters, as I have spent over a couple of hours talking to their representative in the Philippines and the United States.

BackBeat GO 2

In any case, I enjoyed the company, so when I started looking for a new pair, I was very excited to see that Plantronics released a new version of BackBeat GO.

I could connect them to up to two devices, so even if I were watching a movie on my iPad, they would automatically pause it and switch to my phone if I get a call.

The addition of a charging case was a very nice bonus. I wasn’t using it as often as I initially thought I would, but that was fun to have it.

Eventually, I lost them, still sorrowful about that.

 

BackBeat Pro

All in all, I think this are the best headphones I have ever used. I can connect them to up to two devices at the same time. The battery lasts for over 24 hours of continuous listening. I can connect them with a wire if the battery does run out or if I want to avoid the latency while practicing guitar.  And they have active and passive noise cancellation.

But they weren’t, however, perfect. Headphones are pretty big, so I can’t comfortably use them laying down, and I can’t use them with my bicycle helmet. And I have to go to the Bluetooth settings and disconnect the headphones before I can reconnect them to something else.

AirPods

And now the AirPods. I was pretty skeptical about them, but after reading and watching several reviews, I have decided to give them a go. I have been using them almost daily for the last month or so, and I think I have formed a pretty strong opinion about them, so let me share it with you.

Things I love about them

AirPods are great at so many things!

Pairing

Pairing the AirPods with my iPhone was a breeze. I have opened the case, and the pairing dialog appeared on my iPhone right away. I didn’t have to open the settings menu, press the “Pairing” button, enter a pin code or anything else like that. I just pressed the “Connect” button on the phone, and… That’s all it takes! What is more, this was enough to pair my AirPods with all of my devices thanks to the iCloud synchronization. Almost magic!

Charging case

The case is perfect for carrying the headphones around and keeping them together. Plus they charge when they are inside of the case which is an excellent bonus. Every time I don’t use them I put them back into the case. I enjoy that the case is subtle, can fit in any pocket and that I don’t have to connect any cables when I put them away. Almost too easy!

Switching between different devices

Oh my god, this is by far my most favorite feature. I can listen to the music on my iPhone on the way home, then sit down in the front of my computer and with a click of a button on the computer itself disconnect the headphones from my phone and connect them to the Mac.

With all of my previous headphones, I had to take the old device, press the disconnect button, then get the new device and press the connect button. No longer the case!

Software updates

AirPods can get over-the-air software upgrades. There is no update button, there is no cable to be connected, no firmware tool to be installed on the computer and it is silent. You just know that your headphones get better and better over time without any interaction from your end. Awesome!

Battery indicator

Apple puts all of the battery indicators in one place. With a single widget, I can get the current battery status of my iPhone, my iPhone case, my watch, each of the AirPods as well as the AirPods case. Neat!

Automatic pause

AirPods detect when you remove a headphone from an ear, and it puts the play function of your device on pause. Regardless whether you were listening to music, watching a YouTube video, listening to an audio book or anything else. Especially neat when you just met somebody on the street and want to exchange a few words with them. There is no need to get the phone out to put the music on hold anymore.

Being able to use just one headphone

I have a bad habit of watching movies, YouTube, and educational videos in bed. And quite often, I only use one of the two headphones when I am on my side. What is neat is that the other headphone can recognize this and shut down preserving the power. I don’t understand how Apple managed to achieve this, but it is great!

Things I hate about them

AirPods are far from being perfect. Below I will list a few things which annoy me.

No buttons

None, not a single one. You cannot pause them. You cannot skip tracks. You cannot change the volume. Nothing!

The only gesture they understand is a double tap to enable Siri. You need to use the voice assistance for the rest of the functionality. I think we are still too far away from using the voice assistance in public. I am in any case. But even at home, double tapping the headphones, waiting for Siri to respond, then giving a command just to skip a track is way too much effort. I can perform a lot of the functionality from an Apple Watch, but they are too slow, so I have to take my phone out of my pocket way more often than I want for the wireless technology.

Inconsistent volume

I hope this is one of the glitches they will resolve in an upcoming version. A few times they volume was too soft low when the volume indicator was on maximum. Pressing the “volume down” button magically increased the volume. Very confusing and annoying, but not too common.

Desynchronization

Ok, before I mention how annoying desynchronization is, let me note that it is very impressive that most of the time they are in sync. Think about it. You have two independent pieces of technology connected to your phone. Even the slightest delay in one of the headphones would be very noticeable. So the fact that it doesn’t happen very often is incredible! Kudos to engineers at Apple, I’m sure it took a very long time to figure.

However! They do get out of sync. So one headphone is less than a second ahead of the other. It sounds like something is echoing inside of your head, incredibly annoying. Taking the headphone out and placing it back into an ear solves this, though.

Color

Oh, how I wish that Apple would give me more options than just white!

Things I wish Apple added

Waterproof design

From what I have seen on YouTube, they are pretty good at resisting the water. Being 100% waterproof would’ve been an excellent bonus.

Ability to locate them with a phone

AirPods are small. And I tend to misplace small things. Would be awesome if they were able to make loud enough sound to be able to hear them when you try to locate them.

Louder sound output

The maximum volume is not high enough. My EarPods were louder.

Improved sound quality

Sound quality is not that great. It is not bad, but it could be much better.

Noise cancellation

I guess there is no easy way to achieve this, but after using the noise canceling headphones, it is hard to go back.

Bottom Line

AirPods are great if you expect to use them with more than two Apple devices. For any other situation, I would recommend you to look for something else.

View Holder design pattern for Android

About this post

The View Holder design pattern is one of the most important ways to increase the performance of an Android application with a ListView. However, most of the Android projects I review at Udacity entirely omit this pattern. Personally, I think that Android itself is to be blamed here. View Holder is not a complicated pattern, but it takes a bit of getting used to, and the benefits may not be that visible, so students may prefer to build their applications in the simplest way and move onto the next project.

But, once you learn how a View Holder works and how to implement one you will never go back. And it will be a lot easier for you to move onto a RecyclerView, which is a lot more powerful and flexible view comparing to a ListView. I’m planning to cover a RecyclerView in one of the upcoming posts.

About a List View

ListView is designed to tackles the problem of displaying a long or even huge list of items. Some examples may include a list of contacts, songs, your favorite coffee shops, latest transactions of your bank account or many others. The challenge here is that users can only see a small portion of these items. A user will never be able to see all of their 4579 songs at the same time, but rather a small portion of them.

 

It does not make sense to try to render the whole list at once. It would take a significant amount of time, device memory and may be unnecessary as users may be interested in the third item of the list and never scroll to the bottom.

To increase the performance of scrolling, a ListView would “recycle” its views, by taking a view which is no longer visible to the users and appending it at the bottom of the list, as shown below.

This is already a very efficient process, the only problem here is the findViewById() method, which is pretty slow and depending on the complexity of a list item it may be called multiple times per item, here is a simple example.

@NonNull
@Override
public View getView(int position, @Nullable View convertView, 
                    @NonNull ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext())
                .inflate(R.layout.contact_item, parent, false);
    }

    Contact contact = contacts.get(position);
    ((TextView)convertView
            .findViewById(R.id.name_text_view))
            .setText(contact.getName());
    ((TextView)convertView
            .findViewById(R.id.mobile_text_view))
            .setText(contact.getMobile());
    ((TextView)convertView
            .findViewById(R.id.landline_text_view))
            .setText(contact.getLandline());

    return convertView;
}

As you can see in the code above, the findViewById method is called three times and this is done every single time we display a new item on the screen. However, once we implement the ViewHolder design pattern this will no longer be required.

Starter Code

I wrote a very simple application with a ListView as a starting point for this tutorial. You are welcome to fork or download the Starter Code from Github or from my blog.

You can open the project with Android Studio, compile and run it. It is a very simple application which is designed to mock a contacts list.

You can refer to the Contact.java and MockDataGenerator.java classes if you are interested in looking under the hood of the application. The first one is a Model class, which contains the first and the last name of a person as well as their contact numbers. And MockDataGenerator is used to generate a List of random contacts.

Most important, however, is the ListViewActivity.java file, so let’s have a look a closer look at it.

public class ListViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list_view);

        ListView listView = (ListView) findViewById(R.id.list);
        listView.setAdapter(new ContactsAdapter(this));
    }

    class ContactsAdapter extends ArrayAdapter<Contact> {
        private List<Contact> contacts;

        public ContactsAdapter(Context context) {
            super(context, -1);
            this.contacts = MockDataGenerator.getMockContacts(1000);
        }

        @NonNull
        @Override
        public View getView(int position, 
                            @Nullable View convertView, 
                            @NonNull ViewGroup parent) {
            
            if (convertView == null) {
                convertView = LayoutInflater
                        .from(getContext())
                        .inflate(R.layout.contact_item, parent, false);
            }

            Contact contact = contacts.get(position);
            ((TextView)convertView
                    .findViewById(R.id.name_text_view))
                    .setText(contact.getName());
            ((TextView)convertView
                    .findViewById(R.id.mobile_text_view))
                    .setText(contact.getMobile());
            ((TextView)convertView
                    .findViewById(R.id.landline_text_view))
                    .setText(contact.getLandline());

            return convertView;
        }

        @Override
        public int getCount() {
            return this.contacts.size();
        }
    }
}

There are two classes in this file. Keeping different classes in the same file is not always the best practice, but I did this to make the tutorial simpler so that we don’t have to navigate between multiple different files. First class is called ListViewActivity and it extends AppCompatActivity, this is very standard. And the class implements a single method only.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_list_view);

    ListView listView = (ListView) findViewById(R.id.list);
    listView.setAdapter(new ContactsAdapter(this));
}

In this method we attach the activity_list_view layout file as the main view, then we find the ListView inside of that layout and assign a new instance of the ContactsAdapater to it.

The ContactsAdapter has three methods. First, we have a constructor. It accepts an instance of Context and passes it to the super class. And then it instantiates the local variable called contacts with a list of 1000 random contacts.

public ContactsAdapter(Context context) {
    super(context, -1);
    this.contacts = MockDataGenerator.getMockContacts(1000);
}

Then we have a method called `getCount()` which returns the size of the local variable called contacts.

@Override
public int getCount() {
    return this.contacts.size();
}

And lastly we have our getView() method which is responsible for inflating and recycling the views. The method is checking if the convertView parameter is null and inflates a new instance of the contact_item view if it is.

In either case, we take this view, locate the three text views inside of it and fill them up with a relevant instance of the Contact class.

@NonNull
@Override
public View getView(int position, @Nullable View convertView, 
                    @NonNull ViewGroup parent) {
    if (convertView == null) {
        convertView = LayoutInflater.from(getContext())
                .inflate(R.layout.contact_item, parent, false);
    }

    Contact contact = contacts.get(position);
    ((TextView)convertView
            .findViewById(R.id.name_text_view))
            .setText(contact.getName());
    ((TextView)convertView
            .findViewById(R.id.mobile_text_view))
            .setText(contact.getMobile());
    ((TextView)convertView
            .findViewById(R.id.landline_text_view))
            .setText(contact.getLandline());

    return convertView;
}

Adding a ViewHolder

The purpose of a view holder is to hold ._. references to the views. So, rather than trying to find a view by its identifier each time it is about to appear on the screen, we only need to do this once and then use the reference to modify the content.

We’ll start by creating a new class. This class can be located inside of the ContactsAdapter class for now. There are three text views inside of the list item, so our view holder needs to have three references. Here it is:

class ViewHolder {
    private TextView nameTextView;
    private TextView mobileTextView;
    private TextView landlineTextView;
}

Now let’s add a constructor. The constructor needs to accept a reference to a View and instantiate all of the references to the private variables. This code will probably feel familiar.

public ViewHolder(@NonNull View view) {
    this.nameTextView = (TextView)view
            .findViewById(R.id.name_text_view);
    this.mobileTextView = (TextView)view
            .findViewById(R.id.mobile_text_view);
    this.landlineTextView = (TextView)view
            .findViewById(R.id.landline_text_view);
}

And this is all we need to do to implement the class itself! Now we just need to make sure to use it inside of our adapter. The only place we need to change is our getView method.

We need to create a new instance of a `ViewHolder` every time we inflate a list item. And then we store this reference. This is where setTag() method becomes very useful. We can assign any object to a view which we can retrieve later. Here is the modified code.

ViewHolder viewHolder;

if (convertView == null) {
    convertView = LayoutInflater.from(getContext())
            .inflate(R.layout.contact_item, parent, false);

    viewHolder = new ViewHolder(convertView);
    convertView.setTag(viewHolder);
}

We also need to add an else statement for those situations when the convertView is already inflated. Here we just need to read the tag and cast it to the class.

} else {
    viewHolder = (ViewHolder) convertView.getTag();
}

The last part is to start using the viewHolder to reference the views instead of our old code.

viewHolder.nameTextView.setText(contact.getName());
viewHolder.mobileTextView.setText(contact.getMobile());
viewHolder.landlineTextView.setText(contact.getLandline());

And we are done! You can find the final version of the code in this Github repository or download it right here.

Introduction into Google VR and Unity

Over the last several months I have had a chance to dive into VR development with Unity and Google SDK, so I thought I would use this opportunity to write several posts about my experience.

In this post, I will describe how to create a simple scene with Unity, add Google VR SDK, attach the input module called “Reticle” and implement a simple on click listener.

I’m planning to add more posts in the future including some of the projects I have developed.

The Result.

By the end of the article, we will have a VR scene with a 3D cube in the middle. We will be able to interact with it using the button on the Google cardboard. Our cube will move up every time we press the button. Here is a demo of the scene.

Required Software.

All of the necessary software and SDKs are free. In fact, it is possible to complete a game and release it on Google Play or Apple Store without spending a single dollar. I’ll be focusing on the education side of this, though.

Unity.

Unity is a cross-platform development IDE focused specifically on game development. It is powerful and free to use application, which can be intimidating at first glance. You can find the download link here. Personal version is more than enough to complete this tutorial.

Google VR SDK.

Google VR SDK is a set of scripts, tools, and models developed to make working with virtual reality scenes simpler. You can find the download link here.

Step 1. The Unity Scene.

Alright, all of the software is downloaded and installed, it’s time to get started. Let’s launch Unity, select the “NEW” button, give a descriptive name to our project, select any convenient location, make sure that the project is set to “3D” and select the “Create project” button.

Alright, we have an empty 3D scene with a camera, a skybox and a directional light. Without going too deep into terminology, a skybox is what is visible beyond the scene, like a horizon line, and a directional light is used to represent the sun. Here is what we will see if we press the play button.

Not particularly impressive, but everybody has to start somewhere.

Let’s add a “Plane,” which we will be using as our floor, and a 3D Cube, which we will program to interact with later in the post. Press the “Play” button again to stop the scene, then select “Create” -> “3D Object” -> “Plane”

And then follow the same steps to “Create” -> “3D Object” -> “Cube”.

Pressing the “Play” button again will reveal a slightly more interesting scene now.

We can re-arrange all of the objects, including the camera, by using the “Move” tool at the top left-hand corner. Select any object, then select the “Move” tool and then re-position the object by dragging the colored arrows as shown below.

I would prefer to move the plane to below the camera as if we were standing on top of it and the cube a little further away so that it doesn’t appear intimidating, like so.

Great start, now we can convert this scene to VR!

Step 2. Google VR SDK.

Adding the Google VR SDK might be one of the simplest and coolest integrations I have seen with software. The SDK has the extension.unitypackage. All we need to do is double click it while our Unity scene is opened and paused.

Unity will prompt us with the “Import” dialog, without changing the default selection we can click the “Import” button. Alternatively, we can uncheck the “Demos” selection, as we will not be using any of them at the moment. Depending on the power of your computer it may take up to a couple of minutes.

Now we can add the SDK to our scene. Under the “Assets” directory locate “Prefabs,” then select the “GVRViewerMain.prefab” file, drag and drop it anywhere in the scene.

Now if we press the play button we will notice that our screen gets separated into two halves, one for the left eye and the other for the right. We can press and hold the “alt” button on the keyboard and move the mouse cursor to look around as shown in the demo below.

That was easy, wasn’t it? The next thing we need to do is adding an element called “Reticle.” A Reticle is an analog for a mouse cursor used in Virtual Reality. It is a little dot which always stays in the middle of the screen, and it is used to point at elements. We need to grab the GvrReticlePointer prefab under “Assets” -> “GoogleVR” -> “Prefabs” -> “UI” directory and drop it on top of the Main Camera instance.

Pressing the play button again will reveal a new white dot which always stays in the middle of the screen.

Almost there, now we need to add an event system to make sure that we can capture all of the events. Using the “Hierarchy” dialog select “Create” -> “UI” -> “Event System”.

Now we need to add the “Gvr Pointer Input Module” as a new component of the Event System. Select the “Event System,” then navigate to the “Inspector” tab, click “Add Component” button, and locate the “Gvr Pointer Input Module.”

We need to make sure that this module has a higher priority than the “Standalone Input Module,” otherwise it would be very hard to select the elements with our Reticle. We can do this by selecting the gear icon next to the pointer module and then selecting the “Move Up” option.

One last step! To make sure that the reticle gets activated when it points at the cube we need to add the Raycast module to our primary camera. Select the “Main Camera” from the Hierarchy, then select the “Add Component” button and locate the Physics Raycaster.

Step 3. Custom code.

We need to create a new script and associate it with our cube. To do this, we need to select the Cube from the hierarchy, open the “Inspector” panel, tap the “Add Component” button, type “MovingCube” into the search bar and hit the “Enter” key when the “New Script” option appears.

Following these steps will create a new C# script called “MovingCube,” associate it with the Cube we have just created and launch a C# development IDE, either Mono or Visual Studio depending on which operating system you have installed.

The script will be pre-populated with the skeleton code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MovingCube : MonoBehaviour {

 // Use this for initialization
 void Start () {
 
 }
 
 // Update is called once per frame
 void Update () {
 
 }
}

We only need to create a single method which will be triggered every time we point at the cube and click the cardboard button. We can call this method MoveCube. The code is below, every time the method is called it moves the “Y” position of the cube by 1 meter.

public void MoveCube() {
    transform.Translate(Vector3.up * 1);
}

Next, we would need to add a Trigger component to our cube in a very similar way to how we added a script. Select the cube, then the “Add Component” button, then locate the “Event Trigger” option.

Inside of the “Event Trigger” component we need to select the “Add New Event Type” button and then select the “Pointer Click” option.

Next step is a little tricky. We need to press the “Plus” button, select the “Moving Cube” component, drag it and drop it into the “None (Object)” field, like shown in the demo below.

Then we need to add the function. Select the “No Function” drop down, then the “MovingCube” component, then the “MoveCube” method.

And we are done! Pressing the play button will launch our VR scene. Now we can move around, point at the cube and move it up by pressing the Cardboard button. On a computer, we can simulate the button with a mouse click.

Udacity has launched Blitz connecting alumni with companies

About Udacity Blitz

Udacity Blitz is free to use platform built and supported by Udacity to connect companies from all over the world who is looking for professionals and the Udacity Alumni who are looking for temporary, contract or permanent jobs. The platform is working on a project by project basis with a new team assembling for each project as fitted best to meet the requirements and the timelines specified by the business.

Udacity Blitz for Alumni

Trough window glass. Designer brainstorming new ideasUdacity Blitz is a great program for the Alumni to get more experience in the field of their expertise, expand their portfolio, find the contract or permanent jobs, and to get to know clients and other professionals in the industry. Udacity opened the program to all Alumni, and I would encourage the learners to look into the following Nanodegrees if they are interested participating in the program:

  1. Android Basics Nanodegree
  2. Android Development Nanodegree
  3. iOS Development Nanodegree
  4. Machine Learning Engineer Nanodegree
  5. VR Developer Nanodegree
  6. Front-End Web Developer
  7. Full Stack Web Developer
  8. Data Analyst Nanodegree
  9. Artificial Intelligence Nanodegree

Udacity Blitz for Companies

For the companies, the platform provides an excellent way to find the talent for projects of all sizes, whether it is a brand new website, application, business reporting based on the data or anything else similar to the categories above. The platform provides competitive rates and, most importantly, a 100% money-back guarantee if the job was not up to the standard.

How it works

Business comes up with an idea. It could be a website for a restaurant, a new social application or anything else. They register their interest to build the product using the official website. One of the Technical Project Managers (TPM) gets in touch with the business to discuss the details, then size and estimate the project costs. After the firm and the TMP agree on the features and the price, the TMP will assemble a team of the engineers, and they start working on the projects together. The TPM will regularly keep in touch with the development team to make sure that the project is on schedule and the budget. When the engineers complete the project, they deliver it to the business and all of the payments get finalized. If the company decides to continue working on the project or add new features, then they can keep working with the same team or even hire the engineers for a permanent position.

My experience

I was very fortunate to work on one of the early Blitz projects in a team of four people – myself (I was mainly focusing on iOS), an Android developer, a designer, and a TPM. We have completed and delivered the project within three months. I had the most positive experience working on this project. My TPM was very approachable and helped me to keep the line of communication open to make sure that the product is built the best to meet all of the requirements of the business.

Even more reasons to study with Udacity

With a Job Guarantee, support with career development, the most up-to-date technology stacks taught by the top of the industry and now Udacity Blitz, Udacity is by far the most obvious choice for me concerning the online education.

My first experience building an application for tvOS (Apple TV) and all the things which went wrong.

I have had a 3rd generation Apple TV for a few years now. I loved it! It worked extremely well for watching Netflix and mirroring the screen from an Apple device, but it did not allow any third party applications for a very long time. Until Apple TV 4 has been announced along with tvOS. I was super excited! I purchased the Apple TV as soon as I had the opportunity to, but never really had a chance to write an app for it. Until a couple of weeks back.

Project Idea

The idea was very simple. We have a TV installed right above our team. Unfortunately, the information displayed on that TV is not very valuable for our team, so I thought it would be cool to implement an application with a very simple user interface, which would allow anybody to change the content displayed on that TV. My idea was to create two applications. The first application would run on the Apple TV, which would download a list of web addresses from a back end and then loop through those addresses. The second portion would be a web app, which would allow people to modify the list of the addresses picked up by the TV.

My idea was to use a single view controller with a WebView in it, a timer running in a loop, and Firebase SDK to subscribe to the real-time database with a list of addressed. It didn’t quite work.

USB C

I hit my first road block when I have tried to connect the Apple TV to my Mac, just to realise that instead of using a lightening port Apple decided to use a USB C port. Don’t get me wrong. I have nothing against USB C. I just don’t understand why Apple decided to put it here. Most of the iOS devices come with a lightning port. The Apple TV remote controller is charged through a lightning port, the Apple TV comes with a lightning cable in the box, so why USB C on the device itself? After finding the cable, I started writing the application, just to see that…

tvOS does not allow to use UIWebView

UIWebView is disallowed. It is there, it is functional, it works in very much the same way as UIWebView for iOS, but the application is not compiling if you try to reference it. As I wasn’t planning to release the application to the App Store I had to find a way around it, which I did here.

To some degree, I can understand why Apple decided to do this. I think they were worried that the App Store would be filled with applications which don’t have anything else, but a wrapper around their responsive website. But completely removing UIWebView from the operating system is a bit silly in my opinion. How does one suppose to implement OAuth? Well, I have hacked around it, so moving on.

Firebase is not compatible with tvOS

Argh… StackOverflow is talking about a beta version of the SDK available, but not publicly. I have tried to “hack” my way around this, without any luck. I have attempted to find a similar back-end solution but didn’t want to spend hours researching, so I gave up on this idea as well.

At the end, I decided to use the company’s wiki page as a “backend.” The idea was that my app would load the wiki page every so often and parse the list of links from there. Every user already has access to the Wiki, and they don’t need to learn how to use it, so in some way, that solution was probably even better, but…

The Wiki page is password protected

I have added a very hacky JavaScript logic to log into the wiki page. It wasn’t pretty but worked well for the demo version of the application.

The results

I built the project within a day. It is not very pretty, but it is functional.

Building the application icon was a lot of fun! The designer had to supply three different images, which I “plugged into” Xcode to get a very cool 3D effect.

Working with the remote controller was harder than I expected it to be. Not that it took me very long, but I was hoping to see a more explicit interface for the main way for the users to interact with the application.

The documentation is rather poor. I had to rely on StackOverflow more than I’d like to for the first experience with the platform.

Overall, I don’t think I will be writing more apps for tvOS anytime soon. The use cases seem to be rather limited, so I’m not sure if it will be very popular beyond video games and video streaming services.

Making a server logs available online with Firebase (Part 3 of 3)

This post is the last in the “Making a server logs available online” series.

You can read about uploading the server logs to Firebase in part 2 and how to setup Firebase account in part 1.

Webpage

Now when I had my logs available in the cloud, I just needed to add a web interface to display them to the users. Fortunately, Firebase makes it incredibly busy, the whole “project” only required 136 lines of code.

The template

I started building my app with the following template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Logger</title>
    <link rel="stylesheet" href="main.css">
    <link rel="stylesheet" href="form_sign_in.css">
  </head>
  <body>
    <script></script>
  </body>
</html>

Adding Firebase

First of all, I needed to add the link to the Firebase library

<script src="https://www.gstatic.com/firebasejs/3.3.0/firebase.js"></script>

 

The Firebase initialisation code went inside of the <script> tag of the <body>, like so:

var config = {
  apiKey: "",
  authDomain: "",
  databaseURL: "",
  storageBucket: ""
};
firebase.initializeApp(config);

Adding the Log in page

I’ve used jQuery to help me reduce the amount of code I needed to write, so I had to add the library into the header.

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

Here is the HTML code of my “login container”

<div id="login_screen" class="container">
  <div class="form-signin">
    <h2 class="form-signin-heading">Please sign in</h2>
    <div id="login_screen_error" class="error_box" style="display: none"></div>
    <input id="username_field" type="text" class="form-control" placeholder="Email address">
    <input id="password_field" type="password" class="form-control" placeholder="Password">
    <button class="btn btn-lg btn-primary btn-block" id="btn_login">Sign in</button>
  </div>
</div>

And the jQuery logic to handle the user input and displaying the error message if required (the awesome part is that the error message itself is supplied by Firebase).

  $("#btn_login").click(function() {
  $("#login_screen").hide();
  var username = $("#username_field").val();
  var password = $("#password_field").val();

  firebase.auth().signInWithEmailAndPassword(username, password).then(function () {
    $("#main_screen").show();
    getLogs();
  }).catch(function(error) {
    $("#login_screen").show();
    var login_screen_error = $("#login_screen_error");
    login_screen_error.show();
    login_screen_error.text(error.message);
  });
});

Displaying the logs

All I wanted to do is getting the latest 20 logs and displaying them on the page. Firebase couldn’t make it easier for me!

Html portion:

<div id="main_screen" style="display:none;" class="container">
  <div class="panel panel-primary">
  <div class="panel-heading">
  <h3 class="panel-title">Latest application logs</h3>
  </div>
  <div class="panel-body" id="logs_content">
  Loading...
  </div>
  </div>
</div>

JavaScript/jQuery potion:

firebase.database().ref('/logs/' + username).limitToLast(20).on('value', function (snapshot) {
  $("#login_screen").hide();
  var logs_content = $("#logs_content");
  logs_content.empty();

  var result = snapshot.val();

  for (var property in result) {
    if (result.hasOwnProperty(property)) {
      logs_content.append("<div>" + result[property] + "</div>");
    }
  }
});

Making it pretty

I have used bootstrap library to add responsiveness to my webpage:

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

Making a server logs available online with Firebase (Part 2 of 3)

This is the second part of the post. The first one is available here.

Uploading the server logs to Firebase.

This task proved to be very simple. I wanted to achieve the following

  1. Add a timestamp to the message.
  2. Upload the message to Firebase. Each of the users should have their instance of the log file.
  3. Print the message into the log.
  4. Erase the old messages every 10 minutes.
Without going much further into the details, here is the class I ended up using.
package com.spreys.udacity;

import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created with Intellij IDEA
 * @author vspreys
 * Date: 18/04/15
 * Contact by: vlad@spreys.com
 */
public class Logger {
    private static final SimpleDateFormat TIMESTAMP_FORMAT 
         = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    private final DatabaseReference databaseReference;

    public Logger(String username) {
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        this.databaseReference = database
                                    .getReference("logs/" + username);
        startCleaner();
    }

    /**
     * Prints out message into the console with the current date/time
     * @param message message to be printed
     */
    public void println(String message){
        String timeStamp = TIMESTAMP_FORMAT.format(new Date());

        String messageWithTimestamp = timeStamp + ": " + message;

        //Print out the message
        System.out.println(messageWithTimestamp);

        //Update the database with the new message
        databaseReference.push().setValue(messageWithTimestamp);
    }

    private void startCleaner() {
        new Thread(new Runnable() {
            public void run() {
                do {
                    databaseReference.setValue(null);
                    println("The logs have been cleaned");

                    //Clean the logs every 10 minutes
                    waitFor(10 * 60);
                } while (true);
            }
        }).start();
    }

    private void waitFor(float seconds){
        try {
            Thread.sleep((int)(seconds * 1000)); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Making a server logs available online with Firebase (Part 1 of 3)

About the project

Over the last 12 months or so I have been working on a small Java application which needs to be continuously running in the background. The application itself is not that interesting, all it does is collecting the information from different APIs and sending me occasional emails when it finds new information. It has only two users (including myself), and I have no intention of making it public.

The setup around this application, however, is a lot more interesting, and I have learnt a lot from it, so I thought I would share some of my learnings.

The problem

Until I have implemented the solution described below the only way to read the logs of my application (it prints a lot of time) was to SSH to my server, and open an instance of the “screen” application on which it runs. It was way too many steps, and it meant that I could only do so from a computer, so I thought I should make them available on the Internet so that I could access them from any device which has a connection to WWW. I decided to use Firebase for this purpose.

I will separate the whole process into three parts:

  1. Setting up Firebase (this article);
  2. Updating my Java application to start uploading the information to the server;
  3. Creating a website which can access the data;

Firebase setup

I have created a new project from the Firebase console by giving the name and my location.

screen-shot-2016-09-11-at-8-27-01-am

Then I needed to add a service account which would be used to write the logs. I have followed the official Firebase documentation to achieve that step.

As I mentioned, I have two users (including myself), so I added two accounts in the Firebase console. I went to “Auth” section and then selected “SET UP SIGN-IN METHOD”.

screen-shot-2016-09-11-at-8-31-15-am

screen-shot-2016-09-11-at-8-32-07-am

For now, I only needed to “Enable” the simple “Email/Password” option. After that, I could return to the “USERS” section to add my two accounts.

screen-shot-2016-09-11-at-8-33-46-am

That was all of the setup I needed on the Firebase side.

 

Design your future presentation at AUT

On the 12th of May this year Auckland University of Technology gave me this amazing opportunity to give a speech during their “Design Your Future” event. I have spent the last 5 and a half years studying at AUT part time and I was fortunate to meet fantastic people who are very passionate about Software and Education.

I told about my journey into software development to Dr Stephen Thorpe who asked me to share this story with the students of AUT.

You can find my presentation below. It’s about my Successes, Failures and everything in between.

 

Tools for remote software development teams collaboration

Over the last 2-3 years I had several opportunities to work with teams which don’t share the same office. It comes with its own challenges, so I wanted to create a short (hopefully) post to list some of the software which proved to be useful for the remote teams collaboration. In this post I am not going to cover open source software, as it is a very different beast, but I’d rather focus on small(ish) private projects with team size of up to 5 people.

Source Versioning Control

I have tried a few different systems, including keeping the source code in a shared Dropbox folder (yes, that did happen and no, I’m not proud of it), private SVN repositories, Team Foundation Service, Bitbucket and a private Github repository.

All of them come with their own pros and cons. Personally I would stop on either Team Foundation Service, aka Visual Studio Online or a private Github repository.

Github is very pleasant from the coding perspective, it has a very mature UI, it is easy to make pull requests, merge and fork code, it is possible to quickly overview all of the code changes and it is very fast. All of that been said, in most of the cases Visual Studio Online would win for me for two reasons:

  1. It is free for teams of up to 5 people
  2. It combines project managements tools as well as the version control system, and having the two tools to work side by side is awesome.

Communication

Emails, phone calls, Skype, Facebook groups, Google Hangouts and Slack are the tools I have been using for the team communication. So far Slack is the winner. It allows to create different channels for different purposes, it is very easy to search the communication history, there is an insane amount of integrations with different services, it is possible and easy to share files and images and it is free unless your team is getting very big.

Documentation

So far nothing managed to convince me to move away from the Google Docs. Ability for several people to work on the same document at the same time is priceless. It is very fast, easy to use and it is free.

Diagrams

For a long time I was a very big fan of Lucidchart. It is working fast, it allows to design any type of a diagram I could think of, it allows an online collaboration and it is very easy to use. All of this been said, I have found their current pricing model a little much, which eventually forced me to move away from Lucidchart. For better or worse I don’t need to create diagrams very often, so I might use the software for a couple of days every couple of months and then forget about it. And their restrictions on the free version of the product are rather aggressive.

So lately I have been using draw.io. It is almost as powerful as Lucidchart and it is completely free. Plus it allows to save all of the charts on Google Drive.

Design

I don’t have to say too much on this topic. Invision does everything I could ask from a design software. At times I find it unnecessary hard to use, but maybe that’s because I’m not spending too much time in it.

Project Management

Researching a good project management software was one of my assignments at the university a few years back. I have tried a lot of different applications some of which are better than others, but I’m yet to find one I would fell in love with. Visual Studio Online is my current tool of choice. Mainly because it is in the cloud and it is free for small team.

Continues Integration System

Argh, CI is something we should use a lot more often than we do. The amount of times something is working on one machine, but not the other is too high and CI could totally resolve this problem. Unfortunately I’m yet to find an easy to setup solution with low overhead. The best I have found so far is a standalone installation of TeamCity. It does require a lot of resources and setting it up to work in a cloud is not as straight forward as I’d like it to be.

Source of Truth

It is very easy to get lost when so many different tools are used. Personally I found it incredibly valuable to have a website to store all of the build artefacts including exported versions of documents, wireframes, designs, copies of diagrams, application builds, etc, all stored in one easily accessible and secured location. WordPress is my GoTo engine whenever I need to create a website. It doesn’t take longer than a couple of hours to setup a brand new website from scratch and start storing the documentation.