AbolfaZlRezaEe / NMock

NMock is an application that you can use to mock your trips with fake locations. This application uses Google Map SDK and Neshan API for Map and location information.
22 stars 6 forks source link
android coroutines coroutines-android database gps-location hilt kotlin map mock reactive-programming retrofit room-database sentry sharedflow stateflow

NMock Banner

:collision: What is NMock?

Ever wondered how Android developers test map features and functionalities in their projects? Do they ride their cars or bikes to do so, or do they walk in the streets? The answer is no.

There are applications in Android called Mock applications. They help us generate fake locations and trips to test map features.

NMock is a tool that helps you generate fake locations and trips to test the map feature in your product. It enables you to share them with others as well. We've built this application with the help of the following products and services:

:v: Contribution

Make me happy by contributing to this project:blush:! You can help me fix bugs, add features and resolve issues so NMock can grow. To start your contribution, submit new issues and create pull requests. You can also check out the list of problems in the Issues Section.

No knowledge of programming? Don’t worry; you can contribute by asking questions and reporting issues in the Issues Section.

:triangular_ruler: Architecture

I started this project based on the experiences I gained in previous projects. Private and public projects like Niky. I learned a lot of helpful tips and tricks that played essential roles in doing this project.

I used the MVVM, and the MVI approaches to implement this project. The whole architecture can be summarized in the following image:

architecture picture

Data source

As you can see in the above image, there are two sources of data in this application:

Using the remote API, you can

Then you can store all this information in your local database.

Neshan API is one of the APIs we use to retrieve information. Check out their documentation as well.

Repositories

We created three repositories to help us manage ViewModel requests. This section is critical because it creates and controls all processes. We receive data and transform it into a standard model that ViewModels can use and parse for Views.

The following image, shows the difference between the two of them:

architecture models

The code on the left represents the data structure we receive from the server, and the code on the right indicates the format we need for our view.

In ViewModels, we have two different approaches to accessing the views. Each ViewModel has two outputs that can be used by Views to manage their views and actions:

private fun initObservers() {
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.mockEditorState.collect { state ->
                    showLoadingProgressbar(false)

                    state.originAddress?.let {
                        it.ifNotHandled { address -> processOriginAddress(address) }
                    }

                    state.destinationAddress?.let {
                        it.ifNotHandled { address -> processDestinationAddress(address) }
                    }

                    state.lineVector?.let {
                        it.ifNotHandled { lineVector -> processLineVector(lineVector) }
                    }

                    state.originLocation?.let {
                        it.ifNotHandled { location -> processMarker(true, location) }
                    }

                    state.destinationLocation?.let {
                        it.ifNotHandled { location -> processMarker(false, location) }
                    }
                }
            }
        }
        lifecycleScope.launchWhenStarted {
            viewModel.oneTimeEmitter.collect { processAction(it) }
        }
    }

One of the important actions that Sharedflows can do upon receiving an action from the ViewModel is to parse the action and undo something in view. For example, imagine that you sent a request to the server to retrieve data, but the server did not respond; now, we should send an action and hide or disable something that was shown or enabled before. The following image shows the flow:

error architecture

:arrow_left::arrow_right: Mock Import/Export file structure

Sometimes you need to share your trip data with your friends or colleagues. We have implemented a feature allowing you to share your mocked data in JSON format easily.

Export

We store your mock trip data and its state in the database. We use the same format to export this data. The following JSON is how we structure this data to export:

{
  "file_created_at": "Mon Jul 18 19:48:16 GMT+04:30 2022",
  "file_owner": "User UUID",
  "version_code": 7,
  "mock_information": {
    "type": "CUSTOM_CREATION",
    "name": "Hallo",
    "description": "Hallo description",
    "origin_address": "your mock origin address",
    "destination_address": "your mock destination address",
    "speed": 90,
    "bearing": 0,
    "accuracy": 1,
    "provider": "GPS_PROVIDER",
    "created_at": "Mon Jul 18 19:48:08 GMT+04:30 2022",
    "updated_at": "Mon Jul 18 19:48:08 GMT+04:30 2022"
  },
  "route_information": {
    "origin_location": "your mock origin location",
    "destination_location": "your mock destination address",
    "route_lines": [
      {
        "id": 87,
        "latitude": 35.71972,
        "longitude": 51.34778000000001,
        "time": 1658157488796,
        "elapsed_real_time": 1517906677658857
      },
      {
        "id": 88,
        "latitude": 35.719370000000005,
        "longitude": 51.34763,
        "time": 1658157488803,
        "elapsed_real_time": 1517906684490742
      },
    ]
  }
}
Name Type Description
file_created_at String Creation Date/Time of the exported JSON file
file_owner String User UUID
version_code Number Application version code
mock_information Object Necessary mock data
route_information Object Route information and line. route_lines is the most important field in this object. It is an array containing a list of positions (nodes) to draw lines on the map. Every array item has a latitude and longitude for its position.

Import

As you see in the previous section, you can export and share your mock data with your friends and colleagues in JSON format. To import any data to your project, you can easily import this file using the import feature. ( We have plans in the near future to add other methods to import data )

We store this imported JSON data like standard mock data in a different database table. We add the following additional column to each row:

We separated the imported data so we could manage them easily. These are the reasons that give us the ability to do so:

The following image indicates the current structure of the Mock model section of the application.

mock model instruction

:bookmark_tabs: Helpful tips

These are some helpful tips for developers: