Mehedi Hassan Piash | Senior Software Engineer | Android | iOS | KMP | Ktor | Jetpack Compose | React-Native.

December 21, 2021

Collapsible toolbar programatically in android

December 21, 2021 Posted by Piash , No comments

Sometimes may need the toolbar collapsible in the initial stage or in a certain condition. In that time we implement the functionality programmatically. Here is the following code or function we can call in a particular condition.

fun setCollapsibleToolbar() {
val params = appBar.layoutParams as CoordinatorLayout.LayoutParams
val behavior = params.behavior as AppBarLayout.Behavior?
if (behavior != null) {
val valueAnimator: ValueAnimator = ValueAnimator.ofInt()
valueAnimator.interpolator = DecelerateInterpolator()
valueAnimator.addUpdateListener { animation ->
behavior.topAndBottomOffset = (animation.animatedValue as Int)!!
appBar.requestLayout()
}
valueAnimator.setIntValues(0, -900)
valueAnimator.duration = 400
valueAnimator.start()
}
}

Ref: https://piashcse.medium.com/collapsible-toolbar-programatically-in-android-988a94e6795e

 

December 18, 2021

Get child data in parent table by backReferencedOn in kotlin Exposed Ktor part-3

December 18, 2021 Posted by Piash , No comments

UserId is a foreign key in UserHasType table . Now if we want to get UserHasTypeTable data as child data in UsersTable we need to point it as val userType by UserHasTypeEntity backReferencedOn UserHasTypeTable.user_id

object UsersTable : IdTable<String>("users") {
override val id: Column<EntityID<String>> = text("id").uniqueIndex().entityId()
val user_name = text("user_name")
val email = text("email")
val password = text("password")
val mobile_number = text("mobile_number").nullable()
val email_verified_at = text("email_verified_at").nullable() // so far unkmown
val remember_token = text("remember_token").nullable()
val verification_code = text("verification_code").nullable() // verification_code
val created_at = datetime("created_at").defaultExpression(CurrentDateTime()) // UTC time
val updated_at = datetime("updated_at").nullable()
val is_verified = text("is_verified").nullable() // email verified by validation code
override val primaryKey = PrimaryKey(id)
}

class UsersEntity(id: EntityID<String>) : Entity<String>(id) {
companion object : EntityClass<String, UsersEntity>(UsersTable)
var user_name by UsersTable.user_name
var email by UsersTable.email
var password by UsersTable.password
var mobile_number by UsersTable.mobile_number
var email_verified_at by UsersTable.email_verified_at
var remember_token by UsersTable.remember_token
var verification_code by UsersTable.verification_code
var created_at by UsersTable.created_at
var updated_at by UsersTable.updated_at
var is_verified by UsersTable.is_verified
val userType by UserHasTypeEntity backReferencedOn UserHasTypeTable.user_id
fun userResponse() = UsersResponse(
id.value,
user_name,
email,
mobile_number,
email_verified_at,
remember_token,
is_verified,
userType.userHasTypeResponse()
)
}

data class UsersResponse(
val id: String,
val userName: String,
val email: String,
val mobileNumber: String?,
val emailVerifiedAt: String?,
val rememberToken: String?,
val isVerified: String?,
var userType: UserHasType
)

UserHasTypeTable and UserHasTypeEntity

object UserHasTypeTable : IdTable<String>("user_has_type") {
override val id: Column<EntityID<String>> = text("id").uniqueIndex().entityId()
val user_id = reference("user_id", UsersTable.id)
val user_type_id = text("user_type_id")
val created_at = text("created_at")
val updated_at = text("updated_at")
override val primaryKey = PrimaryKey(id)
}

class UserHasTypeEntity(id: EntityID<String>) : Entity<String>(id) {
companion object : EntityClass<String, UserHasTypeEntity>(UserHasTypeTable)
var user_id by UserHasTypeTable.user_id
var user_type_id by UserHasTypeTable.user_type_id
var created_at by UserHasTypeTable.created_at
var updated_at by UserHasTypeTable.updated_at
//var users by UsersEntity referencedOn UserHasTypeTable.user_id
fun userHasTypeResponse() = UserHasType(id.toString(), user_type_id)
}

data class UserHasType(
val id: String, val user_type_id: String
)

User controller

class UserController {
fun login(loginBody: LoginBody) = transaction {
val query = UsersTable.leftJoin(UserHasTypeTable).select { UsersTable.email eq loginBody.email }
val result = UsersEntity.wrapRows(query).first()
if(loginBody.password == result.password)
return@transaction result.userResponse()
else
null
}
}

UserRoute

