BananaHackers blog


Read the latest posts from BananaHackers blog.

from farooqkz

After my recent so long messages in the BananaHackers community chat rooms regarding why KaiOS sucks, I thought it would be much better if I write a blog post in the BH blog to let more people hear my voice and read my reasons regarding why one should not use KaiOS.

In the beginning, I chose Nokia 8110 4G instead of an Android phone for the following reasons:

  • Avoiding social media and carrying them everywhere with myself. You know it is harder to chat using an ABC keypad!
  • I needed a cheap phone capable of the basics of every mobile phone(Calls and SMS) plus 3G or 4G internet sharing with WiFi hotspot so that I could feed the internet to my Onyx Boox Poke Pro which is an Android ebook reader with an E-Ink display(which doesn't hurt eyes).

KaiOS is still capable of those for me including a few other stuff which I didn't need in the beginning but not everyone's use case just like mine.

Here I go through many reasons one might want to avoid using KaiOS and go for an Android phone instead. Many of the reasons I have listed here may only apply to app developers.

Note that all these reasons mostly apply to current versions of KaiOS excluding KaiOS 3.0

Poor support from manufacturers

How many OTA updates have your device got? one? two? perhaps zero? It seems that manufactures aren't much interested in giving away firmware updates for their KaiOS devices. As far as I remember my late bananaphone(aka Nokia 8110 4G) had got just 2 OTA updates. And it never got an update to KaiOS 2.5.2!

But for Android phones, the story is so different as most manufacturers bump Android version once or twice. And for KaiOS, Nokia didn't even go up by 0.0.1 which really sucks. This means the customer or user probably needs to buy a new phone to get every new minor software update.

So at least most current KaiOS devices, if not all, will never get to KaiOS 3.0, unfortunately.

Recent Let's Encrypt certificates problem and OTA updates

As far as I know, due to a recent problem, KaiOS recognizes websites with Let's Encrypt certificates as insecure. And since there are no OTA updates for most phones, at least not so soon, this ruins a lot of functionalities of a KaiOS device. The problem's not with browsing website's with the poor browser of KaiOS. You can hardly browse a website with that browser. And if you ever wanted to, you could add websites using LE certificates as exceptions which is kinda annoying but at least works.

The real problem arises when an app tries to access some API of itself. However, I've read in the BH App development chat room from tbrrss(if I remember correctly) that there is a workaround:

Visit API of your Application in KaiOS's browser and add it as an exception.

I haven't tested it myself so I can't confirm it but let's be optimistic and suppose it does work. Imagine two API servers for each KaiOS app and a total of 5 apps on your device using APIs. I guess you'll need to adb pull all 5 apps off your device, find the API servers in the source code of those 5 apps and type in KaiOS's browser with ABC keyboard. Typing API endpoints even using Android's QWERTY keyboard is not an easy job...

And it's not the end of the certificates story: Not all apps work like this, using one or more API endpoints and retrieving data from them. For example for my friend's RSS reader app, John David's feedolin, you'd have to do this for all the websites you want to read feeds from and are using LE certificates.

And yet for John's app, it is the good part. What about some Podcast app? I guess the developer has to get a server with a database(or a list) of podcast websites using LE certificates and tell the user to do the process for every website, including the API endpoint of the app itself if any. The developer should also add Dear Users, I know this really sucks but it is OEM's fault and you've got no other choice

Regarding my Matrix client for KaiOS, Chooj, I've got to tell users to visit their homeserver address with browser to make Chooj work.

As a final word in this sub-section, it seems to be no workaround for other protocols using LE certificates like the ones used by Email app.

KaiStore takes a big share of the income of your KaiOS app

This section and the next one apply only if you are a KaiOS app developer. If you are a user, you might want to skip this section.

According to Christian, developer of AirshipCombat3D and SpaceWalk3D, and many other developers also, Kai takes about 70% of the income your app makes through ads. I remember Christian had said:

App Development for KaiOS is burning time and money. my game(AirshipCombat3D) has hardly made the costs of the server.

Surprise: KaiStore has stupid rules for you dear developers!

One stupid rule Kai has made for dear developers is that you must add KaiAds to your app!

So this means one of these:

  • You must integrate your app with KaiAds but you can simply disable it. However, it will make your app about 4KiB larger. Possibly with useless API calls to Kai.

  • You must add KaiAds to your recipe and you must use it!

Both suck, the latter sucks more. That's why many developers and I have never submitted our apps to KaiStore, yet. Besides, I will probably make my free/open source app, non-free by letting KaiAds in.

There's however this quote from KaiOS developers FAQ which I'm unaware how much is it real:

If for the specific reason you can’t monetize your content or would not like to monetize, kindly reach out to

Another stupid rule is the one regarding VoIP apps when they want to use Mobile data for voice or video calls. I don't know if it is still there. Luxferre had pointed to it somewhere(on the forum?) and I had seen it myself on Kai's website. This means I probably cannot submit Chooj to KaiStore even if I wanted to use KaiAds!

Weak hardware and crappy devices

As far as I know, all KaiOS devices come either with 512MiB or 256MiB of RAM. I know KaiOS can run on 256MiB of RAM and that's great but what about the apps?

And their processor is usually pretty weak dual/quad-core ones. I was lucky to have Qualcomm's processor on my Nokia phones but what about the other users?

Another problem is with the shape of devices: The Bananaphone is curved and the Flip of Nokia is... Flip. Both are subject to be easily breakable...

And as the last set of problems I'll specify here, I would like to mention that there are hardware or software bugs in many devices which never got fixed. Hey, Nokia! Don't you hear the voice of probably thousands of users of 8110 including me complaining about its keypad? Or the problem of 6300's GPS perhaps?

You may install apps from KaiStore or... KaiStore!

Unlike in Android which you can simply download APKs from the Internet and install them on your device or use third party stores like the cool and free(as in freedom) F-droid, on KaiOS the only source of apps is KaiStore.

Some users might mention sideloading with WebIDE but firstly, it requires a computer of some sort and secondly, it is not available on all devices easily.

Even on those which you can easily sideload stuff, there is a code which you should dial which nowhere(as far as I've seen) in the official documentation of KaiOS(not FirefoxOS), it has been written! And to enable the developer menu you need to sideload something like Luxferre's Wallace Toolbox after you enabled debug mode with that code.

Also on the newer firmware build for the Flip and the Tough of Nokia which is v30, sideloading seems to be disabled and you have to patch the /boot partition with EDL to be able to sideload apps again. Fortunately, I didn't upgrade to the v30 build for my 800 Tough.

Other reasons in brief why KaiOS sucks...

  • Except for Jiophone which is only available in India and working with their carriers only, KaiOS phones are not so cheap. And yet Kai advertises about devices as cheap as 10 USD...

  • KaiOS phones officially got no task manager of some sort for managing open apps

What am I going to do?

I will wait till KaiOS 3.0 and only if it satisfied me, I would continue being on this platform and develop for it. Otherwise, I would leave it and perhaps go for an Android phone. Nevertheless, I shall continue developing Chooj if possible.

I might be wrong in some cases. So I love to hear from you, readers! Consider commenting at the bottom of this post.


from farooqkz

#chooj #matrixclient #matrix

I would like to go LIVE on BigBlueButton for the development of Chooj, a Matrix chat and call client for KaiOS. But first I would like to know if anyone's interested in attending such a meeting or LIVE and if anyone's interested, when would they attend?

The meeting is going to happen on a BigBlueButton instance so you will need just your modern web browser to attend. Also, it would take less than an hour of time. And I will try to record the meeting and upload it to BananaHacker's PeerTube channel.

So if you are interested, comment on this post with the date and time you will be able to attend.


from root

If anyone wants to write on this blog, email Farooq with a sample Kai post of their own and he'll reply with an invitation link as soon as possible.

Here's the email address:

fkz [at] riseup [dot] neeeeet

Note that it is not neeeeet but robots don't know this :))


from farooqkz

#chooj #matrixclient #matrix

I have renamed the repository, package and app name to Chooj and from now on this is the name of the project.

I have also added a few numbers of badges to the project's README.

Project's repository

What does Chooj mean?

In my local language, Bandari, which is a version of Persian mixed with Arabic, English and many other languages, Chooj is name of a plant.

What works so far?

Currently, only login process with only password works on a real device. Even through much more works in a recent browser and I'm looking for workarounds to fix this problem.

These stuff has been implemented so far and should work(in browser and not on KaiOS, yet):

  • Login with password
  • Seeing a list of DMs(1 to 1 rooms)
  • Contacting project author(me) via Email in About tab by pressing Call key
  • Seeing a list of messages in each DM. A text-box exists too but does not do anything, yet.

from LolloDev5123 – an application to aid in hiking

coolappbanner Hits License Checks CommitActivity Starts

Hello everyone! Im new here to this blog, and in my first post, we'll talk about an application I have been adapting to my needs and made open source some time ago,

How I started off

I started off forking, I was full of ideas at the moment, unfortunately, some days later I had to go in vacation and left my computer at home, but wait! I built it later at my location so I could continue development! I had made lots and lots of updates, automatically fetch location, weather, accuracy, and wait, I had an idea that was supported by a friend, iGameEveryDay06, I suggested that I should edit the app to fit the style of KaiOS, it seemed pretty easy, but then I realized everything was written in react, which needs to be compiled, minified, it's pretty annoying. One day, when I was hopeless, Cyan linked to me a GitHub Repo containing native code for KaiUI, it looked beautiful, it was still difficult to implement, but then I realized I could easily add the item class to make the items selectable, once I implemented it enough, it seemed like it would be more difficult to revert back to the old modified style.

What i am currently working on

Im currently working on adding .kml file support, fix a SoftKey bug and maybe improve the code as it is currently a mess + all of the random fixes I do which makes it 100% optimizable if some javascript god happens to run across my repo and make a giant pull request :)

Help me

If you want to support us (me and perry share bits of our code so and will be always updated), the Repo is here:

Some screenshots

screen screen screen screen screen 5cb.png)


