Tag

java

Browsing

Every modern operating system has the support for multi-threading–so does the application built to run on that operating system. No, doubt multi-threading programming increase the performance and concurrency in our application. For certain applications, it is easier to code different procedures calls and conversation in a different thread than to manage them from the same thread.

Mostly in a client-server application, you definitely want the create the server application in a multi-threaded environment where thousands of clients connected to one server. Well if you think that we’re going to build a client-server application than you’re right. Wait! don’t just close the tab because this time I have got a real-world problem.

Multithreading Meme

Application Overview

First, a little intro to my application so that we’re all on the same page. The application is about to build a smart meter (GPRS Meter) data collector. The application simply opens up a ServerSocket and after that, it accepts clients (Smart Meter) waiting for the connection. There are thousands of smart meters trying to connect to that application. So, when the smart meter connects with the application via socket, the application creates its own separate thread for communication.

Promgramming thread meme

Get Started

The application that we’re going to build will be in Java programming language. So, the first step was simple, I try to open up the ServerSocket holding the Pepsi can in my hand.

public class DeviceListenerRunnable implements Runnable {

    private final int portNumber;  // 1
    private final ServerSocket serverSocket;  
    private final IConnectionEventArgs connectionEventArgs; // 2

    public DeviceListenerRunnable(int portNumber, IConnectionEventArgs connectionEventArgs) {
        this.portNumber = portNumber;
        serverSocket = new ServerSocket(portNumber);  // 3
        this.connectionEventArgs = connectionEventArgs; 
    }

    @Override
    public void run() {
        Socket socket;
        while (!Thread.currentThread().isInterrupted()) {
            try {
                socket = serverSocket.accept();   // 4
                connectionEventArgs.onDeviceConnected(socket, socket.getRemoteSocketAddress().toString());  // 5
                if (!socket.isClosed())
                    new ReceiverThread(socket, connectionEventArgs).start();  // 6
            } catch (Exception ignored) {
            }
        }
    }
}

Here’s what’s going on inside the code:

  1. Port number for ServerSocket.
  2. An interface which notifies the caller that the new smart meter has connected. We’ll see the implementation of IConnectionEventArgs in a couple of minutes.
  3. Creates the ServerSocket with the specified port number.
  4. Waiting for a new client (Smart Meter) to become online.
  5. Sending the Socket and info of connected smart meter back to the caller class.
  6. Creating a new separate thread for the connected smart meter.

Examining the ReceiverThread class

The ReceiverThread class basically processing all the incoming data from the connected smart meter and send data back to caller class via IConnectionEventArgs interface. Every smart meter connected to an application has its own instance of this class. So, if there are a thousand devices connected to the server than it means every device has it’s own instance of ReceiverThread class because every device communicates in a separate thread. Let’s see the implementation of this class.

public class ReceiverThread extends Thread {
    
    private final Closeable closeable;
    private final IConnectionEventArgs connectionEventArgs;  

    public ReceiverThread(@Nonnull Closeable closeable, IConnectionEventArgs connectionEventArgs) {
        this.closeable = closeable;
        this.connectionEventArgs = connectionEventArgs;
    }

    @Override
    public void run() {
        if (closeable instanceof Socket) {
            Socket socket = (Socket) closeable;
            while (!isInterrupted() && !socket.isClosed()) { // 1
                String info = socket.getRemoteSocketAddress().toString();
                try {
                    byte[] data = handleTcp(socket);  // 2
                    connectionEventArgs.onDataReceived(info, socket, data)  // 3
                } catch (IOException e) {
                    connectionEventArgs.onDeviceDisconnected(info, e);  // 4
                    try {
                        interrupt();   // 5
                        socket.close();   // 6
                    } catch (IOException ignored) {
                    }
                    break;
                }
            }
        }
    }

    private byte[] handleTcp(Socket socket) throws IOException {
        // Logic for reading the input stream 
    }
}

Let’s take a brief look at different steps:

  1. Nothing out of ordinary happens simply start a while loop until the current thread is not interrupted or socket is closed.
  2. Handling the incoming TCP data from a smart meter. (If someone want to see the logic behind handleTcp data method just ask in the comment section)
  3. Sending the incoming data back to caller class. (We’ll see the caller class in a couple of minutes)
  4. If IOException occurs, notify the caller class that the smart meter has been disconnected.
  5. Needs to call the interrupt method on the current thread.
  6. Close socket for the smart meter.

Before going any further I think you guys need to see the legendary IConnectionEventArgs interface implementation.

interface IConnectionEventArgs {

     void onDeviceConnected(Socket socket, String info);

     void onDeviceDisconnected(String info, IOException e);

     void onDataReceived(String info, Closeable c, byte[] data); 
}

Implementation of caller class

We got the basics down now we just need to implement the IConnectionEventArgs interface and start the thread for ServerSocket class. So, the DeviceListenerRunnable class listens to new incoming connections from smart meters.

public class ParentMediaHelper implements IConnectionEventArgs {

    private final Thread listenerThread;
    private final DeviceCollection deviceCollection = DeviceCollection.instance();

    public ParentMediaHelper(int portNumber) {
        DeviceListenerRunnable meterListenerRunnable = new DeviceListenerRunnable(portNumber, this); 
        listenerThread = new Thread(meterListenerRunnable);
    }

    public void startListener() { 
        listenerThread.start();  
    }

    @Override
    public void onDeviceConnected(Socket socket, String info) {
        // handle new smart meter connection 
    }

    @Override
    public void onDeviceDisconnected(String info, IOException e) {
        deviceCollection.remove(info) 
    }

    @Override
    public void onDataReceived(String info, Closeable c, byte[] data) {
         if(containsSerialNumber(data)){ 
              String serialNumber = extractSerialNumber(data)
              deviceCollection.insert(Device(info, c, serialNumber))
         }
         // handle other things
    }
}

I know, many of you think that there are thousands of smart meter connected to the server. How can I determine that the data came from which smart meter? Actually when the first time smart meter sends the data (current or voltage) after a successful socket connection. It also sends its serial number (unique identifier) and with that serial number, I create a new Device model and insert the model in my DeviceCollection class. The DeviceCollection simply a singleton class performs the CRUD functionality.

Similarly when the onDeviceDisconnected calls we remove the device from our collection.

Running the Application Server

Nice! all the hard work is done. Now I just need the main function which simply calls the startListener method inside the ParentMediaHelper class.

public class ddssd {

    private static final int PORT_NUMBER = 14001; // Always use port above 1024

    public static void main(String[] args) {
        ParentMediaHelper mediaHelper = new ParentMediaHelper(PORT_NUMBER);
        mediaHelper.startListener();
    }
}

After running the above program, my application starts accepting connection from the smart meter.

Note: If you’re running application on Linux based OS you need to open the specified port.

Alright, guys, this was my story of creating a Java-based server application. If you like this article please share it with the community.

Thank you for being here and keep reading…

This story is the third part of our Android Cab Booking App tutorial If you didn’t read the previous ones you can start here.

Previously In Android Cab Booking App

In the previous article, we discussed how to read the online-drivers from Firebase Realtime Database, create the data structure for Drivers and animate multiples markers on Google Maps.

Also, I update the apps on GitHub. You can follow me by looking at the code. Java application link and Kotlin application link.

9. Show progress animation inside PinView

If you guys see the demo in the first article, you’ll understand that as soon as the Google Maps camera movement start. The ProgressBar inside the PinView start animating until the nearest Driver found and after that, we’ll calculate the distance with DistanceMatrixAPI between the nearest Driver location and the PinView location. Later the distance calculation we hide the ProgressBar and show the distance duration inside the PinView.

So, in order to animate the ProgressBar, we need to implement OnCameraMoveStartedListener on MainActivity. The OnCameraMoveStartedListener has its callback function which defines what action needs to be done when the camera starts its movement. In this callback, we need to start the ProgressBar animation.

Let’s start the ninth part of Cab Booking Application by implementing the OnCameraMoveStartedListener on MainActivity.

class MainActivity : AppCompatActivity(), GoogleMap.OnCameraIdleListener, GoogleMap.OnCameraMoveStartedListener {
      private var googleMap : GoogleMap? = null
      override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            .......
            .......
            val supportMapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment supportMapFragment.getMapAsync { googleMap ->
                    googleMap.setOnCameraIdleListener(this)
                    googleMap.setOnCameraMoveStartedListener(this)  // implements the OnCameraStartedListener                        
                    this.googleMap = googleMap 
            }
     }

The OnCameraMoveStartedListener has one abstract method and we need to implement it as well. Below is the onCameraMoveStarted overridden method.

override fun onCameraMoveStarted(p: Int) {
     pinTimeTextView.visibility = GONE
     pinProgressLoader.visibility = VISIBLE
}

In the onCameraMoveStarted method, we show the ProgressBar and hide the previously shown TextView. Now if you run the application, you’ll see that when the app opens the ProgressBar start animating inside the PinView.Google Maps PinView Animation

10. Get the nearest driver and calculate the Distance

In order to get the nearest Driver, we need to know the PinView location exactly where the user stops while dragging it. If you guy’s remembered from the previous article, we exactly face the same problem when we need to Reverse Geocode a location where user drags the Pin. So, for this, we need to update our onCameraIdle method inside the MainActivity.

Update the onCameraIdle method inside the MainActivity class.

override fun onCameraIdle() {
    val position = googleMap.cameraPosition.target
    viewModel.makeReverseGeocodeRequest(position, geoCoderValue.value)
    viewModel.onCameraIdle(latLng);
}

Next, add the below method inside the MainActivityViewModel class.

fun onCameraIdle(latLng: LatLng) {
        launch(coroutineContext + Dispatchers.Default) {
            if (driverRepo.allItems().isNotEmpty()) {
                val driver = driverRepo.getNearestDriver(latLng.latitude, latLng.longitude)
                driver?.let { calculateDistance(latLng, it) }
            }
        }
    }

At first, we launch a coroutine because the getNearestDriver method is a suspended method. After that, we check if the List<Driver> that we’re keeping inside the DriverCollection is not empty. Later we call the getNearestDriver method inside DriverCollection and call the calculateDistance method if the nearest Driver is not null.

You can get the DriverCollection class from GitHub.

Add the below calculateDistance method inside the MainActivityViewModel class.

private fun calculateDistance(latLng: LatLng, driver: Driver) {
    launch(coroutineContext + Dispatchers.IO) {  // 1
        val destination = arrayOf(driver.lat.toString() + "," + driver.lng.toString())
        val origins = arrayOf(latLng.latitude.toString() + "," + latLng.longitude.toString())
        DistanceMatrixApi.getDistanceMatrix(googleMapHelper.geoContextDistanceApi(), origins, destination)  // 2
            .mode(TravelMode.DRIVING)
            .setCallback(object : PendingResult.Callback<DistanceMatrix> {

                override fun onFailure(e: Throwable?) {
                }

                override fun onResult(result: DistanceMatrix?) {
                    if (result != null)
                        _calculateDistance.postValue(result.rows[0].elements[0].duration.humanReadable)  // 3
                }
            })
    }
}

Let’s go through the logic behind the above code:

  1. launch a coroutine in IO dispatcher, because it is a good approach to execute all network requests inside the IO dispatcher.
  2. The DistanceMatrixApi class is from the dependency which we add in the first article. You can read more about how to use the library here on GitHub.
  3. If the DistanceMatrix result is not null then we pass the result to MainActivity via LiveData to show the distance duration inside the PinView.

Note: The distance we’re calculating is from Driver location to PinView location. That’s how the Careem application shows the calculated distance inside PinView.

Next, add the geoContextDistanceApi method inside the GoogleMapHelper class.

class GoogleMapHelper(private val resources : Resources) {

   companion object {
       private val geoApiContextBuilder = GeoApiContext.Builder()
   }

   .......
   .......

   private fun distanceApi(): String {
        return resources.getString(R.string.google_distance_matrix_api_key)  // replace with your own distance matrix api key.
   }

   fun geoContextDistanceApi(): GeoApiContext {
        return geoApiContextBuilder
            .apiKey(distanceApi())
            .build()
   }
}

Now that we’ve added the utility method inside the GoogleMapHelper class. We need to declare _calculateDistance inside MainActivityViewModel class in order to observe from MainActivity.

private val _calculateDistance = MediatorLiveData<String>()

val calculateDistance : LiveData<String> = _calculateDistance

Next, add the following code inside the MainActivity onCreate method to observe calculateDistance instance from MainActivityViewModel class.

// 1
viewModel.calculateDistance
            .observe(this, Observer { distance ->
                   pinTimeTextView.text = distance
                   pinTimeTextView.visibility = VISIBLE
                   pinProgressLoader.visibility = GONE
            })

When the Observer interface invoked we simply set the distance to pinTimeTextView and hide the currently showing pinProgressLoader.

So, here we’ve completed the tenth part of the Frisbee application. Now when you run the application you’ll see the nearest Driver duration inside the PinView and also the duration updates when the Google Maps camera movement stops. Build and run to view the application progress. Here is mine:

Google Map Custom PinView With Text

Bravo! this concludes that our Frisbee application is complete. Hopefully, the next article will be on Driver application and it’ll be the last article on Android cab booking app tutorial. Stay tuned!

Thank you for being here and keep reading…

Previous Part

Disclaimer: The information provided in this article is my own personal opinion and research. You may share your opinion in the comment section at the end of this article.

I still remember that day back in 2013 when I decided to learn programming and that was one of the best decision I took in my life. But before start learning, I asked myself.

What Programming language should I learn first?

As we advance to 2019, it’s a good time to reflect on our top learning priorities for 2019. Before start talking about Programming Languages let me clarify:

  • I’m not arguing that any language is objectively better than any other.
  • I agree that developers should eventually learn more than one language.

Let’s dive right in with the first Programming Language:

1. Python

Python has been a growing programming language and it shows no signs of disappearing. You’ll find it in web applications, desktop apps, network servers, machine learning, media tools and more.

You might find Python useful for back-end services and API’s, if you’re in security or Site Reliability Engineering. Python-based web development framework like DjangoPyramid and Turbo Gear have found more and more popularity.

