Android – How To Work Flow APIs In Kotlin ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn how Flow APIs work in Kotlin and how can we start using it in our android projects.

If we are working as an Android developer and looking to build an app asynchronously we might be using RxJava as it has an operator for almost everything. RxJava has become one of the most important things to know in Android.

But with Kotlin a lot of people tend to use Co-routines. With Kotlin Coroutine 1.2.0 alpha release Jetbrains came up with Flow API as part of it. With Flow in Kotlin now you can handle a stream of data that emits values sequentially.

In Kotlin, Coroutine is just the scheduler part of RxJava but now with Flow APIs coming along side it, it can be alternative to RxJava in Android.”

We will cover the following topics to understanding the Flow API :

  • What is Flow APIs in Kotlin Coroutines?
  • Start Integrating Flow APIs in your project
  • Builders in Flows
  • Few examples using Flow Operators.

A famous quote about learning is :

“Learn as though you would never be able to master it; hold it as though you would be in fear of losing it.”

So Let’s begin.

What is Flow APIs in Kotlin Coroutines?

Flow API in Kotlin is a better way to handle the stream of data asynchronously that executes sequentially.

So, in RxJava, Observables type is an example of a structure that represents a stream of items. Its body does not get executed until it is subscribed to by a subscriber and once it is subscribed, subscriber starts getting the data items emitted. Similarly, Flow works on the same condition where the code inside a flow builder does not run until the flow is collected.

Start Integrating Flow APIs in your Project

Let us create an android project and then let’s start integrating the Kotlin Flow APIs.

Step 01

Add the following in the app’s build.gradle,

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"

and in the project’s build.gradle add,

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"

Step 02

In MainActivity’s layout file let’s create a UI that will have a button.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="Launch Kotlin Flow"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step 03

Now, let’s begin the implementation of Flow APIs in MainActivity. In onCreate() function of Activity lets add two function like,

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

Here, setupFlow() is the function where we will define the flow and setupClicks() is the function where we will click the button to display the data which is emitted from the flow.

We will declare a lateinit variable of Flow of Int type,

lateinit var flow: Flow<Int>

Step 04

Now, in setupFlow() I will emit items after 500milliseconds delay.

fun setupFlow(){
    flow = flow {
        Log.d(TAG, "Start flow")
        (0..10).forEach {
            // Emit items with 500 milliseconds delay
            delay(500)
            Log.d(TAG, "Emitting $it")
            emit(it)

        }
    }.flowOn(Dispatchers.Default)
}

Here,

  • We will emit numbers from 0 to 10 at 500ms delay.
  • To emit the number we will use emit() which collects the value emittedIt is part of FlowCollector which can be used as a receiver.
  • and, at last, we use flowOn operator which means that shall be used to change the context of the flow emission. Here, we can use different Dispatchers like IO, Default, etc.

flowOn() is like subscribeOn() in RxJava.”

Step 05

Now, we need to write setupClicks() function where we need to print the values which we will emit from the flow.

private fun setupClicks() {
    button.setOnClickListener {
        CoroutineScope(Dispatchers.Main).launch {
            flow.collect {
                Log.d(TAG, it.toString())
            }
        }
    }
}

When we click the button we will print the values one by one.

Here,

flow.collect now will start extracting/collection the value from the flow on the Main thread as Dispatchers.Main is used in launch coroutine builder in CoroutineScope. The output which will be printed in Logcat is,

D/MainActivity: Start flow
D/MainActivity: Emitting 0
D/MainActivity: 0
D/MainActivity: Emitting 1
D/MainActivity: 1
D/MainActivity: Emitting 2
D/MainActivity: 2
D/MainActivity: Emitting 3
D/MainActivity: 3
D/MainActivity: Emitting 4
D/MainActivity: 4
D/MainActivity: Emitting 5
D/MainActivity: 5
D/MainActivity: Emitting 6
D/MainActivity: 6
D/MainActivity: Emitting 7
D/MainActivity: 7
D/MainActivity: Emitting 8
D/MainActivity: 8
D/MainActivity: Emitting 9
D/MainActivity: 9
D/MainActivity: Emitting 10
D/MainActivity: 10

As we can see Flow starts only when the button is clicked as it prints Start Flow and then starts emitting. This is what we meant by Flows are cold.

Let’s say we update the setupFlow() function like,

private fun setupFlow() {
    flow = flow {
        Log.d(TAG, "Start flow")
        (0..10).forEach {
            // Emit items with 500 milliseconds delay
            delay(500)
            Log.d(TAG, "Emitting $it")
            emit(it)
        }
    }.map {
        it * it
    }.flowOn(Dispatchers.Default)
}

Here we can see that we added map operator which will take each and every item will square itself and print the value.

Anything, written above flowOn will run in background thread.

Builders in Flow

Flow builders are nothing but the way to build Flows. There are 4 types of flow builders:

  1. flowOf() – It is used to create flow from a given set of values. For Example:
flowOf(4, 2, 5, 1, 7).onEach { delay(400) }.flowOn(Dispatcher.Default)

Here, flowOf() takes fixed values and prints each of them after a delay of 400ms. When we attach a collector to the flow, we get the output:

D/MainActivity: 4
D/MainActivity: 2
D/MainActivity: 5
D/MainActivity: 1
D/MainActivity: 7

2. asFlow() – It is an extension function that helps to convert type into flows. For Example:

(1..5).asFlow().onEach{ delay(300)}.flowOn(Dispatchers.Default)

Here, we converted a range of values from 1 to 5 as flow and emitted each of them at a delay of 300ms. When we attach a collector to the flow, we get the output,

D/MainActivity: 1
D/MainActivity: 2
D/MainActivity: 3
D/MainActivity: 4
D/MainActivity: 5

The output is the number being printed from 1 to 5, whichever were present in the range.

3. flow{} – This example has been explained in the Android Example above. This is a builder function to construct arbitrary flows.

4. channelFlow{} – This builder creates cold-flow with the elements using send provided by the builder itself. For Example,

channelFlow {
    (0..10).forEach {
        send(it)
    }
}.flowOn(Dispatchers.Default)

This will print,

D/MainActivity: 0
D/MainActivity: 1
D/MainActivity: 2
D/MainActivity: 3
D/MainActivity: 4
D/MainActivity: 5
D/MainActivity: 6
D/MainActivity: 7
D/MainActivity: 8
D/MainActivity: 9
D/MainActivity: 10

Now, finally, let’s discuss how to use an operator of Flow in our project.

Few examples using Flow Operators

Zip Operator

In above Android Example, we have two functions setupFlow() and setupClicks(). We will modify both functions in MainActivity.

First, we will declare two lateinit variables of Flow of String type,

lateinit var flowOne: Flow<String>
lateinit var flowTwo: Flow<String>

Now, the two functions setupFlow() and setupClicks() will be called in onCreate() of MainActivity.

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    setupFlow()
    setupClicks()

}

and in the setupFlow(), we will initialize two flows to the two variables,

private fun setupFlow() {
    flowOne = flowOf("1", "2", "3").flowOn(Dispatchers.Default)
    flowTwo = flowOf("4", "5", "6").flowOn(Dispatchers.Default)

}

and in setupClicks(), we will zip both the flows using zip operator,

private fun setupClicks() {
    button.setOnClickListener {
        CoroutineScope(Dispatchers.Main).launch {
            flowOne.zip(flowTwo)
            { firstString, secondString ->
                "$firstString $secondString"
            }.collect {
                Log.d(TAG, it)
            }
        }
    }
}

Here,

  • when the button is clicked the scope is launched.
  • flowOne is zipped with flowTwo to give a pair of values that we have created a string and,
  • then we collect it and print it in Logcat. The resulting output will be,

D/MainActivity: 14
D/MainActivity: 25
D/MainActivity: 36

If both flows doesn’t have the same number of item, then the flow will stop as soon as one of the flow completes.

That’s all about in this article.

Conclusion

In this article, we learned about how Flow APIs work in Kotlin and how can we start using it in our android projects. We have also discussed builders in flow and zip operators.

Thanks for reading ! I hope you enjoyed and learned about Flow API concepts in Kotlin. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Android – How To Optimize APK Size ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn how to optimize application size (APK) in Android. Most of the user would not like to download a large APK as it might consume most of his Network/Wifi Bandwidth, also most importantly, space inside the mobile device. The size of our APK has an impact on how fast our app loads, how much memory it uses, and how much power it consumes.

It’s important to optimize the size of the app since mobiles are always memory and space constraint devices. We will discuss about the various ways in which we can improve our apk size in Android-Development.

A famous quote about learning is :

” That is what learning is. You suddenly understand something you’ve understood all your life, but in a new way.”

So Let’s begin.

Understanding Android App Bundles

An Android App Bundle is a publishing format that includes all your app’s compiled code and resources, and defers APK generation and signing to Google Play.

Google Play uses our app bundle to generate and serve optimized APKs for each device configuration, so only the code and resources that are needed for a specific device are downloaded to run our app. We no longer have to build, sign, and manage multiple APKs to optimize support for different devices, and users get smaller, more optimized downloads.

App Bundles are Publishing formats

An Android App Bundle is a file (with the .aab file extension) that we upload to Google Play. App bundles are signed binaries that organize your app’s code and resources into modules. Code and resources for each module are organized similarly to what you would find in an APK—and that makes sense because each of these modules may be generated as separate APKs. Google Play then uses the app bundle to generate the various APKs that are served to users, such as the base APK, feature APKs, configuration APKs, and (for devices that do not support split APKs) multi-APKs. The directories that are colored in blue—such as the drawable/values/, and lib/ directories—represent code and resources that Google Play uses to create configuration APKs for each module.