fun Route.userRoute(userController: UserController) {
post("login") {
val loginBody = call.receive<LoginBody>()

val db = userController.login(loginBody)
db.let {
call.respond(JsonResponse.success(loginResponse,HttpStatusCode.OK))
}
}
}

Ref:  https://piashcse.medium.com/get-child-data-in-parent-table-by-backreferencedon-in-kotlin-exposed-ktor-part-3-80bb14675871

October 23, 2021

Kotlin Exposed create an entity with reference for Ktor part-2

October 23, 2021 Posted by Piash No comments

 

PostgreSql UserTable

UserTable Entity for Ktor

import org.jetbrains.exposed.dao.Entity
import org.jetbrains.exposed.dao.EntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IdTable
import org.jetbrains.exposed.sql.Column

object UsersTable : IdTable<String>("users") {
override val id: Column<EntityID<String>> = text("user_id").uniqueIndex().entityId()
val user_name = text("user_name")
val email = text("email")
val password = text("password")
val mobile_number = text("mobile_number").nullable()
val email_verified_at = text("email_verified_at").nullable() // so far unkmown
val remember_token = text("remember_token").nullable()
val verification_code = text("verification_code").nullable() // verification_code
val created_at = text("created_at").nullable()
val updated_at = text("updated_at").nullable()
val is_verified = text("is_verified").nullable() // email verified by validation code
override val primaryKey = PrimaryKey(id)
}

class UsersEntity(id: EntityID<String>) : Entity<String>(id) {
companion object : EntityClass<String, UsersEntity>(UsersTable)
var userId by UsersTable.id
var user_name by UsersTable.user_name
var email by UsersTable.email
var password by UsersTable.password
var mobile_number by UsersTable.mobile_number
var email_verified_at by UsersTable.email_verified_at
var remember_token by UsersTable.remember_token
var verification_code by UsersTable.verification_code
var created_at by UsersTable.created_at
var updated_at by UsersTable.updated_at
var is_verified by UsersTable.is_verified
var userType by UserTypeEntity via UserTypeTable
fun userResponse() = UsersResponse(userId.value, user_name,email, mobile_number, email_verified_at, remember_token, created_at, updated_at, is_verified)
}
data class UsersResponse( val userId :String,
val userName :String,
val email :String,
val mobileNumber:String?,
val emailVerifiedAt :String?,
val rememberToken:String?,
val createdAt:String?,
val updatedAt :String?,
val isVerified :String?)

UserHasTypeTable Entity

import org.jetbrains.exposed.dao.Entity
import org.jetbrains.exposed.dao.EntityClass
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.dao.id.IdTable
import org.jetbrains.exposed.sql.Column

object UserHasTypeTable : IdTable<String>("user_has_type") {
override val id: Column<EntityID<String>> = text("user_has_type_id").uniqueIndex().entityId()
val user_id = text("user_id").references(UsersTable.id)
val user_type_id = text("user_type_id")
val created_at = text("created_at")
val updated_at = text("updated_at")
override val primaryKey = PrimaryKey(id)
}

class UserHasTypeEntity(id: EntityID<String>) : Entity<String>(id) {
companion object : EntityClass<String, UserHasTypeEntity>(UserHasTypeTable)
var id_ by UserHasTypeTable.id
var user_id by UserHasTypeTable.user_id
var user_type_id by UserHasTypeTable.user_type_id
var created_at by UserHasTypeTable.created_at
var updated_at by UserHasTypeTable.updated_at
var users by UsersEntity referencedOn UserHasTypeTable.user_id
}

Ref: https://piashcse.medium.com/kotlin-exposed-create-entity-with-reference-for-ktor-part-2-1905836c400c

October 20, 2021

PostgreSQL database connection in Ktor part-1

October 20, 2021 Posted by Piash , No comments
PostgreSQL database connection in Ktor. 

 build.gradle dependency

// Exposed ORM library
implementation "org.jetbrains.exposed:exposed-core:0.35.1"
implementation "org.jetbrains.exposed:exposed-dao:0.35.1"
implementation "org.jetbrains.exposed:exposed-jdbc:0.35.1"
implementation "org.postgresql:postgresql:42.2.2"
implementation 'com.zaxxer:HikariCP:3.4.2'

resource/hikari.properties

dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=postgres
dataSource.password=p123
dataSource.databaseName=db_ktor
dataSource.portNumber=5432
dataSource.serverName=localh

Database helper class