from farooqkz

#infernojs #inferno #matrix #matrixclient #voip #voicecall

It has been a few days which I have started the development of the app. Just like the prototype I had coded before, InfernoJS is used as framework to create the app.

You can see the Github repository here.

Why InfernoJS?

InfernoJS is a fork of ReactJS but with a performance comparable to Vanilla JS which is Javascript without any framework. You can see benchmarks here. Let me explain the reasons Inferno has been chosen. If you are already familiar with React-like frameworks, you can skip this section and jump to Why Github?

Just like React, an Inferno app is made of components and each component is parent of some other component or components. Of course there are “low level” components which are home to real CSS and HTML. But you code those low level ones once and them everywhere without a need to waste your time to think about HTML or CSS again. As an example, for Login component this is the tree:

  - Header
  - ListView
     - TextInput(for homeserver address)
     - TextInput(for username)
  - SoftKey

As you see when writing Login component, I only need to know about usage of Header, ListView, TextInput and SoftKey components. I don't need to know about their details and I can focus on important things. Regarding these child components I only need to write them once and use them everywhere which makes more free space in my mind to care about stuff I should really care about like the logic of my app and other things.

This makes my code highly readable and components which I write are reusable. I could also distribute the components which are common so that someone else or I, would only need to use them afterwards. Just like how you use a library or module without caring about their details.