Android App Bundles — File Targeting and Serving

  • How do these Android App bundles help in File targeting? It’s simple, let’s say we have hdpi, xhdpi, xxhdpi resources in our application. Based on the device on which the application is being downloaded, if it’s a hdpi device (for example), only the resources from hdpi will be installed on the device.
  • If the application is targeting multiple languages (English, Spanish, French, etc.), only the specific string resources will be downloaded onto the device.
  • This helps in saving the space on the device’s memory.

Building the Android App Bundle

Building the Android app bundle is straight forward. Just select the Build option from the Android Studio menu and select Build Bundles.

Android Size Analyzer

In order to understand which files are actually taking up more space in the application, use the Android Size Analyser plugin inside Android Studio. For installing the plugin.

  1. Select File > Settings (or on Mac, Android Studio > Preferences.)
  2. Select the Plugins section in the left panel.
  3. Click the Marketplace tab.
  4. Search for the “Android Size Analyzer” plugin.
  5. Click the Install button for the analyzer plugin.

Restart the IDE after installing the plugin. Now, to analyze the application, go to Analyze > Analyze App Size from the menu bar. We will get a window something similar to this:

The recommendations can help us in reducing the app size in a much better way.

Remove Unused Resources

As we have already discussed the size of the apk has an impact on how fast the app loads, how much memory it uses, and how much memory power it consumes. Hence, one of the main things that can be implemented to reduce apk size is to remove unused resources in the application.

Also, it is advised to use scalable drawable objects(importing vector assets) instead of other image formats like PNG, JPEG, etc.

Using Vector Drawable is one of the best ways to reduce the size significantly.

Using Lint

Lint actually helps in generating warnings or unused code inside the application. So this can actually help in removing the same thereby helping in reducing the size of the application.

Reduce libraries size

Check if we can reduce the size when it comes to the usage of libraries. For example, use only specific libraries of Google Play Services. Compile only which is required.

Reuse Code

Object-Oriented Programming has solved a lot of problems in the programming world. Try reusing the code as much as possible instead of repetitive code. Repetitive code also leads to increased file size thereby effecting the Apk size.

Compress PNG and JPEG files

If using PNG and JPEG files is something mandatory in our project, we can compress them using image quality tools like TinyPNG.

In most of the applications, Images are used to convey messages or improve the UX. But the biggest drawback here might be using a lot of images that can bloat up the size of the app. Ensure that the Image Compression techniques are understood and implemented to reduce the size of the apk before releasing the app to the play store.

Use WebP file format

As we have seen in the image shared for the Android Analyser plugin above, one of the recommendations was to change the PNG file to a WebP file format.

Use Proguard

Every time we build a new project, we see the following piece of code in the app-level build.gradle file.

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

ProGuard makes the following impact on our project,

  • It reduces the size of the application.
  • It removes the unused classes and methods that contribute to the 64K method counts limit of an Android application.
  • It makes the application difficult to reverse engineer by obfuscating the code.

Create Multiple APKs

If we are not using App Bundles, we can go with the traditional way. We can create multiple APKs similar to App Bundle. Multiple apk is mainly used to generate specific APKs for different screen densities and different CPU architecture.

ShrinkResources

Reduce resources where ever possible. Using shrinkResources attribute in the Gradle will remove all the resources which are not being used anywhere in the project. Enable this in your app-level build.gradle file by adding below line:

buildTypes {
    release {
        ........
        shrinkResources true
        ........
    }
}

ResConfigs

Remove the localized resources which are not needed by using resConfigs. All the support libraries may have localized folders for the other languages which we don’t need.

The Gradle resource shrinker removes only resources that are not referenced by our app code, which means it will not remove alternative resources(device/location-specific) for different device configurations. If necessary, you can use the Android Gradle plugin’s resConfigs property to remove alternative resource files that our app does not need.

The following snippet shows how to limit our language resources to just English and French:

android {
    defaultConfig {
        ...
        resConfigs "en", "fr"
    }
}

As discussed, having unused language resources only swells the apk size. Hence it is important to remove unused files and resources.

DebugImplementation

Remove any debug library you have in the app. It can be done by using debugImplementation while building testing debug apk.

Use R8 to reduce APK size

R8 shrinking is a process in which we reduce the amount of code of our application and by doing so, the APK size automatically gets reduced. R8 does most of the work as Proguard. 

So Why do we need to prefer it?

The reason is it works with Proguard rules and shrinks the code faster while improving the output size.

So understanding and implementing these different methods in our applications to deliver an optimized apk. 

That’s all about in this article.

Conclusion

In this article, we learned about different methods to optimize app size in Android.

Thanks for reading ! I hope you enjoyed and learned about Reducing application size in Android. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Android – How To Communicate Between Fragments Using SharedViewModel ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will learn how we can use the ViewModel in our application to communicate between various fragments in our application. We say it as SharedViewModel. Communication between Activities or Fragments in Android is a very common thing. Almost every application has some communication between various activities or fragments.

Using SharedViewModel, we can communicate between fragments.

A famous quote about learning is :

“Live as if you were to die tomorrow. Learn as if you were to live forever.”

So Let’s begin.

Data sharing between Fragments

we can communicate between fragments using SharedViewModel. If we consider two fragments, both the fragments can access the ViewModel through their activity.

In this example, one fragment updates the data within the ViewModel which is shared between both the fragments and another fragment observes the changes on that data. We need to add the dependencies required for ViewModel, LiveData in the example.

First, we will create a class SharedViewModel.

class SharedViewModel : ViewModel() {
    val message = MutableLiveData<String>()

    fun sendMessage(text: String) {
        message.value = text
    }
}

Now, we are going to create two Fragments:

  • MessageReceiverFragment: This Fragment is going to receive the message which will be sent by MessageSenderFragment. It will have a TextView which will show the received message.
  • MessageSenderFragment: This Fragment is going to send the message which will be received by MessageReceiverFragment. It will have a Button to send the message.

MessageReceiverFragment class:

class MessageReceiverFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_receiver, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val model = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
        model.message.observe(viewLifecycleOwner, Observer {
            textViewReceiver.text = it
        })
    }
}

fragment_receiver layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/textViewReceiver"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Your Message"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MessageSenderFragment class:

class MessageSenderFragment : Fragment() {
    lateinit var model: SharedViewModel

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_sender, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        model = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
        button.setOnClickListener { model.sendMessage("MindOrks") }
    }
}

fragment_sender layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send Your Message"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Now, let’s update the activity_main.xml.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/receiverFragment"
        android:name="com.mindorks.sharedviewmodelsample.MessageReceiverFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toTopOf="@+id/senderFragment"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <fragment
        android:id="@+id/senderFragment"
        android:name="com.mindorks.sharedviewmodelsample.MessageSenderFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/receiverFragment" />


</androidx.constraintlayout.widget.ConstraintLayout>

Our MainActivity Class:

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

Now, we are ready to run the app, see if it is working as expected. It should work.

Let’s discuss how it is working:

  • Here, we have created an activity that consists of two fragments. The same activity is the host for both the fragment.
  • In both the fragment, we have created the object of SharedViewModel which is the same object as we are using the same single activity as an owner. This is the reason it is shared. Notice that we have used the requireActivity().
  • In the MessageSenderFragment, we are sending the message on button click, which sets the value of message - LiveData in the SharedViewModel.
  • Then, in the MessageReceiverFragment, we are observing the change in the message - LiveData, and whenever the message is coming, we are updating the data in textView.

This is how it works.

That’s all about in this article.

Conclusion

In this article, we learned about Shared ViewModel in Android to communicate with other fragments. In the last, we saw one example of fragment communication using Shared ViewModel

Thanks for reading ! I hope you enjoyed and learned about Shared ViewModel in Android to communicate with other fragments. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !! ???

Android – Understanding Dex and Multidex

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about Dex and Multidex in Android. Most of developers get 64K method limit exceeded error while building APK. This error comes due to DEX. So, in this article, we will try to gain more knowledge about Dex and Multidex in Android.

In Java, if we compile our code then that code is converted into a .class file by the compiler because our machine understands that .class file. The same is the process for the Android Application. In Android, the compiler converts our source code into DEX(Dalvik Executable) file.

So understanding the Dex and Multidex Concepts, We will cover the below topics:

  • Android Build System
  • Multidex in Android
  • Enabling Multidex support in Project
  • Limitations of Multidex support library

A famous quote about Learning is :

” The beautiful thing about learning is that nobody can take it away from you.”


So Let’s Start.


Android Build System

Before moving on to DEX, let’s revise some concepts of the build system of Android. Android compiles the resources and source code of our app and packages them into APKs. Conversion of our project into an APK requires many tools and involves many processes. You can understand the build process with the help of the below diagram:

The build process of a typical Android App can be summarized as below:

  1. The compilers convert the source code into DEX (Dalvik Executable) files, which include the bytecode that runs on Android devices.
  2. After having the DEX files, the APK Packager combines the DEX files and compiled resources into a single APK.
  3. After that, the APK Packager signs the APK.
  4. Before generating the final APK, various methods are followed to optimize the code so as to avoid the unused code.


Multidex in Android

In Android, the compilers convert your source code into DEX files. This DEX file contains the compiled code used to run the app. But there is a limitation with the DEX file. The DEX file limits the total number of methods that can be referenced within a single DEX file to 64K i.e. 65,536 methods. So, you can’t use more than 64K methods in a particular DEX file. These 64K methods include Android framework methods, library methods, and methods in our code also. This limit of 64K is referred to as the “64K reference limit“.

So, if our app exceeds 65,536 methods, we will encounter a build error that indicates our app has reached the limit of the Android build architecture. The error is as follows:

Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

Older versions of the build system report a different error, which also indicates the same problem:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

Both the above error are known as 64K reference limit i.e we are trying to use more than 64K methods in our code. So, here comes the role of Multidex support in our Android Project. Next time if we want to use more than 64K methods in our project then we can use the Multidex to achieve this.