In the end, it’s a good choice for beginner developers to learn Python, as it’s high-level and easy to read and comprehend language. Python stats according to PYPL site.

2018 Programming Languages Stats2. JavaScript

JavaScript is the most popular language according to Stack OverFlow. More than half of all developers use JavaScript. It’s vital to front-end development and increasingly relevant to back-end development. And it’s rapidly expanding into areas like game development and the (IOT) Internet of things. JavaScript stats according to Stack OverFlow survey for 2018.

Stack OverFlow lanfuages stats for 2018

JavaScript allows you to build interactive websites, and it’s truly an essential web tool technology alongside HTML and CSS, and because most browsers in some way implement JavaScript. It’s crucial for getting into web-development and learning this language but it’s generally easier to pick and do something tangible with, in part because of all accessible UI.

JavaScript Gif

3. Rust

If you haven’t heard Rust before, it’s a new system-level programming language that is changing the way we think about programming. Rust came in first place in the 2018 Stack OverFlow Developer survey for developer most loved and wanted language.

Stack OverFlow 2018 loved programming languages

Rust language originally developed by Mozilla Foundation and it operates as a low-level language, suited for performance critical code. Rust is created with the purpose of avoiding the dangling pointers, buffer overflows or any other kind of memory errors.

For a beginner, Rust might be a bit of a struggle to pick up as it insists on various rules to achieve memory safety. However, experienced developers love it, and it’s quite possible that in the next few years Rust will be in very high demand.

rust programming language fire

4. Go

Go is a minimal language like Python. Since it is developed by Google, who are also Python lovers, they came up a language which is simple to write like Python but more efficient like C++Go provides better features to write concurrent programs. In the era when multi-core apps are being written, Go addresses the need quite well and also there’s built-in support of concurrency in it.

Go programming languages

Combining the best aspects of functional and object-oriented programming, as well as featuring a valuable set of inbuilt development tools. Some good and famous projects are using it, for instance, kubernetes and Ethereum Cryptozoic Project are based on Go.

5. Swift

If you want to get into IOS mobile development, you should definitely consider Swift as a high-paid career path. Swift is a relatively new programming language released in 2014. It’s Apple’s new language options for programming native IOS and Mac-OS applications. Native apps have been found to outperform hybrid apps, and Sprite-Kit makes it even easier to build 2D games.  It is considered an improvement in terms of usability and performance compared to Objective-C.

Swift Programming Language

Swift is a statically typed language means that XCode checks your error for you, so your errors are easier to track down, and further, it operates faster. By the way, XCode is the editor for the Swift language.

6. Kotlin

Kotlin is the second most loved and wanted a programming language in 2018 Stack OverFlow survey. Kotlin language is originally developed by JetBrains. It is fully inter-operable with Java and comes with no limitations. It can be used almost everywhere Java is used today: for server-side development, Android Apps, and much more.

Android developer has also been using Kotlin language from some time and loved the most. In 2017 Google announced that, Kotlin is now the official language for Android development. Kotlin works great with all existing Java libraries and frameworks and runs with same level of performance as with Java.

Kotlin language and Android

7. C++

C++ is a highly efficient and flexible language, first created back in 1985. It has remained in high demand due to high performance, reliability, and variety of contexts you can use it in. Microsoft Windows and Google Chrome are the two of the most well-known projects created with C++, and indeed most of Amazon’s website are written in C++.

C++ still going strong

A career with C++ involves developing desktop applications, especially performance-intensive tasks. You’ll find C++ in a wide range of applications– from GUI application to 3D graphics for a game to real-time mathematical solutions.

8. TypeScript

TypeScript is a programming language designed for large-scale JavaScript application development. In 2018 TypeScript capture the imagination of wider developer community. This language is not just for a front-end developer, it is now used to power back-ends, create hybrid mobile applications, architect cloud solutions, design neural networks and even control robots.

typescript_everywhere

It’s no surprise that TypeScript is now fundamental to core JavaScript frameworks – even Google decided to use it in Angular.

9. Java

Java is arguably the most popular programming language you’ve ever heard. It is a language created by mighty James Gosling from Sun MicroSystems in 1991. There’s a great saying ”write once run everywhere” capture one of the keys that make Java so valuable. It’s powerful JVM (Java Virtual Machine) which makes it cross-platform compatible.

Learn Java

There are so many Gurus and Pandits saying that the Java will be forgotten after the Kotlin language introduced. Java has died and resurrected more times than we can count and it is still right here. According to the latest 2018 Stack OverFlow survey Java is still on number fifth in Programming & Markup Languages section.

10. F#

F# is originally developed by F# Software Foundation. There was a time nothing much happening in Web regarding of F# but according to the latest survey, F# ranks in highest salary comparative to other programming languages. F# is most often used as a crossed-platform Common Language Infrastructure (CLI) language, but it can also generate JavaScript and GPU code. The following shows the F# salary comparison:

Stack OverFlow salary survey 2018

That concludes the list of top ten programming languages you should consider learning in 2019. If you like what you read, share your knowledge with the community.

Thank you for being here and keep reading…

Here’re some more Articles you might be interested:

— 10 Funny Jokes Of 2019 Only True Programmers Will Get

— 10 Simple Rules For Best Programming Practices

— Some Keeps to avoid bugs while Programming

In this article, I walk you through the development of a very basic Java JAX_RS web-services with Jwt (Json web token) authentication. For web-services, we’re going to use Jersey which is an open source framework for RESTful Web Services in Java. Before jump into coding and start authenticating the user I want to tell you a brief workflow of our application.

Application Workflow

  • In order to use the web-services, the user sends a request to get a token by passing his/her credentials.
  • Our web-service validates the credentials, and return an encrypted privateKey aka token, which will only be valid for the next thirty minutes.
  • With every request, the user needs to send the privateKey in the request header, and if the key is invalid or expires then we send back the WebApplicationException, else we simply return the result.

We’ll implement a custom ContainerRequestFilter, which is in the simple words, a gateway of our application. Every request made by the client first came to our custom filter and we validate the privateKey before allowing the request to go to any service.

Like I said at the start of this article, we’ll create a privateKey aka token with Jwt (Json web token). In order to create a web-based token, we’ll use the Java Jwt library made by mighty lhazlewood.

There’s a great article on Json Web Token go and check it out => 5 Easy Septs to understand Json Web Token (Jwts)

Application Workflow Diagram

As mention above, in the Application Workflow section our server or web-services will generate a privateKey or Jwt token for the user. With the Jwt token, the user then safely communicate with the application. Below is the workflow diagram.

Jwt workflow diagram

This is indeed a simplistic introduction to our application.  Next, below is the demo of our application for visualization.

In case I miss something, you can follow me by looking in the code which I pushed on GitHub.

Get Started

To begin, create a new Maven web project using an IDE and open the pom.xml file. Here we need to add dependencies for Jersey and Jwt.

<dependencies>
        ...........
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.19.4</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-grizzly2</artifactId>
            <version>1.19.4</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.19.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-entity-filtering</artifactId>
            <version>2.14</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        .........
    </dependencies>

Once you’ve added the above dependencies compile the Maven project and you’re good to go.

In order to start building our application first let’s see our EndPoint class. Below is our HomeApiService, which is an EndPoint of our application.

@Path("/")
public class HomeApiService {

    @POST
    @Path(value = "authorization_service")
    @JwtCustomToken
    @Produces(MediaType.APPLICATION_JSON)
    public Response authorizationService(@QueryParam("username") String userName, @QueryParam("password") String password) {
        if (userName.isEmpty())
            return getResponse(new BaseResponse(BaseResponse.FAILURE, "username field cannot be empty!"));
        if (password.isEmpty())
            return getResponse(new BaseResponse(BaseResponse.FAILURE, "password field cannot be empty!"));
        String privateKey = JwTokenHelper.getInstance().generatePrivateKey(userName, password);
        return getResponse(new AuthorizationResponse(BaseResponse.SUCCESS, "You're authenticated successfully. Private key will be valid for 30 mins", privateKey));
    }
    
    @GET
    @Path("allDevices")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAllDevices() {
         return getResponse(new DeviceCollection(Arrays.asList(new Device("Electric Kettle", 1, true), new Device("Computer", 1, true), new Device("Motorcycle", 3, false), new Device("Sandwich Maker", 4, true))));
    }

As you can see the basic JAX-RX Endpoint has two methods both returning a Response object. Now if you guy’s have seen the demo, then you probably see that in order to get allDevices we first need to authenticate our user and pass the privateKey inside the header of the request. Below is the explanation of the above two methods:

  • authorizationService: The user needs to get authenticated, invoking an HTTP POST and passing a username and password . Once authenticated, we simply call our jwTokenHelper class to create a token based on the username and password also set some other claims like thirty minutes expiration. You’ll see that how to create Jwt token in a couple of minutes.
  • getAllDevices: Simply returns a List of devices.

Filter checking for json web Token (Jwt)

So, we’ve added the EndPoint to our application but where did we check that the user adds the privateKey inside the header of the request. For this, we need to implement  ConatinerRequestFilter and after that the filter allows us to check the headers for every request. Like I said at the above of this article, the filter is like a gateway to our application. Every request sent by the client first came to our custom filter and after that, it goes to the EndPoint address. Below is JsTokenFilterNeeded class.

@Provider   
@JwtCustomToken   // 1
@Priority(Priorities.AUTHENTICATION)  // 2
public class JsTokenFilterNeeded implements ContainerRequestFilter {
   
   private static final String AUTHORIZATION_SERVICE_PATH = "authorization_service";  
   private static final String PRIVATE_KEY = "privateKey";   
   private JwTokenHelper jwTokenHelper = JwTokenHelper.getInstance();

   @Override
    public ContainerRequest filter(ContainerRequest request) {  // 3
        String path = request.getPath();                     
        if(path.equals(AUTHORIZATION_SERVICE_PATH))        // |       4
             return request;
        String privateKeyHeaderValue = request.getHeaderValue(PRIVATE_KEY);  // 5
        if (privateKeyHeaderValue == null || privateKeyHeaderValue.isEmpty())
            throw new WebApplicationException(getUnAuthorizeResponse(PRIVATE_KEY + " is missing in header"))   // 6
        try {
             provider.jwTokenHelper.claimKey(privateKeyHeaderValue);   // 7
        } catch(Exception e) {
            if (e instanceof ExpiredJwtException) {
                throw new WebApplicationException(getUnAuthorizeResponse(PRIVATE_KEY + " is expired"));
            } else if (e instanceof MalformedJwtException) {
                throw new WebApplicationException(getUnAuthorizeResponse(PRIVATE_KEY + " is not correct"));
            }
        }
        return request;
    }

    private Response getUnAuthorizeResponse(String message) {
       return Response.ok(BaseResponse.FAILURE, message
       ).status(Response.Status.UNAUTHORIZED)
        .type(MediaType.APPLICATION_JSON)
        .build()
    }
}

Let’s go through the logic behind the implementation.

  1. The JwtCustomToken is just a JAX-RS name binding (think of it’s as a CDI interceptor binding), so it’s just an annotation that binds to a filter. We’ll see that how to create JwtCustomToken annotation in a couple of minutes.
  2. Priority for user authentication. You can read more about other priorities in this link.
  3. The filter method is invoked at runtime whenever a new request came.
  4. If the path of the current request is authorization_service then we simply return the ContainerRequest immediately because at here our client trying to create a new privateKey. Also in here, we don’t need to check that user added the Jwt token inside the header request or not.
  5. Gets the HTTP Authorization header from the request (the privateKey).
  6. If privateKey is not added inside the header of the request then we simply throw WebApplicationException with a message (privateKey is missing in header).
  7. It validates the token (privateKey) using the Jwt library. If the token is valid then, in the end, we simply return the ContainerRequest and if it is not valid or token expires WebApplicationException thrown with a specific message.

The following shows the code snippet for JwtCustomToken annotation class.

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@NameBinding
public @interface JsonTokenNeeded {
}

Issue a json web token (Jwt) or privateKey

Now we have a filter that checks that the privateKey is passed inside the HTTP header. But how is this token issued? Here comes our JwTokenHelper class which create JJwt token based on user’s username and password also claims the token.

public class JwTokenHelper {

   private static JwTokenHelper jwTokenHelper = null;
   private static final long EXPIRATION_LIMIT = 30;
   private Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);

   private JwTokenHelper() {
   }

   public static JwTokenHelper getInstance() {
      if(jwTokenHelper == null)
           jwTokenHelper = new JwTokenHelper();
      return jwTokenHelper;
   }

   //  1
   public String generatePrivateKey(String username, String password) {
       return Jwts
                .builder()
                .setSubject(username)
                .setSubject(password)
                .setExpiration(getExpirationDate())
                .signWith(key)
                .compact();
   }
   
   // 2
   public void claimKey(String privateKey) throws ExpiredJwtException, MalformedJwtException  {
      Jwts
                .parser()
                .setSigningKey(key)
                .parseClaimsJws(privateKey);
   }

   // 3
   private Date getExpirationDate() {
       long currentTimeInMillis = System.currentTimeMillis();
       long expMilliSeconds = TimeUnit.MINUTES.toMillis(EXPIRATION_LIMIT);
       return new Date(currentTimeInMillis + expMilliSeconds);
   }

}

Below is the explanation of the above code.

  1. In here we set few claims for Json Web Token. Add the username and password, set expiration date for privateKey and sign in with SignatureAlgorithm.HS256.
  2. Validating the key with Jwts parser. If the key is not valid then the method throws MalformedJwtException and if it expires then it throws ExpiredJwtException.
  3. This is the method which sets that the privateKey is only valid for the next thirty minutes.

Now that we’ve all part’s, let’s put them together and run our application. In this article, we only see the configuration by extending ResourceConfig instead of a web.xml file.

public class MyResourceConfig extends DefaultResourceConfig {

    
    public MyResourceConfig() {
        super(HomeApiService.class); 
        Map<String, Object> maps = new HashMap<String, Object>();
        maps.put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS, CORSFilter.class);  
        maps.put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, JsTokenFilterNeeded.class);
        setPropertiesAndFeatures(maps);
    }
}

