Thursday, May 2, 2019

How to include a CMake project in a Xcode project

For an iOS app I'm working on I needed to include a C++ project, have it build according to the current scheme (debug / release) and be able to debug it. I don't know much about C++, but I know that CMake is a popular build tool and for the project I was trying to import it was the preferred way to build it anyway. Turns out there are not a lot of people doing this as most of the information you'll find is either outdated (no, I'm not using Xcode 5 anymore) or requires a lot of background knowledge about both Xcode and CMake - which I'm both lacking.

To save myself and others some time in the future, I'd like to walk through an example of how you can build a CMake project for iOS in Xcode:

1. Create iOS Xcode project

Doh! Assuming you don't have one already. There is nothing specific to do here.

2. Clone the C++ project you'd like to include in your project

I'll be using glog for the purpose of this tutorial. Please note that some projects do not build out of the box on iOS for different reasons. I have created a fork of some projects that I needed on iOS, maybe you are lucky and the one you are looking for is among them:

3. CMake, meet Xcode.

First you need to clone a toolchain for iOS to teach CMake how to compile for iOS. Please note: I was not able to use the latest version at the time of writing this article. Instead, I used a specific commit.
Next, run the following one-liner inside your project folder in the terminal:
mkdir build/ && cd build/ && cmake -G "Xcode" -DCMAKE_TOOLCHAIN_FILE=../ios-cmake/ios.toolchain.cmake ../glog.ios/ && cd ../
I usually place that in a file called build.sh as you will need to rerun this whenever the C++ project changes (i.e. new files added).

The above commands will take a while to complete, but at the end you should see something along the lines of:
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/tom/workspace/cmake-sample.ios/build
Please note that you might have to install CMake first and the Xcode command line tools.

4. Xcode, meet CMake!

If the previous step succeeded and did not report any errors in the last three lines you are already halfway there! Hang tight. You should see a new .xcodeproj-file now in a folder called "build" if you look at your project using the file explorer. In my case it's called glog.xcodeproj. Drag this file into the file panel (on the left) of your Xcode project to link them. It doesn't really matter where exactly you drag it to as the file structure of a Xcode project is purely virtual.
Files created by CMake after running the above commands
This is what your Xcode project might look like after dragging the project created by CMake into it


A few more things left to click-click configure in Xcode: go to your project file and under "General" click the Add-button for "Linked Frameworks and Libraries". In the dialog that pops up you should see your C++ project show up. Add it!
Linking the framework generated by CMake