If we are getting some type of DEX error then before configuring our app for multidex to enable the use of 64K or more reference methods, we should try to reduce the total number of reference methods that are being used by our app. Try the following strategies to avoid using 64K reference methods:

  1. Manage dependencies: While importing some dependencies for our project, sometimes we import each and every library and use only a few of them. So, instead of keeping all those dependencies, we can keep only the required one.
  2. Remove unused code: Enable code shrinking in your project. By doing so, we are not shipping unused code with our APK.


Enabling Multidex support in Project

Here, we will see how to enable multidex for following:

  • API level lower than 21: That is if your minSdkVersion is set to lower than 21.
  • API level 21 and higher.

We follow only one of the following based on the minSdkVersion.

  • Multidex support for API level lower than 21
  • Multidex support for API level 21 and higher


Multidex support for API level lower than 21

For executing app code, versions of Android lower than Android 5.0 (API level 21) use the Dalvik runtime, and the limitation of using Dalvik is that you can’t use more than one classes.dex bytecode file per APK. To overcome this limitation, you will have to add the Multidex support library.

To add the multidex support library to our project for API level lower than 21, add the following dependency in our build.gradle file.

dependencies {
    implementation 'androidx:multidex:{latest-version}'
}

If we aren’t using AndroidX, add the following support library dependency instead:

dependencies {
  implementation 'com.android.support:multidex:{latest-version}'
}

By adding this library, our app can manage the access of additional DEX files. In other words, if we are having more than 64K methods, then we will be having more than one DEX file and these DEX files will be managed by using this multidex support library.

Then, modify the module-level build.gradle file to enable multidex using multiDexEnabled true.

android {
    defaultConfig {
 ...
        minSdkVersion 15 
        targetSdkVersion 28
        multiDexEnabled true
 }
 ...
}

dependencies {
 implementation 'androidx:multidex:{latest-version}'
}

Then, depending on whether we override the Application class, perform one of the following:

1. If we do not override the Application class, edit our manifest file to set android:name in the <application> tag as follows:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example">
    <application
            android:name="android.support.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

2. If you do override the Application class, change it to extend MultiDexApplication (if possible) as follows:

public class MyApplication extends MultiDexApplication { ... }

3. Or if we do override the Application class but it’s not possible to change the base class, then we can instead override the attachBaseContext() method and call MultiDex.install(this) to enable multidex:

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
}


Multidex support for API level 21 and higher

Our task becomes easier if we are making an app for Android version 5.0 (API level 21) or higher. API level 21 uses a runtime called ART which supports loading multiple DEX files from APK files. So, we do NOT need to add the support library for multidex in Android 5.0 or higher.

Now, for API level 21 or higher, we need to set multiDexEnabled to true in our module-level build.gradle file, as shown here:

android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 28
        multiDexEnabled true
    }
    ...
}

Then, depending on whether we override the Application class, perform one of the following:

1. If we do not override the Application class, edit our manifest file to set android:name in the <application> tag as follows:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example">
    <application
            android:name="android.support.multidex.MultiDexApplication" >
        ...
    </application>
</manifest>

2. If we do override the Application class, change it to extend MultiDexApplication (if possible) as follows:

public class MyApplication extends MultiDexApplication { ... }

3. Or if we do override the Application class but it’s not possible to change the base class, then we can instead override the attachBaseContext() method and call MultiDex.install(this) to enable multidex:

public class MyApplication extends SomeOtherApplication {
  @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
}

So, now when we build our app, one primary DEX file will be constructed, and supporting DEX files will also be added to it. The primary DEX file is normally marked as classes.dex and other supporting DEX files as classes1.dex, classes2.dex, … and so on.


Limitations of Multidex support library

A good Android Developer know about the benefits of using some library but a professional developer also knows the limitations of using that library.

The multidex support library has some known limitations that we should be aware of before using it in our app. Some of the limitations are:

  • If our secondary DEX file is larger than the primary DEX file, then we may encounter some Application Not Responding (ANR) error. In this case, we should apply code shrinking to minimize the size of DEX files and remove unused portions of code.
  • If we are targeting API levels lower than 21, test thoroughly on those versions of the platform, because our app might have issues at startup or when particular groups of classes are loaded.

Code Shrinking can reduce or possibly eliminate these issues.

That’s all about in this article.


Conclusion

In this article, We understood about Dex and Multidex in Android. If we are working on an Android application that includes more than 64K methods , then to avoid the 64K reference limit, we can use Multidex in our application. So, implement Multidex in our project, but before doing so, make sure that our code is totally shrunk because code shrinking will help in reducing or possibly eliminating the Dex error.

Thanks for reading ! I hope you enjoyed and learned about Dex and Multidex concepts in Android. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Android – Extension Functions vs Static Utility Class in Kotlin

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about Extension Functions and Static Utility Class differences in Kotlin. We will talk about when to use extension function and when to use static utility class in the android project using Kotlin.

To understand the extension function and static utility class concepts, We will focus on the below topics :

  • What are Extension function and Util Class?
  • Use Cases
  • Where we use them?
  • Advantages of using Wrapper like Extension or Util Class.

A famous quote about Learning is :

” Change is the end result of all true learning.”


So Let’s Start.


What are Extension function and Util class?

Extension function:

These are like extensive property attached to any class in Kotlin. It provides additional methods to that class without manually inheriting the class.

For example, Let’s say, we have views where we need to play with the visibility of the views. So, we can create extension function for views like,

fun View.show() {
    this.visibility = View.VISIBLE
}

fun View.hide() {
    this.visibility = View.GONE
}

and to use it we use, like,

toolbar.hide()

Here, we have attached an additional feature of hide() and show() to views in android.

Here, these above two extension functions can only be used by View Type and not any other type. For example, String can’t use the functions here.

And to access, that view in the function we use this.

Util Class:

Util class is like a collection of static functions whose code can be reused again and again by passing the reference of the type as a parameter.

For example, if we take the above example of visibility Gone and Visible then update the code according to Util class way,

object Util {
    
    fun show(view: View){
        view.visibility = View.VISIBLE
    }
    fun hide(view: View){
        view.visibility = View.GONE
    }
}

and to use it we use,

Util.show(imageView)

Here, we can see unlike extension function, we need to pass the reference of the view as a parameter.

Or we can directly write the util functions without Util object. For example, we will create a file Util.kt and update the file as,

fun show(view: View){
    view.visibility = View.VISIBLE
}
fun hide(view: View){
    view.visibility = View.GONE
}

and to use this we can directly call,

show(imageView)

We can create Util both ways mentioned above.


Use Cases

Consider this like, when creating an extension function in Kotlin, it creates a property for that specific type(let’s say ImageView) which can be accessed across by all the ImageViews.

But, when Using Util, we don’t add this property again, and again to use the util functions, we need to explicitly call it.

So, now let’s understand this with an example.

Consider we have an ImageView, where we want to load image from url. We might consider using Glide or Picasso for this. So, here I will use Glide and create an extension function like

fun ImageView.loadImage(url: String) {
    Glide.with(this.context).load(url).into(this)
}

Here, we can see, we created an extension function called loadImage() which takes url as a parameter and we load the url into the ImageView.

Now, to use this we just use,

imageViewProfile.loadImage("url")

This loadImage property is accessed by the imageViewProfile and here the extension function is helping the ImageView to load the image from url.

Now, think this as this won’t be just accessible for imageViewProfile but for all the ImageViews in the app but will only be accesible by ImageViews. loadImage() has become like property to ImageViews now. All the ImageViews can access it but just using the dot operator.

Now, Consider the same example using Util class. Here we need to pass both them imageView and the url to load the image.

fun loadImage(imgView:ImageView,url:String){
    Glide.with(this.context).load(url).into(imgView)
}

and to use this we have to call 

Util.loadImage()

Now, here it is not associated with imageView. We are passing the ImageView as a parameter to this function along with the url to load the url in the image view.


When to use Extension function or Util function?

Let’s say if we have a multiple occurrence of the same action across the app like loading image from url in ImageView in multiple ImageViews across the app, we should prefer using extension function as it is like the major use-case here and so it gets attached to the imageView as a property.

But, when we don’t want to use the property heavily and its a very rare occurrence in the app like once or twice we should use util functions.


Advantages of using Wrapper like Extension or Util Class

In any case, using either extension functions or util class helps us a lot while developing the android app. It helps us,

  • to make the code reusable.
  • to make the code more readable.
  • to migrate to another library very easily.

Let’s say in the above example,

fun ImageView.loadImage(url: String) {
    Glide.with(this.context).load(url).into(this)
}

Here, the loading of image using glide is written once and can be used multiple times.

Using the loadImage() as the name makes our code readable as when we use it like,

imageViewProfile.loadImage("url")

the name itself makes it more clear that we are trying to load a url to the ImageView.

And at last, the biggest advantage of using a wrapper helps us in migration to another library if required. For example, let’s say someday we need to remove the Glide library and replace the code with Picasso to load images.

Then we need to only update the code only once in either extension function or the util class and the library would be replaced successfully. We would not have to change or tweak any code in view files.

That’s all about in this article.


Conclusion

In this article, We understood about Extension Functions and Static Utility Class Usage in Kotlin. Depending upon the use-case we should decide which way to use to make our code reusable.

Thanks for reading ! I hope you enjoyed and learned about Extension Functions and Static Utility Class Concepts in Kotlin. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

A Short Note – How Redux Works?

Hello Readers, CoolMonkTechie heartily welcomes you in A Short Note Series (How Redux Works?).

In this note series, we will understand about the Redux work flow concepts in ReactJS.

So Let’s begin.

Redux

Redux is just one variation of a whole trend in UI architecture called : Unidirectional User Interface Architecture.

For example, there is Flux (Redux is just a variation of Flux), Cycle.js, MobX, and Elm has its own implementation of that architecture.