The DefaultResourceConfig class is itself an extension of JAX-RX Application class and also provides some convenience methods like setPropertiesAndFeatures to register our filters. Now in our MyResourceConfig constructor, we define a Map<String,Object> that will hold our resource and response filters and later set maps to ResourceConfig.

Run your rest Service

To run your web application paste the following code snippet inside your main method and afterward run the application like you run a simple java program.

public static void main(String[] args) {
        ResourceConfig resourceConfig = new MyResourceConfig();
        try {
             // change with your application ip and port address. 
            GrizzlyServerFactory.createHttpServer(URI.create("http://000.000.000.000:xxxx"), resourceConfig);   
            System.in.read();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Closing Up

In this article, I just wanted to show you how easy it is to issue and validate the Json Web Token with JAX-RX. Anything which I miss in this article please let me know via comment.

What’s next

Thank you for being here and keep reading…

This article is the second part of the series, Frisbee an Android cab booking app tutorial. If you did not read the previous one, you can start here.

Previously in Android cab booking App

In the previous pit stop, we had our discussion on GoogleMaps, Marker Animation and on Reverse Geocode. We learned how to show GoogleMaps, how to animate the Marker to user current location and Reverse Geocode the location where a user drags the PinView.

You can follow me by looking commits of code that I update on Github. Java application link and Kotlin application link.

4. Setting up firebase realtime Database

In the fourth part of Android Cab booking, we need to add firebase to our project. Please see the Manually add Firebase section in this link and configure your Android project into the firebase realtime database.

Note: Please set the security rules for firebase realtime database in a test mode. 

5. Read online drivers from firebase realtime Database

After setting up the firebase project in firebase console we need to read the online drivers from the realtime database but there are some prerequisites before start reading the drivers.

5.1 Online drivers database Structure

Before start reading the online Drivers, you guys need to know how data represented in the firebase realtime database.

Firebase realtime databaseYou see each Driver in online_drivers has its own key.  Once any update happens like (Driver location changed) at a certain Driver node or a new Driver added you’ll receive a DataSnapshot. We parse snapshot to get the value, pretty straightforward! You’ll see how to do this in a couple of minutes.

5.2 Setting up the firebase DatabaseReference

In order to connect the DatabaseReference with the firebase database, we need to get the reference from FirebaseDatbase. Paste the following code at the top of the MainActivityViewModel class.

companion object {
   private const val ONLINE_DRIVERS = "online_drivers"  // 1
}

private val databaseReference = FirebaseDatabase
           .getInstance() // 2
           .reference  // 3
           .child(ONLINE_DRIVERS)  // 4

Here’s what each line means:

  1. The root node name for online drivers. All online drivers will be in this node.
  2. Get the default FirebaseDatabase instance.
  3. Get the reference of the database, which effectively points to the root of the tree/directory.
  4. Inside the root node get the reference to the online_drivers node because we only need to read the online drivers.
5.3 Read online drivers

Now that we’ve online drivers in firebase realtime database and Database Reference, why not read it back from the database and show them inside our application. To read data or receive snapshots, we need to use Firebase’s Value Listener.  There are three ways to read the online Drivers from the firebase realtime database. Let’s see what’s best for our use case:

  • First, by calling the addListenerForSingleValueEvent on DatabaseReference, you read data only once. After you received it, the listener is removed. This is great when you need to read something once to use it in your app.
  • Second, using the addValueEventListener method, you listen to a certain node and all its changes. Even if the smallest thing changes you get the entire snapshot again. This is great for showing data that isn’t large but tends to change and can benefit from a realtime update like a single Driver model.
  • Lastly, with the addChildEventListener method, you subscribe to each change for each child in a node. If we change any of them, remove them or update them, we get an event for each of the mention cases. More importantly, it will emit each of the children one by one, by the first time you attach the listener.

The addChildEventListenermethod is best suitable for our use case, it will download all online Drivers from the database at application start and notify us whenever there’s a slight change in the online driver’s node.

Now add the child event listener to DatabaseReference inside the MainActivityViewModel init block. The reason we’re setting the event listener inside the initializer block because we need to retrieve all online drivers at application startup.

val firebaseValueEventListener = FirebaseValueEventListenerHelper(this)

init {
     databaseReference.addChildEventListener(firebaseValueEventListener)
}

The addChildEventListener method accepts the ChildEventListener type instance and our FirebaseValueEventListenerHelper class implements the ChildEventListener. Another thing we need to discuss is this parameter that we’re passing inside FirebaseValueEventListenerHelper. The FirebaseValueEventListenerHelper class constructor accepts the FirebaseObjectValueListener instance as a parameter and our MainActivityViewModel needs to implement it.

Create the below FirebaseObjectValueListener interface inside the listener package.

interface FirebaseObjectValueListener {

    fun onDriverOnline(Driver driver);

    fun onDriverChanged(Driver driver);

    fun onDriverOffline(Driver driver);
}

After creating the FirebaseObjectValueListener we need to implement the listener on MainActivityViewModel class and override all the abstract methods. You can get the Driver class inside the models’ package from GitHub code.

public class MainActivityViewModel : ViewModel(), CoroutineScope, FirebaseObjectValueListener {

    .......
    .......
    .......

    override fun onDriverOnline(driver : Driver) {
      Log.e(TAG, "On driver online -> ${driver.toString()}")
    }

    override fun onDriverChanged(driver : Driver) {
      Log.e(TAG, "On driver updated -> ${driver.toString()}")
    }

    override fun onDriverOffline(driver : Driver){
      Log.e(TAG, "On driver removed -> ${driver.toString()}")
    }

}

After implementing the listener on MainActivityViewModel class, we only need to call those abstract methods from FirebaseValueEventListenerHelper class. Add the following code inside FirebaseValueEventListenerHelper class.

class FirebaseValueEventListenerHelper constrcutor (private val firebaseObjectValueListener : FirebaseObjectValueListener) : ChildEventListener {

    // 1
    override fun onChildAdded(dataSnapshot : DataSnapshot, s : String?) {
       val driver = dataSnapshot.getValue(Driver.class)
       firebaseObjectValueListener.onDriverOnline(driver)
    }

    // 2
    override fun onChildChanged(dataSnapshot : DataSnapshot, s : String?) {
       val driver = dataSnapshot.getValue(Driver.class)
       firebaseObjectValueListener.onDriverChanged(driver)
    }

    // 3
    override fun onChildRemoved(dataSnapshot : DataSnapshot) {
       val driver = dataSnapshot.getValue(Driver.class)
       firebaseObjectValue.onDriverOffline(driver)
    }

    override fun onChildMoved(dataSnapshot : DataSnapshot, s : String?) {       
    }

    override fun onCancelled(databaseError : DatabaseError) {
    }

}

Let’s go through the logic behind the implementation:

  1. This method will be triggered whenever there’s a new Driver added inside the online_drivers node. Notice how we parse the Driver model, by calling the getValue method, the snapshot is parsed to whatever data model you want. After parsing the data we simply call the onDriverOnline method, which implemented inside the MainActivityViewModel class.
  2. This method will be triggered whenever the Driver node update in the online_drivers node.
  3. The onChildRemoved method will be called when there’s a Driver goes offline inside the online_drivers node.

So, we create the DatabaseReference and start listening to the online_drivers node. But what did we read? because currently, there are no online drivers in our online_drivers node. If you don’t want to test and run the application you can skip the Dummy insertion in a realtime Database and jump to the Driver Data Structure part.

6. Dummy insertion in firebase realtime Database (Optional)

I’ve created a couple of dummy drivers myself inside the online_drivers node for testing. You can see the following video of how to create dummy drivers inside the firebase realtime database.

 

After creating the dummy driver in the realtime database, build and run your application you should see the online Drivers log inside the Android Studio Logcat.

firebase_driver_online

In order to see the update or remove driver log. Go ahead and change the lat or lng from any of the Driver nodes for an update and delete a single Driver node for remove.

firebase_update_remove_driver

Note: You can also insert dummy driver while opening the application, the moment you hit enter immediately you’ll see the log for online Driver inside Android Studio Logcat.

7. Drivers Data Structure

In order to store the multiples driver inside our application, we need to have some kind of Data Structure so, that we can update the Driver Marker whenever their current location changed or remove the Driver Marker when they go to offline. The same thing goes with the online, we insert the Driver inside our collection.

Now in this article, I’m not gonna discuss our Data Structure because it is a simple CRUD. Currently, we’ve DriverCollection and MarkerCollection inside our collection package. You can get these collections classes from GitHub.

The DriverCollection simply holds our online Drivers information inside List and have some utility methods regarding insert, delete, retrieve and update.

The MarkerCollection has the Map<String,Marker>, where String is for Driver’s key and Marker is for value. It also has the almost same utility method for insert, update, delete and retrieve.

7.1 Explanation of DriverCollection and MarkerCollection

Whenever a new online driver found inside the onDriverOnline method, we insert the Driver in DriverCollection, create a new instance of Marker and store the Marker with driver’s key inside the MarkerCollection’s class. Similarly, when the Driver node updates inside fiirebase database and the onDriverChanged method gets called, we get the previous Driver instance from DriverCollection and update the Driver with the updated lat, lng. After the update of Driver, we get the instance of Marker from MarkerCollection and animats the Marker to Driver’s new location.

8. Show or animate multiple markers simultaneously | remove | insert

Now that we’ve our collections classes, we only need to use these collections classes CRUD methods. Update the following methods inside MainActivityViewModel class.

public class MainActivityViewModel : ViewModel(), CoroutineScope, FirebaseObjectValueListener{

   .....
   .....
   .....

   // 1
    override fun onDriverOnline(driver: Driver) {
        if (driverRepo.insert(driver)) {
            val markerOptions = googleMapHelper.getDriverMarkerOptions(LatLng(driver.lat, driver.lng), driver.angle)
            _addNewMarker.value = Pair(driver.id, markerOptions)
        }
    }

   // 2
    fun insertNewMarker(key: String, value: Marker) {
        makerRepo.insert(key, value)
    }

   // 3
    override fun onDriverChanged(driver: Driver) {
        launch(context = coroutineContext) {
            val fetchedDriver = driverRepo.get(driver.id) ?: [email protected]
            fetchedDriver.update(driver.lat, driver.lng, driver.angle)
            val marker = makerRepo.get(fetchedDriver.id) ?: [email protected]
            withContext(Dispatchers.Main) {
                marker.rotation = fetchedDriver.angle + 90
                MarkerAnimationHelper.animateMarkerToGB(
                    marker,
                    LatLng(fetchedDriver.lat, fetchedDriver.lng),
                    LatLngInterpolator.Spherical()
                )
            }
        }
    }

    // 4
    override fun onDriverOffline(driver: Driver) {
        launch(context = coroutineContext) {
            if (driverRepo.remove(driver.id))
                makerRepo.remove(driver.id)
        }
    }

}

Let’s go through the logic behind the implementation:

  1. The driver will be stored inside the DriverCollection. After the insertion, we get the MarkerOptions from GoogleMapHelper class and send a Pair(String, MarkerOptions) back to our MainActivity via LiveData.
  2. To insert the new Marker inside the MarkerCollection, we call this method from MainActivity.
  3. We launch a coroutine because our get method for DriverCollection and get method for MarkerCollection are suspending functions. After the update of Driverwe switch context to Main Dispatcher from IO because in order to update Marker we need to be in Main Thread.
  4. Again launch a coroutine because of the remove method for DriverCollection and remove method for MarkerCollection are suspending. After launching a coroutine we simply remove the Driver from DriverCollection and remove Marker from MarkerCollection.

Before start observing the Pair<String,MarkerOptions> inside MainActivity, we need to define the _addNewMarker in the MainActivityViewModel class. Add the following code inside the MainActivityViewModel class.

private val _addNewMarker = MediatorLiveData<Pair<String, MarkerOptions>>()

val addNewMarker: LiveData<Pair<String, MarkerOptions>> = _addNewMarker

Now go to MainActivity and paste the following code inside the onCreate method to observe the addNewMarker instance from MainActivityViewModel.

viewModel.addNewMarker
      .observe(this, Observer<Pair<String,MarkerOptions> { markerPair ->
          val marker = googleMap.addMarker(markerPair.second)
          viewModel.insertNewMarker(markerPair.first, marker)
      })

When the Observer interface invoked we simply add the Marker in the GoogleMaps and call the insertNewMarker method.

Build and run to view your progress so far. You should see the Driver car markers in Google Maps. In order to see the Marker animation, you need to change the Driver location from firebase realtime database. I know! I know this is not a good solution but for now, we’ve to work like this. In the next article, we’ll see how to update the Driver location from a mobile application like real-time and the Frisbee app able to see the Driver car moving without updating it from the database.

Car Marker AnimationNote: You’ll not able to see the Driver car markers if the driver’s location inside the firebase realtime database is not near you.

Alright, guy’s, this was all from this article. See you in the next article.

Thank you for being here and keep reading…

Previous Part

Next Part

Hey, Android Developers! I would like to share my experience with you guys when I got to make Cab booking application. I learn a lot during the development of this application. The following are the features which we’re going to discuss in this article:

  • Show GoogleMaps.
  • Animate multiples marker simultaneously on GoogleMaps.
  • Calculate the distance from the PinView location to the nearest driver.
  • Show multiples online drivers on GoogleMaps.
  • Animate the User PinView and show nearest driver distance time.
  • Working with Firebase Real-time Database.
  • Reverse Geocode location where the user drags current Marker.

What our app will be?

To show you how to implement above mention features in an app, we’re going to create a simple app called Frisbee: it will start listening to drivers from firebase realtime database and show the online drivers in the application. Animate the multiple driver markers simultaneously whenever their current location changed in firebase realtime database. Calculate the distance from PinView location to the nearest driver location, animate the Marker while calculating the distance and show the result inside the custom Marker.

Before to start coding the Frisbee, I want to show you guys the demo of application:

Prerequisite

  • Requires Google Maps API key to show Google Maps. Go to Developer Console -> Sign In with your Gmail account -> Create a new project -> API & Services -> Library -> Search for Google Maps and click on Maps SDK for Android -> Enable API. After enabling the Maps SDK, go to API & Services -> Credentials -> Create Credentials -> API key -> Restrict API key for your Android project.
  • Google Distance Matrix API key to calculate distance. Go to the previously created project in Developer Console -> API & Services -> Library -> Search for Distance Matrix and click on Distance Matrix API -> Enable API. After enabling the Distance Matrix API, go to API & Services -> Credentials -> Create Credentials -> API key -> Restrict key, change the name (optional), and finally click on save button. To add restrictions to an API key see this link.

Note: This tutorial will not focus on how to build the app for scale or for performance. It’s basically designed so that you can have fun while building it, and how you can create something that mimics Uber or Careem. Think of this as though building a Minimum Viable Product to demonstrate your idea or startup, for a proof-of-concept.

Now that everything is done, let’s make our hands dirty and create a new Android Studio Empty project:

Android Studio

In Android Studio go to Create Android Project, press next twice and select Empty Activity, then finish. After the Android Studio gradle builds successfully you’re ready to do the code. You can see MainActivity like below:

import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Before start coding our application we need to add some dependencies to our app level build.gradle file. The following shows the dependencies:

// Google dependencies
implementation 'com.google.android.gms:play-services-maps:16.0.0'
implementation 'com.google.firebase:firebase-database:16.0.5'
implementation 'com.google.android.gms:play-services-location:16.0.0'

// Material dialog dependency
implementation 'com.afollestad.material-dialogs:core:0.9.6.0'

// ViewModel dependencies
implementation 'android.arch.lifecycle:viewmodel:1.1.1'
implementation 'android.arch.lifecycle:extensions:1.1.1'

// Kotlin coroutines dependencies
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

// Map services dependency
implementation 'com.google.maps:google-maps-services:0.2.4'

Sync the project and everything should be fine without any kind of gradle error.

Let’s make our activity_main.xml file to show the views on the screen.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/mainActivityRootView"
        tools:context=".activities.main.ui.MainActivity">
    
    // 1
    <fragment xmlns:tools="http://schemas.android.com/tools"
              android:id="@+id/map"
              android:name="com.google.android.gms.maps.SupportMapFragment"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              tools:context="spartons.com.frisbee.activities.main.ui.MainActivity"/>

    // 2
    <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true">

        <FrameLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="100dp"
                tools:ignore="UselessParent">

            <FrameLayout
                    android:id="@+id/pinViewLine"
                    android:layout_width="2dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginTop="40dp"
                    android:background="@drawable/line_background"/>

            <FrameLayout
                    android:id="@+id/pinViewCircle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:background="@drawable/circle_background">

                <TextView
                        android:id="@+id/pinTimeTextView"
                        android:layout_width="40dp"
                        android:layout_height="45dp"
                        android:layout_gravity="top|center_horizontal"
                        android:gravity="center"
                        android:padding="2dp"
                        android:textColor="@android:color/white"
                        android:textSize="12sp"/>

                <ProgressBar
                        android:id="@+id/pinProgressLoader"
                        android:layout_width="45dp"
                        android:layout_height="45dp"
                        android:layout_gravity="top|center_horizontal"
                        android:layout_margin="4dp"
                        android:contentDescription="@null"
                        android:indeterminate="true"
                        android:visibility="gone"/>

            </FrameLayout>

        </FrameLayout>

    </FrameLayout>

    //  3
    <TextView
            android:id="@+id/currentPlaceTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerInParent="true"
            android:ellipsize="end"
            android:gravity="center"
            android:maxLines="1"
            android:background="@drawable/place_search_style"
            android:layout_margin="30dp"
            android:padding="10dp"
            android:text="@string/search_place"
            android:textColor="@color/colorPrimaryText"/>

    // 4

    <ImageButton
            android:id="@+id/currentLocationImageButton"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:layout_above="@+id/currentPlaceTextView"
            android:layout_alignParentEnd="true"
            android:layout_marginBottom="10dp"
            android:layout_marginEnd="2dp"
            android:contentDescription="@null"
            android:src="@drawable/current_location_icon"
            android:layout_alignParentRight="true"
            android:layout_marginRight="2dp"/>

</RelativeLayout>

Below is the explanation of the above code:

  1. The fragment tag to show the Google Maps.
  2.  FrameLayout for the custom Marker. The custom Marker is for a user to drag anywhere on the Google Map and set the pick-up location for a ride.
  3.  TextView for the current location place name.
  4. Finally, the ImageButton is for to moves the camera to a user’s current location.

Build your application and run to view your progress so far.

Custom Google Map MarkerThere are many key points in this application. So, we’re gonna need to break the application into smaller parts.

I will try to explain as many of lines of code as I can. You can follow looking on commits of code that I published on GitHub. Java application link and Kotlin application link.

1. Initialize The Google Maps

In order to use Google Maps, we need to initialize it first in our MainActivity onCreate method and store the instance of Google Maps so that later we can use it.

class MainActivity : AppCompatActivity() {

    private var googleMap : GoogleMap? = null

    override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
           .......
           .......

          val supportMapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
          supportMapFragment.getMapAsync { googleMap ->
                this.googleMap = googleMap
          }
    }

}

2. Animate Google Maps to user current location:

In this part of an application, we’re going to request user current location from LocationServices and animate the Google Map to that location. Before requesting the last known location from a device we need to check that if the user has PlayServices installed in his/her mobile. Add the below code in MainActivity onCreate method:

if(!uiHelper.isPlayServicesAvailable()) {
     toast("Play Services is not installed!")
     finish()
} else requestLocationUpdates()

If the user has not installed PlayServices in his/her mobile phone then we’re gonna exit the application and show Toast else, we simply request location updates from the device. The UiHelper is the utility class with just a bunch of helper method.

Next, add the following code inside the UiHelper class.

fun isPlayServicesAvailable() : Boolean {
    val googleApiAvailability = GoogleApiAvailability.getInstance()
    val status = googleApiAvailability.isGooglePlayServicesAvailable(context)
    return ConnectionResult.SUCCESS == status
}

As you may have noticed that if the user has PlayServices installed then we’re calling our requestLocationUpdates method. Add the below method inside MainActivity.

private fun requestLocationUpdates() {
        if (!uiHelper.isHaveLocationPermission()) {
            ActivityCompat.requestPermissions(
                this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION
            )
            return
        }
        viewModel.requestLocationUpdates()
    }

The code above checks if the app has been granted the ACCESS_FINE_LOCATION permission. If it hasn’t, then request it from the user because, starting with Android 6.0, user permission is handled little differently than before. You don’t request permission during the installation of your app; rather, you request them at runtime when the permission is actually required.

If the user granted the location permission then simply we ‘re gonna call our requestLocationUpdates method inside the ViewModel. All of our network calls and logical stuff will be handled inside MainActivityViewModel and listens to the data via LiveData.

You can check out my other articles on LiveData and ViewModel.

Add the below method inside MainActivityViewModel class.

fun requestLocationUpdates() {
   locationProviderClient.requestLocationUpdates(uiHelper.getLocationRequest(), locationCallback, Looper.myLooper());
}

The FusedLocationProviderClient request location updates with LocationCallback on a specified Looper. Also, you may have noticed that we need a locationCallback and  LocationRequest to successfully receive location updates.

Add the following getLocationRequest method inside the UiHelper class.

fun getLocationRequest() : LocationRequest {
   val locationRequest = LocationRequest.create()
   locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
   locationRequest.interval = 3000
   return locationRequest
}

The LocationRequest object is usually used to request a quality of service for location updates. You see we’re setting high priority accuracy and location interval to 3 seconds. Now after every 3 seconds our application will receive a Location update via LocationCallback which we’ve passed previously when requesting location updates.

After adding LocationRequest we only need to create our LocationCallback instance. Add the LocationCallback object creation as follows inside MainActivityViewModel class.

private val locationCallback: LocationCallback = object : LocationCallback() {

    override fun onLocationResult(locationResult: LocationResult?) {
        super.onLocationResult(locationResult)
        if (locationResult?.lastLocation == null) return
        _currentLocation.postValue(locationResult.lastLocation)
    }
}

The onLocationResult method called immediately when the device location information is available. The other thing we’re doing in this method is sending the location back to our MainActivity via LiveData.

Before start observing the current location in MainActivity we need to define this _currentLocation LiveData inside our MainActivityViewModel class.

private val _currentLocation = MediatorLiveData<Location>()

val currentLocation: LiveData<Location> get() = _currentLocation

You see we’re not exposing our MediatorLiveData instance publically instead we simply given a LiveData just to observe the location. By doing this we’re keeping our immutability principle safe.

Now that we’ve successfully requested location updates. Go to MainActivity and paste the following code inside the onCreate method to observe the user’s current location from MainActivityViewModel.

viewModel.currentLocation
         .observe(this, Observer<Location> { location ->
               if (firstTimeFlag) {
                        firstTimeFlag = false;
                        animateCamera(location);
               }
               showOrAnimateMarker(location);         
         })

The Observer interface is immediately invoked providing the most recent Location stored in currentLocation. The firstTimeFlag is our globally initialized bool, a default set to true. The reason we’re checking the firstTimeFlag condition, is because we need to animate the Google Maps camera to user current location when a user opens the application only the first time. After that, we simply animate the user current location Marker from previous coordinates to new coordinates.

Add the below animateCamera method inside MainActivity class.

private fun animateCamera(location : Location) {
     val cameraUpdate = googleMapHelper.buildCameraUpdate(location)
     googleMap.animateCamera(cameraUpdate, 10, null)
}

The animateCamera method animates the camera to the user’s current location. The GoogleMapHelper class provides several utility methods (CameraUpdate, default map settings, UserMarker) for Google Maps.

Next, add the following buildCameraUpdate method inside GoogleMapHelper class.

fun buildCameraUpdate(location: Location): CameraUpdate {
    val cameraPosition = CameraPosition.Builder()
        .target(LatLng(location.latitude, location.longitude))
        .tilt(TILT_LEVEL.toFloat())
        .zoom(ZOOM_LEVEL.toFloat())
        .build()
    return CameraUpdateFactory.newCameraPosition(cameraPosition)
}

Now add the showOrAnimateMarker method in the MainActivity class.

private fun showOrAnimateMarker(Location location) {
     if(currentLocationMarker == null){
           currentLocationMarker = googleMap.addMarker(googleMapHelper.getUserMarker(location))
     } else {
         MarkerAnimationHelper.animateMarkerToGB(currentLocationMarker, location, LatLngInterpolator.Spherical())
     }
}

You see first we check if the currentLocatinMarker is null then we create a new MarkerOptions with the help of GoogleMapHelper utility class, add Marker inside googleMap and store the Marker instance in the currentLocationMarker. Afterward, if it is not null then we simply animate the currentLocationMarker to user new location.

The LatLngInterpolator and MarkerAnimationHelper class are same which I explain in my previous article.

Build and run to view your progress so far. You should see a pin on your location and also your blue dot location Marker will animate if you’re traveling, walking, running etc.

Google Map Current Location MarkerNow that everything is done for showing the current location on Google Map and animate the Marker with user current location let’s start building our third application part.

3. Reverse Geocode PinView Coordinates And Show PlaceName

In order to Reverse Geocode the coordinates, we need to have user PinView Location. We can easily get these coordinates from CameraPosition target method. The target method will always give us the center point coordinates of Google Map which we see on screen and our PinView also stays in the middle of the screen. Now if we get the center point coordinates from target method, it means we’re getting the PinView coordinates.

Another thing we need to discuss is this, where do we call our Reverse Geocode method? If you guys have clearly see the demo of application you’ll understand that as soon the Google Map camera movement stopped the place name appeared inside the TextView. So, for this, we can easily implement OnCameraIdleListener on MainActivity. The OnCameraIdleListener has its callback function which defines what actions needs to done when the camera stopped its movement. In this callback, we need to get the coordinates from PinView and execute our Reverse Geocode request.

Let’s start the third part of an application by implementing the OnCameraIdleListener on MainActivity.

class MainActivity : AppCompatActivity(), GoogleMap.OnCameraIdleListener {

      private var googleMap : GoogleMap? = null

      override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            
            .......
            .......

            val supportMapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment supportMapFragment.getMapAsync { googleMap ->
                    googleMap.setOnCameraIdleListener(this)                          
                    this.googleMap = googleMap 
            }
     }

Now in onCameraIdle method, we need to get the current camera target coordinates from Google Maps and call the Reverse Geocode method.

override fun onCameraIdle() {
    val position = googleMap.cameraPosition.target
    viewModel.makeReverseGeocodeRequest(position, geoCoderValue.value); 
}

I know you guys must be thinking what is geoCoderValue. The geoCoderValue is nothing just a lazy initialized GeoCoder instance. It’s a good approach that we only initialized our GeoCoder once instead of creating a new instance every time. Add the below code inside the MainActivity to create lazy GeoCoder.

private val geoCoderValue = lazy {
      Geocoder(this)
  }

After creating GeoCoder inside MainActivity add the following code inside the MainActivityViewModel class to Reverse Geocode the PinView coordinates:

fun makeReverseGeocodeRequest(latLng: LatLng, geoCoder: Geocoder) {

    //1
    launch(context = coroutineContext) {

        // 2
        val result = geoCoder.getFromLocation(latLng.latitude, latLng.longitude, 1)
        if (result != null && result.size > 0) {
            val address = result[0]

             // 3
            _reverseGeocodeResult.postValue(address.getAddressLine(0).plus(" , ").plus(address.locality))
        }
    }
}

Here’s what’s going on in the makeReverseGeocodeRequest  method:

  1.  launch a coroutine builder so that our called thread will not be blocked. The Google documentation recommend us to Reverse Geocode in a separate thread instead of UI thread.
  2.  The getFromLocation method returns an array of Addresses that are known to describe the area.
  3. If the GeoCoder results are not null then we pass the result to MainActivity via LiveData to show the result in the TextView.

Before going to MainActivity and start observing the result we need to create our _reverseGeocodeResult LiveData inside MainActivityViewModel class.

private val _reverseGeocodeResult = MediatorLiveData<String>()

val reverseGeocodeResult : LiveData<String> = _reverseGeocodeResult

Now that we’ve successfully got the place name from coordinates. Go to MainActivity and paste the following code inside the onCreate method to observe the result from MainActivityViewModel.

viewModel.reverseGeocodeResult
            .observe(this, Observer<String> { placeName
                currentPlaceTextView.text = placeName
            })

When the Observer interface invoked we simply set the placeName in the TextView.

As a result, run the application you’ll see that the place name will be updated when you drag the PinView.

Reverse Geocode And Marker AnimationAlright, guys, that was all for this article. In the next article, we’ll see how to read online drivers from firebase realtime database and show or animate multiple Markers simultaneously.

Thank you for being here and keep reading…

Next Part

Couple of years ago, when I’m studying at my University. We have given the assignment to make a color changer app. The app is very basic where we have only one button and when a user clicks the button it changes its background color.

So like I said, the app is very basic and I’ve made the app in just half an hour. When the user presses the button, it perfectly changes its background. But when a user rotates the phone, it vanished the current state of an app and shows a default color instead of the previously shown background color.

So, what happened..? Rotating a phone can cause a configuration change. The configuration changes can cause your whole Activity to tore down and then recreate it. So, to save the current state of the activity we need some kind of UI data holder. As for beginner, I use the onSaveInstanceState trick to store the app state.

The onSaveInstanceState is the best approach to store the small amount of data. Also in my scenario, I only need to store the current background color.

Problem

What happened if I need to store a large amount of data instead of just storing the background color. Let’s say I need to store the list of users and their profile picture when the app going to rotate. In here we cannot use onSaveInstanceState trick because it can only be used to store a small amount of data. Now how we can store the data…?

Thanks to this, at Google I/O 2017 the Android Framework team introduced a new Architecture Component which deals this kind of rotation.

ViewModel

The ViewModel class is designed to store and manage UI-related data in a conscious way. The ViewModel is able to live through the configuration changes. It means that even after the Activity is destroyed and recreated after the phone rotation, you’ll still have the same ViewModel with the same data.

Now instead of storing all of your UI data in your Activity put in the ViewModel. One common pitfall that we all do when developing the Android application is putting a lot of variables, logic, and data into your Activity and Fragment. This creates a large unmaintainable whole mess of class and violating the Single Responsibility Principle.

The Lifecycle of ViewModel

The ViewModel is responsible for preparing and managing the data for an Activity or Fragment. It is always created in the scope of an Activity or Fragment and will be retained as long as the scope is alive. The lifecycle of a ViewModel extends from the associated UI when it’s first created until it is completely destroyed. The following shows the lifetime of a ViewModel associated with Activity lifecycle.

You see the ViewModel exists throughout the activity lifecycle. The onCreate may be called several times through during the lifecycle of an Activity, such as when the app is rotated but the model remains.

So, enough of this theory let’s how we can create a simple ViewModel class.

Creating a ViewModel

To make the view model you end up extending the ViewModel class and then put all your UI related data in the model class, that you gonna show in the Activity or Fragment. So, let’s create a ViewModel for the screen to store the current background color.

The following shows how to create a ColorChangerViewModel.

class ColorChangerViewModel : ViewModel() {
    private var colorResource: Int = 0xfff

    fun setColorResource(colorResource: Int) {
        this.colorResource = colorResource
    }

    fun getColorResource() = colorResource
}

You see our ViewModel is only responsible for holding the data that you’re gonna show in the UI. In our case, our ViewModel only needs to know about the color.

Note: ViewModel should not contain elements, that contains a reference to the UI such as Views since this will create an indirect reference to a Context. It will also cause a memory leak.

Now you guys must be thinking if I need Context inside ViewModel to get the SystemService or any other logic you wanna do with it. So, thankfully we’ve AndroidViewModel which is simply a ViewModel that includes an Application reference. Storing an Application Context inside ViewModel is ok because an application context is tied to the application lifecycle.

So, we create ViewModel let’s see how we gonna use this view model inside the activity.

MainActivity

For creating a ViewModel instance you use the utility class called ViewModelProviders.

class MainActivity : AppCompatActivity() {

    private lateinit var colorChangerViewModel: ColorChangerViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        colorChangerViewModel = ViewModelProviders.of(this).get(ColorChangerViewModel::class.java)
        mainActivityRootView.setBackgroundColor(colorChangerViewModel.getColorResource())
        changeColorButton.setOnClickListener {
            val color = generateRandomColor()
            mainActivityRootView.setBackgroundColor(color)
            colorChangerViewModel.setColorResource(color)
        }

    }

    private fun generateRandomColor(): Int {
        val rnd = Random()
        return Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
    }
}

