Intro Part 1 of 6

Installing Flutter in the terminal and using Vim instead of Android Studio.

Given the choice, I’d rather avoid huge complex apps like Android Studio. They use a lot of system resources and are very GUI/point-and-clicky. Those things definitely have their place but I prefer keyboard control where it makes sense, and for me programming in Flutter is one of those situations.

A lot of what Android Studio does behind the scenes is automatically editing text files and running shell commands such as flutter run, flutter build and so on. If you’re comfortable with the terminal these commands are fairly simple to run manually.

As an IDE Android Studio also helps with stuff like syntax highlighting, code completion, refactoring etc. If you’re into Vim it can be set up to give you these pleasantries. I’m sure there is stuff Android Studio can do that Vim can’t, but whatever it is I’m not missing it and I feel good when I use Vim.

I’ve set up a couple of systems with this Flutter dev environment recently and hit some stumbling blocks. They weren’t too hard to resolve but I wanted to write up the process for future reference and to help anybody else in a similar situation.

Dependencies and Environment Part 2 of 6

Get the basics set up.

To get started I’m presuming you have a Linux installation of something like Debian/Ubuntu.

General Dependencies

Git

You probably already have this but just in case:

sudo apt install git

Ensure Java JDK is installed and recent enough

sudo apt install openjdk-17-jdk

Stuff Flutter Needs

The latest info about this should be here but at time of writing:

sudo apt-get install -y curl git unzip xz-utils zip libglu1-mesa

And some other tools Flutter uses:

sudo apt install clang cmake ninja-build

If using Chromium browser instead of Chrome

The Android SDK likes to know where Chrome is on your system. I use Chromium and the SDK can’t find it.

So I export an environment variable to let Flutter know where to find Chromium eg in ~/.profile

export CHROME_EXECUTABLE=/usr/bin/chromium

Parts of the SDK Part 3 of 6

What are all these different things?

There are several components making up the SDK. I’ll list them here along with examples of how they can be installed later on when the SDK manager is set up and working.

This is just an overview to help your mental model of what’s what, we’re not installing anything just yet.

We download them as a zip and place them in a specific directory, as detailed later.

Command Line Tools

These commands can do several things like signing and optimising APKs, but the main one we are interested in is sdkmanager. This is the command we use to install the other tools.

Platform Tools

These are tools for interfacing with Android which you may already be familiar with, such as adb and fastboot.

sdkmanager 'platform-tools'

Platforms

A platform represents a specific version of Android. It includes multiple system images, which the device emulator uses to emulate various devices on that platform.

Information used to compile your app for this platform version, and source code to be used for debugging are also included.

Multiple platforms can be installed alongside each other on the same system.

sdkmanager 'platforms;android-33'

Build Tools

These are tools used for building Android apps. I’m not 100% clear on what these are and why they are different from Platform Tools, it seems that they were part of Platform Tools in the past but have been sectioned off into their own thing.

Anyway, we need them. Usually use the latest version, but sometimes if you’re targeting specific platforms eg older ones, errors may indicate that you need an older version.

sdkmanager 'build-tools;33.0.2'

Install the Android SDK Part 4 of 6

Flutter uses the Android SDK and related tools, so we'll get that installed next.

Getting the Android SDK set up manually can be tricky, I think the expectation is that most people will use Android Studio so not a lot of work has been put in to making manual installation user-friendly.

Pick a directory where you’ll keep the SDK

This is an important directory that will always store all the Android-SDK specific tools, platforms, build tools etc. Various bits and pieces need to know where these things are, so we’ll set some environment variables for them later.

I’m using $HOME/android_sdk/ in these examples.

mkdir $HOME/android_sdk

Install the SDK Manager

This is a set of command line tools used to install different versions of the SDK (for when you want to target different Android devices).

Based on Google’s instructions at https://developer.android.com/tools/sdkmanager.

You should end up with something like the following (I’m using tree to list the directory contents but don’t worry about that, just make sure your directories are in the right places):

$ tree -L 2 cmdline-tools/
cmdline-tools/
└── latest
    ├── NOTICE.txt
    ├── bin
    ├── lib
    └── source.properties