As stated from the Redux motivation, Redux tries to make: “state mutation predictable”, and it tries to achieve that by the following:

  • Have one single source of truth (from the state)
  • States are read only and immutable.
  • Changes are made with pure functions.

Redux Work Flow

There is a wonderful diagram that describes the flow in Redux.

(we use This diagram as an educational and information purpose).

This is the data flow:

  1. Models/states in the application should reside in a container called “Store”. Even we can have many stores in an application, but Redux differs from others (like Flux) by leaning toward one store.
  2. Communication to the store should happen through one gate, which is a function called “dispatch”.
  3. Anything wants to modify the state should dispatch “Actions” which are a simple JavaScript objects that describe what we want to modify and the new data.
  4. The Store receives the actions and pass it to “Reducers” which are pure functions that modify the store’s state and produce a new state.
  5. Store’s state is immutable, and any modification will generate always a new state.
  6. The Store will notify any subscribers about new changes.
  7. UI render itself, using pure functions, taking the store’s state as input parameter.
  8. Asynchronous network calls will modify the store through actions as everything else.

Why Redux is better ?

Redux solves many problems:

  • Because we use pure functions everywhere, so always the output is deterministic, and we have deterministic UI.
  • Time Travelling: Because we change the state through actions which are pure JavaScript objects, which means we can at any moment re-create the state from scratch if we keep a log of those actions, so time-travelling will be a breath.
  • Logging actions, we can know who modify the state, and when exactly.
  • Collaborative programs like (google docs) can be achieved easily by sending Actions on the wire and recreate them there.
  • Easy debugging, by logging all actions on production we can re-create the whole situation.
  • Deterministic UI, because UI rendering using pure function, and the same input will always generate the same output.
  • Unit test is so easy, because we are testing pure functions for UI and state mutation.

Conclusion

In this note series, we understood about the Redux Work Flow Concepts in ReactJS. We discussed that how Redux works and why it is better.

Thanks for reading! I hope you enjoyed and learned about Redux Work Flow Concepts in ReactJS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe to the blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow official website and tutorials of React as below links :

If you have any comments, questions, or think I missed something, leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – 3 Best Quick Ways To Handle Multithreading In iOS

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about three best available options to handle multithreading in iOS. Production applications will often need to perform heavier operations such as downloading high-resolution images or a executing non-cached database queries. To prevent stalling the main thread (and a hit in frame rate), Apple has provided a few tools to help us. We will discuss below available options to handle multithreading:

  • Grand Central Dispatch
  • NSOperation and NSOperationQueue
  • performSelectorInBackground

A famous quote about Learning is :

” I am always ready to learn although I do not always like being taught. “


So Let’s begin.


1. Grand Central Dispatch

Grand Central Dispatch is a technology that abstracts away the low-level details of multithreading. When using GCD, we only have to think about the tasks we want to perform. These tasks can then be added to serial or concurrent queues. Moreover, we can add tasks to groups and run code after all tasks within the group complete.

Let’s walk through an example where we download an image from a remote URL and then use it to populate a UIImageView.

// Assume we have an `imageView` property on self
private func loadWallpaper() {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { [weak self] in
        guard
            let wallpaperURL = NSURL(string: "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-157301.jpg"),
            let imageData = NSData(contentsOfURL: wallpaperURL)
        else {
            return
        }

        dispatch_async(dispatch_get_main_queue()) {
            self?.imageView.image = UIImage(data: imageData)
        }
    }
}

Most uses of GCD start with a call to dispatch_async, which takes in a queue to use and the block to execute. In our example, we’d like to execute the wallpaper download on a background queue, so we make use of the system-defined global queue with a background quality of service (QoS), DISPATCH_QUEUE_PRIORITY_BACKGROUND. The flag passed into dispatch_get_global_queue should always be 0.

Now we have the block of work to execute. We construct a NSURL via its fail-able String initializer and then fetch the data associated with that resource via NSData(contentsOfURL:). If the above step completes successfully (else we just return from the block), we now have our data at hand.

To update imageView‘s image property, we need to make sure we return to the main thread via dispatch_async(dispatch_get_main_queue()) { /* ... */ }Remember in iOS, all UI updates should be performed on the main thread. Inside the main thread block, we set the image using the NSData initializer on UIImage.

Now that we’ve seen a one-off block example, let’s dive into how we can accomplish groups of dependent tasks. Imagine we wanted to download multiple wallpapers and present an alert to the user when all of the images finish loading. Dispatch groups will be our best friends in these scenarios.

First, let’s refactor the loadWallpaper function from the previous example to accept a dispatch_group_t and a target URL.

private func loadWallpaper(group: dispatch_group_t, url: String) {
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { [weak self] in
        defer {
            dispatch_group_leave(group)
        }

        guard
            let wallpaperURL = NSURL(string: url),
            let imageData = NSData(contentsOfURL: wallpaperURL)
        else {
            // In production scenarios, we would want error handing here
            return
        }

        // Use imageData in some manner, e.g. persisting to a cache, present in view hierarchy, etc.
        print("Image downloaded \(url)")
    }
}

The function has been modified slightly to accept a parameter group of type dispatch_group_t (we’ll go into how to create these groups in the next snippet) and a target URL. Additionally, our previous call to dispatch_async has been replaced with dispatch_group_async, signalling that the block should be associated with group. Lastly, after completing our work with the resulting imageData we must notify group that the block is complete via dispatch_group_leave.

To use loadWallpaper(_:url:) a call site could look like so:

private func fetchAllWallpapers() {
        let urls = [
            "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-329991.jpg",
            "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-329805.jpg",
            "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-330201.jpg"
        ]

        let wallpaperGroup = dispatch_group_create()

        urls.forEach {
            dispatch_group_enter(wallpaperGroup)
            loadWallpaper(wallpaperGroup, url: $0)
        }

        dispatch_group_notify(wallpaperGroup, dispatch_get_main_queue()) { [weak self] in
            let alertController = UIAlertController(title: "Done!", message: "All images have downloaded", preferredStyle: .Alert)
            alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))

            self?.presentViewController(alertController, animated: true, completion: nil)
        }
    }

We start by creating a dispatch group, wallpaperGroup, using dispatch_group_create(). With the group in hand, we loop over all of the wallpaper URLs, first signalling to the group that we are about to start an operation by making a call to dispatch_group_enter(wallpaperGroup) (each group entry call must pair with a group leave call). We then proceed to call loadWallpaper(_:url:).

To run code after completion of the group, we specify a block in a dispatch_group_notify call. In our case, we’ll simply present a UIAlertController letting the user know that all of the downloads have finished.

While GCD can be extremely powerful, it can be a bit cumbersome to work with in practice. To help with this, we can use Swifty GCD wrapper .

protocol ExcutableQueue {
    var queue: dispatch_queue_t { get }
}

extension ExcutableQueue {
    func execute(closure: () -> Void) {
        dispatch_async(queue, closure)
    }
}

enum Queue: ExcutableQueue {
    case Main
    case UserInteractive
    case UserInitiated
    case Utility
    case Background

    var queue: dispatch_queue_t {
        switch self {
        case .Main:
            return dispatch_get_main_queue()
        case .UserInteractive:
            return dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)
        case .UserInitiated:
            return dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
        case .Utility:
            return dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
        case .Background:
            return dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)
        }
    }
}

enum SerialQueue: String, ExcutableQueue {
    case DownLoadImage = "myApp.SerialQueue.DownLoadImage"
    case UpLoadFile = "myApp.SerialQueue.UpLoadFile"

    var queue: dispatch_queue_t {
        return dispatch_queue_create(rawValue, DISPATCH_QUEUE_SERIAL)
    }
}

Using this wrapper, our example above could be rewritten as:

Queue.Background.execute {
    guard
        let url = NSURL(string: "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-157301.jpg"),
        let data = NSData(contentsOfURL: url)
    else {
        return
    }

    Queue.Main.execute { [weak self] in
        self?.imageView.image = UIImage(data: data)
    }
}


2. NSOperation and  NSOperationQueue

NSOperations and NSOperationQueues provide you with a higher-level API, when compared to GCD. They were first introduced in iOS 4 and are actually implemented with GCD under the hood. Typically, we’ll want to use this API over GCD, unless you’re performing a simple unit of work on a specific queue. NSOperations provide us with powerful functionality such as cancellation and dependencies.

To start, we’ll port the wallpaper downloading example to use an NSBlockOperationNSBlockOperation is a simple wrapper on a block of work that can be added to a queue.

private func loadWallpaper(queue: NSOperationQueue, url: String) {
    guard let wallpaperURL = NSURL(string: url) else { return }

    let downloadOperation = NSBlockOperation {
        guard let imageData = NSData(contentsOfURL: wallpaperURL) else { return }

        NSOperationQueue.mainQueue().addOperationWithBlock { [weak self] in
            self?.imageView.image = UIImage(data: imageData)
        }
    }

    queue.addOperation(downloadOperation)
}

The initializer for NSBlockOperation simply takes a block to run. In our case, we’ll download the data from wallpaperURL and return to the main queue to set the image property on imageView. After initializing downloadOperation, we add it to queue.

When creating an NSOperationQueue, we have a few points of customization.

let queue = NSOperationQueue()
queue.maxConcurrentOperationCount = 1

// If you want to hold the queue, use the `suspended` property
queue.suspended = true

The maxConcurrentOperationCount property allows us to set a limit on how many operations may run concurrently in a given queue. Setting this to 1, implies our queue will be serial (queing order may not be preserved, as operations only run when their ready flag is set to true). If this property isn’t set, it defaults to NSOperationQueueDefaultMaxConcurrentOperationCount, which is dictated by system conditions.

By default, all operations that are ready (ready property is true) are run when added to a queue. We can halt all execution on a queue by setting the suspended property to true.