Notice the ViewModelProviders takes an activity instance. This is the mechanism that allows you to rotate the device to get a technically new activity instance but always ensures that activity instance is associated with the same ViewModel.

You see here our activity is only responsible for knowing how to draw that data to the screen and receiving user interactions but not for processing them. Our ViewModel instance, we’re accessing the getter and setter to save and retrieve the color.

Every time the user presses a button it updates the previous color with the new color in ViewModel. So, when the user rotates the app it destroys the activity and again calls the onCreate method which sets previous background color instead of white default color.

When creating an instance of a ViewModel with ViewModelProviders.of(this).get(SomeViewModel::class.java). In this scenario, we have a default constructor, what if we need the parameterize constructor for our ViewModel. For this kind of ViewModel, we need to create the custom ViewModelProvider.Factory.

Creating ViewModelProvider.Factory

To create a custom model factory we need to implements the ViewModelProivder.Factory interface. The custom model factory is responsible to instantiates the ViewModels.

The following shows how to create ViewModelProvider.Factory.

class CustomViewModelFactory(private val user: User) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return UserViewModel(user) as T
    }
}

You see in create method we’re calling our parameterize ViewModel constructor. Let’s see the UserViewModel class.

class UserViewModel(val user: User) : ViewModel(){
    .......
    .......
}

