Android notifications in GNOME Linux with GSConnect

MacOS’s Continuity show the possible level of integration between an iPhone and a Mac computer when a single company controls the OS stack of both devices. Sync notifications, make and pick-up phone calls from the desktop, file sharing, etc. Less powerful, but on the same line, the Android – ChromeOS integration offered by Google.

I’ve always missed something similar to show my Android phone notifications on my Linux desktop, without using questionable cloud services (in terms of privacy). But today I almost completely filled the gap, thanks to KDE Connect.

KDE Connect allows devices to securely share content like notifications or files and other features like SMS messaging, clipboard sync and remote control. The complete list of features supported by KDE Connect is impressive:

  • Receive phone notifications on the desktop computer and reply to messages
  • Control music playing on the desktop from the phone
  • Use the phone as a remote control for the desktop
  • Run predefined commands on the desktop PC from connected devices
  • Check the phone’s battery level from the desktop
  • Ring the phone to help find it
  • Share files and links between devices
  • Browse the phone from the desktop
  • Control the desktop’s volume using the phone
  • Send SMS from the desktop

And there are two additional good news: everything runs locally on the Linux desktop computer (no cloud needed), and there is a porting for GNOME, called GSConnect. It uses GNOME Shell with Nautilus, Chrome and Firefox integration.

KDE Connect wiki has detailed instructions on how to install and configure the software. Below, I’ll report what I did to install and configure GSConnect on my Linux box with Ubuntu 20.04.

GSConnect installation

Despite being available as gnome-shell-extension-gsconnect package since Focal (20.04), it seems the recommended way to install GSConnect is via a GNOME Shell extension. So, I opened the relative GNOME Shell Extensions website on my Linux desktop computer, and agreed in installing the extension.

Alternatively, there is a manual installation procedure, consisting in download the latest release of the Extension from GitHub, and then installing it using the following command:

gnome-extensions install --force gsconnect@andyholmes.github.io.zip

A restart of GNOME Shell is required, and there are different ways of doing it, based on Wayland or X11/Xorg (how to know the server in use).

Android installation

In parallel, the app KDE Connect needs to be installed from Google Play or F-Droid.

Then, the setup can continue following the standard instructions, both on Android phone, and on the desktop computer. In a couple of minutes, the mobile device should be paired with the desktop.

The GSConnect extension menu, after paired with the mobile device

Several app features will work only after granting the respective Android App Permissions to KDE Connect. The app shows a list of those that are disabled, and tapping on one of them opens the corresponding system setting, where the permission can be given.

For example, to share notifications with the desktop computer, open the app, tap on the “Notification sync”, and then tap again to open the corresponding system setting for granting the permission.

To enable integration with Nautilus, in order to send files from the desktop computer to the mobile device, the python-nautilus package has to be installed:

sudo apt install python-nautilus
Easily send files from desktop to the configured destination folder on the mobile device

In case of problems, the Help section of the wiki contains troubleshooting instructions to follow.

Conclusions

GSConnect desktop app, and the KDE Connect mobile app, offer a long list of feature that will require some time to be explored and mastered. But they almost allow to forget to have a mobile phone while using a desktop computer.

As a final note, there are early releases of KDE Connect for Windows and MacOS.

Conversational power for Android apps, Codemotion Milan

Conversational interfaces are the new cool. During the session we’ll see how to add conversational power to any Android app: from listening to the user, understand what she said and provide voice replies. Using internal APIs, external service and a little bit of code.

(Codemotion Milan, 25 November 2016)

Conversational power for Android apps, DevFest Nantes

Conversational interfaces are the new cool. During the session we’ll see how to add conversational power to any Android app: from listening to the user, understand what she said and provide voice replies. Using internal APIs, external service and a little bit of code.

(DevFest Nantes, 9 November 2016)

Advanced dev tips for the Android Wear, Droidcon Turin

You first Android Wear app is finally complete. A working notification system, a couple of custom wear activities and an exciting voice input
control. Now what?
In this session, you’ll learn about some of the advanced Android Wear programming guidelines, code optimizations, useful community libraries, best UI patterns seen so far, brilliant watch faces, pitfalls to avoid and other “real world” Android Wear tips’nd tricks.

(Droidcon Turin, 9th April 2015)

The second screen world in the Google Cast era, Codemotion Rome

TVs are the biggest, most beautiful screen in people’s living rooms. Google Cast is a technology that enables true multi-screen experiences for the users. Integrating Google Cast into existing applications is simple, and we’re going to cover the SDK and resources available to make your application Cast enabled really easily. Android, iOS and Web. Possibilities? Endless: not only casting video or audio, but also games where the TV becomes the new and high-tech game board or a variety of other apps to enjoy with friends, sitting together on the couch.

(Codemotion Roma 2015)

Environmental variables, API key and secret, BuildConfig and Android Studio

You wanna create an Android app that uses Twittet APIs, so yo need an API key and an API secrets only you and your apps know. Because you need these values inside you app, it’s easy and quick to write them down directly in your source code. But when you commit this code to GitHub (or any other public repo), practically you’re telling your secret keys to entire world. Seems uncommon? Unfortunately, not so much! Same for Dropbox SDK.

One simple way to avoid this bad practice is to store your values inside an environmental variable, so only your machine knows it, then read this values in some way and inject them in your code at build time.
Let’s see how to do that using Android Studio, Gradle, and BuildConfig.

First, we need to create these environmental vars. In Linux and Mac, create or edit the file ~/.gradle/gradle.properties (pay attention to the actual Gradle User Home directory position) and add some values:

#define your secret values
TwitterConsumerKeyProp=xxxxxx66666666634333333ddddddTwitterConsumerSecretProp=3nkl3sds3skmslSDF394asdk39dmasd

Second, in your module’s build.gradle file, add these lines

apply plugin: 'com.android.application'
 
//Add these lines
def TWITTER_CONSUMER_KEY = '"' + TwitterConsumerKeyProp + '"' ?: '"Define Twitter Consumer key"';def TWITTER_CONSUMER_SECRET = '"' + TwitterConsumerSecretProp + '"' ?: '"Define Twitter Consumer secret"';
 
android.buildTypes.each { type ->
    type.buildConfigField 'String', 'TWITTER_CONSUMER_KEY', TWITTER_CONSUMER_KEY    type.buildConfigField 'String', 'TWITTER_CONSUMER_SECRET', TWITTER_CONSUMER_SECRET
}

Please note the “TwitterConsumerKeyProp” and “TwitterConsumerSecretProp” have to be the same in both Gradle settings file and Gradle build file.
Finally, to use these values in your code, filled at runtime by Gradle in the build script for you, simply use:

ConfigurationBuilder cb = new ConfigurationBuilder()
    .setDebugEnabled(BuildConfig.DEBUG)
    .setApplicationOnlyAuthEnabled(true)
    .setOAuthConsumerKey(BuildConfig.TWITTER_CONSUMER_KEY)    .setOAuthConsumerSecret(BuildConfig.TWITTER_CONSUMER_SECRET);

That’s all, then it’s up to you how to create more elaborated configurations. For example, you can have different values based on different android.buildTypes types, or the gradle settings file in a common network folder used by the entire team or…