NSOperations become really powerful when we separate them out into operation subclasses. To demonstrate this, let’s make a wallpaper resizing operation. We’ll need to subclass a custom wrapper of NSOperation that has the proper KVO notifications in place.

class ResizeImageOperation: Operation {

    enum Error {
        case FileReadError
        case ResizeError
        case WriteError
    }

    let targetSize: CGSize
    let path: NSURL
    var error: Error?

    init(size: CGSize, path: NSURL) {
        self.targetSize = size
        self.path = path
    }

    override func execute() {
        // Need to signal KVO notifications for operation completion
        defer {
            finish()
        }

        guard let sourceImage = UIImage(contentsOfFile: path.absoluteString) else {
            error = Error.FileReadError
            return
        }

        let finalWidth: CGFloat, finalHeight: CGFloat
        let ratio = sourceImage.size.width / sourceImage.size.height

        // Scale aspect fit the image
        if sourceImage.size.width >= sourceImage.size.height {
            finalWidth = targetSize.width
            finalHeight = finalWidth / ratio
        } else {
            finalHeight = targetSize.height
            finalWidth = finalHeight * ratio
        }

        let imageSize = CGSize(width: finalWidth, height: finalHeight)
        UIGraphicsBeginImageContextWithOptions(imageSize, true, 0.0)
        defer { UIGraphicsEndImageContext() }

        let rect = CGRect(origin: .zero, size: imageSize)
        sourceImage.drawInRect(rect)

        guard
            let resizedImage = UIGraphicsGetImageFromCurrentImageContext(),
            let imageData = UIImageJPEGRepresentation(resizedImage, 1.0)
        else {
            error = Error.ResizeError
            return
        }

        guard imageData.writeToFile(path.absoluteString, atomically: true) else {
            error = Error.WriteError
            return
        }
    }
}
  • To help with error handling, we add a nested Error enum with a few cases.
  • ResizeImageOperation can be initialized with a target size and path to write,
  • The meat of the operation is placed in the execute method (overridden from Operation). We need to make sure to defer a call to finish(), so that the Operation superclass can signal the proper KVO notifications.
  • We then proceed with the resizing the image (scale aspect fit) and saving it to disk.

Now that we have a resizing operation in hand, let’s refactor our download operation a bit to work with it:

private func downloadWallpaper(url: NSURL, path: NSURL) -> NSOperation {
    return NSBlockOperation {
        guard
            let imageData = NSData(contentsOfURL: url),
            let image = UIImage(data: imageData)
        else { return }

        UIImageJPEGRepresentation(image, 1.0)?.writeToFile(path.absoluteString, atomically: true)
    }
}

We now return an NSOperation and have the operation write the image data to disk. Lastly, to make the download and resize operations dependent, we can use them like so:

// Assume self has `imageView` and `wallpaperQueue` properties

if
    let cacheDirectory = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true).first,
    let cacheDirectoryURL = NSURL(string: cacheDirectory)
{

    let targetURL = cacheDirectoryURL.URLByAppendingPathComponent("wallpaper.jpg")
    let downloadOperation = downloadWallpaper(NSURL(string: "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-329991.jpg")!, path: targetURL)

    let resizeOperation = ResizeImageOperation(size: CGSize(width: imageView.bounds.size.width * 2, height: imageView.bounds.size.height * 2), path: targetURL)
    resizeOperation.addDependency(downloadOperation)

    resizeOperation.completionBlock = { [weak self, weak resizeOperation] in
        if let error = resizeOperation?.error {
            print(error)
            return
        }

        guard
            let path = resizeOperation?.path,
            let imageData = NSData(contentsOfFile: path.absoluteString)
        else {
            return
        }

        NSOperationQueue.mainQueue().addOperationWithBlock {
            self?.imageView.image = UIImage(data: imageData)
        }
    }

    wallpaperQueue.suspended = true
    wallpaperQueue.addOperation(downloadOperation)
    wallpaperQueue.addOperation(resizeOperation)
    wallpaperQueue.suspended = false
}
  • The key line to notice is resizeOperation.addDependency(downloadOperation). That’s how we express the resizing operation’s dependency on downloadOperation.
  • Moreover, in the completion block of resizeOperation, we check for errors and proceed with displaying the resized image.
  • Note: we make sure to suspend the queue first, then add the operations. This prevents the operations from beginning immediately upon addition.


3. PerformSelectorInBackground

To wrap up, let’s show a simple example of performSelectorInBackground. Assuming self has a method sleepAndPrint(_:), we can make the following call:

performSelectorInBackground("sleepAndPrint:", withObject: "supsup")

If our target selector had no argument, the selector would simply be "sleepAndPrint").

func sleepAndPrint(message: String) {
    NSThread.sleepForTimeInterval(1)
    print(message)
}

That’s all about in this article.


Conclusion

In this article, We understood about three best available options to handle multithreading in iOS. We’ve discussed about GCD, NSoperations, and NSObject‘s performSelectorInBackground method as means of performing work in a multithreaded fashion. If we have small units of work to perform, we’ll want to reach for GCD or performSelectorInBackground. On the other hand, if we have larger operations that may have dependencies, NSOperation should be our tool of choice.

Thanks for reading ! I hope you enjoyed and learned about three best available options to handle multithreading in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Android – Understanding Property Delegation In Kotlin

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about Property Delegation concepts in Kotlin. The Kotlin programming language has native support for class properties. Properties are usually backed directly by corresponding fields, but it does not always need to be like this – as long as they are correctly exposed to the outside world, they still can be considered properties. This can be achieved by handling this in getters and setters, or by leveraging the power of Delegates.

We will discuss the below topics to understand the Property Delegation Concepts in Kotlin:

  • What is Property Delegation?
  • What are Default Delegated Properties in Kotlin?
  • How to create a custom Delegation Property?
  • How to use Kotlin Delegation Property with Android Development?

A famous quote about Learning is :

” The beautiful thing about learning is that nobody can take it away from you.”


So Let’s begin.


What is Property Delegation?

A “Delegate” is just a class that provides the value of a property and handles its changes. This will help us to delegate(assign or pass on)the getter-setter logic altogether to a different class so that it can help us in reusing the code.

Simply put, delegated properties are not backed by a class field and delegate getting and setting to another piece of code. This allows for delegated functionality to be abstracted out and shared between multiple similar properties – e.g. storing property values in a map instead of separate fields.

Delegated properties are used by declaring the property and the delegate that it uses. The by keyword indicates that the property is controlled by the provided delegate instead of its own field.

This is an alternative to inheritance property.


What are Default Delegated Properties in Kotlin?

Kotlin contains some inbuilt examples for Delegated Properties such as:

  • lazy properties: the value gets computed only upon first access;
  • observable properties: listeners get notified about changes to this property;
  • storing properties in a map, instead of a separate field for each property.


How to create a custom Delegation Property?

For the case of simplicity, let’s take a very simple use-case. Let’s consider a scenario where we want a String property that always gets trimmed and has a common appended string after the original value.

The general way we would do this is:

var string: String = ""
    set(value) {
        field = "${value.trim()} is a String!"
    }
fun main() {
    string = "checking.....        "
    println(string)
}

//output: checking..... is a String!

We can see that the extra spaces are trimmed and the required string is appended.

Well, this is good for one variable. What if we have a bunch of string variables containing the same functionality?

We have to keep adding this setter property repeatedly:

var stringOne: String = ""
    set(value) {
        field = "${value.trim()} is a String!"
    }
var stringTwo: String = ""
    set(value) {
        field = "${value.trim()} is a String!"
    }
var stringThree: String = ""
    set(value) {
        field = "${value.trim()} is a String!"
    }
.
.
.
.

This meets our requirement but we see a lot of repetitive code. So, how can we resolve this?

Yes, We can resolve by Property Delegation!

Here, we shall “delegate” the property of trimming and appending the common string to a separate class so that we can reuse this wherever required.

There will be times that we want to write our delegates, rather than using ones that already exist. This relies on writing a class that extends one of two interfaces – ReadOnlyProperty or ReadWriteProperty.

Both of these interfaces define a method called getValue – which is used to supply the current value of the delegated property when it is read. This takes two arguments and returns the value of the property:

  • thisRef – a reference to the class that the property is in
  • property – a reflection description of the property being delegated

The ReadWriteProperty interface additionally defines a method called setValue that is used to update the current value of the property when it is written. This takes three arguments and has no return value:

  • thisRef – A reference to the class that the property is in
  • property – A reflection description of the property being delegated
  • value – The new value of the property

Let’s understand by String Trimming Example below as step by step .

  • Let’s create a custom class, let’s name it TrimAppendDelegate
  • To use this class as a Delegate, we have to implement the ReadWriteProperty<> interface
  • Once we implement the interface, we have to implement the abstract members in the interface which are getValue and setValue
  • Finally, we define a private variable of String type(since we are defining a custom Delegate for our String property) inside our Delegate class and define the getValue and setValue properties.
class TrimAppendDelegate : ReadWriteProperty<Any, String> {
    private var trimAppendedString = ""
    override fun getValue(thisRef: Any, property: KProperty<*>) =   trimAppendedString

override fun setValue(thisRef: Any, property: KProperty<*>, value: String) {
        trimAppendedString = "${value.trim()} is a String!"
    }
}
}

//Usage :

private var trimmedString by TrimAppendDelegate()
trimmedString = "This..      "
println(trimmedString)

//Output : This.. is a String!

This is how we can achieve the property of Delegation.


How to use Kotlin Delegation Property with Android Development?


Using Built-in delegated property Lazy:

Most of the time, we see the usage of lateinit var in our UI(Activities/Fragments) classes or View Models. We can use the concept of the lazy delegate in place of lateinit var. The variable will be initialized the first time it is used.


Using Built-in delegated property Observable:

  • Most of our Android applications use Recycler views. We know that every recycler view is associated with its respective adapter. Every time the data structure (list of objects) changes in the adapter, we call notifyDataSetChanged to update our Recycler view.
  • We can use the inbuilt delegated property “Observable” to get the old and changed values of the data structure(list of objects)
private var users: ArrayList<User> by Delegates.observable(arrayListOf()) { property, oldValue, newValue ->
    Log.d("Old value ${property.name} size", "${oldValue.size}")
    Log.d("New value ${property.name} size", "${newValue.size}")
    notifyDataSetChanged()
}

In the above code snippet, we can consider User as one of the model classes, and “users” is a list of User objects. We can access the old and new values whenever the value for “user” changes. Finally, we can call notifyDataSetChanged, if there is a change in oldValue and newValue by comparison.

To access the advantage of this Observable delegated property, the parameter should be a “var” instead of “val”. Else the changes cannot be identified, because, val, in Kotlin, is read-only.


Using Built-in delegated property Observable along with Lazy:

We can also use this “Observable” property along with “lazy” for updating our views. This can be very helpful if we are not using the concept of LiveData in our application.

Let’s understand the code snippet :

class MainActivity : AppCompatActivity() {
    
    private val textView: TextView by lazy { textview }
    private var text: String by Delegates.observable("") { _, _, newValue ->
        textView.text = newValue
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        text = "NewText"
    }
    
}

In the above code snippet, We have initiated textView with a lazy delegate just for our safety so that there will be no null pointer exception while accessing it. Whenever there is a change in the “text” variable, the text view is updated with the new value. This is similar to the concept of Live Data.


Using Built-in delegated property Lazy along with Custom Delegate:

Let’s say we want to save a boolean shared preference in our MainActivity.kt file (Any activity class file). Let’s create a custom delegate to store a Boolean shared preference value:

//Delegating the boolean preference saving option
class BooleanPreference(
    private val preferences: Lazy<SharedPreferences>,
    private val name: String,
    private val defaultValue: Boolean
) : ReadWriteProperty<Any, Boolean> {
    
    @WorkerThread
    override fun getValue(thisRef: Any, property: KProperty<*>): Boolean {
        return preferences.value.getBoolean(name, defaultValue)
    }
    override fun setValue(thisRef: Any, property: KProperty<*>, value: Boolean) {
        preferences.value.edit().putBoolean(name, value).apply()
    }
    
}

We can see that our custom delegate class takes three parameters, the preferences instance, the name(Key in this case), and the default value.

So, let’s create our shared preferences global instance in our Activity file.

private val prefs: Lazy<SharedPreferences> = lazy { // Lazy to prevent IO access to main thread.
    this.applicationContext.getSharedPreferences(
        PREFS_NAME, MODE_PRIVATE
    )
}
companion object {
    const val PREFS_NAME = "Preferences"
    const val TOGGLE_PREFS = "toggle"
}

Let’s say we are handling the preference of a toggle here in our Activity class. We can just use our custom delegate as follows:

private var togglePreference by BooleanPreference(prefs, TOGGLE_PREFS, false)

Now, let’s say if we want to change the value in the onCreate method(or any click listener, in general):

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    togglePreference = true
    Toast.makeText(this, "$togglePreference", Toast.LENGTH_SHORT).show()  // Shows true
}

We just use it as a simple variable assignment. Looks clean and concise!

That’s all about in this article.


Conclusion

In this article, We understood about Property Delegation concepts in Kotlin. We have discussed about What is Property Delegation, Default Delegated Properties, create Custom Property Delegation and how to use Property delegation with Android Development. Property delegation is a powerful technique, that allows you to write code that takes over control of other properties, and helps this logic to be easily shared amongst different classes. This allows for robust, reusable logic that looks and feels like regular property access.

Thanks for reading ! I hope you enjoyed and learned about Property Delegation concepts in Kotlin. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – How To Make Our iOS Applications More Secure ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about iOS App Security. Mobile applications are the center of most peoples’ technology usage. They deal with a lot of private and sensitive user data like your personal health information or banking information. Protecting this data as well as possible is heavily important and the topic of this article.

We’ll discuss concrete techniques for making our iOS apps more secure. Our best practices cover means for securely storing data as well as sending & receiving data over the network. We’ll see why it is so hard to get security right and how we can improve our app security by using services from Apple and other providers.

We will focus on three main topics related to iOS App Security:

  • Storing user data safely.
  • Secure data transportation.
  • How to use Apple’s new cryptographic APIs.

A famous quote about Security and Learning is :

” Learning how to live with insecurity is the only security. “


So Let’s begin.

Chances are that our app handles private data that we don’t want to end up in the wrong hands. Therefore, we need to make sure to store this data safely and make data transportation as secure as possible.


Best Practices for Storing User Data

If we are developing iOS apps lots of security features are already provided by the OS. All iOS devices with an A7 processor or later also have a coprocessor called the Secure Enclave. It powers iOS security features in a hardware-accelerated way.


Apple’s App Sandbox

All apps running on iOS run in a sandbox to make sure the app can only access data which is stored in the app’s unique home directory. If an app wants to access data outside of its home directory it needs to use services provided by iOS, like the ones available for accessing iCloud data or the photo album. Therefore, no other app can read or modify data from our app.

Apple’s App Sandbox is powered by UNIX’s user permissions and makes sure that apps get executed with a less privileged “mobile” user. Everything outside the app’s home directory is mounted read-only. All system files and resources are protected. The available APIs don’t allow apps to escalate privileges in order to modify other apps or iOS itself.

For performing specific privileged operations an app needs to declare special entitlements. These entitlements get signed together with the app and are not changeable. Examples of services that need special entitlements are HealthKit or audio input. Some entitlements are even restricted to be only used if Apple gives you access to them. This includes services like CarPlay. They are stronger protected because misusing them could have fatal consequences.

Next to entitlements giving us special rights, apps can make use of the iOS extensions system. The OS has many points to be used by app extensions. App extensions are single-purpose executables bundled with the app. They run in their own address space and get controlled by the OS.

Additionally, iOS has methods to prevent memory-related security bugs. Address space layout randomization (ASLR) randomizes the assigned memory regions for each app on every startup. This makes the exploitation of memory-corruption-bugs much less likely. Also, memory pages are marked as non-executable with ARM’s Execute Never (XN) feature to stop malicious code from being executed.


Data Protection API

All iOS versions since iOS 4 have a built-in security feature called Data Protection. It allows an app to encrypt and decrypt the files stored in their app directory. The encryption and decryption processes are automatic and hardware-accelerated. Data Protection is available for file and database APIs, including NSFileManager, CoreData, NSData, and SQLite.

The feature is enabled by default but can be configured on a per-file basis to increase security. Every file can be configured to use one of 4 available protection levels. By default, all files are encrypted until the first user authentication but it might make sense to increase the protection level for certain data.

The four available protection levels include:

  • No protection: The file is always accessible and not encrypted at all
  • Complete until first user authentication: This is enabled by default and decrypts the file after the user unlocks their device for the first time. Afterward, the file stays decrypted until the device gets rebooted. Locking the device doesn’t encrypt the data again.
  • Complete unless open: The file is encrypted until the app opens the file for the first time. The decryption stays alive even when the device gets locked by the user.
  • Complete: The file is only accessible when the device is unlocked.

We can specify the protection level when we create files like this:

try data.write(to: fileURL, options: .completeFileProtection)

But we are also able to change the protection level of existing files by setting the resource values:

try (fileURL as NSURL).setResourceValue( 
                  URLFileProtection.complete,
                  forKey: .fileProtectionKey)

It is important to understand which protection levels fits our needs. By default, we should use the highest protection level possible. However, if we need access to files in the background while the phone is locked we can’t use complete data encryption for them.


Keychain

The keychain is our secure place to store small chunks of data. It is a hardware-accelerated secure data storage that encrypts all of its contents. It is used by the system to store data like passwords and certificates but we as an app developer have also access to this data storage.

Our app or app group has its own space in the keychain and no other app has access to it. This way, we don’t need to store encryption keys in our app and can rely on the system to provide the highest level of security.

The keychain is the secure key-value storage replacement for NSUserDefaults. NSUserDefaults are not encrypted at all and should be avoided for sensitive data.

For every keychain item, we can define specific access policies for accessibility and authentication. We can require user presence (requesting Face ID or Touch ID unlock) or that the biometric ID enrolment didn’t change since the item was added to the keychain.

As an additional feature of the iOS Keychain, we can decide if we want to store the information in the local keychain which is only available on this specific device, or in the iCloud Keychain which gets synchronized across all Apple devices. This gives us the ability to share the information between our iPhone, iPad and Mac counterparts.

Even though the Keychain Services API should be used whenever possible, its interface is not exactly nice to use in Swift. If we plan to use such functionality more often in our codebase consider wrapping it with a nicer Swift API.

let query: [String: Any] = [
    kSecClass as String: kSecClassInternetPassword,
    kSecAttrAccount as String: account,
    kSecAttrServer as String: server,
    kSecValueData as String: password
]

let status = SecItemAdd(query as CFDictionary, nil)

This code snippet stores some credentials to the keychain. A lot of casting is necessary and in the end, we call SecItemAdd which synchronously stores the credentials and returns either a success or error status code.


Best Practices for Secure Data Transportation

Next to storing the user data safely, we should make sure that the communication between our app and its remote counterparts is secured. This prevents attackers from collecting private data by sniffing the network traffic or by running malicious servers.


HTTPs

Most network communication is done over the HTTP protocol between a client and a server. By default, HTTP connections are not encrypted. It is easily possible for attackers to sniff data from our local network or to perform man-in-the-middle attacks.

Since iOS 9, there is a new feature called App Transport Security (ATS). It improves the security of network communication in our apps. ATS blocks insecure connections by default. It requires all HTTP connections to be performed using HTTPS secured with TLS.