Now we have the model factory and ViewModel class let’s see how we can use this in the Activity.

class MainActivity : AppCompatActivity(){
       ......
       ......
       override fun onCreate(savedInstanceState: Bundle?) {
             .......
             .......
             val factory = CustomViewModelFactory(someUserModel)
             val userViewModel = ViewModelProviders.of(this, factory).get(UserViewModel::class.java)
       }
}

When creating a view model we need to pass the Activity reference along with ViewModelProvider.Factory instance.

Removing ViewModel Lifecycle Forwarding

At some point, you may need to clean up the view model. The idea is that you may want to delete or remove the data in the ViewModel on configuration change. Simply override the onCleared method in the view model class. You can also cancel a long-running task in the onCleared method.

override fun onCleared() {
    super.onCleared()
    cleanUpSomeBackgroundWork()
}

The onCleared method will call when the Activity completely gets destroyed.

ProTip

The ViewModel class is also designed to work well LiveData and Data Binding. Using all of these together you can create a Reactive UI which is just a fancy way of saying a UI that automatically updates whenever the underlying data changes.

Alright, this is my demonstration about how to simply create ViewModel and work with it. I hope you guys have learned something from this post. If you have question or comments regarding this post please do comment below.

Thank for being here and keep reading…

This is the third and last part of Android ktx tutorial. In this part, we’re gonna explore the core ktx library extension functions. The core ktx have so much cool extension function which makes the Android coding much concise, simple and idiomatic. The core ktx currently cover some of the most used classes in Android like Animation, Content, Graphics, Drawables, Net, OS, Preference, Text, Transition, Util, View, Widget and many more to come.

Note:  I hope you guy’s have seen my previous blogs. In previous blogs of Android ktx, I briefly explain with examples how we can use the fragment ktx, SQLite ktx, palette ktx, collection ktx, lifecycle view-model ktx and work-runtime ktx.

To get started using the core ktx dependency add in your app level build.gradle.

implementation 'androidx.core:core-ktx:1.0.0-alpha3'

7. Core-ktx:

The core ktx include many packages.  Let’s see them one by one.

Animation Package:

There are so many extension functions that have added to the Animation package. Let’s take a look at what we have available in this release of core ktx. For the animation, there are a bunch of listeners added to the Animator class.

Now you can add the animation listener with extension function and don’t need to override all of the abstract methods.

animator.addListener(onStart = {

}, onEnd = {

}, onRepeat = {

}, onCancel = {
    
})

The onStart, onEnd, onRepeat, and onCancel listener are the default values. If you do not want, you can just use the addListener method like below.

animator.addListener {
    val myAnimator: Animator = it
    handleAnimationResult(myAnimator)
}

We can also listen to the animation pause and animation resume events. In animation ktx, we have an addPauseListener extension function.

animator.addPauseListener(onResume = {
    
},onPause = {
    
})

Again the only requiring callback we need to pass in the function. The onResume and onPause are the default callbacks.

animator.addPauseListener {
    val myAnimator: Animator = it
    handleAnimationResult(animator)
}

We can also listen to the individual animation events.

animator.doOnEnd {
   handleAnimation(it)
}
animator.doOnCancel { 
   handleAnimation(it) 
}
animator.doOnResume {  
    handleAnimation(it)
}
animator.doOnRepeat { 
    handleAnimation(it)
}
animator.doOnStart { 
    handleAnimation(it)
}
animator.doOnPause { 
    handleAnimation(it)
}

You see how much less code we require to listen to the animation events compares to java. Most of all it is easier to read.

Core Graphics Package:

Most of the application we work in are going to use graphics package somewhere throughout the project. So, the good news is ktx added so many extension functions in the graphics package and it also has the top-level function for creating Bitmap and Matrix.

Graphics Package Top-level Functions:

To begin with, we have a handy top-level function to create the bitmap.

val bitmap = createBitmap(50, 50)

It returns a mutable bitmap with specified width and height. You can also set bitmap default values config, alpha, and colorSpace when creating a bitmap.

val bitmap = createBitmap(50, 50,config = Bitmap.Config.ARGB_8888,hasAlpha = false,colorSpace = ColorSpace.get(ColorSpace.Named.SRGB))

Note: The above top-level function is only used when min SDK is 26 or higher.

The Matrix class also give some top-level function to create a matrix. Let’s see how we can create a matrix with some rotation.

val matrix = rotationMatrix(degrees = 50.0f, px = 0.1f, py = 0.5f)

Creates a rotation matrix defined by rotation angle in degrees. The px and py have the default values 0.0f and 0.0f respectively. The same goes for scaleMatrix top-level function.

val matrix = scaleMatrix(sx = 1.0f,sy = 1.0f)

Creates a scale matrix with the scale factor of sx and sy on the x-axis and y-axis. The sx and sy also have the default values of 0.1f and 0.1f respectively.

You can also set translation when creating Matrix. Let’s see an example.

val matrix = translationMatrix(tx = 0.1f,ty = 0.1f)

Creates a translation matrix with the translation amounts tx and ty on the x-axis and y-axis. The tx and ty have the default values of 0.0f and 0.0f respectively.

Graphics Package Extension Functions:
graphics.Bitmap

When it comes to Bitmap we have some key operations using extension functions.

bitmap.applyCanvas {
            
        }

It creates a new Canvas on this bitmap and executes the specified block. If you want the value of a pixel at the specified location then you have the bitmap extension function for this.

val pixelLocation : Int = bitmap.get(x = 1, y = 2)

Returns the value of the pixel at the specified location. You can also set the pixel color with x and y coordinate into the bitmap.

bitmap[50, 50] = Color.MAGENTA

Writes the specified color int into the bitmap at the specified x and y coordinates. Scaling a bitmap with extension function is look more concise.

val newBitmap : Bitmap = bitmap.scale(50, 50, filter = true)

Returns a new bitmap, scaled from this bitmap. If the specified width and height are the same as the current width and height of this bitmap, this bitmap is returned and no new bitmap is created.

graphics.Canvas

Working with Canvas has been made simpler too.

// wrap the specified block in calls to canvas.save and canvas.restoreToCount.
canvas.withSave {            
        }

// Wrap the specified block in calls to Canvas.save, Canvas.translate and Canvas.restoreToCount. The x and y have default 0.0f and 0.0f values respectively. 
canvas.withTranslation(x = 0.0f, y = 0.0f) {            
        }

// Wrap the specified blocks in call to Canvas.save, Canvas.rotate and Canvas.restoreToCount. The degrees, pivotX and pivotY have default values 0.0f, 0.0f and 0.0f respectively. 
canvas.withRotation(degrees = 0.0f, pivotX = 0.0f, pivotY = 0.0f) {            
        }

// Wrap the specified block in calls to Canvas.save, Canvas.scale and Canvas.restoreToCount. The x, y, pivotY and pivotX have default values 1.0f, 1.0f, 0.0f and 0.0f respectively.
canvas.withScale(x = 1.0f, y = 1.0f, pivotY = 0.0f, pivotX = 0.0f) {            
        }

// Wrap the specified block in calls to Canvas.save, Canvas.skew and Canvas.restoreToCount. The x and y have default values 0.0f and 0.0f respectively.
canvas.withSkew(x = 0.0f, y = 0.0f) {             
        }

// Wrap the specified block in calls to Canvas.save, Canvas.concat and Canvas.restoreToCount. The matrix is default parameters with default Constructor[Matrix()].
canvas.withMatrix(matrix = Matrix()) {
            
        }
graphics.Color

The Color class also have some additional extension functions. Getting the RGB value of color with the extension function.

// Returns the first component of color. When the color model of color is RGB, then the first component is red.
val redColor = color.component1()
// Return the second component which is green.
val greenColor = color.component2() 
// Return the third component which is blue.
val blueColor = color.component3() 
// Return the alpha of color.
val alpha = color.component4()

You can also get RGB value from the destructing method.

val (red ,green ,blue,alpha) = color

The plus extension function is really cool and allows us to add two colors and return the result of both colors.

val resultColor = color.plus(otherColor)
               OR
val resultColor = color + otherColor
Kotlin.int

The Int type in Kotlin offers us a collection of extension functions when working with the color class.

// Return the alpha component of a color int. This is equivalent to calling Color.alpha(someInt).
val alpha: Int = int.alpha 
// Return the blue component of a color int. This is equivalent to calling Color.blue(someInt).
val blue: Int = int.blue 
// Return the green componenr of a color int. This is equivalent to calling Color.green(someInt).
val green: Int = int.green 
// Return the red component of a color int. This is equivalent to calling Color.red(someInt).
val red: Int = int.red 
// Return the realitive luminance of a color int, assuming sRGB encoding. This equivalent to calling Color.luminance(someInt).
val luminance: Float = int.luminance 
// Destructing the values from int.
val (alpha, red, green, blue): Int = intValue 
// Creates a new instance from a color int. The resulting color is in the sRGB color space.
val color: Color = someInt.toColor()
// Converts the specified ARGB int color RGBA long color.
val longColor: Long = someInt.toColorLong()
Kotlin.Long

