This project started as a group project at the Rotterdam University of Applied Sciences. The only requirements for the project were that it should be written in a object-oriented language and that it has a clear audience. We decided to build the app using Google’s Flutter platform, which was still in beta at the time.
We were allowed to choose the subject of our apps. At the time the video game Fortnite was enjoying huge mainstream popularity. We saw potential in a “Fortnite Companion App” and decided that the game was going to be our subject.
The app ended up having a lot of functionality, because we suffered a bit from feature creep. The app was graded with a 10. After the project was finished at school I started to continue the project with an eventual commercial release in mind. I did so with consent of the former project members. I removed their code and rewrote their contribution. This process was not a lot of work, since I had done the lion’s share of the programming.
I took a while before I got the application to a polished state I was satisfied with. At this time Fortnite itself had launched on Android, outside of the Google Play Store. This made a large part of the companion app obsolete. When I published the app as ‘Lucky LLama: Fortnite Companion’ it was flagged as “Impersonation” by bots of the Google Play Store.
I appealed but nothing came out of it. At this point in time I was quite burned out on the whole Fortnite theme. I stopped development and my efforts to publish the app. At the time I was quite disappointed with the situation, but in hindsight it the whole experience was a great learning experience.
Development of features
The app had a lot of features. Most of them are glorified CRUD operations, but all packed together they offered a great set of functionalities for an enthusiastic Fortnite player.
The players could see their stats, see the current Battle Pass challenges, view the current items in the shop, read the latest news, discover the map and chest locations, pick a random drop location, view the weapon stats, view all the items in the game and last but not least pick a favorite streamer and be redirected to the twitch app.
Statistics Display and Challenges Overview
The stats display was one of the easiest tasks in theory, but in practice it turned out to be very tricky. We called an api and displayed the data to the user. Nothing fancy going on. The first api we used was undocumented, which was cumbersome. The whole data structure changed when the seasons of the game switched. At a later stage in the project I switched to a documented and paid api, to make my life a whole lot easier.
The current battle pass challenges were a lot of manual work to gather the information. At the time there wasn’t a public api providing this data, so we had to gather it every week our self.
Besides Flutter we also used Google’s Firebase. We only used two features of the platform: the real-time database and the hosting. The battle pass information was for example saved in the real-time database.
Daily store items and all items
Things get a little more interesting when we have a look at the daily items. I could not be bothered to manually enter this data every day. At the time there was no open api available for this information. I decided to write a web scraper in Python to gather this information.
Fnbr.co displays the current rotation of the item shop in a predictable way. The site was built with bootstrap, an therefore fairly easy to scrape. The Python scraper used the requests library to get the page and lxml to parse and extract the data I wanted.
I realized that this website also had a list of all current cosmetic items in the game. I wrote a separate scraper for this and that is how the “View all items” feature was born.
Random locations and weapon stats
The pick a random location feature was also a lot of manual work. I made all the featured images by hand in the Fortnite Replay tool. I placed the images on the Firebase hosting. The app loaded the images and then cached them for offline use.
Weapon stats were gathered manually, which was not efficient. The stats were thereafter uploaded to the real-time database.
The map feature is one of the more interesting features. At least its implementation is. At first, I struggled with coming up with a solution. How was I going to show the map and have it feel like you are scrolling through Google Maps. I tried multiple plugins for Flutter, so I could have native maps. They were sadly not satisfactory.
To display the map in the app I used the Flutter Webview plugin which worked quite well. The user could not distinguish this part of the app with any other. The only downsides to this approach were a slightly bigger loading time when opening the map and no caching or local storage. On the other hand it saved me a lot of time.
The twitch integration was quite straightforward. When the user loads the app the twitch api is called and the data is cached to the Firebase Realtime Database. The queries are formed in such a way that only Fornite streamers are included in the result. When the max amount of calls is reached for the api, the users gets the data from the realtime database.
In hindsight this could have been engineered in a more elegant way. It is unwise to let the application directly call the Twitch api. If I had to build it again, I would have made a server script that ran on an interval and uploaded the data to the real-time database. The user then queries the database and never talks to the Twitch api directly.
We ended up having a server anyway, so this functionality could also be done by a server. But more on that later.
Last but not least the news feature. This is my personal favorite, because it was the most complex feature to build. The news section displays the latest articles about the game. We linked to the articles in the app and if the user clicks an article it opens a webview in-app. The user is also able to share the articles using the Android sharing mechanisms.
We gathered articles from a handful of websites. For the data aggregation I build a Python script that parses the RSS feeds of these websites. Some of the website were completely focused on Fortnite content. Some of the others were actual video game journalism outlets.
I wanted the news section to be exactly like the Google Now feed. Therefore I also needed imagery. As a last step the python script scraped all the pages of the articles looking for meta image tags. When the script finished it would upload the data to the real-time database.
The script that scraped the articles, items and daily items were deployed with Docker on a Digital Ocaen Docker droplet (server).
I learned a lot from this project and I had a blast working on it. I learned about Flutter (and Dart), Firebase, Python scraping, RSS feeds, API integrations and software architecture patterns. If I had to build the app again I would build if quite differently.
The most important thing I would do differently is building a custom backend solution to handle data aggregation and storing. A handful of Python scripts linked to Firebase was sufficient, but really sub-optimal and non-scalable.