ATS can be configured in many ways to loosen up these restrictions. We can, therefore, allow insecure HTTP connections for specific domains or change the minimum TLS version used for HTTPS.

If our app contains an in-app browser we should use the NSAllowsArbitraryLoadsInWebContent configuration which allows our users to browse the web normally and still makes sure that all other network connections in our app use the highest security standards.


SSL Pinning

By default, HTTPS connections are verified by the system: it inspects the server certificate and checks if it’s valid for this domain. This should make sure the connected server is not malicious. However, there are still ways for attackers to perform more complex man-in-middle attacks.

The system certificate trust validation checks if the certificate was signed by a root certificate of a trusted certificate authority. To circumvent this security mechanism attackers would need to explicitly trust another malicious certificate in the user’s device settings or compromise a certificate authority. The attacker could then perform a man-in-the-middle attack to read all messages sent between client and server.

To prevent these kinds of attacks an app can perform additional trust validation of server certificates. This is called SSL or Certificate Pinning. We can implement SSL Pinning by including a list of valid certificates (or its public keys or its hashes) in our app bundle. The app can, therefore, check if the certificate used by the server is on this list and only then communicate with the server.

Implementing this validation from scratch should be avoided since implementation mistakes are very likely and lead to even more security vulnerabilities. We can recommend using an Open Source framework like TrustKit.

Introducing SSL Pinning, unfortunately, introduces the risk of bricking our app. Since we hardcode the trusted certificates, the app itself needs to be updated if a server certificate expires. To avoid such a situation, pin the future certificates in the client app before releasing new server certificates.


Push Notifications

To send push notifications to our users, we need to use Apple’s APNS services. If we want to use end-to-end encryption or if we just don’t want to give Apple the (theoretical) chance to read your messages you can use UNNotificationServiceExtension extensions to modify the messages on the client-side.

This allows us to send either encrypted messages to our clients or use placeholders for sensitive data. The messages will simply be used as a wakeup call for the app. The app can then decrypt the message or respectively for placeholder messages fetch the necessary information from the local device and replace the placeholders with the sensitive data. The clear text message will then be shown on the user’s lock screen without any sensitive information being sent to Apple’s servers.

In the following example, we can see how easily we can change our message content in our notification service extension.

class NotificationService: UNNotificationServiceExtension {

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
            fatalError("Cannot convert notification content to mutable content")
        }

        mutableContent.title = decryptText(mutableContent.title)
        mutableContent.body = decryptText(mutableContent.body)

        contentHandler(mutableContent)
    }

    // ...

}


End-to-end encryption

End-to-end encryption is the “holy grail” for secure data transportation. It allows us to encrypt messages in a way that only the sender and receiver can decrypt them and neither Apple or our servers can read the cleartext data.

End-to-end encryption is not easy to implement and requires a lot of experience in cryptographic processes. If our team doesn’t have the experience it is very advisable to consult a third party expert helping with the implementation of the encryption mechanism.


CloudKit

If our app doesn’t need a server , we can use Apple’s CloudKit. CloudKit allows us to store data in iCloud containers while using our Apple ID as the login mechanism for our app. This way, we don’t need to implement all of these services on our own.

CloudKit was made with security in mind. As an app developer, we don’t have access to concrete user data and the communication is encrypted by default.

All the communication between our app and the server can be done using Apple’s client-side CloudKit framework. If we have an additional Android or Web app, we can still use CloudKit using its JavaScript and Web services.

To make this even better: CloudKit is completely free of charge to a certain amount. We can reach millions of users without fearing costs for traffic, data storage or requests.


Best Practices of Using Apple’s cryptographic APIs

The iOS SDK includes APIs to handle common cryptographic tasks for us. As we said above it is generally a good idea to rely on proven crypto implementations and not reimplement them ourself.


Apples CryptoKit

Apples CryptoKit is a new API that was introduced in iOS 13 and provides lower-level APIs to perform cryptographic operations or implement security protocols.

CryptoKit is based on top of more lower-level APIs. They were available before but introduced additional risk factors since developers often used them in a wrong way.

CryptoKit also allows us to use the SecureEnclave to get cryptographically safe functions that are performant and optimized for the device’s hardware.

If we want to support older iOS versions, we can use those lower-level APIs or use well known open-source third-party libraries like CryptoSwift.


Hashing data

Hash functions are functions that convert data of arbitrary size to fixed-size values. Good hash functions should minimize duplication of output values (so-called collisions) and be very fast to compute. Swift includes hashing functionality in the Swift Standard Library, but these functions are heavily focused on being fast and have a relative high collision rate. This makes them a good fit for performance-critical operations, but not so much for security related operations.

Securely hashing data is simple using CryptoKit. We just need to call the hash function on one of our Structs and choose a hash algorithm. CryptoKit supports the most common ones from SHA512 to SHA256.

let data = ...
let dataDigest = SHA512.hash(data: data)
let hashString = dataDigest.description


Authenticating Data using Message authentication codes

A message authentication code (MAC) is used to authenticate the sender of a message and confirm the integrity of that message. It allows the receiver to verify the origins of messages and detect changes to the message’s content.

To use this kind of integrity checks we can, for example, use CryptoSwift’s hashed authentication codes, also known as HMACs. The HMAC struct is a generic type that can be used with all the hash functions included in CryptoSwift.

To create a message authentication code , we can use this simple code snippet.

let key = SymmetricKey(size: .bits256)

let authenticationCode = HMAC<SHA256>.authenticationCode(for: messageData, using: key)

We can verify the message by using:

let isValid = HMAC<SHA256>.isValidAuthenticationCode(
    Data(authenticationCode),
    authenticating: messageData,
    using: key
)

As we can see, we need to create a symmetric key first and securely share it between the sender and receiver.


Encrypting Data using symmetric keys

Encrypting and decrypting data using a symmetric key is simple, too. We can use one of two available ciphers: ChaChaPoly (ChaCha20-Poly1305) or AES-GCM in CryptoSwift:

let encryptedData = try! ChaChaPoly.seal(data, using: key).combined

let sealedBox = try! ChaChaPoly.SealedBox(combined: encryptedData)

let decryptedData = try! ChaChaPoly.open(sealedBox, using: key)

We should always make sure not to hardcode these symmetric keys in our app though. We can generate a symmetric key at runtime and then store it safely in the keychain. That way, no one has access to our key to decrypt data.


Performing Key Agreement

In a lot of cases, we will need to perform some form of key exchange to exchange cryptographic keys over an insecure channel. With key agreement protocols like Elliptic-curve Diffie–Hellman (ECDH), we can derive a common secret.

1. Create private/public key-pairs for Alice and Bob

let alicePrivateKey = P256.KeyAgreement.PrivateKey()
let alicePublicKey = alicePrivateKey.publicKey
let bobPrivateKey = P256.KeyAgreement.PrivateKey()
let bobPublicKey = bobPrivateKey.publicKey

Both Alice and Bob create their own private/public key-pairs and share their public keys.

2. Deriving shared secret

let aliceSharedSecret = try! alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPublicKey)

let bobSharedSecret = try! bobPrivateKey.sharedSecretFromKeyAgreement(with: alicePublicKey)

We were now able to derive a common secret by using the own private key together with the counterpart’s public key. aliceSharedSecret and bobSharedSecret are now the same.

3. The created secret number should not be used as an encryption key by itself. Instead it can be used to generate a much larger and more secure encryption key using HKDF or X9.63 key derivation.

let usedSalt = "Secure iOS App".data(using: .utf8)!

let symmetricKey = aliceSharedSecret.hkdfDerivedSymmetricKey(
    using: SHA256.self,
    salt: protocolSalt,
    sharedInfo: Data(),
    outputByteCount: 32
)

That’s generally how you could implement it! Also note that Apple has an implementation of Diffie-Hellman in iOS as part of Secure Transport.


Creating and Verifying Signatures

If we want to send messages and make sure that the sender is the person we thought it is we can use signatures. To do so, we need a private/public key pair first.

let signingKey = Curve25519.Signing.PrivateKey()
let signingPublicKey = signingKey.publicKey

Using the private key any form of data can be signed.

let data = ...
let signature = try! signingKey.signature(for: data)

This signature is then sent together with the actual data to the receiver which can use the public key to validate the signature.

let isSignatureValid = signingPublicKey.isValidSignature(signature, for: data)

That’s all about in this article.


Conclusion

In this article, We understood about Apple’s iOS security Best Practices. Creating secure and robust iOS applications is not easy. However, we can improve security in our iOS apps without much effort by sticking to best practices. Protecting user data must be a high priority and should never be ignored.

Thanks for reading ! I hope you enjoyed and learned about Apple’s iOS security Best Practices. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

ReactJS – How to Effectively Think In React Hooks ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, we will understand about the rules of React Hooks and how to effectively start using them in our projects. We will discuss the two most important rules of React Hooks and how to effectively think in Hooks.

” React Hooks are a new addition in React 16.8 that let you use state and other React features without writing a class component. In other words, Hooks are functions that let you “hook into” React state and lifecycle features from function components. (They do not work inside class components.)”

A famous quote about learning is :

” The more I live, the more I learn. The more I learn, the more I realize, the less I know. “

So Let’s begin.


What is React Hook?

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. It mainly uses to handle the state and side effects in react functional component. React Hooks are a way to use stateful functions inside a functional component. Hooks don’t work inside classes — they let you use React without classesReact provides a few built-in Hooks like useState and useEffect. The React hooks do :

  • Best practices
  • Easy to under understand
  • Easy to test
  • Increases the performance and so on.


Why React Hook?

There are two reasons to use React hooks :

  • The first main reason is the Introduce state in a functional component. We know that the states cannot be used in functions. But with hooks, we can use states.
  • Another reason is the handle side effect in react component. It means, now we can use newly introduced state such as useEffect.