The Long type in kotlin also offers us the same extension functions as Kotlin.Int.

// Return the alpha component of a color long. This is equivalent to calling Color.alpha(someInt).
val alpha: Float = long.alpha 

// Return the blue component of a color long. This is equivalent to calling Color.blue(someInt).
val blue: Float = long.blue 

// Return the green component of a color long. This is equivalent to calling Color.green(someInt).
val green: Float = long.green 

// Return the red component of a color long. This is equivalent to calling Color.red(someInt).
val red: Float = long.red 

// Return the relative luminance of a color long. This equivalent to calling Color.luminance(someInt).
val luminance: Float = int.luminance 

// Destructing the values from int.
val (alpha, red, green, blue): Int = intValue 

// Creates a new instance from a color int. This is equivalent to calling the Color.value(longValue).
val color: Color = songLong.toColor()

// Converts the specified ARGB int color ARGB long color. This is equivalent to Colot.toArgb()
val intColor: Long = someInt.toColorInt()

// Indicates whether the color is sRGb. This is equivalent to Color.isSrgb(someLong)
val isSrgbResult: Boolean = longValue.isSrgb

// Returns the color space encoded in the specified color long. This is equivalent to Color.colorSpace(someLong)
val isSrgbResult: Boolean = longValue.isSrgb
graphics.Point

The Point class has been also given some extension functions to ease the process when working with them.

// Returns the x coordinates of point class.
val x = point.component1()

// Returns the y component of point class.
val y = point.component2()

// Getting x and y component using destructing declarations when working with the points.
val (x , y) = point

// Add the offsets this point by the specified point and returns the result as a new point.
val newPoint = point.plus(otherPoint)

// Add the offsets this point by the specified amount on both X and Y axis and returns the result as a new point.
val newPoint = point.plus(xy : someInt)

// Subtract the offsets this point by the negation of the specified point and returns the result as a new point.
val newPoint = point.minus(otherPoint)

// Subtract the offsets this point by the negation of the specified amount on both X and Y axis and returns the result as a new point.
val newPoint= point.minus(xy : someInt)

// Returns a PointF representation of this point.
val pointF : PointF = point.toPointF()
graphics.PointF

The PointF class has been offering the same extension function as Point.

// Returns the x coordinates of pointF class.
val x = pointF.component1()

// Returns the y component of pointF class.
val y = pointF.component2()

// Getting x and y component using destructing declarations when working with the points.
val (x , y) = pointF

// Add the offsets this pointF by the specified pointF and returns the result as a new pointF.
val newPointF = pointF.plus(otherPointF)

// Add the offsets this pointF by the specified amount on both X and Y axis and returns the result as a new pointF.
val newPointF = pointF.plus(xy : someFloat)

// Subtract the offsets this pointF by the negation of the specified pointF and returns the result as a new pointF.
val newPointF = pointF.minus(otherPointF)

// Subtract the offsets this pointF by the negation of the specified amount on both X and Y axis and returns the result as a new pointF.
val newPointF = pointF.minus(xy : someFloat)

// Returns a Point representation of this pointF.
val point : Point = pointF.toPoint()
graphics.Rect

When working with the Rect class, we can make use of the below extension functions.

// Returns 'left' the first component of the rectangle.
val left : Int = rect.component1()

// Returns 'top' the second component of the rectangle.
val top : Int = rect.component2()

// Returns 'right' the third component of the rectangle.
val right : Int = rect.component3()

// Returns 'bottom' the fourth component of the rectangle.
val bottom : Int = rect.component4()

// Rect class allows using destructuring declarations when working with rectangles.
val (left, top, right, bottom) = rect

// Performs the union of this rectangle and the specified rectangle and returns the result of the new rectangle.
val newRect : Rect = rect.plus(otherRect)

// Returns a new rectangle representing this rectangle offset by the specified amount on both X and Y axis.
val newRect : Rect = rect.plus(xy : someInt)

// Returns a new rectangle representing this rectangle offset by the specified point.
val newRect : Rect = rect.plus(xy : point)

// Returns the difference of this rectangle and the specified rectangle as a new region.
val region : Region = rect.minus(otherRect)

// Returns a new rectangle representing this rectangle offset by the negation of the specified amount on both X and Y axis.
val newRect : Rect = rect.minus(xy : someInt)

// Returns a new rectangle representing this rectangle offset by the negation of the specified point.
val newRect : Rect = rect.minus(xy : point)

// Returns the union of two rectangles as a new rectangle.
val newRect : Rect = rect.and(otherRect)

// Returns the intersection of two rectangles as a new rectangle. If the rectangles do not intersect, returns a copy of the left-hand side rectangle. By left-hand means the calling rectangle.
val newRect : Rect = rect.or(otherRect)

// Returns the union minus the intersection of two rectangles as a new region.
val region : Region = rect.xor(otherRect)

// Returns true if the specified point is inside the rectangle. The left and top are considered to be inside, while the right and bottom are not. This means that for a point to be contained: left <= x < right and top <= y < bottom. An empty rectangle never contains any point.
val boolValue : Boolean = rect.contains(point)

// Returns a RectF representation of this rectangle.
val rectF : RectF = rect.toRectF()

// Returns a Region representation of this rectangle.
val region : Region = rect.toRegion()
graphics.RectF

The same goes for RectF class with a similar function available.

// Returns 'left' the first component of the rectangle.
val left : Float = rectF.component1()

// Returns 'top' the second component of the rectangle.
val top : Float = rectF.component2()

// Returns 'right' the third component of the rectangle.
val right : Float = rectF.component3()

// Returns 'bottom' the fourth component of the rectangle.
val bottom : Float = rectF.component4()

// RectF class allows using destructuring declarations when working with rectangles.
val (left, top, right, bottom) = rectF

// Performs the union of this rectangle and the specified rectangle and returns the result of the new rectangle.
val newRectF : RectF = rectF.plus(otherRectF)

// Returns a new rectangle representing this rectangle offset by the specified amount on both X and Y axis.
val newRectF : RectF = rectF.plus(xy : someFloat)

// Returns a new rectangle representing this rectangle offset by the specified point.
val newRectF : RectF = rectF.plus(xy : pointF)

// Returns the difference of this rectangle and the specified rectangle as a new region. This rectangle is first converted to a Rect using RectF.toRect extension function.
val region : Region = rectF.minus(otherRectF)

// Returns a new rectangle representing this rectangle offset by the negation of the specified amount on both X and Y axis.
val newRectF : RectF = rectF.minus(xy : someFloat)

// Returns a new rectangle representing this rectangle offset by the negation of the specified point.
val newRectF : RectF = rectF.minus(xy : pointF)

// Returns the union of two rectangles as a new rectangle.
val newRectF : RectF = rectF.and(otherRectF)

// Returns the intersection of two rectangles as a new rectangle. If the rectangles do not intersect, returns a copy of the left-hand side rectangle. By left-hand means the calling rectangle.
val newRectF : RectF = rectF.or(otherRectF)

// Returns the union minus the intersection of two rectangles as a new region. The two rectangles are first converted to Rect using RectF.toRect extension function.
val region : Region = rectF.xor(otherRectF)

// Returns true if the specified point is inside the rectangle. The left and top are considered to be inside, while the right and bottom are not. This means that for a point to be contained: left <= x < right and top <= y < bottom. An empty rectangle never contains any point.
val boolValue : Boolean = rectF.contains(pointF)

// Returns a Rect representation of this rectangle. The resulting rect will be sized such that this rect can fit within it.
val rect : Rect = rectF.toRect()

// Returns a Region representation of this rectangle. The resulting rect will be sized such that this rect can fit within it.
val region : Region = rectF.toRegion()

// Transform this rectangle in place using the supplied Matrix and returns this rectangle.
val rectF : RectF = rectF.transform(m : matrix)
graphics.Path

There is also some operation available for working with Path class.

// Returns the union of two paths as a new Path.
val newPath : Path = path.plus(otherPath)

// Flattens (or approximate) the Path with a series of line segments. The acceptable error for a line must be positive and is set to 0.5f by default.
val newPath: Iterable<PathSegment> = path.flatten(error = 0.5f)

// Returns the difference of two paths as a new Path.
val newPath : Path = path.minus(otherPath)

// Returns the intersection of two paths as a new Path. If the paths do not intersect, returns an empty path.
val newPath : Path = path.or(otherPath)

// Returns the union minus the intersection of two paths as a new Path.
val newPath : Path = path.xor(otherPath)
graphics.Region

When it comes to Region class we have a bunch of available extension functions available to use. Just like Rect and RectF class, we can now easily perform plus, minus, or, and, and xor function to Region class.

// Return the union of this region and the specified region as a new region.
val newRegion : Region = region.plus(otherRegion)

// Return the union of this region and the specified Rect as a new region.
val newRegion : Region = region.plus(rect)

// Return the difference of this region and the specified region as a new region.
val newRegion : Region = region.minus(otherRegion)

// Return the difference of this region and the specified Rect as a new region.
val newRegion : Region = region.minus(rect)

// Return the intersection of this region and the specified region as a new region.
val newRegion : Region = region.or(otherRegion)

// Return the intersection of this region and the specified Rect as a new region.
val newRegion : Region = region.or(rect)

// Return the union minus the intersection of this region and the specified region as a new region.
val newRegion : Region = region.xor(otherRegion)

// Return the union minus the intersection of this region and the specified Rect as a new region.
val newRegion : Region = region.xor(rect)

// Returns the negation of this region as a new region.
val newRegion : Region = region.unaryMinus()

// Return true if the region contains the specified Point.
val boolValue : Boolean = region.contains(point)

// Returns the negation of this region as a new region.
val newRegion : Region = region.not()

// Performs the given action on each rect in this region.
region.forEach{ 
    // handleEachRect(it)
}

// Returns an Iterator over the Rects in this region.
val iterator : Iterator<Rect> = region.iterator()
Kotlin.String

For String, there is a single extension available at this time. With string, you can easily convert it to Color.

// Return a corrresponding int color of this String. This extenion function supported formats are RRGGBB, AARRGGBB. The following names can accepted : "red", "blue", "green", "black", "white","gray", "cyan", "magenta", "yellow", "lightgray", "darkgray","grey", "lightgrey", "darkgrey", "aqua", "fuchsia", "lime","maroon", "navy", "olive", "purple", "silver", "teal".
val blackColor : Int = "black".toColorInt()
graphics.Matrix

Previously above the post we the Matrix top-level function. Now it’s time to explore Matrix extension function. There is two extension function added to matrix class. Now you can multiply the matrix with another matrix and get the values of a matrix with extension functions.

// Multiplies this [Matrix] by another matrix and returns the result as a new matrix.
val newMatrix : Matrix = matrix.times(otherMatrix)

// Returns the 9 values of this Matrix as a new array of floats.
val floatArray : FloatArray = matrix.values()
graphics.PorterDuff.Mode

There is also some operation available when working with the PorterDuff.Mode class.

// Creates a new PorterDuffXfermode that uses this PorterDuff.Mode as the alpha compositing or blending mode.
val porterDuffXMode: PorterDuffXfermode = porterDuffMode.toXfermode()

// Creates a new PorterDuffColorFilter that uses this PorterDuff.Mode as the alpha compositing or blending mode, and the specified color.
val porterDuffColorFilter: PorterDuffColorFilter = porterDuffMode.toColorFilter(someIntColor)
graphics.Shader

You can also perform a transform operation on a Shader with the help extension function.

// Wrap the specified block, under the hood in calls Shader.getLocalMatrix and Shader.setLocalMatrix.
shader.transform{
    // blockExecuted()
}
graphics.Drawable

There are some handy extension functions available to convert the Bitmap into Drawable and Icon.

// Create a BitmapDrawable from this Bitmap.
val bitmapDrawable: BitmapDrawable = bitmap.toDrawable(resource: resources)

// Create an Icon from this Bitmap. This function internally called Icon.createWithBitmap static method. This function requires API level 26 or higher.
val icon : Icon = bitmap.toIcon()

And in relation to that, when we need to convert Int to drawable or color to drawable has been made simpler too.

// Create a ColorDrawable from this color value. 
val colorDrawable : ColorDrawable = someInt.toDrawable()

// Create a ColorDrawable from this Color via Color.toArgb. This function requires API level 26 or higher.
val colorDrawable : ColorDrawable = color.toDrawable()

The Drawable class also have given some extension function to convert a drawable into the bitmap and a function to update the drawable bounds.

// Return a Bitmap representation of this Drawable. If this instance is a BitmapDrawable and the width, height, and config match, the underlying Bitmap instance will be returned directly. If any of those three properties differ then a new Bitmap is created. For all other Drawable types, a new Bitmap is created. The width, height, and config are the default parameters, intrinsicWidth of drawable, intrinsicHeight of drawable and Config.ARGB_8888 are the default values respectively.
val bitmap: Bitmap =  drawable.toBitmap(width: someInt, height: someInt, config: bitmapConfig)

// Updates this drawable's bounds. This version of the method allows using named parameters to just set one or more axes. The left, top, right and bottom are the default values if not given then default bounds.left, bounds.top, bounds.right and bounds.bottom values respectively.
drawable.updateBounds(left : someInt , top : someInt, right : someInt, bottom: someInt)

When it comes to Uri to convert into Bitmap then the ktx have an extension function for this.

// Create an Icon from this Uri. This function internally called Icon.createWithContentUri static method. The method requires API level 26 or higher.
val icon : Icon = uri.toIcon()

The ByteArray class also given an extension to convert a byte array into Icon.

// Create an Icon from this ByteArray. The function internally called Icon.createWithData static method. This method required API level 26 or higher.
Core Content Package:

There is a bunch of extension function added to the content package. The content package also offers a top-level function. Let’s take a look at what is there currently offer.