Add some environment variables to ~/.profile

Make sure these make sense based on what we’ve done so far if you’ve used different directories to me.

# ~/.profile
export ANDROID_SDK_ROOT=$HOME/android_sdk
export PATH=$PATH:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools

Source the profile with source ~/.profile. Then run sdkmanager and see if it does something. If you get command not found double-check everything and try rebooting.

My sdkmanager binary name clash (this won’t affect you but click to expand if you’re interested)

In my case I already had a binary installed with the name sdkmanager, as that’s the name Garmin use for their ConnectIQ SDK Manager. Apparently neither Garmin nor Google could foresee that anyone other than themselves might call their SDK manager software ‘sdkmanager’.

So I had to do some hacky stuff with bash aliases in ~/.profile to let the two live alongside each other, and remind me of the situation:

alias sdkmanager='echo "Use either *sdkmanager-garmin* or *sdkmanager-android*"'
alias sdkmanager-android=$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager
alias sdkmanager-garmin=$HOME/.local/bin/sdkmanager

Accept SDK licences

The SDK licences must be accepted for everything to work.

sdkmanager --licenses

Then type Y and press Enter for each prompt

Install the Android toolchain

To pass the ‘Android toolchain’ step of flutter doctor (in a bit) we need 3 things:

  1. Platform tools (generic)
  2. A valid platform
  3. Build tools to match the platform

Various instructions online will tell you to do things like sdkmanager "platform-tools" "platforms;android-33" (ie pass multiple arguments to sdkmanager), but as observed in this StackOverflow answer if using the command line tools, the platform tools need to be installed via separate commands ie:

sdkmanager 'platform-tools'
sdkmanager 'platforms;android-33'
sdkmanager 'build-tools;33.0.2'

If the installation has worked correctly you should end up with something like:

$ tree -L 1 android_sdk/
android_sdk/
├── build-tools
├── cmdline-tools
├── licenses
├── platform-tools
└── platforms
Another weird, me-specific problem I encountered…

At first, my installations weren’t appearing in my android_sdk directory and Flutter tools were complaining about not being able to find the Android SDK.

Forcing the SDK path like this worked: sdkmanager --verbose "platform-tools" --sdk_root=$HOME/android_sdk/

But something smelt wrong, as the original sdkmanager install commands seemed to be completing without error. I investigated this by running the following:

sdkmanager 'platform-tools' --verbose

Which revealed that they were going into:

/data/data/com.termux/files/usr/share/android-sdk/

This is because I was on Android using Termux, in a proot container, and I had previously installed the SDK in the main (non proot) Termux environment. This was not needed any more so I deleted the other installation.

This is an exotic situation and you’re probably not as stupid as I am to get into this situation, but maybe this note will help in some other situation.

Install Flutter Part 5 of 6

Now to get the Flutter tools installed.

Follow instructions from https://docs.flutter.dev/get-started/install/linux/android

# ~/.profile
export PATH="$HOME/.local/bin/flutter/bin:$PATH"

For ARM64 architectures the Flutter SDK cannot be found at the above link, nor in the archives. In this case the SDK can be obtained by cloning the main flutter repo, then running a flutter command to trigger a download of dependencies

git clone -b main https://github.com/flutter/flutter.git
./flutter/bin/flutter --version

Agree to more licenses and get Flutter doctor to pass

First, agree to several laughably long licence agreements which Google knows full well that nobody reads.

flutter doctor --android-licenses

Then type Y and Enter for each prompt

Now run flutter doctor. It should pass every test except ‘Android Studio (not installed)’. If so, we’re ready to start building Flutter apps (with Android Studio not installed).

Sample project

You can make a really simple sample project to check that everything’s installed correctly and see how it works.

flutter create sample-project

This will create a sample-project directory with a Flutter app in it, a simple built-in demo of a button which counts up as you tap it.

To run the app:

cd sample_project
flutter run

Set up Vim for Flutter Part 6 of 6

Make Vim nice with some plugins and config.

There are various ways of installing Vim plugins. I use vim-plug in my examples here but I’ll add links to instructions for each plugin so you can do it your own way.

Dart

