How to Get Up and Running With Turbo Android Part 1

alt text Photo by Tyler Lastovich on Unsplash

Turbo Android - Part 1 Getting Setup

In previous blog posts, I’ve covered getting set up with Turbo iOS and implementing native functionality.

However, Android is a massive part of the mobile market, and there are too few resources on getting up and running with Turbo Android.

This post aims to rectify that.

You will need Android Studio for this tutorial.

The Basics

First of all, we will assume you have a Turbo-enabled app. I’ll be using this app for a talk I’m giving.

The app is called CRM ME. It’s a simple CRM app. You can add, delete and update contacts—all your basic functionality.

You can create your own using the following Rails command.

rails new crm_me -j esbuild

Note that we’re using esbuild. This is because import maps are not supported on the Android browser yet.

With your Rails app installed, you can run rails g scaffold Contacts name:string followed by rails db:migrate, and you’re good to go.

Let’s run your app on the following port.

bin/dev -p 3000 

Setting up Turbo Android and Installing the Library

Open up Android Studio, click New Project, then click ‘No Activity’.

alt text

On the next screen, you can name the app whatever you want and click Finish.

To get Turbo up and running, we first need the Hotwire library.

Open up build.gradle(Module:app)

At the bottom of this file, you’ll see the following:

dependencies {

    implementation 'androidx.core:core-ktx:1.8.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

Add in the Turbo Android library.

dependencies {

    implementation 'androidx.core:core-ktx:1.8.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

    implementation "dev.hotwire:turbo:7.0.0-rc18" 
}

You will be asked to sync your Gradle file. Ensure that you do as this installs all the dependencies.

Now, we need to get our boilerplate up and running.

Creating the MainActivity and MainSessionNavHost

Android is made up of activities. An activity is a single screen with a user interface. We will then add this activity to the Android Manifest file.

Let’s dive into the code:

First, create a kotlin file called MainActivity under the java/com.example.yourappname

Enter the following code:

package com.example.yourappname


import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import dev.hotwire.turbo.activities.TurboActivity
import dev.hotwire.turbo.delegates.TurboActivityDelegate

class MainActivity : AppCompatActivity(), TurboActivity {
    override lateinit var delegate: TurboActivityDelegate

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        delegate = TurboActivityDelegate(this, R.id.main_nav_host)
    }
}

You’ll notice that activity_main and main_nav_host are currently red. We’ll rectify that soon.

We must first create our MainSessionNavHost, the main class that handles the flow of our application.

Create a kotlin file called MainSessionNavHost under java/com.example.yourappname

Enter the following:

import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import dev.hotwire.turbo.config.TurboPathConfiguration
import dev.hotwire.turbo.session.TurboSessionNavHostFragment
import kotlin.reflect.KClass

class MainSessionNavHost : TurboSessionNavHostFragment() {
    override var sessionName = "main"
    override var startLocation = "http://10.0.2.2:3000"

    override val registeredFragments: List<KClass<out Fragment>>
    get() = listOf()


    override val registeredActivities: List<KClass<out AppCompatActivity>>
    get() = listOf()

    override val pathConfigurationLocation: TurboPathConfiguration.Location
    get() = TurboPathConfiguration.Location( assetFilePath = "json/configuration.json")

}

Now we have three more files to create; a small change to our Android manifest file, and we should be up and running. We need to make three resource files, a json/configuration.json asset file, a main_activity layout and a WebFragment.

Let’s start with our JSON file.

Right-click on the app and go to New > Folder > Assets Folder.

alt text

Next, right-click on the assets directory, New > Directory and create the JSON directory.

alt text

Finally, right-click on the json directory and add a file called configuration.json.

alt text

Add the following to the file.

{
  "settings": {
    "screenshots_enabled": true
  },
  "rules": [
    {
      "patterns": [
        ".*"
      ],
      "properties": {
        "context": "default",
        "uri": "turbo://fragment/web",
        "pull_to_refresh_enabled": true
      }
    }
  ]
}

This is the most important file as it determines the navigation on your Turbo-enabled app. We will cover Path Configuration in a future article, but I highly recommend reading this documentation.

Next, we will create a WebFragment file.

Place this in the same directory as your MainActivity

It will have the following:

import dev.hotwire.turbo.fragments.TurboWebFragment
import dev.hotwire.turbo.nav.TurboNavDestination
import dev.hotwire.turbo.nav.TurboNavGraphDestination


@TurboNavGraphDestination(uri = "turbo://fragment/web")
open class WebFragment : TurboWebFragment(), TurboNavDestination {}

We add this to the list of registered fragments in our MainSessionNavHost

override val registeredFragments: List<KClass<out Fragment>>
    get() = listOf(
        WebFragment::class
    )

We are so close to getting up and running. There are just three little things to do.

First, we create our layout_main file.

Click Resource Manager > Layout > + Icon > Layout Resource File

alt text

Mine looks like this:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/main_nav_host"
        android:name="com.example.thirdturbo.MainSessionNavHost"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="false" />

</androidx.constraintlayout.widget.ConstraintLayout>

Finally, we have to edit our Android Manifest(found in the top-level directory) file to ensure we can access the internet and localhost.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:usesCleartextTraffic="true"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ThirdTurbo"
        tools:targetApi="31">
    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

Now you should be able to click the Run button and watch it build your app.

alt text

Congratulations, you now have a Turbo-enabled Android app.

In the next part, we’ll take the app further by adding more Turbo-enabled fragments, such as modals and native screens.

Learn to Build Android, iOS and Rails Apps using Hotwire

© 2024 William Kennedy, Inc. All rights reserved.