object DatabaseFactory {
fun init() {
// Database.connect(hikari())
initDB()
transaction {
//create(Fruits, UserTable, ProductTable)
}
}

private fun initDB() {
// database connection is handled from hikari properties
val config = HikariConfig("/hikari.properties")
val ds = HikariDataSource(config)
Database.connect(ds)
}

// database connection for h2 d
private fun hikari(): HikariDataSource {
val config = HikariConfig()
config.driverClassName = "org.h2.Driver"
config.jdbcUrl = "jdbc:h2:file:~/documents/db/h2db"
config.maximumPoolSize = 3
config.isAutoCommit = false
config.transactionIsolation = "TRANSACTION_REPEATABLE_READ"
config.validate()
return HikariDataSource(config)
}
}

Application class

fun main() {
//val environment = System.getenv("KTOR_ENVIRONMENT") ?: "development"
val configName = "application.conf"
val appEngineEnv = applicationEngineEnvironment {
config = HoconApplicationConfig(ConfigFactory.load(configName))
log = LoggerFactory.getLogger("ktor.application")
module {
DatabaseFactory.init()
}
connector {
host = config.property("ktor.deployment.host").getString()
port = config.property("ktor.deployment.port").getString().toInt()
}
}

embeddedServer(Netty, appEngineEnv).start(wait = true)
}

September 22, 2021

Bottom navigation in android[Koltin]

September 22, 2021 Posted by Piash , No comments

Bottom navigation with the android navigation component is a little bit tricky. I found most of the resources are activity-based. I wanna implement it inside fragment with navigation component. So let’s start step by step…

Bottom navigation screenshoot
  1. res/menu/bottom_navigation_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/detailFragmentBottom"
android:enabled="true"
android:icon="@drawable/ic_home_24"
android:title="@string/home"/>
<item
android:id="@+id/imagePickerFragmentBottom"
android:enabled="true"
android:icon="@drawable/ic_music_note_24"
android:title="@string/music"/>
<item
android:id="@+id/expandableRecyclerViewFragmentBottom"
android:enabled="true"
android:icon="@drawable/ic_article_24"
android:title="@string/article"/>
</menu>

2. res/navigation/bottom_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/bottom_navigation"
app:startDestination="@id/detailFragmentBottom">

<fragment
android:id="@+id/detailFragmentBottom"
android:name="com.piashcse.experiment.mvvm_hilt.ui.fragment.DetailFragment"
android:label="DetailFragment" />
<fragment
android:id="@+id/expandableRecyclerViewFragmentBottom"
android:name="com.piashcse.experiment.mvvm_hilt.ui.fragment.ExpandableRecyclerViewFragment"
android:label="fragment_expandable_recycler_view"
tools:layout="@layout/fragment_expandable_recycler_view" />
<fragment
android:id="@+id/imagePickerFragmentBottom"
android:name="com.piashcse.experiment.mvvm_hilt.ui.fragment.ImagePickerFragment"
android:label="fragment_image_picker"
tools:layout="@layout/fragment_image_picker" />

</navigation>

3. res/layout/fragment_bottom_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.fragment.BottomNavigationFragment">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_bottom_navigation"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/bottom_navigation" />

<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="@menu/bottom_navigation_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

4. BottomNavigationFragment.kt

package com.piashcse.experiment.mvvm_hilt.ui.fragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.piashcse.experiment.mvvm_hilt.R
import com.piashcse.experiment.mvvm_hilt.databinding.FragmentBottomNavigationBinding
import com.piashcse.experiment.mvvm_hilt.utils.hide
import com.piashcse.experiment.mvvm_hilt.utils.show
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class BottomNavigationFragment : Fragment() {
private var _binding: FragmentBottomNavigationBinding? = null
private val binding get() = requireNotNull(_binding) // or !!_binding
private lateinit var navController: NavController
private lateinit var navHostFragment: NavHostFragment
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = FragmentBottomNavigationBinding.inflate(layoutInflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initView()
}

fun initView() {
navHostFragment =
childFragmentManager.findFragmentById(R.id.nav_host_fragment_bottom_navigation) as NavHostFragment
navController = navHostFragment.navController
binding.bottomNavigation.setupWithNavController(navController)
navController.addOnDestinationChangedListener { _, destination, _ ->
when (destination.id) {
R.id.detailFragmentBottom, R.id.expandableRecyclerViewFragmentBottom, R.id.imagePickerFragmentBottom -> {
binding.bottomNavigation.show()
}
else ->
binding.bottomNavigation.hide()
}
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

}

Github: https://github.com/piashcse/blog_piashcse_code/tree/master/MVVM_Hilt

Ref: https://piashcse.medium.com/bottom-navigation-in-android-koltin-42c746b3ddf4