Content Package Top-level Functions:

Now it is easy to create ContentValues instance using a contentValuesOf top-level function.

val contentValues : ContentValues = contentValuesOf(pairs : Pair<String,Any?>)  // Returns a new ContentValues with the given key and value as a elements.
Content Package Extension Functions:

Performing write operation to SharedPreference with extension function looks more concise.  Now we do not call apply or commit method to persist the changes.

sharedPreference.edit{
    putInt(key,value)
}

Styled attributes can also be worked with below extensions functions.

// Executes block on a receiver. The block holds the attribute values in set that are listed in attrs. In addition, if the given AttributeSet specifies a style class (through the `style` attribute), that style will be applied on top of the base attributes it defines.
context.withStyledAttributes(set : attributeSet,attrs : intArray, @AttrRes defStyleAttr : Int = 0,@StyleRes defStyleRes: Int = 0){
   // execute block
}

// Executes block on a receiver. The block holds the values defined by the style resource [resourceId] which are listed in attrs.
context.withStyledAttributes(set : attributeSet,attrs : intArray){
    // execute block
}

In every application somehow you need to retrieve the system service like NotificationManager, AlarmManager, etc. Getting the system service with the extension function.

// Return the handle to a system-level service by class.
val notificationManager : NotificationManager = getSystemService<NotificationManager>()
Core View Package:

There is some handy extension function added to core.view package. The ktx added extension function in View, Menu, ViewGroup and MarginLayoutParams class. Let’s see them one by one.

view.View

Updating the padding for a View is now easier. The ktx added bunch of function for updating the padding of a view.

// Updates this view's relative padding. This method using named parameters to just set one or more axes. All of the padding parameters are the default if you do not set the default parameters the calling view parameter will be used.
view.updatePaddingRelative(start : someInt, top : someInt, end : someInt, bottom : someInt)

// Updates the view padding. This method using named parameters to just set one or more axes. All of the padding parameters are the default if you do not set the default parameters the calling view parameter will be used.
view.updatePadding(left : someInt, top : someInt, right : someInt, bottom : someInt)

// Sets the view's padding. This method sets all axes to the provided size.
view.setPadding(size : someInt)

Now we have some extension functions for post animation with delayed in the view class.

// Re-orders the view parameters, allowing the action to be placed outside the parentheses.
view.postOnAnimationDelayed(delayInMillis : someLong){
   // handleCallback
}

// Re-orders the view parameters, allowing the action to be placed outside the parentheses.
view.postDelayed(delayInMillis : someLong){
   // handleCallback
}

Similar extension functions available for setting the view callbacks.

// Performs the given action when this view is next laid out. The function itself called addOnLayoutChangeListener to the view and remove the listener when calling the callback.
view.doOnNextLayout{
    val view = it
    // handleCallback
}

// Performs the given action when this view is laid out. If the view has been laid out and it has not requested a layout, the action will be performed straight away otherwise, the action will be performed after the view is next laid out.
view.doOnLayout{
   val view = it
   // handleCallback
}

// Performs the given action when the view tree is about to be drawn.
view.doOnPreDraw{
    val view = it
    // handleCallback
}

Converting view into the bitmap with a single line of code.

// Return a Bitmap representation of this View. The resulting bitmap will be the same width and height as this view's current layout dimensions. This does not take into account any transformations such as scale or translation. The default value for config is Bitmap.Config.ARGB_8888.
val bitmap = view.toBitmap(config : Bitmap.Config.ARGB_8888)

Updating the LayoutParams for a view is now a lot cleaner and easier to do.

// Executes block with the View's layoutParams and reassigns the layoutParams with the updated version.
view.updateLayoutParams{
   // executeBlock
}
view.ViewGroup.MarginLayoutParams

We can now update the margins for the layout params like we update the padding of the view previously.

// Sets the margins in the ViewGroup's MarginLayoutParams. This method sets all axes to the provided size.
marginLayoutParams.setMargins(size = 50)

// Updates the margins in the ViewGroup.MarginLayoutParams. This version of the method allows using named parameters to just set one or more axes. The left, top, right, bottom are the default params if you did not set params then the calling view params will be used.
view.updateMargins(left = someInt, top = someInt, right = someInt, bottom = someInt)

// Updates the relative margins in the ViewGroup's MarginLayoutParams. This version of the method allows using named parameters to just set one or more axes. The start, top, end, bottom are the default params if you did not set params then the calling view params will be used. The function requires API level 17.
view.updateMarginsRelative(start = someInt, top = someInt, end = someInt, bottom = someInt)


view.ViewGroup

Working with ViewGroup become much cleaner with extension functions. You can now loop through to children of a view group with forEach.

// Performs the given action on each view in this view group.
viewGroup.forEach{
    val view = it
    // performActionOnEachView(view)
}

// Performs the given action on each view in this view group, providing with sequential index.
viewGroup.forEachIndexed{ view, index -> 
    // performActionOnEachViewWithIndex(view,index)
}

You can also get Iterator from the ViewGroup with the extension function.

// Returns a MutableIterator over the views in this view group.
val viewGroupIterator : MutableIterator<View> = view.iterator()

There is also some utility extension function added to the view group class. You can now add, remove, get the view and check if the empty or not.

// Returns the view at index. IndexOutOfBoundsException throw, if the index is less than 0 or greater than or equal to the count
val view = viewGroup[0]

// Returns true if view is found in this view group.
val booleanValue : Boolean = viewGroup.contains(view)

// Removes view from this view group.
viewGroup.minusAssign(view)

// Returns true if this view group contains no views.
val booleanValue : Boolean = viewGroup.isEmpty()

// Returns true if this view group contains one or more views.
val booleanValue : Boolean = viewGroup.isNotEmpty()

// Adds a view to this view group.
viewGroup.plusAssign(view)
view.Menu

Similar to extension function for ViewGroup, we can now loop through to children of a Menu, in a similar manner with following functions.

// Performs the given action on each item in this menu, providing its sequential index.
menu.forEachIndexed{ index,menuItem -> 
    // performActionOnEachMenuItemWithIndex(index, menuItem)            
}

// 
menu.forEach{
    val menuItem = it
    // performActionOnEachMenuItem(menuItem)
}

Get Iterator from the Menu with the extension function.

// Returns a MutableIterator over the items in this menu.
val menuItemIterator : MutableIterator<MenuItem> = menu.iterator()

You can also get the Sequence of menu items from the menu extension. It is a final variable in menu class gives you a sequence over the menu items.

// Returns a Sequence over the items in this menu.
val menuItemsSequence : Sequence<MenuItem> = menu.children

Also, some utility extension function added to the menu class. You can now add, remove, get the menu item and check if has a menu item or not.

// Returns the menu item at index. The IndexOutOfBoundsException is thrown, if an index is less than 0 or greater than or equal to the count
val menuItem : MenuItem = menu[index]

// Returns true if the menu item is found in this menu.
val booleanValue : Boolean = menu.contains(menuItem)

// Removes menu item from this menu.
menu.minusAssign(menuItem)

// Returns true if this menu contains no menu items.
val booleanValue : Boolean = menu.isEmpty()

// Returns true if this menu contains one or more menu items.
val booleanValue : Boolean = menu.isNotEmpty()
Core Util Package:

The core ktx added a util package, there is a collection of an extension function related to AtomicFiles, Int, Float, Array, and SparseArray and many more classes.

Convert data into Half classes with other data types is now become more simple.

// Returns a half instance with the given float.
val half = someFloat.toHalf()

// Returns a half instance with the given double.
val half = someDouble.toHalf()

// Returns a half instance with the given short.
val half = someShort.toHalf() 

// Returns a half instance with the given string.
val half = someString.toHalf()
util.AtomicFiles

For atomic files, there is some function added for reading and writing to files. Let’s take a look at what are the extension’s functions available for writing to the file.

// Perform the write operations inside the block on this file. If the block throws an exception the write will be failed. Otherwise, the write will be applied atomically to the file. The function requires API level 17.
atomicFile.tryWrite {
   val outputStream: FileOutputStream = it
   // startWritingData(outputStream)
}

// Sets the content of this file as an array of bytes. The function requires the API level 17. This function internally called the tryWrite function.
atomicFile.writeBytes(array = bytesArray)

// Sets the content of this file as text encoded using UTF-8 or specified charset. If this file exists, it becomes overwritten. This function internally called the writeBytes function. The charset is default parameter, if not set it used Charsets.UTF_8. Requires the API level 17.
atomicFile.writeText(text = someText, charset = Charsets.UTF_8)


Similar to writing functions we have some functions for reading also.

// Gets the entire content of this file as a byte array. This method is not recommended on huge files. It has an internal limitation of 2 GB file size. Required API level 17.
val fileBytes : ByteArray = atomicFile.readBytes()

// Gets the entire content of this file as a String using UTF-8 or specified [charset]. This method is not recommended on huge files. It has an internal limitation of 2 GB file size. This function also requires API level 17.
val fileText : String = atomicFile.readText(charset = Charsets.UTF_8)
util.SparseArray

For the LongSparseArray, SparseArray, SparseBooleanArray, SparseIntArray and SparseLongArray have collection of extension functions available.

// Returns the number of key/value pairs in the collection.
val arraySize : Int = sparseArray.size

// Returns true if the collection contains the key.
val booleanValue : Boolean = sparseArray.contains(key : key)

// Allows the use of the index operator for storing values in the collection.
sparseArray.set(key : key value : someValue)

// Creates a new collection by adding or replacing entries from other.
val newSparseArray : SparseArray<T> = sparseArray.plus(other : otherSparseArray)

// Returns true if the collection contains value.
val booleanValue : Boolean = sparseArray.containsValue(value : someValue)

// Return the value corresponding to a key, or defaultValue when not present. 
val someValue : T = sparseArray.getOrDefault(key : key, defaultValue : someDefaultValue)

// Return the value corresponding to a key, or from defaultValue when not present. In this function for defaultValue, we need to pass a function with a return type of T.
val someValue : T = sparseArray.getOrElse(key : key) {
    [email protected] t
}

// Return true when the collection contains no elements.
val booleanValue : Boolean = sparseArray.isEmpty()

// Return true when the collection contains elements.
val booleanValue : Boolean = sparseArray.isNotEmpty()

// Removes the entry for key only if it is mapped to value.
val booleanValue : Boolean = sparseArray.remove(key : key , value : someValue)

// Update this collection by adding or replacing entries from other.
sparseArray.putAll(other : otherSparseArray)

// Performs the given action for each key/value entry.
sparseArray.forEach { key, value -> 
     // performOperationOnEachKeyAndValue(key,value)            
}

// Return an iterator over the collection's keys.
val keyIterator = sparseArray.keyIterator()

// Return an iterator over the collection's values.
val valueIterator : Iterator<T> = sparseArray.valueIterator()
util.Range

Working with Range class have become little easier. The Range class requires API level 21 or higher.

// Return the smallest range that includes this and value.
val newRange : Range<T> = range.plus(value : someValue)

// Return the smallest range that includes this and other.
val newRange : Range<T> = range.plus(other : otherRange)

// Return the intersection of this range and other. Throw IllegalArgumentException if this is disjoint from other.
val newRange : Range<T> = range.and(other : otherRange)

// Returns this Range as a ClosedRange. 
val closedRange : ClosedRange<T> = range.toClosedRange()

// Return Range from ClosedRange.
val newRange : Range<T> = closedRange.toRange()

util.Pair

We can also perform a bunch of operation on Pair class instance with provided extension functions.

// Returns the first component of the pair. 
val first = pair.component1()

// Returns the second component of the pair.
val second = pair.component2()

// Destructing declarations when working with Pair.
val (first, second) = pair

// Return the pair as Kotlin.Pair class.
val kotlinPair = pair.toKotlinPair()
util.Size & util.SizeF

The Size and SizeF class also given a bunch of extension function to work with.

// Returns width, the first component of this size.
val width = size.component1()

// Returns height, the first component of this size.
val height = size.component2()

// Allows to use destructuring declarations when working with Size classes, for example:
val (width , height) = size
Core Widget Package:

In every application somewhere down the road, you need to show the Toast.  The core ktx add an extension function to show a toast.

// Creates and shows a Toast with the given text. The duration parameter is the default, if not set then Toast.LENGHT_SHORT will be used.
context.toast("Show some toast",length = Toast.LENGTH_SHORT)

// Creates and shows a Toast with text from a resource. The duration parameter is the default, if not set then Toast.LENGHT_SHORT will be used.
context.toast(R.string.someResource,length = Toast.LENGTH_SHORT)
Core Text Package:

In most of the Android app, we’re going use Text somewhere in the app. The core ktx added some extension functions and one top-level function. Within the text package, there is a collection of extension function let’s see them one by one.

Core Text Top-level Functions:

Working with the spans API. The core ktx added a top-level extension to the main class. Let’s say, you want some text to be bold, italic and underline at the same time programmatically.

val string: SpannedString = buildSpannedString {
    append("Hello There")
    bold {
        append("bold")
        italic {
            append("bold and italic")
            underline {
                append("then some text with underline")
            }
        }
    }
}
textView.text = string

You see using directly top-level function converting the text into bold, italic and underline is a massive reduction of code.

Core Text Extension Functions:
Kotlin.CharSequence

In the CharSequence class ktx added some cool extension functions to work with. Say if you want to check if the char sequence contains the only digit.

// Returns whether the given CharSequence contains only digits.
val booleanValue : Boolean = charSequence.isDigitOnly()

There is also an extension function for getting the trimmed length of a char sequence.

// Returns the length that the specified CharSequence would have if spaces and ASCII control characters were trimmed from the start and end, as by String.trim.
val length : Int = charSequence.trimmedLength()

If you need to convert char sequence to Spanned or Spannable instance, then the core ktx have extension function for this.

// Returns a Spannable from a CharSequence.
val spannable : Spannable = charSequence.toSpannable()

// Return a Spanned from CharSequence.
val spanned : Spanned = charSequence.toSpanned()
Kotlin.String

With String, we have the ability to convert a string into HTML encoding with the extension function.

// Html encode the String
val htmlEncodeString : String = someString.htmlEncode()

There is also an extension function for parsing the string as Html.