As Flutter uses the Dart language, install Dart support for Vim. I add the following to my ~/.vimrc:

" Between the 'plug#begin()' and 'plug#end()' lines
Plug 'dart-lang/dart-vim-plugin'

Then I restart Vim and run :PlugInstall.

This adds syntax highlighting and auto-indentation of Dart code.

Language Servers

Language Servers/LSPs (LSP = Language Server Protocol but both terms are often used interchangeably) give your editor information about the structure of a language and enable it to do syntax highlighting and code completion, along with deeper functionality such as allowing you to jump to the definition of a function, do refactoring etc.

LSPs are used in Visual Studio for a lot of its advanced functionality but they can also be used in Vim. There’s more than one way of doing this but I use coc-nvim (despite the name it works in modern versions of Vim, not just Neovim).

Install the coc.nvim plugin in Vim

Using vim-plug I add the following to my ~/.vimrc:

" Between the 'plug#begin()' and 'plug#end()' lines
Plug 'neoclide/coc.nvim', {'branch': 'release'}

Again, I restart Vim and run :PlugInstall.

For other ways of installing just follow the instructions .

Install a Flutter LSP

Install the Flutter language server in CoC, coc-flutter. This provides lots of helpful functionality for working with Flutter in Vim as described in the link.

:CocInstall coc-flutter

This LSP needs to know where the Flutter SDK is installed. In Vim, run :CocList FlutterSDKs and make sure it finds at least 1 SDK. If not, add a line to CoC settings (:CocConfig):

"flutter.sdk.path": "$HOME/.local/flutter/bin"

You can find the correct path with which flutter in the terminal.
Originally, I had installed my Flutter SDK at /usr/bin. That caused invisible errors with coc-flutter as it couldn’t access the path properly to find the Flutter SDK. I was having trouble getting this step working. I then moved the Flutter SDK to $HOME/.local/flutter and everything started to work properly

coc.nvim settings

To change CoC settings the command :CocConfig can be used in Vim. On my system it opens up the file ~/.vim/coc-settings.json. You can open/edit this file directly but depending on your Vim configuration it may be in a different location.

Here are some of the settings I prefer:

{
  "diagnostic.checkCurrentLine": true,
  "diagnostic.enableMessage": "jump",
  "colors.enable": true,
  "suggest.noselect": true,
  "inlayHint": false
}

"diagnostic.checkCurrentLine": true,

By default, Coc will show you a diagnostic error or warning when your cursor is over the word causing the problem. Setting this to true means you only have to be on the same line as the error to see the dialog, not the exact word.

"diagnostic.enableMessage": "jump",

This diagnostic popups can be really helpful, but it’s all a bit frenetic for me, I’m a prefers-reduced-motion kind of person. Setting this to jump means they don’t pop up automatically, but can still be shown when I want to see them. I also add this line to ~/.vimrc:

nmap <silent> gh <Plug>(coc-float-hide)
nmap <silent> gl <Plug>(coc-diagnostic-info)

Which allows me to show/hide the diagnostics with gh/gl respectively.

"colors.enable": true,

This setting is for another CoC addition called coc-highlight. I installed this in Vim with:

:CocInstall coc-highlight

This adds various types of colour highlighting, but the one I was most interested in is how it will detect any colours (eg RGB or hex) in your code and change the colour of their text to give you a preview of them. This feature is enabled with the colors.enable line as above.

"suggest.noselect": true,

When you start typing a word, CoC will default to inserting its first suggested autocompletion word. This is a bit more ‘help’ than I like, so I add this setting to make the process more intentional.

"inlayHint": false,

By default CoC inserts inlay hints, for example if you haven’t added a type hint to indicate what kind of widget is being referred to somewhere, it will insert the <Widget> hint for you as a piece of magical ghost text.

These bizarre bits of text appear in the middle of lines of code, except they aren’t really there, you can’t select them or delete them and if you’re moving your cursor around it acts as if they don’t exist. I’m sure some people enjoy them, and for those people I’m glad that they exist. For me, they are disgusting, obnoxious devil-warts.

Thankfully, they can be vanquished by adding this line to the CoC settings.

Want to become a better programmer? Join the Recurse Center!