Create An Android Mobile App Using Kotlin That Consumes An API From A Drupal Instance

 

Drupal is a content management system(CMS) written using PHP and is used to build websites and web applications. Popular websites that use Drupal include: NokiaPrime Minister Of Australia and Tesla. Below are the steps one can use to extend Drupal to the Android client. The assumption is that the Drupal instance has been installed and is running.  

 

 Drupal

  1. Install and enable the JSON:API module on the Drupal instance
  2. Run the endpoints using Postman to simulate how the requests will be made by the Android client. 

 

Drupal URL structure

In the JSON:API, each resource has a globally unique type property. For example:

  • node–article  for articles
  • user–user for users
  • node–pages for pages

 

When running the Postman requests, represent the URL as follows. Replace the BASE_URL with your domain or IP Address.

  • https://BASE_URL/jsonapi/node/article    get articles
  • https://BASE_URL/jsonapi/node/page     get pages
 

 

Kotlin Android Client

The Android App makes HTTP requests to the Drupal instance. Below are the steps used when building the App.

1. Open Android Studio and create a project

2. Add the necessary dependencies 

dependencies {

    implementation("androidx.core:core-ktx:1.13.1")
    implementation("androidx.appcompat:appcompat:1.7.0")
    implementation("com.google.android.material:material:1.12.0")
    implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
    implementation("androidx.room:room-common:2.6.1")
    testImplementation("junit:junit:4.13.2")
    androidTestImplementation("androidx.test.ext:junit:1.2.1")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
    implementation("androidx.hilt:hilt-work:1.2.0")
    implementation("androidx.work:work-runtime-ktx:2.9.0")
    kapt("androidx.hilt:hilt-compiler:1.2.0")
    implementation("com.google.dagger:hilt-android:$hilt")
    kapt("com.google.dagger:hilt-compiler:$hilt")
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3")
    implementation("com.squareup.retrofit2:retrofit:$retrofit")
    implementation("com.squareup.retrofit2:converter-moshi:2.9.0")
    implementation ("com.squareup.okhttp3:okhttp:4.9.3")
    implementation("de.hdodenhof:circleimageview:3.1.0")
    implementation("androidx.activity:activity-ktx:1.9.0")
}

3. Add the Data Classes corresponding to the JSON structure of your Drupal API responses.

data class ArticleResponse(
    @field:Json(name = "data") val data: List<Data> = listOf()
)

data class Data(
    @field:Json(name = "id") val id: String? = "",
    @field:Json(name = "attributes") val attributes: Attributes = Attributes()
)

data class Attributes(
    @field:Json(name = "title") val title: String? = "",
    @field:Json(name = "created") val created: String? = "",
    @field:Json(name = "path") val path: Path = Path(),
    @field:Json(name = "body") val body: Body = Body()
)

data class Path(
    @field:Json(name = "alias") val alias: String? = "",
    @field:Json(name = "pid") val pid: Int? = 0
)

data class Body(
    @field:Json(name = "value") val value: String? = ""
)

4. In this case, we made use of the Retrofit library to make HTTP requests to the JSON API.

    @Singleton
    @Provides
    fun provideRetrofit(): Retrofit{
        val okHttpClient = OkHttpClient().newBuilder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .build()
        return Retrofit.Builder()
            .baseUrl(Common.BASE_URL)
            .addConverterFactory(MoshiConverterFactory.create())
            .client(okHttpClient)
            .build();
    }

5. Set the API endpoints

interface ArticleApi: Common {

    @GET("node/article")
    suspend fun getArticles(): ArticleResponse;

}

6. Ensure you have the requisite permissions 

    /* AndroidManifest.xml file */
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
/* Kotlin Activity class */

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {


    @Inject
    lateinit var articleRepository: ArticleRepository;
    lateinit var mainActivityMvc: MainActivityMvc;
    lateinit var networkTools: NetworkTools;
    val mainActivityViewModel: MainActivityViewModel by viewModels<MainActivityViewModel>();

    companion object {
        lateinit var appCompatActivity: AppCompatActivity;
    }

    init {
        appCompatActivity = this;
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mainActivityMvc =
            MainActivityMvc(LayoutInflater.from(this), null, this, articleRepository, mainActivityViewModel);
        setContentView(mainActivityMvc.getRootView_())
        networkTools = NetworkTools(this);
        mainActivityMvc.setListerners();
        appCompatActivity = this;
        mainActivityMvc.sendAPIRequest();
        mainActivityViewModel.observe(this, this, mainActivityMvc, mainActivityViewModel);

        requestMultiplePermissionLauncher.launch(
            arrayOf(
                Manifest.permission.INTERNET,
                Manifest.permission.ACCESS_NETWORK_STATE
            )
        )



    }

    override fun onResume() {
        super.onResume()

        if (networkTools.checkConnectivity()) {

        }


    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            val homeIntent = Intent(Intent.ACTION_MAIN)
            homeIntent.addCategory(Intent.CATEGORY_HOME)
            homeIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
            startActivity(homeIntent)
            return true
        }
        return super.onKeyDown(keyCode, event)
    }

    private val requestMultiplePermissionLauncher =
        registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) { result ->

        }



}

 

The above codebase is also available on Github 

 

Symatech Labs is a Software Development company based in Nairobi, Kenya that specializes in Software Development, Mobile App Development, Web Application Development, Integrations, USSD and Consultancy.