// Returns a Spanned from parsing this string as HTML. 
val spanned : Spanned = someString.parseAsHtml()
text.Spanned

If we have a Spanned instance which we wish to convert into HTML string for then we can do so with a toHtml extension function.

// Returns a string of HTML from the spans in this Spanned. The options is default parameter.
val htmlString : String = spanned.toHtml(option : Html.TO_HTML_PARAGRAPH_LINES_INDIVIDUAL)

If you need to get all the spans inside the Spanned instance then we have a getSpans extension function for this.

// Get all the spans inside the spanned. The start and end are the default parameters, if you did not set then 0 value will be used for start and the end value will be spanned length.
val spanArray : Arra<T> = spanned.getSpans(start = 0, end = spanned.length)
text.Spannable

The core ktx have some utility function when working with Spannable. Like the previous classes, the core ktx added some basic functions for Spannable adding the new spans, remove spans, setting spans at the specific position and clearing the spans.

// Add span to the entire text. The span is the type of 'Any' in Kotlin and 'Object' in Java.
spannable.plusAssign(span : someSpan)

// Remove span from the entire text. The span is the type of 'Any' in Kotlin and 'Object' in Java.
spannable.minusAssign(span : someSpan)

// Clear all spans from the entire text.
spannable.clearSpans()

// Add span to the range of the text. The span is the type of 'Any' in Kotlin and 'Object' in Java. The range is the type of 'IntRange' in kotlin. The range end value is exclusive.
spannable.set(range : intRange , span : someSpan)

// Add span to the range start and end of the text. 
spannable.set(start : intValue, end : intValue, span : someSpan)

// Example of setting Span
val spannable = "Hello, World".toSpannable()
spannable.set(0 , 5 , Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
text.SpannableStringBuilder

At the beginning of core text package, we see one top-level function of creating spannable builder. Now there are a collection of extension functions available for SpannableStringBuilder class. To begin with, if you want to add some bold text to builder then we have an extension function for this.

// Wrap appended text in block in a bold StyleSpan.
builderSpan.bold { 
   append("Make this text bold")
}

Like the bold extension function, we have some other cool function for making the text to underline and italic.

// Wrap appended text in block in an italic StyleSpan. 
builderSpan.italic {
    append("Make this text italic")
}

// Wrap appended text in block in an UnderlineSpan.
builderSpan.underline {
    append("Make this text underline")
}

There are also build functions for setting the background color or wrap the text that you’re appending in spans.

// Wrap appended text in a block in spans. The spans will only have the correct position if the block only appends or replaces text. Inserting, deleting, or clearing the text will cause the span to be placed at an incorrect position. The span parameter is the type of 'Any' in Kotlin and 'Object' in Java.
builderSpan.inSpan(span : spanItem) {
    append("Add this text to span builder")
}

// Wrap appended text in a block in the ForegroundColorSpan.
builderSpan.color(color : R.color.someColor) {
    append("Change the foreground color of this text only")
}

// Wrap appended text in a block in the BackgroundColorSpan.
builderSpan.backgroundColor(color : R.color.someColor) {
   append("Change the background color of this text only")
}

Core Net Package:

Within the core.net package of ktx we a bunch of extension function to convert String into Uri, File into Uri and Uri to File.

// Creates a Uri from the given encoded URI string. Internally this function called the Uri.parse static method.
val uri : Uri = someString.toUri()

// Creates a Uri from the given file. Internally this function called the Uri.fromFile static method.
val uri : Uri = someFile.toUri()

// Creates a File from the given Uri. It internally creates a new File with Uri path.
val file : File = uri.toFile()
Core OS Package:

There is a bunch of extension and top-level functions provided for the OS package.

Core OS Top-Level Functions:

Creating a new instance of Bundle with top-level function looks nicer.

// Returns a new Bundle with the given key/value pairs as elements. The method will throw an IllegalArgumentException When a value is not a supported type of Bundle.
val bundle : Bundle = bundleOf(pairs : Pair(firstValue,secondValue))

// Returns a new PersistableBundle with the given key/value pairs as elements. This method will throw an IllegalArgumentException When a value is not a supported type of PersistableBundle. This function requires API level 21 or higher.
val persistentBundle : PersistentBundle = persistentBundleOf(pairs : Pair(firstValue,secondValue))

Writing trace messages can also be done with the top-level function.

// Wrap the specified block in calls to Trace.beginSection with the supplied sectionName and Trace.endSection. 
tracr(string : someSectionName) {
   // handleTraceStart
}
Core OS Extension Functions:

The core ktx also include some extension functions when working with Handler class.

val runnable : Runnable = handler.postDelayed(delayInMills: someLongValue) {
    // doSomething 
}

val runnable : Runnable = handler.postAtTime(uptimeMillis : someLongValue) {
    // doSomething
}

Wrap

That’s it guys here we’re going to complete our Android ktx tutorial series. You guys have seen ktx offer us awesome extension function and also some top-level functions to use in our Android Applications. Like I said the library is in preview mode,  and I’m excited to see what other extension functions will be added in the library.

I hope you guys have learned from this post. If you any queries please do comment below.

Thank for being here and keep reading.

Previous Part

If you’re developing an Android application with Kotlin, then I have a good news for you. Recently Google released an Android ktx library, which is a set of Kotlin Extension function. Android ktx is a part of Jetpack family. The purpose of Android ktx is to write less code and more concise. Android ktx brings us lots of extension functions, named parameters, lambdas, and parameter with the default value. It does not add any new features to existing Android Api’s.

I read all the documentation on android-ktx and thought to write some notes on it. It’s not just reading on Android developer documentation. We’re going to see the extension functions with example and explore most of them.

Note: Android ktx is currently in preview mode but it is open for the developer to give it a try and give feedback to contributors. It may be offering more extension functions when it is released.

To get started with Android ktx add the google repository in build,gradle file.

repositories { 
    google() 
}

Android ktx dependency in split into the modular approach. By modular means, you don’t have to add the core dependency, if you do not want to use all of the extension’s functions. Here is the list of dependency of Android ktx.

implementation 'androidx.core:core-ktx:$currentVersion'
implementation 'androidx.fragment:fragment-ktx:$currentVersion'
implementation 'androidx.palette:palette-ktx:$currentVersion'
implementation 'androidx.sqlite:sqlite-ktx:$currentVersion'
implementation 'androidx.collection:collection-ktx:$currentVersion'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:$currentVersion'
implementation 'androidx.lifecycle:lifecycle-reactivestreams-ktx:$currentVersion'
implementation 'android.arch.work:work-runtime-ktx:$currentVersion'

After syncing the project you’re good to go to use Android ktx. Now let’s start with the first modular dependency.

1. Fragment-ktx:

Fragment ktx dependency right now supports only one extension function. The only extension function is about triggering the fragment transaction. Without ktx performing a fragment transaction, the transaction requires starting a transaction triggering an action like replacing or adding a fragment and then the signing on one of the four commit methods. Now let’s see how we can remove the boilerplate code with fragment ktx extension.

supportFragmentManager.transaction(now = false, allowStateLoss = false) {
      replace(R.id.frag_container, myFrament,FRAGMENT_TAG)
}

Fragment ktx as the transaction extension function to the FragmentManager class removing all the begin transaction boilerplate code. As well as providing the four value for sync and stateloss that you can easily override.

nowallowStateLossMethod
falsefalsecommit()
falsetruecommitAllowingStateLoss()
truefalsecommitNow()
truetruecommitNowAllowingStateLoss()

2. Palette-ktx:

Like I said the library is currently in the preview that’s why we only have two extension function for palette ktx. Now let’s take a look at what extension function we have…?

Now you can easily create Palette. Builder with the bitmap.

val paletteBuilder : Palette.Builder = bitmap.buildPalette()

You can easily get Palette. Swatch from Palette class.

val paletteSwatch = pallete[Target.DARK_VIBRANT]

Returns the selected swatch for the given Target from the palette, or if null one could not be found. With palette swatch, you can retrieve RGB color by calling the getRgb method.

3. SQLite-ktx:

SQLite ktx dependency right now supports only one extension function. When implementing database transaction you need a lot of boilerplate code, with the SQLite ktx, you can focus on what matters the operation that you want to make in the database. Let’s see an example of handling transaction with sqlLite ktx.

sqLitedatabase.transaction(exclusive = true){
    // Insert data, delete data, update data
}

If you setting exclusive to true it called beginTransaction and when setting false it called beginTransactionNonExclusive.

4. Collection-ktx:

If you use the Kotlin top-level function of creating collection then you absolutely love this collection ktx dependency. It supports many extension functions and it also supports top-level function of creating the collection. Let’s see them one by one.

4.1 Collection-ktx Top-level Functions:

With the .collection package of ktx, you can easily create an arrayMapOf with top-level function to create ArrayMap.

val arrayMap = arrayMapOf<String,String>()   // returns an empty new ArrayMap

You can also give a list of Pair where the first component is the key and second component is the value.

map = arrayMapOf(pairs = *arrayOf(
          Pair("Jon", "Doe"),
          Pair("Hilary", "Clinton"))
)    // returns a array map with specified content.

The ArraySet also gives some top-level function to ease the process when working with them.

val arraySet = arraySetOf<Int>()   // returns an empty new ArraySet.

You can also give a vararg to create ArraySet.

val arraySet = arraySetOf(1,2,3)  // return an array set with specified content.
4.2 Collection-ktx Extension Functions:

When working with the LongSparseArray and SparseArrayCompat we can make use of the below extension function. Both of the classes pretty much offers the same functionalities.

val longSparseArray = LongSparseArray<String>()   // create a LongSparseArray of String

//   returns true if the collection contain the key
longSparseArray.contains(key: Long)    

// You can use index operator to store value a specified index
longSparseArray.set(key : Long,value : String)   // value is String, because our sparse array is String type

// create new collcetion by adding or replacing entries from other
longSparseArray.plus(other : LongSparseArray<String>)

// returns true if the collection contains the key
longSparseArray.containsKey(key : Long)

// return true if the collection contains the value
longSparseArray.containsValue(value : String)

// return the value corresponding to the key, or default when no present.
longSparseArray.getOrDefault(key : Long, defaultValue : String)  // return defaultValue if no value found according to the key

// return true when the collection contains one or more than element in the array.
longSparseArray.isNotEmpty()

// removes the entry from the array only if it is mapped to value in the specified index.
longSparseArray.remove(key : Long, value: String)

// updates this collection by adding replacing entries from other.
longSparseArray.putAll(other: LongSparseArray<String>)

// performs foreach on every key/value entry.
longSparseArray.forEach(action : (key : Long, value : String) -> Unit)

// Example of foreach function
longSparseArray.forEach{ key,value -> 
     // Use the key and value to perform the operation
}

// return Iterator over the collection key.
val iterator : LongIterator = longSparseArray.keyIterator()

// return Iterator over the collection values.
val iterator : Iterator<String> = longSparseArray.valueIterator()

That’s it guy’s, I’m going to end this blog here for more further reading about Android ktx see the part 2. In the next part, I’m going to explain about lifecycle ktx, reactive streams ktx and runtime ktx. Finally, in the third part, we’re gonna explore the core ktx.

I hope you guy’s have learned something from this post. If you’ve any queries about this post please do comment below.

Thank you for being here and keep reading.

Next Part

Finally, Android O support library got this feature covered. Material design recommends using a dynamic type instead of smaller type sizes or truncating larger size text. A TextView that automatically resize the text, expand and fill its layout based on the text view characteristics and boundaries. These characteristics make it easier to optimize the text size with different screen size and dynamic content.

Auto-resizing can also help you avoid empty spaces in your layout or text that gets cut off mid-sentence because you tried to add too many words into a TextView.

Dependency

For to use Autosize TextView you need to add a dependency in your build.gradle file.

implementation 'com.android.support:appcompat-v7:27.1.0'
Types of setting Autosize TextView
  • Default
  • Granularity
  • Preset Sizes
1. Default

To define the default settings of Autosizing TextView with xml set “setautoSizeTextType” to uniform. Let’s see an example how we can use it in the xml file.

<TextView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeTextType="uniform" />

Now this setting of TextView scale uniformly on horizontally and vertically ignoring the text size attributes. If you’re not settings the minTextSize, maxTextSize, and granularity properties then the default values will be used 12sp, 112sp, and 1px respectively.

Note: If you set Autosizing in an XML file, it is not recommended to use the value “wrap_content” for the layout_width or layout_height attributes of a TextView. It may produce unexpected results.

You can also set Autosizing of a TextView programmatically.

emojiCompatTextView.setAutoSizeTextTypeWithDefaults(TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM)
2. Granularity

With Granularity, the TextView will scale uniformly in the range between minimum and maximum size in increments of step granularity. If you don’t set these properties the default values will be used.

To implement Autosizing using granularity you’ll need to add the following attributes in the xml file. Below is the example how to use granularity in xml.

<TextView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeTextType="uniform"
    app:autoSizeMinTextSize="12sp"
    app:autoSizeMaxTextSize="100sp"
    app:autoSizeStepGranularity="2sp" />

You can also set Autosizing using granularity programmatically.

emojiCompatTextView.setAutoSizeTextTypeUniformWithConfiguration(12, 100, 2, TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM)
3. Preset Sizes

To have more control over the final size. e.g your app needs to compile with specific text size design guidelines. You can provide an array of supported text sizes and it will use the largest one that fits. All you need to do for Preset Sizes create an array in your resources and then set “autoSizePresetSizes” in xml.

<TextView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:autoSizeTextType="uniform"
    app:autoSizePresetSizes="@array/autosize_text_sizes" />

An array of resources.

<array name="autosize_text_sizes">
    <item>12sp</item>
    <item>24sp</item>
    <item>36sp</item>
    <item>48sp</item>
    <item>60sp</item>
    <item>72sp</item>
</array>

You can also set Autosizing using Preset Sizes programmatically.

emojiCompatTextView.setAutoSizeTextTypeUniformWithPresetSizes(resources.getIntArray(R.array.auto_size_array),TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM)

Alright guy’s, that’s my explanation about Autosizing TextView with programmatically and with xml. If you guys have any query about this post please do comment below.

Thank you for being here and keep reading.