In the same file under "Build Phases" add your C++ project to "Target dependencies" (note: there are lots of targets showing up here. It's usually the one with a grey house-like icon and the exact same name as your C++ project). If you don't do this, Xcode won't automatically rebuild your C++ project if necessary.
Adding the framework as a build dependency

Last but definitely not least you have to tell Xcode where to find the headers of the C++ project. Again in the project file, under "Build Settings" search for a setting called "Header Search Paths", add the path to the header files and make it "recursive" (should work with "non-recursive" too if you put the correct folder there). One would expect this setting to change automatically, but unfortunately you'll have to do this for each C++ dependency you add.
Specifying path to lo

5. Wrap C++ with Objective-C to use it in Swift

As of now Swift does not support calling C++ directly. Instead you have to call Objective-C, which can call C++. There's a lot of stuff about this online already, so give it a go. Feel free to leave a comment if you can't get it to work.

(A few tips and tricks to fix common quirks)

  • If your project doesn't build and you are completely out of ideas what went wrong, try removing the build-folder, rerunning the commands to create it and restart Xcode (yes, that does help sometimes).
  • Sometimes, cleaning the project twice makes a difference. I swear I'm not kidding.
  • All of this is very unstable in my experience, so it could be that it stops working with the next Mac / Xcode update. CMake versions do matter too (I'm using 3.14.0).

Wednesday, May 1, 2019

Ways to legitimately improve your rating on Google Play Store

User ratings on Google Play Store are... hard to read sometimes. It really hurts to see how people seemingly did not care to understand what your app actually does and then complain about it by leaving a bad rating. However, there is a big opportunity for you as developer to turn some of those heart-breaking-swear-ratings into something that does not drag down your average rating shown to future users.

By replying to reviews in a very polite way you can turn at least some of those - 50% in my case into something that is at least a little more positive. I had cases where people (accidentally?) rated the app with one star, but turned it into the full five stars after I had replied to their rating.

Again, it's important to not let your feelings take over and reply in a mean or emotional way. Stay professional, stay classy 😎. My opening phrase is usually "Thanks for your feedback" - even if the feedback was non-existent or not constructive at all. This is how you make some people aware of how stupid their review was in the first place. Next, I ask along the lines of "what exactly went wrong" or "how can we improve the app" to get a discussion going. Last but not least I often end with "contact me via email at [email protected]" in order to make it obvious for less technically versed people how to continue the discussion (if I'm not mistaken, there is a big button saying "REPLY" in the email that Google is sending to users, but still...).

Long story short: Keep an eye on your reviews, reply to them in a polite and professional manner and give the user concrete actions to take.

If your problem is not receiving enough ratings in the first place, I highly suggest to include a dialog that asks users to review your app. If you do this in a way that does not annoy users you'll see many more reviews for your app soon. In my case the conversion rate is very low - only 2% of users asked to leave a rating agree to do so.

Thursday, April 25, 2019

Create a simple landing page for your app in just a few clicks - for free

After redesigning one of my apps from scratch recently I decided it’s time to upgrade the accompanying website for it too. Previously it was hosted on a hidden subpage of my Blogger blog and I hardly ever updated it. Still, it received quite some traffic via the Google Play Store…

So a new website, right? Shouldn’t be that hard since I was looking for something simple: title, a short description, the logo and a few screenshots. Oh, a link to the app stores would be nice too of course. However I could not find any useful template / services to create a minimalist app landing page without designing it myself (my CSS is rusty to say the least). There are a gazillion templates that promise to deliver app landing pages, but most of them were bloated with unnecessary features or design elements. Shortly before giving up - and considering to refresh my CSS skills - I found LaunchKit. One of their tools allows you to create a website from the information available on the App Store (screenshot, logo, description, etc) - for free! Unfortunately they shut down their services after getting acquired by Google, but all of their code is open-source now and you can host it yourself: https://github.com/launchkit/launchkit/

Here’s a sneak peek of what I created:


Not too shabby, right? I even added some custom JavaScript to show a live chat for customers to ask questions (not shown on the screenshot). Here is the live version of it: opendocument.app

There is a few different ways how you can get something similar for your app too now that LaunchKit is not live anymore:

1. Host it yourself

LaunchKit released everything you need to host their services yourself. However, that means you’ll need a server to run it on - which costs a few bucks per month. Worth it, but definitely not the easiest solution if you keep in mind that you have to fix it yourself if the server goes down one night. Also, scalability? Nope. If you go down this route I would suggest to take a look at a fork that makes use of Docker: https://github.com/victorkifer/LaunchKitDocker/pull/1

2. Have someone else host it for you

Some people were smart enough to take the code that was published and host it so that others can use it. The only one I found so far is apptoolkit.io - it offers most of the features for free but some of them are paid (at an unreasonably high monthly rate).

3. Generate the website and export it as a static website

If you put in some extra effort you get the best of both worlds: create a website for free, host it for free and also have someone else worry about your servers. PLUS this scales infinitely (theoretically). And who else to use for hosting than good old Google? More specifically, we’ll use Firebase Hosting.

First generate a website using either a hosted or self-hosted version (localhost is enough) of LaunchKit. Afterwards export it as a static website using some bash magic: https://gist.github.com/mikecrittenden/fe02c59fed1aeebd0a9697cf7e9f5c0c

Last but not least you upload the “exported” website to Firebase by leveraging their Hosting service: https://firebase.google.com/docs/hosting/deploying

I won’t go into details here, but the steps provided above give you an idea of how the process works. The website you end up with is scalable (please mind the limitations of the free Firebase plan), fast, customizable and even supports connecting to a custom domain. If you link this up with Cloudflare now you are pretty good to go. One less thing to worry about if your app becomes the next big thing over night. ;)

Monday, December 24, 2018

Custom domain for Google MyBusiness websites

Unfortunately there is no way of setting a custom domain for websites created using the tools provided by Google MyBusiness, except ordering the domain via Google. That however is only possible in some countries at the moment, so it is not an option for some...

To solve that issue I created an app for CloudFlare, which makes your Google MyBusiness website appear under your own domain without confusing the user. You can find and install the app for free here. Read on to know why I think this is a good solution for a bad problem.

When looking at this problem I saw only two reasonable solutions: 1. forwarding your domain to the domain provided by Google (ending in . business.site) and 2. using an iFrame to load the website "within your website) without the user noticing. While the latter is not a perfect solution either, forwarding your domain creates a very bad user experience because the user starts his journey by typing in your domain but suddenly ends up on a possibly very different domain. This can cause confusion and a feeling that something went wrong for the user.