You can check code for Login here

Why Github?

If you were already following me and my projects, you could see that I was always using for projects but for this app I've switched to Github a service by Microsoft running a propriety software. But I have reasons to choose it over NotABug and Gitlab as well which I'll explain them in two parts.

The main reason I've chosen Github over NotABug is to use Github Actions to improve the development of the project and automate stuff. Of course I could combine NotABug with an external CI/CD provider but I haven't got any machine to run CI/CD jobs on it and also I wanted to focus on the project rather than other stuff.

However I could use Gitlab which provides a similar service to Github Actions(actually Gitlab had this before Github as far as I remember) for free of charge but I live in Iran in which because of sanctions I can't use Gitlab even for public free/open source software projects directly. An alternative way would be using some kind of VPN or proxy to change my IP address to one which is not from Iran but that reduces the quality of my internet connection which being in Iran is already very low. To realize what do I mean by “very low”, I should tell you that my wired home connection is 2Mbps ADSL which in reality is a bit lower than 2Mbps...


from farooqkz

Nokia 800 Tough image

#matrix #voip #voicecall

As of now, enough money has been raised for the project to get a Nokia 800 Tough but not enough to even start the first stage of the project. Thanks to all of you who donated and also those who wanted to donate but they couldn't due to any reason(including an empty pocket!).

If you wanna still donate, you can send some Bitcoin Cash to the address I shall write in the project's page but please DO NOT send anything to the addresses specified in the previous post.

Because of what was not raised, I don't promise working 15 hours a week on the project but due to what was raised I cannot leave the project so I plan to work on the project about 7 hours a week starting from 1-2 weeks later.

In the next post I will write about status of the project and also address of project's page on Github.


from affe-null

In the last post I wrote about the #ApiDaemon. In this post, I will show that it is possible to add “add-on” services to the daemon, and also explain what else the daemon does.

Remote services

Remote services are like plugins for the API daemon. Unlike normal services, they don't have rust libraries that are compiled into the api-daemon binary, but instead run as a separate “child” daemon. When needed, the API daemon starts the child daemon with the environment variables LD_LIBRARY_PATH set to the remote service's path and IPC_FD set to a file descriptor number that is used for IPC between the API daemon and the child daemon.

General structure

Remote service daemons are located in subdirectories of /data/local/service/api-daemon. The subdirectories are named after the service. Each subdirectory should contain at least a daemon binary but can also have a valid_build_props.txt file. Remote services also need a JS library in the http_root. For example, the wavoip2 service contains the following files:


The valid_build_props.txt file contains a whitelist of values of If the file exists, the service is only considered valid if matches one of the lines and SELinux is in enforcing mode. wavoip2 is even more strict: Even if the daemon does start, it still checks for SELinux enforcing and values. Because of this, WhatsApp calls don't work on rooted or soft-rootable devices. However, you can spoof SELinux enforcing with the following commands:

