[{"content":"If you\u0026rsquo;re familiar with me, you know that I\u0026rsquo;ve been delving into the fascinating world of specialty coffee for several years. Thanks to a friend who happens to be a skilled barista, I\u0026rsquo;ve had the opportunity to learn about various aspects of coffee, including the different stages of bean development, various preparation methods, and the art of tasting. While I don\u0026rsquo;t claim to be a professional, it has become one of my beloved hobbies.\nOver time, I\u0026rsquo;ve explored and acquired different coffee preparation methods, and currently, I have five favorites at home: the French Press, the Italian Mocha, Chemex, Toddy, and the v60 method.\nA coffee brewing method refers to the specific technique used to extract flavors from the coffee grounds. Factors such as the elevation at which the beans were grown, the humidity levels, processing techniques, storage duration, and even the water used can significantly impact the taste profile when employing different brewing methods.\nConsequently, each method offers a unique experience, ranging from more acidic and fruity flavors to fuller-bodied textures. These methods can be classified into categories such as infusion extraction, percolation, vacuum filtering, and my personal favorite (for its simplicity and versatility) drip brewing.\nWithin the realm of drip brewing, we have notable contenders like Chemex, Kalita, and the v60 method, each with its distinctive characteristics and brewing style.\nThe V60 method The V60 method, named after its distinctive conical shape with a 60-degree angle, was developed by Hario in 2004. This innovative design features curved grooves on the interior, facilitating the release of CO2 during the brewing process.\nWhile crafting this blog post, I\u0026rsquo;m currently enjoying a coffee from Villa Rica, located in Pasco, Peru. This particular coffee undergoes the washed process, which I could delve into further in a separate post. It has been medium roasted to enhance its flavors and aromas.\nWhen it comes to brewing, I follow a 1:15 coffee-to-water ratio. Typically, I use 20g of coffee, which corresponds to pouring 300ml of water (20 x 15). To ensure precision, I rely on a laboratory-grade scale I purchased from a specialty store.\nFor brewing, I prefer using filtered and ionized water. In my quest for optimal flavor, I have long abandoned boiled tap water to explore the nuances that different water sources can bring to the cup. The gooseneck kettle proves to be my trusted companion, allowing me to pour water with precision and control.\nTo prepare my coffee, I grind the 20g of coffee beans using the Timemore Chestnut C2 grinder, which consistently produces a medium grind with even particle distribution.\nWhen it comes to filtration, I have the option to choose between a paper filter or a reusable cloth filter from Flowin Filters, a trusted brand recommended by fellow coffee enthusiasts. Whichever option I choose, I ensure it is placed inside the v60 brewer.\nTo begin the brewing process, I pour a small amount of water over 95 degrees Celsius, as indicated by the temperature gauge on my kettle. This initial pour serves to pre-wet the filter, preventing any residual flavors from influencing the taste of the brewed coffee.\nOnce the filter is pre-wetted, I discard the water from the Hario decanter, which serves as the vessel for serving the final brewed coffee. This step ensures a clean and fresh brewing environment for the optimal extraction of flavors.\nAfter placing the 20g of ground coffee in the v60, I begin the pouring process with water that is ideally between 85 and 92 degrees Celsius.\nTo ensure even saturation of the coffee grounds, I occasionally use the handle of a spoon to create a small hole on top of the coffee bed. This allows me to pour water directly into that spot, ensuring that all the grounds are properly wetted.\nThe size of the grind can also impact the pouring technique. Finer grinds may require more careful pouring to ensure thorough extraction, while coarser grinds can result in a quicker and potentially watery extraction if not managed properly.\nDuring the pouring process, I take my time and pour the water slowly, using circular motions in an anti-clockwise direction. I continue this process until I reach a total pour of twice the weight of the coffee (in this case, 40ml). This initial stage is referred to as the bloom, where the coffee bed swells and releases trapped gases, resulting in enhanced flavors and aromas.\nAfter 30 to 45 seconds, the main brewing process begins. Here, I often try different pouring methods: sometimes I pour up to 200ml of water, wait for 30 seconds, and then pour an additional 100ml to reach a total of 300ml. Other times, I experiment with adding 60ml increments with 45-second intervals between each pour.\nWhen I observe the coffee extracting in drops, I know it\u0026rsquo;s time to lift the v60 to prevent over-extraction and avoid a bitter taste.\nIn summary, my current coffee brewing setup as of June 2023 consists of the following:\n20g of medium ground coffee 300ml of filtered water at an average temperature of 90 degrees Celsius Coffee-to-water ratio of 1:15 45 seconds of bloom or pre-infusion time Utilizing the v60 brewing method with Hario white filters This setup allows me to achieve the desired flavors and characteristics in my brewed coffee.\nThere are many more details to explain, but I\u0026rsquo;ll keep it concise in this post. With a winter-but-summer-like in full swing here in Peru, a refreshing cold v60 is an excellent choice. Alternatively, I also enjoy preparing a homemade cold brew and combining it with orange juice for a delightful twist.\nIf you\u0026rsquo;re interested in learning how to prepare an orange-infused cold brew at home without the need for fancy equipment, leave a comment on this post.\nThe v60 brewing method is my personal favorite due to its versatility, allowing me to explore an array of flavors and coffee beans. The resulting body and acidity of the coffee are truly enjoyable to taste.\nFor those venturing into the world of specialty coffee, it\u0026rsquo;s worth noting that the true essence lies in savoring it without sugar. Coffee, being a fruit, can offer an impeccable and delightfully rich flavor through careful preparation, quality beans, and proper grinding. While the adjustment might feel sudden at first, your palate will adapt and appreciate the nuanced taste.\nTo truly indulge in the coffee experience, I highly recommend visiting a specialty coffee shop where every detail is meticulously attended to. Lima, along with various parts of Peru, has witnessed a remarkable growth in its coffee scene over the past years. Today, you can find exceptional coffee establishments like Kaldis, The Coffee Road, Origen, D’Wasi in Cusco, and many more.\nI genuinely hope you feel inspired to explore different coffee brewing methods on your next visit to a specialty coffee shop. It\u0026rsquo;s an exciting opportunity to enhance your coffee journey and discover the full spectrum of flavors that await you. Embrace the experience with a curious and open mind. 😄\nThis post was originally written and published in December 2021 on my Medium profile. I have updated it as of June 2023\n","permalink":"https://flavioquispe.com/posts/english/exceptional-coffee-secret-exploring-v60-method/","summary":"Discover the V60 method and its versatility for exceptional coffee. Learn about the brewing process, ratios, and tips for a perfect cup. Explore specialty coffee shops in Peru and embrace the true flavors.","title":"The Secret to Exceptional Coffee: Exploring the V60 Brewing Method"},{"content":"Welcome to the fourth part of our series, where we dive into the data layer of our KMM application. If you missed our previous articles on architecture design, be sure to catch up.\nWe have three main modules: android, iOS, and core (named shared).\nIn the shared module, under xMain package, we cater to various platforms like web, terminal, and Mac. Let\u0026rsquo;s focus on the key elements in this part:\ncommonMain/data: This is where we implement the data layer, handling data access, repository interfaces, and data sources. Platform-specific database engines are excluded. androidMain: Here, we tackle android-specific code that is reusable across the project\u0026rsquo;s android app modules. We implement the expect classes from the commonMain module. iosMain: Similar to androidMain, but for iOS-specific code implementation. Important note\nIn the shared module, the androidMain and iosMain modules do not directly implement the data access layer, but rather they implement expect classes. These expect classes define contracts for platform-specific functionality.\nFor instance, obtaining the current timestamp may vary between Android and iOS. By creating an expect class, we establish a contract for getting the timestamp, which each platform module then implements accordingly. This approach ensures consistent behavior while accommodating platform differences.\n// inside the shared/commonMain module expect class TimeProvider { var timestamp: Long } // implementation in shared/androidMain module actual class TimeProvider { actual var timestamp: Long = System.currentTimeMillis() } // implementation in shared/iosMain module actual class TimeProvider { actual var timestamp = NSDate().timeIntervalSince1970.toLong() } The same applies for the way how each platform can create an instance of the database engine. We only define the “contract” for getting the database driver:\nexpect class DatabaseDriverFactory { fun createDriver(): SqlDriver } And each platform implements the expect class, for example, Android requires a context:\n// implementation inside shared/androidMain module actual class DatabaseDriverFactory(private val context: Context) { actual fun createDriver(): SqlDriver { return AndroidSqliteDriver( schema = MoviesDb.Schema, context = context, name = \u0026#34;movies.db\u0026#34; ) } } This is how the data layer is looking in our project (as you can see, the data package is in the shared/commonMain module):\nWe have there the domain package for the domain layer as I explained in the previous post, and sqldelight package outside (just below the Kotlin package), and the data package where all the data layer is implemented.\nInside our data layer, we have:\nlocal package: local data access, here we can define an expect class for platform data access implementation (like SharedPreferences in Android), or, as our project, the expect class for creating the database driver (DatabaseDriverFactory.kt).\nThe MovieLocalDataSource is responsible for the CRUD operations related to a local data source (internal database, system preferences, etc). It’s going to be used in the repository implementation (MovieRepositoryImpl).\nremote package: as the name suggests, here we have all code related to remote data access, that is: REST APIs, GraphQL, Firebase, etc. We are only using a REST API from the MovieDB service. Moreover, we can define the responses and requests, these must be the same for any platform, that’s why is defined here.\nTimeProvider and PropertiesProvider: expect classes that returns platform specific data, TimeProvider returns the current timestamp and PropertiesProvider the API KEY for consuming the REST API.\nMovieRepositoryImpl: the implementation of the MovieRepository interface inside the domain layer. It’s very easy to notice that this is shared by any platform: we request the movies list, we ask inside our local data source is the data is outdated, if it is, then we request to the REST API, we save the result in the local data source (that is, we update it) and return the updated data.\nThis is going to be invoked by the GetMoviesInteractor inside our domain layer, and the GetMoviesInteractor should be injected into a ViewModel, Presenter, etc.\nNote: I recommend to you to read the SQDelight library documentation to understand how it works, it’s easy to implement but there are some details to know such as setting the same package structure for defining the database scheme.\nIn Summary In this Kotlin Multiplatform project:\nThe data layer is implemented in the commonMain module of the shared module for maximum reusability.\nClasses in the data layer are injected into domain layer classes, but the injection occurs on each platform.\nIf platform-specific data is required, expect classes are defined and implemented in the platform modules within the shared module.\nIt is advisable to keep the data layer logic within the data package, as repository functionality and CRUD operations may vary by platform.\nYou can follow the progress of the project on GitHub:\nGithub - jflavio11/LayeredKotlinMultiplatform Example of Mobile Kotlin Multiplatform app for showing about layered architecture\ngithub.com\nWhat’s Next This has been the fourth post in which we have talked about the domain layer. In the following, we will talk about the data layer. This guide is divided into the following posts:\nIntroduction Designing the solution Creating the domain layer Creating the layer data (this post) Implementing the presentation layer ","permalink":"https://flavioquispe.com/posts/english/understanding-layered-architecture-kmm-part-4-data-layer/","summary":"Learn how to build the data layer in a KMM application. Master handling external and local data sources efficiently. Optimize API and database access in your project. Boost performance and code reuse.","title":"Understanding Layered Architecture in KMM, Part 4 — The Data Layer"},{"content":"In a KMM project, the goal is to maximize code reuse. The business logic remains consistent across platforms, so it\u0026rsquo;s logical to have the domain layer, written in pure Kotlin, in the shared module. This layer can be reused across web, mobile, and terminal platforms. Here, we define the contracts or interfaces for repositories and interactors. In our example, we have a single interactor called GetMoviesInteractor, responsible for retrieving movies. It depends on the MovieRepository interface in the domain package.\nclass GetMoviesInteractorImpl(private val repo: MovieRepository) { override suspend fun execute(): List { return repo.getMovies() } } In the domain layer, the classes and functions are independent of any specific platform framework, such as iOS or Android. They rely only on their own definitions. The GetMoviesInteractor constructor expects an object that implements the MovieRepository interface and returns objects within the same layer.\nYou may question the need for a use case that simply calls a repository function. While it may not appear significant initially (especially in small apps), using interactors can simplify the construction and maintenance of business logic.\nFor instance, let\u0026rsquo;s say our Movie model has a directorDetail attribute of type MovieDirector. The movie repository might not have the director information, requiring us to consult another repository for the details.\nclass GetMoviesInteractorImpl( private val moviesRepo: MovieRepository, private val directorsRepo: MovieDirectorRepository, private val productionCompanyRepository: ProductionCompanyRepository ) { override suspend fun execute(): List { val movies = moviesRepo.getAll() val moviesDetail = movies.map { movie -\u0026gt; MovieDetail( movie = movie, director = directorsRepo.getDirectorDetailById(movie.directorId), productionCompany = productionCompanyRepository.getCompanyDetailById(movie.productionCompanyId) ) } return moviesDetail } } In the shared module, we organize our shared application core as follows:\nandroidMain: This includes a SqlDelight implementation for Android, serving as the database driver factory. iosMain: Similar to androidMain, this implements the SqlDelight database instance for iOS. commonMain: This is where the multiplatform magic happens. It contains divisions for the domain and data layers. The domain package includes the interactor, Movie model, and repository interface. Additionally, we have a DispatcherProvider.kt defining the Dispatchers for Kotlin Coroutines, to be used in data layer implementations of repositories or data sources. In the androidMain and iosMain packages, you\u0026rsquo;ll find platform-specific Kotlin code, such as the SQLight database manager. However, the business/domain layer code is located in commonMain for maximum reusability and independence.\nIt\u0026rsquo;s important to note that the domain layer, implemented in the domain package within the shared/commonMain module, will be reused by both platforms and the data layer. Hence, its implementation is not included in androidMain and iosMain.\nOne more thing: make sure to add the Kotlin Coroutines dependency to our shared module to leverage its power.\n// shared/build.gradle.kts sourceSets { val coroutineVersion = \u0026#34;1.6.0-native-mt\u0026#34; val commonMain by getting { dependencies { implementation(\u0026#34;org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion\u0026#34;) { version { strictly(coroutineVersion) } } } } ... } Stay tuned for the next post, where we\u0026rsquo;ll explore the structure of the data layer!\nYou can follow the progress of the project on GitHub:\nGithub - jflavio11/LayeredKotlinMultiplatform Example of Mobile Kotlin Multiplatform app for showing about layered architecture\ngithub.com\nWhat’s Next This has been the third post in which we have talked about the domain layer. In the following, we will talk about the data layer. This guide is divided into the following posts:\nIntroduction Designing the solution Creating the domain layer (this post) Creating the layer data Implementing the presentation layer ","permalink":"https://flavioquispe.com/posts/english/understanding-layered-architecture-kmm-part-3-domain-layer/","summary":"Unlock the potential of Kotlin Multiplatform Projects with a focus on code reuse. Dive into the domain layer\u0026rsquo;s independence and discover how it empowers cross-platform development. Explore platform-specific code in androidMain and iosMain packages. Optimize concurrency with Kotlin Coroutines.","title":"Understanding the Layered Architecture With KMM, Part 3 — The Domain Layer"},{"content":"Designing the solution The app we\u0026rsquo;re building may seem simple, but to demonstrate the benefits of layered architecture, we\u0026rsquo;ll intentionally make it more complex than necessary. Our primary goal is to display a list of movies. However, we\u0026rsquo;ll still create separate layers with distinct responsibilities. Here\u0026rsquo;s the order in which we\u0026rsquo;ll develop them:\nDomain\nIn the domain layer, we\u0026rsquo;ll focus on creating the central \u0026ldquo;Movie\u0026rdquo; model, along with the repository contract and data sources.\nThe repository will be an interface residing in the domain package, while the data sources, including the libraries for local database storage and REST service integration, will be covered in the upcoming chapter of this series.\nThis layer will encapsulate all the application logic, independent of the platform it will be implemented on.\nFor instance, if our app needs to display a list of movies, we\u0026rsquo;ll create a class responsible for retrieving the movies. This class is commonly referred to as a Use Case or Interactor. Regardless of whether we\u0026rsquo;re developing for Android or iOS, the functionality of displaying the movie list remains the same.\nThis highlights the importance of our domain module being decoupled from the specific source code of the Android app. It should be versatile enough to be utilized in other frameworks while preserving its core functionality.\nYou may think that creating a class with a single function, which simply returns a list of movies from the repository, might not seem particularly useful. It may resemble a handrail or bridge-like structure.\nHowever, consider this: based on the following structure, what do you think the purpose of this example app is?\nIt\u0026rsquo;s understandable to assume that the app is a shopping cart application, where users can view products, promotions, add items to their cart, and proceed with a purchase after validating the cart contents.\nEncountering such a clear structure in a project saves valuable time when trying to comprehend its functionality. Of course, there may be more complex use cases or interactors involved.\nIn our app, we\u0026rsquo;ll have a single implementation of the use case called GetMoviesInteractor. By the way, I personally prefer using the term \u0026ldquo;interactor\u0026rdquo; when naming the use case classes, as an interactor is an object that implements a system\u0026rsquo;s use case.\nData\nThe data layer should remain consistent across different platforms and frameworks, whether it\u0026rsquo;s Android, iOS, web, or desktop. The implementation of repositories and data sources should be identical.\nHowever, we encounter a challenge here. Each platform has its own methods of connecting to REST APIs or saving data locally. Android primarily uses Retrofit, while iOS apps use Alamofire. So, how can we handle data access consistently, both internally and externally?\nOne option to consider is Retrofit, as it works on any JVM project and Kotlin Multiplatform Mobile (KMM) is built on a pure Kotlin module. However, according to Jake Wharton\u0026rsquo;s explanation in this Github issue, integrating Retrofit into KMM may take some time, as Retrofit relies on other libraries like OkHttp.\nThe best option we can find until now (March 2022) is to use Ktor for consuming REST APIs. It provides a reliable way to handle data access in a unified manner within a Kotlin Multiplatform project.\nWhen it comes to a local data source library for Kotlin Multiplatform projects, SqlDelight is an excellent choice. Its implementation in a KMM project is quite simple and straightforward. You\u0026rsquo;ll need to create the database driver for each platform and place the data source implementations in the commonMain package within the shared module. These data sources will depend on the interface of the database driver. This approach ensures that the code remains reusable and platform-independent, making it easy to manage local data storage across different platforms in your project.\nPresentation\nThe presentation layer in a Kotlin Multiplatform project involves writing the user interface (UI) for each platform, such as using Jetpack Compose for Android or SwiftUI for iOS. However, if you\u0026rsquo;re looking for a more advanced approach, you can consider adding a presentation package within the shared module. Inside this package, you can define contracts for Views, Presenters, and ViewModels, allowing you to implement patterns like MVP (Model-View-Presenter) or MVVM (Model-View-ViewModel). While I haven\u0026rsquo;t personally tried this approach yet, it presents an intriguing and potentially powerful option for structuring the presentation layer in your project.\nFinally…\nThis is the final architecture design of our project:\nAs you can see, we are maximizing the approach of having a unique-cross-business layer that could be used by any platform.\nAnd our project tree should look something like this:\nAs you may have noticed, we are starting to build the software from the core, from the business logic or domain layer. The rules and needs of the business will guide the development of the software: Domain Driven Development.\nNote: I\u0026rsquo;m currently working on an open-source Kotlin Multiplatform project on GitHub as well. Feel free to check it out!\nGithub - jflavio11/LayeredKotlinMultiplatform Example of Mobile Kotlin Multiplatform app for showing about layered architecture\ngithub.com\nSplit of this post series This has been the second post in which we have designed the solution for our project. In the following, we will talk about the domain layer implementation. This guide will be divided into the following posts:\nIntroduction (this post) Designing the solution Creating the domain layer Creating the layer data Implementing the presentation layer ","permalink":"https://flavioquispe.com/posts/english/layered-architecture-kotlin-multiplatform-project-design-solution/","summary":"Learn about Layered Architecture in Kotlin Multiplatform projects. Understand the separation of responsibilities and the importance of domain, data, and presentation layers. Explore tools like Ktor and SqlDelight for data handling. Build platform-specific UI using Jetpack Compose and SwiftUI.","title":"Understanding Layered Architecture in KMM, Part 2 — Designing the Solution"},{"content":"About 11 months ago, I created a demo project in Kotlin Multiplatform. To be honest, I had a lot of difficulties getting it to work with iOS. There were a lot of bugs in the compiler and I had to write some workarounds. Since then I haven’t touched that project again and I haven’t made any (public) apps using Kotlin Cross-Platform either.\nWith the recent update to the Android Architecture Guide, I noticed that several doubts came up on how to respect the already well-known “Clean Architecture”. Or what is the best way to structure your project. And the answer is quite short: it depends.\nSo we are going to review some concepts and recommendations to have a clearer idea of which design option you should go for.\nThis post, specifically, will try to explain the architecture of layers through a Kotlin Multiplatform project, where the need to have a “section” dedicated to business or domain logic will be evident.\nUnderstanding the magnitude of the project When making architectural design decisions, it\u0026rsquo;s important to consider various factors such as project complexity, functionalities, team size, available technologies, and scalability projections.\nThe requirements for a simple app developed by a small team of 3 people will differ from those of a robust point-of-sale system where 50 developers are actively modifying the code on a daily basis.\nFor the former, a monolithic project that separates the data access and graphical user interface components might be sufficient.\nHowever, in the latter case, it becomes necessary to create modules for each functionality, with each team taking ownership of a module. It\u0026rsquo;s important to establish a consistent structure across all modules to ensure coherence and maintainability.\nWhen designing an architecture for your application, the recommendation will always be to respect a basic principle of software development that escapes any technology or framework: The separation of responsibilities or Separation of Concerns.\nIt\u0026rsquo;s crucial to have a clear understanding of the SOLID principles when designing software architecture. These principles guide the separation of responsibilities within your codebase, even in small projects. For instance, if your app\u0026rsquo;s sole purpose is to display a list of movies from a single data source, a complex design may not be necessary.\nHowever, it is still important to differentiate the code responsible for displaying the data (UI) from the code responsible for fetching the movies. In this regard, the Google team made the domain layer, which handles the business logic, optional. For more insights on this topic, you can check out a Twitter conversation I had:\nDomain layer for business logic: repository interfaces, business models, use cases and interactors\nData layer for accessing to data sources, there are repository implementations that depends on different data sources (room, rest apis, files, shared prefs, etc)\n\u0026mdash; Jose Flavio (@jflavio11) December 21, 2021 Layered Architecture or Clean Architecture? Over the past few years, the Android developer community has made significant progress in improving knowledge and best practices for app architecture design. Concepts like SOLID principles, design patterns, and the implementation of \u0026ldquo;Clean Architecture\u0026rdquo; have gained popularity.\nDuring candidate interviews, it is common for individuals to claim familiarity with SOLID principles or having \u0026ldquo;used\u0026rdquo; Clean Architecture. However, they often struggle to provide clear explanations or examples of how they have applied these concepts or made design decisions.\nIt is even often said that \u0026ldquo;Clean Architecture\u0026rdquo; is architecture itself. I do not share this statement. A quick review of the 2012 book or article \u0026ldquo;The Clean Architecture\u0026rdquo;, we can see that what Uncle Bob calls \u0026ldquo;clean architecture\u0026rdquo; is an idea that mixes various architectural designs.\nIn the end, the main goal of the clean architecture is to uphold the principle of Separation of Responsibilities by dividing the code into layers. From my perspective, the clean architecture represents a more focused and precise approach to layered architecture.\nBy the way, I\u0026rsquo;m genuinely interested in hearing your viewpoint on this topic. Architectural discussions are always fascinating!\nNote: I\u0026rsquo;m currently working on an open-source Kotlin Multiplatform project on GitHub as well. Feel free to check it out!\nGithub - jflavio11/LayeredKotlinMultiplatform Example of Mobile Kotlin Multiplatform app for showing about layered architecture\ngithub.com\nWhat’s Next This has been the first post in which I have made a brief introduction to the objective. In the following, we will design the solution and implement it by creating a Kotlin Multiplatform project. This guide will be divided into the following posts:\nIntroduction (this post) Designing the solution Creating the domain layer Creating the layer data Implementing the presentation layer ","permalink":"https://flavioquispe.com/posts/english/introduction-to-layered-architecture-kotlin-multiplatform-project/","summary":"Discover the power of layered architecture in Kotlin Multiplatform projects. Explore the principles of clean architecture and its benefits for code organization. Gain insights on separating responsibilities and enhancing project scalability. Join the discussion on this exciting topic!","title":"Introduction to Layered Architecture in Kotlin Multiplatform Projects"},{"content":"A few times when I’ve conducted technical interviews with candidates for Software Engineer roles at the company where I was working, I’ve come across people who actually know how they might filter or sort a list, however when I delve into the depth of the problem, I start to find difficulties.\nMany times, as software developers, we get used to using libraries and APIs that have most complex solutions already implemented in a single function, making our lives easier. This doesn’t mean that we put aside our curiosity and ability to investigate how things work, at least in its most basic form.\nIn this post, we are going to specifically analyze a very used function of the Kotlin API, this is distinctBy.\nYou can find the official documentation by clicking at this link.\nApplying an algorithm in real life Suppose you have a list of products in which, for reasons not relevant to this post, there are repeated elements. We clearly don’t want to show the user a list of duplicate items. So we know that we should filter the list.\nWe have a couple of alternatives:\nFiltering the list with a loop We could instantiate a new empty list and looping through the original list, adding element by element only if the current item of the iteration is not found in this new list.\nHere we have a slight problem, that “only if it is not found in this new list” implies a search. Let’s assume that we haven’t used a hash table and are using a simple ArrayList.\nWe would have something like this:\nfun filterList(products: List): List { val newList = emptyList() products.forEach { product -\u0026gt; if(findProduct(products, product) == false) { newList.add(product) } } return newList } fun findProduct(list: List, productToFind: Product): Boolean { list.forEach { product -\u0026gt; if(product.id == productToFind.id) { return true } } return false } Doing a quick analysis, the filterList function will call the findProduct function N times, where N is the number of elements in the original list.\nThe findProduct function will take up to N times to complete. Assuming that the element to search for is in the last position of the list, the worst case (worst case scenario) will be O(n).\nThis means that the complexity of our algorithm will be O(n²). That is, it could take n² units of time to finish. And if we talk about Memory Consumption (space complexity), we will have a new list, that is O(n).\nFiltering the list with the distinctBy function Great. It turns out that we know of the existence of a function called distinctBy in which we must pass it as a parameter, a function that indicates the \u0026ldquo;key\u0026rdquo; which will serve as an indicator of whether an element is repeated or not. This can be a first name, a last name, or a code.\nWe just need to write:\nval newList = products.distinctBy { product -\u0026gt; product.code } ¡And, voilá!\nReady, one line of code was enough and we already have a new list that does not contain repeated products with the same code.\nBut… do we know what he does inside? Let\u0026rsquo;s analyze the source code of this function.\nAs we can see, it is an inline extension function applicable to any data structure that implements the Iterable interface.\nThis function depends on two generic classes that it will need for its operation: one that determines the data types of the list to return (the same as the original list) denoted by the letter T, and another that determines the differentiator of the objects, denoted with the letter K.\nIn the first two lines, two new objects are instantiated. The first is a hash table or dictionary data structure that at the same time implements the Set interface (HashSet): it will not allow repeated elements thanks to the fact that it contains a hash table inside. The second is a simple list that will serve as the resulting filtered list.\nIterates over the original list (shown as this in the for statement) and executes the selector function that is passed as a parameter. This selector function is passed the current element of the iteration.\nThat means that in each iteration, the function { product -\u0026gt; product.code } will be returning what we want to serve as a unique identifier, that\u0026rsquo;s why its value is assigned to a variable named \u0026ldquo;key\u0026rdquo;.\nOnce we get the unique identifier (which in our example is the product code), we proceed to insert it into our hash table.\nAs we can see, this insertion occurs inside a conditional if.\nThe Set interface states that the add function will return true if, and only if, the element was inserted. And at what point is the element not inserted? Well, when it already exists (it is verified with a hash table!).\nOnce we know that this identifier did not exist in our identifier hash table (set.add(key) returns true), then we proceed to insert the element (the product) in our new list (list.add(e)).\nNo lookup is performed to see if the iteration item already exists in the list. We only try to insert its identifier (the product code) in the hash table and if this operation is successful (returns true) then we just add this product to the filtered list.\nSince the whole original list is iterated anyway, the time complexity will be O(n), however, the verification of whether or not an element already exists in the list is returns in constant time O(1), due to our hash table inside our HashSet which will tell us if the identifier was inserted or not.\nOf course, when creating two new objects, the memory space used will be a little larger, but not as relevant since the purpose of the HashSet is to store only the identifiers to know if an element has already been created. exists or not in the original list.\nSummary The distinctby function uses a HashSet structure to speed up the cost of time with the verification of the existence of an element in our list.\nUnlike a HashMap, a HashSet needs only one element at insert time and it cannot be repeated, it acts as key and value at the same time (actually, if we look at the internal implementation, a generic static Object object is used as value).\nOf course, distinctBy offers us better performance than if we opted for an implementation of two iterations, one inside the other. However, we could also have used a HashMap and inserted on top of it using the product code as the key and the product as the value. The result would be a clean product structure.\nWhat did you think? Do you also often analyze the functions that we use on a daily basis and that make our lives easier? I would like to know if you know of any other functions or APIs that also make use of these data structures efficiently and simplify our day-to-day developments 😄.\n","permalink":"https://flavioquispe.com/posts/english/analyzing-kotlin-disticnt-func/","summary":"A few times when I’ve conducted technical interviews with candidates for Software Engineer roles at the company where I was working, I’ve come across people who actually know how they might filter or sort a list, however when I delve into the depth of the problem, I start to find difficulties.","title":"Analyzing the algorithmic complexity of the Kotlin API’s distinctBy function"},{"content":"There comes a time when we suddenly feel paralyzed. For an unknown reason, we have lost our way and we don\u0026rsquo;t know what is next, what we should do: we are blocked.\nI remember that in the book Make it happen, by Rubén Turienzo, there was a chapter in which he reminds the reader of the possibility that, in the middle of our path to reach a goal or objective, we come across some situation, thought, problem or event that we do not know how to approach or what steps to follow to overcome it.\nSuddenly we begin to feel a slight fear accompanied by stress that unintentionally increases and ends up paralyzing us. It freezes us. It is as if we simply wanted to escape from the context. This can apply to any framework of our life in which we find ourselves: a problem at work, not knowing if we will pass a course at the University or Institute causing thoughts that question us if we chose the career well or not, uncertainty due to relatives etc\nRubén mentions three techniques that, together with some other books and bibliographies that I have been able to read, could be useful to anyone who consciously wants to apply them as soon as life places them in a certain situation that, to be considered, difficult to clearly have. to get out of it.\nThe past A few months ago I read \u0026ldquo;Excellent Personal Relationships\u0026rdquo; by Daniel A. Hughes, a very good book, from my point of view, as soon as you want to learn a little psychology at the Coquito level and at the same time improve your way of relating to others. the rest.\nWithout so much emphasis on making cherry the book; In it, the author points out that most of the painful events we go through today have a \u0026ldquo;certain\u0026rdquo; resemblance to painful episodes from our childhood or adolescence, which in the end can generate a dissentient or unresolved attachment.\nHaving mentioned the above, and you finding yourself in a circumstance that you might not know how to resolve, pause and ask yourself: Have I ever been faced with a similar scenario? How did I get over it? And if I couldn\u0026rsquo;t get over it, what would I do differently now?\nThese questions, in the midst of a truce with our fast thoughts that rush us to make a decision, can give us a clearer picture to solve the problem, but what if you had never been through a similar situation before?\nThe advice Have you noticed that when we advise another person, not being emotionally involved makes us able to see solutions more clearly? Even though we try to * put ourselves in the other person\u0026rsquo;s shoes * we will never ever experience the same feeling.\nHowever, the benefit is precisely that it gives us a little push to see things in a more objective way, putting our rational part in front of us, which, it must be said, is the one that normally knows how to find a way out.\nSo, if the person you love the most was in the same situation as you, what would you advise? What can you do?\nIt can be a bit difficult to answer at first, but concretely give yourself the opportunity to \u0026ldquo;get out\u0026rdquo; of your own role and try to see things from another perspective.\nThe idol Finally, the one that may seem hilarious to take it as a technique, but deep down is still important (in fact, even there are studies) on the admiration that human beings can feel towards others and the positive effects of this).\nIt\u0026rsquo;s pretty simple: who do you admire?\nIf you\u0026rsquo;ve been able to identify someone you admire or identify with (and if you know their story better), then ask yourself the following question: how do you think I would get through this situation?\n","permalink":"https://flavioquispe.com/posts/english/tres-tecnicas-para-desbloquearte/","summary":"¿Do you remember a time when you had the feeling of not knowing what is next? It is something that could have happened to more than one person. What if you now take into account 3 ways in which you could unlock yourself?","title":"3 techniques to unblock you"},{"content":"In this era of Internet taking over our daily routines, remote work tools, and tricks to boost productivity, it\u0026rsquo;s hard not to compare us with those influencers effortlessly juggling a million things in a day. We\u0026rsquo;re bombarded with channels and blogs preaching about the latest productivity hacks and habit-building strategies. It seems like we\u0026rsquo;ve developed this insatiable urge to constantly be doing something meaningful.\nSome of us long for the end of the day, hoping to feel like we\u0026rsquo;ve accomplished something meaningful. We may have meticulously planned our day, setting no more than five tasks on our agenda. Yet, as the 8-hour workday unfolds, we find ourselves only able to make progress on one of those tasks. We desire to complete the remaining four, but today we feel drained. We\u0026rsquo;re tempted to procrastinate, but procrastination isn\u0026rsquo;t an option for a \u0026ldquo;productive individual.\u0026rdquo;\nYou must set your goals. You must achieve those goals and then set even bigger ones. You must do more. You must program yourself. You chastise yourself if you fail to accomplish something. You are incredibly demanding with yourself. There are no limits. The only limit is exhaustion, which prevents us from being able to \u0026ldquo;do.\u0026rdquo; And it turns out that life is what happens between one goal and another.\nI\u0026rsquo;m not saying that organizing yourself, setting goals, and measuring your progress in order to become a better professional, person, or student is wrong. Just don\u0026rsquo;t let the destinations become eternal while the journey fades away by the time you reach your destination.\nLife is what happens between one goal and another.\nLet\u0026rsquo;s not enslave ourselves to our own goals. Allow yourself to fail. Allow yourself to take the afternoon off. Move your tasks to the next week on Friday and have Saturday and Sunday free. Value rest, because it is the complement to truly being \u0026ldquo;productive.\u0026rdquo; It will give us the energy to achieve what we want and give us the opportunity to try again the next day.\nValue the act of doing nothing. Take a moment to sit, breathe, observe the sky, the trees, the garden, the horizon. Listen to yourself and the sounds of the city in the morning or at night. Don\u0026rsquo;t even try to use that time to generate ideas. Just do nothing. Embrace \u0026ldquo;non-productivity.\u0026rdquo;\n","permalink":"https://flavioquispe.com/posts/english/concepto-productividad-esta-sobrevalorado/","summary":"This post is for if you feel guilty for not feeling like a productive, fulfilled or happy person.","title":"Productivity is overrated"},{"content":"People who know me know that I am one of those who likes to have a long talk on any subject, present ideas, listen to other people\u0026rsquo;s points of view, argue and debate. It is a way of learning, discussing, reaching consensus, negotiations and conclusions. I firmly believe that one of the ways to gain knowledge and wisdom is through your own experience and understanding the experience of other people.\nSometimes I have been able to get someone\u0026rsquo;s thinking to veer the other way and take into account another argument that may have been far removed from their initial opinion.\nA few months ago, when people were very afraid of covid-19 vaccines, I used to read many comments on social networks, which encouraged me to reply explaining my point of view and the safety of vaccines, including sources and scientific articles.\nThey responded to my comment in a somewhat aggressive way and the conversation ended with an insult stating that some laboratory paid me, that I was blind, or that she or he was a person who had already realized things and the \u0026ldquo;new world order\u0026rdquo; or that they \u0026ldquo;hide the truth\u0026rdquo; from us. If it wasn\u0026rsquo;t that, then they deleted his or her comments (something I\u0026rsquo;ve seen happen several times).\nMy brain was exploding. I would literally get stressed when I couldn\u0026rsquo;t make them understand even with practical examples. It only made these people more defensive and defend their idea no matter how foolish it sounded. It was like giving medicine to a dead person.\nThe same is true when you talk about politics, religion, or some other contentious topic. The evidence and best arguments that demolish the idea of the other person (or of us) becomes a transparent object that our brain ignores, that our eyes do not want to see, that we unconsciously know does not agree with us and **for that We give him the counter **.\nIt got to a point where when I saw a message or comment on a topic that I had something to contribute, I would force myself not to leave a reply, because that would probably make me stay up a couple more hours at night.\nMany years ago, a group of psychologists developed a technique called Motivational Interviewing while dealing with patients who abused toxic substances.\nThe general idea was that instead of forcing someone to change, it is best to help them find their own internal motivation to make the change. You do this by conversing and listening carefully to his responses, showing him a mirror in front of him so he can see his own thoughts clearly. If he expressed an intention to change, then you begin to guide the person to do so.\nBottom line: Ask deeply, listen actively to his answers, ask questions and don\u0026rsquo;t judge.\nBelieve it or not, in controlled environments, this technique has helped many people to quit smoking, stop addictions, develop healthy habits such as following a diet and exercising, make voters reconsider their vote and even avoid divorces between parents.\nA 2018 study (The Listener Sets the Tone: High-Quality Listening Increases Attitude Clarity and Behavior-Intention Consequences) concluded that having Active listening in front of another person helps them become less closed and open their point of view, increasing their reflective self-awareness.\nAn example of a classic debate (and widely seen today in the midst of the political situation that Peru is experiencing due to the 2021 presidential elections) is the stage and political points of view. It is preferable to ask someone how they would approach a problem rather than why they advocate a certain approach. That makes them realize the complexity of the problem (such as tax legislation, improvements to the health system, or the elimination of private pension plans) and recognize that they have gaps in what they \u0026ldquo;claim to know.\u0026rdquo;\nHowever, the first psychologists to define Motivational Interviewing, William Miller and Stephen Rollnick, warn of the misuse that this technique can be given to manipulate people. We must be aware that we want to use it to help others achieve a positive change in their lives and not to make them do something at our convenience.\nSo the next time you have such a conversation and you want to help a person achieve a positive goal that will help them grow, try not to keep the conversation about the current state of their thinking, find the \u0026ldquo;desire to change\u0026rdquo; and ask him to explain that desire or intention he has 😉\n","permalink":"https://flavioquispe.com/posts/english/conversar-persona-cerrada-en-sus-ideas/","summary":"Science gives us a way to not stress out while trying to convince or debate a stubborn person.","title":"The science of talking with people closed in their ideas"},{"content":"Perhaps you have read about the benefits that come with meditation: increased concentration, improvements in mental health, more energy, among other changes that you gradually notice. However, when you have tried to start, you haven\u0026rsquo;t been successful. You don\u0026rsquo;t know when to do it during the day, or you simply forget and stop giving it importance.\nBut what if, during one of your first daily activities, like breakfast, you took advantage of having a moment of meditation?\nThe Beginning For a few years now, especially on weekends, I\u0026rsquo;ve unintentionally adopted the practice of having a completely silent breakfast.\nTurning off the TV, leaving my phone in my room, and opening the windows to let in natural light while sipping my cup of coffee have become a daily ritual that creates a space for me to clear my mind, be present, and prepare for the future.\nHowever, I must admit that incorporating this habit has only been practical for me on weekends, as my weekdays were busy due to my daily work routine.\nDuring these months of the pandemic, I have been fortunate to work from home without any issues. Developing new habits, revisiting old ones, better time management, and taking care of my mental health have become priorities that I have gradually organized and learned to handle.\nThe practice of having meals in silence is present in various monastic cultures such as Buddhism, Celtic traditions, Sufism, and Vedas. Applying this activity to breakfast is highly beneficial as it allows your first mental, physical, and emotional connection to be with yourself. Starting your day with gratitude and calmness has significant benefits for your mind and body.\nWhat\u0026rsquo;s next? Practicing having breakfast in complete silence, without any technological devices, not even a book or newspaper by your side, can be quite uncomfortable at first.\nOur minds start working automatically as soon as we wake up, often already thinking about the tasks we need to accomplish during the day, the unfinished ones from yesterday, or the obstacles that may arise.\nFor many years, we\u0026rsquo;ve grown accustomed to starting our mornings with news or social media. Give yourself a chance to break away from this routine because sooner or later, the news or messages on Facebook, Twitter, or Instagram will catch up with you anyway.\nUse this time of silence and nourishment as a period of peace and meditation that you need amidst your daily schedule. Focus on what you\u0026rsquo;re eating, slowly. Look up at the sky, the tree, or the plant in front of you. Breathe just as they do.\nWhen we stay silent, our mind and body react as if we were meditating. It\u0026rsquo;s like our own little meditation session.\nIt\u0026rsquo;s really hard to explain. Start by trying it out on a day when you usually have a lighter morning, like a Saturday.\nFinally, when you finish, be aware that the power to decide what you will do with your life is in your hands. You shape it, and this silent breakfast you just had will help you remember that.\nIf you want to read more testimonials and some comments from health professionals, I highly recommend reading this New York Times article: \u0026ldquo;Shh. It\u0026rsquo;s Breakfast Time\u0026rdquo;, which I read in October 2020 and it made me aware of the habit I had already acquired.\n","permalink":"https://flavioquispe.com/posts/english/rutina-desayuno-en-silencio/","summary":"A way to meditate in the early hours of the day.","title":"Silent Breakfast Routine"},{"content":"Now the world is more interconnected and every device like smartphones, cars, fridges, video cameras, watches, and even washing machines can have an active Internet connection. But for being connected all the time and recollect information constantly from sensors or from the device itself, this connection must be lightweight.\nIn 1999, Andy Standford-Clark and Arlen Nipper wrote the first version of the MQTT (Message Queue Telemetry Transport) protocol which is a publish-subscribe-based messaging protocol that works on the application layer of the TCP/IP or OSI model.\nBut what about Android? Well, actually, Android has its own ways to be connected to servers and services, you know: Firebase, FCM, REST, etc. But imagine using a protocol that is lighter, that strongly considered bandwidth and CPU limitations of a mobile device which can be used for connecting with sensors and IoT devices. Here is where MQTT is recommended.\nOn this article, I will try to show you a little implementation of the MQTT protocol in Android based in my experience.\nMQTT Basics As I previously mention, MQTT is a publish-subscribe-based messaging protocol, this means that clients must subscribe to a specific topic where messages are sent. The MQTT broker (or server) is in charge of managing of sending message to a specific (or specifics) topics and all clients subscribed to it will be receiving the data.\nFigure1. MQTT architecture. Image from HiveMQ\nBut for not increasing this article size, I strongly recommend you to take a look at the MQTT Essentials site from HiveMQ, it has a very well explained definitions for MQTT concepts.\nMQTT Essentials MQTT is the most commonly used messaging protocol for the Internet of Things (IoT). MQTT stands for MQ Telemetry Transport.\nwww.hivemq.com\nLet’s go to Android development Now imagine you have sensors that will capture if the light is on in every room in your house and also you want to change its state. We are going to be a client subscribed to the “home_lights” topic and we are going to receive all sensors information. Every sensor has its own ID (that obviously must be unique to identify each of them) and will send a single data into the payload object in JSON format, something like this:\n{ \u0026#34;type\u0026#34;: \u0026#34;sensors_info\u0026#34;, \u0026#34;payload\u0026#34;: { \u0026#34;sensors_info\u0026#34;: [ { \u0026#34;id\u0026#34;: \u0026#34;living_room\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;Linving room lights\u0026#34;, \u0026#34;turnedOn\u0026#34;: false }, { \u0026#34;id\u0026#34;: \u0026#34;bedroom1\u0026#34;, \u0026#34;name\u0026#34;: \u0026#34;My bedroom lights\u0026#34;, \u0026#34;turnedOn\u0026#34;: true } ] } } So now we create or Android project and we will use the Paho Android Mqtt Library from Eclipse, which is a set of two libraries that work together: The Java and the Android library itself. At the end of the article, I will share the source code on Github. For this example, HiveMQ provide a free MQTT broker admin site which will be useful for testing our app:\nMQTT Websocket Client Websocket client for MQTT projects.\nwww.hivemq.com\nNow start writing code! We have done on adding the Paho dependency to our build.gradle application file and now create a service for having the MQTT Connection alive on background. On this service, we are going to make the connection by creating our own implementation of a MqttAndroidClient. Everytime we open the app, we are going to connect and will ask for temperature of all the sensors and every time that changes we are going to be notified. A use of QOS 0 must be considered for this app since we do not want to receive or send offline messages. Just at most once.\nSo, we have our LightSensorViewModel that extends from ViewModel class and three main methods there:\n1 2 3 4 5 6 7 8 9 10 11 12 fun updateSensor(sensor: CustomLightSensor){ for (i in 0..(tempSensorsList.value!!.size - 1)){ if(tempSensorsList.value!![i].id == sensor.id) { tempSensorsList.value!![i] = sensor } } this.tempSensorsList.postValue(tempSensorsList.value) } fun updateSensorsInfo(list: ArrayList\u0026lt;CustomLightSensor\u0026gt;){ this.tempSensorsList.postValue(list) } fun getSensors() = this.tempSensorsList · updateSensor: for updating just one item of the list.\n· updateSensorsInfo: for updating all the list.\n· getSensors: only returns the list, empty at the beginning.\nLightSensorViewModel will notify our presenter when the list (or an item on it) is updated.\nAnd a repository that will publish and receive messages from the MQTT Server through an Android service that handles the connection. We have two methods there:\nfun updateSensorState(customLightSensor: CustomLightSensor, turnedOn: Boolean){ val message = MqttMessage() val jsonMessage = JSONObject() val sensorInfo = JSONObject() jsonMessage.put(SensorsMqttService.MQTT_MESSAGE_TYPE, UPDATE_LIGHT_STATE) sensorInfo.put(\u0026#34;sensor_id\u0026#34;, customLightSensor.id) sensorInfo.put(\u0026#34;isTurnedOn\u0026#34;, turnedOn) jsonMessage.put(\u0026#34;sensor_info\u0026#34;, sensorInfo) message.qos = 0 message.payload = jsonMessage.toString().toByteArray() // here we ask for home sensors information service.publish(SensorsMqttService.TOPICS[2], message) } fun getAllSensors(vm: LightSensorViewModel) { // we subscribe to sensors topic service.subscribeToTopic(SensorsMqttService.TOPICS[1], 0, object:IMqttActionListener{ override fun onSuccess(asyncActionToken: IMqttToken?) { Log.d(\u0026#34;Mqtt\u0026#34;, \u0026#34;Success subscribing to topic\u0026#34;) } override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) { Log.d(\u0026#34;Mqtt\u0026#34;, \u0026#34;Failure on topic subscription\u0026#34;) } }, IMqttMessageListener { topic, message -\u0026gt; val msgObj = JSONObject(message.toString()) val type = msgObj.getString(SensorsMqttService.MQTT_MESSAGE_TYPE) val payload = msgObj.getJSONObject(SensorsMqttService.MQTT_MESSAGE_PAYLOAD) when(type){ \u0026#34;sensors_info\u0026#34; -\u0026gt; { val array = payload.getJSONArray(\u0026#34;sensors_info\u0026#34;) vm.updateSensorsInfo(SensorMapper().mapJsonArray(array)) } \u0026#34;update_sensor\u0026#34; -\u0026gt; { val obj = JSONObject(message.toString()) .getJSONObject(SensorsMqttService.MQTT_MESSAGE_PAYLOAD) .getJSONObject(\u0026#34;sensor_info\u0026#34;) vm.updateSensor(SensorMapper().mapJson(obj)) } } // end of subscribeToTopic method }) val message = MqttMessage() val jsonMessage = JSONObject() jsonMessage.put(SensorsMqttService.MQTT_MESSAGE_TYPE, GET_SENSORS) message.qos = 0 message.payload = jsonMessage.toString().toByteArray() // here we ask for home sensors information service.publish(SensorsMqttService.TOPICS[0], message) } · updateSensorState: Will send a message to the server for updating the light state: to turning on or off. As you have noticed, we instantiate a MqttMessage object and set the Quality of Service attribute to 0. Moreover, the payload for this MqttMessage will be a String JSONObject. It could be any String but is better to use JSON for having a standardized data-interchange format.\n· getAllSensors: This method will subscribe to the topic “home_lights” (see the graphic at the end) and is going to be listening all messages that arrive on it. For receiving messages, we must ‘ask’ to the broker for them, because of this, we send a request with the message type as ‘get_sensors’ to the topic “home_sensors_info”.\nNow about the implementation on a service\nFor handling the connection to the server, a service has been created based on an interface (MqttModel) with the basic methods: connect, disconnect, subscribe and unsubscribe. This has been named SensorsMqttService which that is going to be started a foreground service if application target is API 26 (Oreo).\nIn addition to creating our SensorsMqttService class and adding it to the AndroidManifest.xml, we will also add an extra service that is started from the MqttAndroidClient class in the Paho library: MqttService. That is, the library is running an Android service called MqttService that is responsible for managing the actions and responses that are given using the protocol.\nThe connectToServer method will try to connect to the server using a MqttConnectOptions object specifying these basics attributes:\nconnectionTimeout: defines the maximum time interval (in seconds) the client will wait for the network connection to the MQTT server to be established.\nisAutomaticReconnect: sets whether the client will automatically attempt to reconnect to the server if the connection is lost. The value, measured in seconds, to wait for a reconnect attempt is going to increase over the time.\nsCleanSession: sets if client and server should remember state across restarts and reconnects. This means, if the value is set to true, messages will not be maintained when a connection lost event occurs and server will treat a subscription as non-durable, client should subscribe to all topics again when reconnect and old messages before the connection broke are not going to be received. If the value is set to false, server will maintain messages and subscriptions when the connection is broken with the client.\nkeepAliveInterval: defines the maximum time interval (measured in seconds) between messages sent or received. These value is used with an AlarmManager object inside the AlarmPingSender class.\nWe call the connect method and pass an IMqttActionListener object as the third parameter. This is going to work as a callback for knowing if the connection was success or fails.\nThe same for the disconnectFromServer method but a difference there is that, when the disconnect event is successful, unregisterResources method from the MqttClient object is called for unregister itself broadcast receiver (the MqttAndroiClient class extends from BroadcasReceiver and implements IMqttAsyncClient for basic operations) and unbinds the MqttService that is running. After this, close is executed for remove all data from the current client and have a clean new connection afterwards.\nBut how do we use the free MQTT Broker for testing?\nFirst, we simulate a connection as a client. On the server, you should have a client/broker that will listen messages on the “home_sensors_info” topic. That’s why we subscribe to it on this panel.\nSo, we only have to click on Connect and then the red button is going to turn to red. Notice that the Host URL is used on our Mqtt service implementation but using TCP and the 1883 port.\nFigure 2. Connect section.\nAn add a new topic subscription to “home_sensors_info”.\nFigure 3. Subscription section.\nWhen the application starts, it will connect and publish to that topic for ‘asking’ about sensors information. We are going to notice that the message from the Android application is going to arrive because we are subscribed to the corresponding topic.\nFigure 4. Messages section.\nAnd for simulate sending the lists of sensors with their information, we use the Publish section. We are going to put the information in JSON format.\nFigure 5. Publish section.\nFigure 6. The application showing the list of light sensors and their state.\nWhen we click on a sensor light item for changing its state, we send a message to the topic “home_sensors_info” with a message type “UPDATE_LIGHT_STATE”. In this example, we click on the bedroom light that is turned on, so we set the value to off (isTurnedOn as false).\nFigure 7. When app changes a light sensor state.\nAnd now we simulate the response from the server to change the application UI.\nFigure 8. Simulating the update light sensor state message from the MQTT broker.\nFigure 9. The bedroom light has been turned off.\nFor generating the JSON structured, I used ObjGen:\nFinally, the basic ecosystem architecture:\nThe project is hosted on Github!\njflavio11/MQTTAndroidExample MqttAndroidExample - An Example Android app using MQTT protocol\nwww.hivemq.com\nUseful links · MQTT Essentials (HiveMQ) — https://www.hivemq.com/mqtt-essentials/\n· HiveMQT Free MQTT Broker — http://www.hivemq.com/demos/websocket-client/\n· ObjGen Live JSON Generator — http://www.objgen.com/json\n","permalink":"https://flavioquispe.com/posts/english/mqtt-protocol-in-android/","summary":"What is the MQTT protocol and how to implemen it in an Android app.","title":"About the MQTT protocol for IoT on Android"}]