Implementing the iFrame-approach was more complicated than expected because it is not a commonly used solution. That's why I took the opportunity to learn more about CloudFlare apps and use them to solve my problem. The app automatically creates a DNS entry pointing to a server which hosts a very small HTML template. The CloudFlare app uses that to load the iFrame using the website of your choice (i.e. Google MyBusiness website).

There is an opportunity to get rid of the server, but that would require CloudFlare workers. Since they are not free I don't expect them to have a very big customer base so I decided not to limit my app unnecessarily.

Installing the app is literally as easy as clicking "Install" on CloudFlare and telling the app which website to redirect to. That of course requires your domain's DNS to be managed by CloudFlare, which I suggest anyway.

Sunday, November 18, 2018

IKEA TRADFRI review - a layman's smart home

I recently bought a few parts of the IKEA TRADFRI collection to get a taste of the future everyone's talking about: smart home. To get to know the system I bought the gateway, remote control, power plug and a light bulb.

Hardware

The components look very good if you like the usual minimalistic IKEA style (I do). They are mostly white and made of plastic that doesn't look too shiny but also doesn't look cheap. In fact, I wouldn't mind to have the gateway standing in the middle of my living room beneath the TV (on an IKEA shelf, obviously).

The IKEA website and also the local guidance at the store made it sound like you have to buy the (quite expensive) remote control in order to pair devices, which sounded ridiculous to me. I bought it anyway to make sure I can go through the whole setup. After setting it all up I understood that in fact I don't need THAT remote control, but I need SOME remote control from the TRADFRI collection. Since I bought the power plug in a bundle with a nice, small remote control I am able to return the expensive remote control now since there is no point in having it for me. After all the idea was to have a smart home, which means less physical controls and use apps instead!

Setup... not necessarily suited for your grandmother


Setup was mostly easy as the app explains what you need to do for each step. The manuals delivered with the product were surprisingly bad as there was 1. a lot of stuff that is not relevant (certifications, warranties, etc) and 2. the usual IKEA-style manuals don't fit such a product very well as pictures are not always enough to cover all the information that is necessary.

After ditching the manuals completely and relying on the instructions given by the app instead I was able to go through the setup. Overall it is more complicated than I'm used to from other IKEA products (which are non-tech products of course), but still better than the setup of other more geeky products. I could imagine a layman to set this up if he dedicates some time and effort into it.

However the thing that made the setup take much longer than expected for me is that there's a certain amount of randomness to the setup. I had to repeat some of the steps once or twice until it finally went through. For example, after setting up the second device I had to pair the first device again for some reason. I'm pretty sure that this was due to an error on my side, but there was no indication what went wrong. A person that is less technically versed might very well have given up halfway through...

Usage and features

After setting it all up the excitement went through the roof. The official app is a pleasure to use, very intuitive and responsive. I've seen much worse apps from big-name companies (look at the Playstation app for example...).

What you get by default is what you would expect: you see the state of each device (turned on / off, etc) and change those settings in a breeze. There's also presets to change the color of a light bulb to match your mood, i.e. "relax" to make it a very dim, warm light.

The real fun started for me when I discovered the Google Home integration. Again the setup for that was not flawless as I had to restart it a few times, but eventually it worked out fine. Afterwards all my devices showed up in the Google Home app, which offers similar features to the app offered by IKEA itself: turn on / off devices, see their current state, change brightness (but not the color!).

The thing that made me whee was when I tried to use this using the Google Assistant: "OK Google, turn on the living room lights." - "Ok, turned on the living room lights" - BOOM! But that's not all: with the IKEA app you are only able to control devices while you are connected to the same WiFi network. Guess what? With Google Home / Assistant you can do the same from anywhere in the world - no further setup required! Not sure if you turned off the lights before leaving home? No problem, you can check it from remote and turn it off if necessary.

The other thing I'm using is the power plug, which controls my towel heater in the bathroom. So lazy me being lazy, I can use an app while sitting on the couch to pre-heat the bathroom. Welcome to the future, you lazy idiot! :)

Conclusion

I'm really happy to own these products now and I'm considering where to apply them next. In my opinion it doesn't make sense to equip your main lightning with smart bulbs as they won't work if somebody turns them off using the physical switch anyway. So in the "worst" case you try to turn it on using the app but it doesn't work because someone used the physical switch to turn it off earlier. That completely defeats the purpose of the whole thing in my opinion. I could imagine to use a few more of the smart power plugs though as they are very versatile and can turn an old-fashioned device into a semi-smart one.