echo -n 1 > /data/local/tmp/enforce
mount -o bind /data/local/tmp/enforce /sys/fs/selinux/enforce

And if you then run setprop QC_8905_3_10_49_SEC_1, wavoip will start successfully.

I haven't figured out the IPC protocol yet, but looking at the API daemon's source code will probably help:


The API daemon also serves the #KaiAds SDK for privileged apps. This is probably used because of CSP restrictions that apply only to privileged and certified apps. Newer versions of the SDK provide a “SDK loader” that decides whether to load the real SDK from or


Another thing which the daemon does is telemetry. I first noticed this when I tried enabling SELinux enforcing to get wavoip working. After running setenforce 1, my phone suddenly became very slow, and when I looked into logcat, there were a bunch of lines saying that the telemetry process couldn't read from /proc/kmsg!!! Later I found out that this process belongs to the API daemon. This means that the API daemon reads the kernel log messages for telemetry purposes.

Also, I found the following lines in the daemon's configuration file:

enabled = true
send_app_opened_events = true
token_uri = ""
metrics_uri = ""

so the daemon also sends “app opened” events to KaiOS.

All of this can be disabled by setting enabled to false. But KaiOS also provides development versions of the API daemon that have enabled set to false by default: I will write about the packages.* domains in the next post.


from affe-null

You might have already heard that #WhatsApp uses some undocumented APIs that are built into the #KaiOS system. These APIs are powered by the api-daemon, a daemon which lies at a lower level than Gecko. In this post, I will explain what I have found out about this daemon.

The api-daemon is written in #Rust, and provides several “services”. Each service has two parts, the JS client and the Rust library. The Rust library is linked into the api-daemon executable. The JS clients are accessible via HTTP at<service>/<script>.js and expose APIs in a lib_<service> variable. A pre-installed version of the daemon is available in /system/kaios, but it is copied to /data/local/service to allow updates without modifying the system partition.

Using the APIs

To demonstrate the usage, let's create a simple app called “Daemon Test”. We will use the telephony service. Although it is meant to be used to get and set the call state, it seems that real calls have no effect on the reported state. However, the state might reflect ongoing WhatsApp and other VoIP calls.

To use the APIs on KaiOS 2.5, we need the external-api permission:


  "name": "Daemon Test",
  "launch_path": "/index.html",
  "description": "An app to demonstrate api-daemon functionality",
  "type": "privileged",
  "permissions": {
    "external-api": {}


<!DOCTYPE html>
    <div id="callstate">Loading...</div>
    <script src=""></script>
    <script src=""></script>
    <script src=""></script>
    <script src="daemon-test.js"></script>

We can now use these APIs as described in, except that we will need to replace localhost with localhost:8081. Note that the documentation is for KaiOS 3.0, but on 2.5 only the telephony, libsignal (for WhatsApp) and tcpsocket services are available. You can also look at the api-daemon source code, which is also only for KaiOS 3.0.

First, we need to set up a sess variable that stores the api-daemon session:

var sess = new lib_session.Session();

Then, we write some handlers that get called when the session connects/disconnects:

function onsessionconnected(){
    /* handle session connect */
function onsessiondisconnected(){
  /* handle session disconnect */

And after that we try connecting.'websocket', 'localhost:8081', 'secrettoken',
  {onsessionconnected, onsessiondisconnected}, true);

Here is the final code:


window.onerror = function(e){
  // Error handling

var sess = new lib_session.Session();
var el_state = document.getElementById('callstate');
var toggleCallState = null;

function callStateChangeCallback(state){
  el_state.textContent = state;

// Set up session callbacks
var onsessionconnected = function(){
  alert('Session connected');
  // Get an instance of the telephony manager
    alert('Got Telephony manager');
    try {
      // Show the call state
        el_state.textContent = 'Call state: ' + state;

      // Show it again if it changes
      manager.addEventListener(manager.CALLSTATE_CHANGE_EVENT, function(state){
          el_state.textContent = 'Call state: ' + state;

      toggleCallState = function(){
        // Get the call state
          // Set the call state
          manager.callState = state ? 0 : 1;
          alert(state ? 'Idle' : 'Calling');
    } catch(e) {
    alert('Failed to get Telephony manager: ' + JSON.stringify(e));
    toggleCallState = null;
var onsessiondisconnected = function(){
  toggleCallState = null;

// Initialize the api-daemon session'websocket', 'localhost:8081', 'secrettoken',
  {onsessionconnected, onsessiondisconnected}, true);

window.addEventListener('keydown', function(e){
  if(e.key == 'Call'){
    // Toggle the state if 'Call' is pressed and the session is ready
    if(typeof toggleCallState === 'function') toggleCallState();

There is a lot more to this. I will also make a wiki page, and some more posts about things such as the updater-daemon and remote services.

More tags: #ApiDaemon