But do we should know for some scenarios, there are 3 places where react failsWhile Reuse logic between components :

  • Has Huge components
  • Confusing


Rules Of React Hooks

Hooks are JavaScript functions, but we need to follow two rules when using them :

  1. Call Hooks at the top level;
  2. Only call Hooks from React components.

Let’s look at these rules in more detail :


1. Call Hooks At The Top Level

Don’t call Hooks inside loops, conditions, or nested functions. Always use Hooks at the top level of your React function. By following this rule, we ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.

Let’s make a Form component which will have two states:

  • accountName
  • accountDetail

These states will have default values, we’ll make use of the useEffect hook to persist the state to either the local storage of our browser or to the title of our document.

Now, this component will be maybe to successfully manage its state if it remains the same between multiple calls of useState and useEffect.

function Form() {
  // 1. Use the accountName state variable
  const [accountName, setAccountName] = useState('Arun');

  // 2. Use an effect for persisting the form
  useEffect(function persistForm() {
    localStorage.setItem('formData', accountName);
  });

  // 3. Use the accountDetail state variable
  const [accountDetail, setAccountDetail] = useState('Active');

  // 4. Use an effect for updating the title
  useEffect(function updateStatus() {
    document.title = accountName + ' ' + accountDetail;
  });

  // ...
}

If the order of our Hooks changes (which can be possible when they are called in loops or conditionals), React will have a hard time figuring out how to preserve the state of our component.

// ------------
useState('Arun')           // 1. Initialize the accountName state variable with 'Arun'
useEffect(persistForm)     // 2. Add an effect for persisting the form
useState('Active')        // 3. Initialize the accountdetail state variable with 'Active'
useEffect(updateStatus)     // 4. Add an effect for updating the status

// -------------
// Second render
// -------------
useState('Arun')           // 1. Read the accountName state variable (argument is ignored)
useEffect(persistForm)     // 2. Replace the effect for persisting the form
useState('Active')        // 3. Read the accountDetail state variable (argument is ignored)
useEffect(updateStatus)     // 4. Replace the effect for updating the status

// ...

That’s the order React follows to call our hooks. Since the order remains the same, it will be able to preserve the state of our component. But what happens if we put a Hook call inside a condition?

// We're breaking the first rule by using a Hook in a condition
  if (accountName !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', accountName);
    });
  }

The accountName !== '' condition is true on the first render, so we run this Hook. However, on the next render the user might clear the form, making the condition false. Now that we skip this Hook during rendering, the order of the Hook calls becomes different:

useState('Arun')           // 1. Read the accountName state variable (argument is ignored)
// useEffect(persistForm)  // This Hook was skipped!
useState('Active')        // 2 (but was 3). Fail to read the accountDetails state variable
useEffect(updateStatus)     // 3 (but was 4). Fail to replace the effect

React wouldn’t know what to return for the second useState Hook call. React expected that the second Hook call in this component corresponds to the persistForm effect, just like during the previous render — but it doesn’t anymore. From that point on, every next Hook call after the one we skipped would also shift by one — leading to bugs.

This is why Hooks must be called on the top level of our components. If we want to run an effect conditionally, we can put that condition inside our Hook.


2. Only Call Hooks From React Components

Don’t call Hooks from regular JavaScript functions. Instead, you can call Hooks from React function components. Let’s take look at the difference between JavaScript function and React component below:

JavaScript Function

import { useState } = "react";

function toCelsius(fahrenheit) {
  const [name, setName] = useState("Arun");
  return (5/9) * (fahrenheit-32);
}
document.getElementById("demo").innerHTML = toCelsius;

Here we import the useState hook from the React package, and then declared our function. But this is invalid as it is not a React component.

React Function


import React, { useState} from "react";
import ReactDOM from "react-dom";

function Account(props) {
  const [name, setName] = useState("Arun");
  return <p>Hello, {name}! The price is <b>{props.total}</b> and the total amount is <b>{props.amount}</b></p>
}
ReactDom.render(
  <Account total={20} amount={5000} />,
  document.getElementById('root')
);

Even though the body of both looks similar, the latter becomes a component when we import React into the file. This is what makes it possible for us to use things like JSX and React hooks inside.

If we happened to import our preferred hook without importing React (which makes it a regular function), we will not be able to make use of the Hook we’ve imported as the Hook is accessible only in React component.


Call Hooks From Custom Hooks

A custom Hook is a JavaScript function whose name starts with use and that may call other Hooks. For example, useUserName is used below a custom Hook that calls the useState and useEffect hooks. It fetches data from an API, loops through the data, and calls setIsPresent() if the specific username it received is present in the API data.

export default function useUserName(userName) {
  const [isPresent, setIsPresent] = useState(false);
  
  useEffect(() => {
    const data = MockedApi.fetchData();
    data.then((res) => {
      res.forEach((e) => {
        if (e.name === userName) {
          setIsPresent(true);
        }
     });
    });
  });
    
  return isPresent;
}

We can then go on to reuse the functionality of this hook in other places where we need such in our application. In such places, except when needed, we don’t have to call useState or useEffect anymore.

By following this rule, we ensure that all stateful logic in a component is clearly visible from its source code.


Function Component Vs Class Component In Hooks

Let’s take a brief look at class components and functional components (with Hooks), before diving into the few Hooks best practices.

The simplest way to define a component in React is to write a JavaScript function that returns a React element:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

The Welcome component accepts props which is an object that contains data and returns a React element. We can then import and render this component in another component.

The class component uses a programming methodology called Encapsulation which basically means that everything relevant to the class component will live within it. Life-cycle methods (constructorscomponentDidMount()render, and so on) give components a predictable structure.

Encapsulation is one of the fundamentals of OOP (Object-Oriented Programming). It refers to the bundling of data within the methods that operate on that data, and is used to hide the values or state of a structured data object inside a class — preventing unauthorized parties’ direct access to them.

With Hooks, the composition of a component changes from being a combination of life-cycle Hooks — to functionalities with some render at the end.


Function Component

The example below shows how custom Hooks can be used in a functional component (without showcasing what the body is). However, what it does or can do is not limited. It could be instantiating state variables, consuming contexts, subscribing the component to various side effects — or all of the above if you’re using a custom hook!

function {
  useHook{...};
  useHook{...};
  useHook{...};
  return (
    ...
  );
}


Class Component

class component requires you to extend from React.Component and create a render function which returns a React element. This requires more code but will also give you some benefits.

class {
  constructor(props) {...}
  componentDidMount() {...}
  componentWillUnmount() {...}
  render() {...}
}

There are some benefits you get by using functional components in React:

  1. It will get easier to separate container and presentational components because you need to think more about your component’s state if you don’t have access to setState() in your component.
  2. Functional components are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks.
  3. You end up with less code.
  4. The React team mentioned that there may be a performance boost for functional components in future React versions.

This leads to the first best practice when using React Hooks.


Hooks Best Practices

There are some best practices in writing Hooks the right and effective way as below:

  1. Simplify Your Hooks
  2. Organize And Structure Your Hooks
  3. Use React Hooks Snippets
  4. Put Hooks Rules into Consideration


1. Simplify Your Hooks

Keeping React Hooks simple will give us the power to effectively control and manipulate what goes on in a component throughout its lifetime. Avoid writing custom Hooks as much as possible; we can inline a useState() or useEffect() instead of creating our own hook.

If we find ourself making use of a bunch of custom Hooks that are related in functionality, we can create a custom hook that acts as a wrapper for these. Let’s take a look at two different functional components with hooks below.

Functional Component v1

function {
  useHook(...);
  useHook(...);
  useHook(...);
  return(
    <div>...</div>
  );
}

Functional Component v2

function {
  useCustomHook(...);
    useHook(...);
    useHook(...);
  return(
    <div>...</div>
  );
}

v2 is a better version because it keeps the hook simple and all other useHooks are inline accordingly. This allows us to create functionality that can be reused across different components and also gives us more power to control and manipulate our components effectively. Instead of adopting v1 in which our components are littered with Hooks, we should make use of v2 which will make debugging easy and our code cleaner.


2. Organize And Structure Your Hooks

One of the advantages of React Hooks is the ability to write less code that is easy to read. In some cases, the amount of useEffect() and useState() can still be confusing. When we keep our component organized it will help in readability and keep the flow of our components consistent and predictable. If our custom Hooks are too complicated, we can always break them down to sub-custom Hooks. Extract the logic of our component to custom Hooks to make our code readable.


3. Use React Hooks Snippets

React Hooks Snippets is a Visual Studio Code extension to make React Hooks easier and faster. Currently, five hooks are supported:

  • useState()
  • useEffect()
  • useContext()
  • useCallback()
  • useMemo()

There are two ways (Command and Extension Marketplace) we can add React Hooks snippets to our project:


4. Put Hooks Rules into Consideration

Endeavor to always put the two rules of Hooks we learned earlier into consideration while working with React Hooks.

  • Only call your Hooks at the top level. Don’t call Hooks inside loops, conditions or nested functions.
  • Always call Hooks from React function components or from custom Hooks, don’t call Hooks from regular JavaScript functions.

The ESlint plugin called eslint-plugin-react-hooks enforces these two rules, we can add this plugin to your project if we’d like it as we explain above in rules of hooks section.

Best practices have not been fully resolved because Hooks are still relatively new. So adoption should be taken with precaution one would take in adopting in any early technology. With that in mind, Hooks are the way for the future of React.

That’s all about in this article.


Conclusion

In this article, We understood about the two most important rules of React Hooks and how to effectively think in Hooks. We looked at functional components and some best practices in writing Hooks the right and effective way. As brief as the rules are, it’s important to make them our guiding compass when writing rules. If we are prone to forget it, we can make use of the ESLint plugin to enforce it.

Thanks for reading ! I hope you enjoyed and learned about the Hook Concepts in ReactJS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

Exit mobile version