Sunday, 15 September 2019

Kotlin Code to break forEach inline loops

In General we are unable to break the forEach inline loops.  Please check the below tries and see the proper way to do so.

1
2
3
4
5
6
7
8
9
 var data = listOf<String>("Dev", "Prd", "Test", "Sbx", "demo")
    data.forEach {
        if (it.equals("Prd")) {
            println("I'm Selected $it")
            return
        }
        println("I'm in the list $it")
    }
    println("Done")

the above code produces the below output, if we use "return" on the line 5 we will be getting the below output, because that will abundantly break and come out of the method.  You can see the "Done" is not printed.

I'm in the list Dev
I'm Selected Prd

Hence to resolve we can try out with the label concept available in kotlin,  Since our programming language says there is no explicit label needed for the inline function. we can directly use it as "return@forEach".  But this will also lead to be failed, this produces the below output.

I'm in the list Dev
I'm Selected Prd
I'm in the list Test
I'm in the list Sbx
I'm in the list demo
Done

The highlighted text are unnecessary to this case.  In the below code snippet run block with label is used to break the loop as soon as we get the expected result and breaks the blocks and proceeds the normal flow function flow.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var data = listOf<String>("Dev", "Prd", "Test", "Sbx", "demo")
    run envBlock@{
        data.forEach {
            if (it.equals("Prd")) {
                println("I'm Selected $it")
                return@envBlock
            }
            println("I'm in the list $it")
        }
    }
    println("Done")

And will get the expected output.


I'm in the list Dev
I'm Selected Prd
Done

Happy Coding :-)

Saturday, 17 August 2019

Kotlin Null Handling


- Kotlin Null Safe
- Here we can’t initialise or assign null value.
- If purposely we need to have null, it provides with Question mark.

val username: String? = null

Here we have 4 types of null handling shots.

1. Safe Call
2. Safe Call with let
3. Elvis Operator
4. Non-Null Assertion Operator.

1. Safe Call: It is represented by "?." and this facilitates to access the methods of the object.  In case the reference object or variable is null it will safely handle that and produce the return value as string as "null"

var username: String? = null
println("Username Length is : ${username?.length}")   // We won't get crash, it just print the value as null
username = "manakular"
println("Username Length is : ${username?.length}")

Output:


Username Length is : null
Username Length is : 9

2. Safe Call with let:  It is also similar to the Safe call, instead of accessing the method this allows you to execute the block of code and implicitly returns the last line of the block based on the code,  here "it" keyword will refer the concern data value.

    var username: String? = "manakularpondy"
    val status: String? = username?.let {
        println("Username is $it")
        if (it.length > 10) "Valid Input" else "Invalid length"
    }
    println(status)

Output:

Username is manakularpondy
Valid Input

In case, if we change the value to null  var username: String? = null  the status value will be also null.  So, in order to handle the failure i.e. null scenario we can take help of run block.


    var username: String? = null
    val status: String? = username?.let {
        println("Username is $it")
        if (it.length > 10) "Valid Input" else "Invalid length"
    }.run {
        "Need Input"
    }
    println(status)

Output:

Need Input

3. Elvis Operator: Hope we most of them aware we don't have ternary operator in kotlin programming, but similar to that we are having this elvis operator.  This will be denoted by ?: as mentioned on the below code snippet the username is initialised as null and once we trying to access the length of the variable we are all aware it going to be a null type.   Hence so we are accessing the username value via Safe call (?), then it sees the value as null our elvis operator helps to executes the or take the values after the ?:  Hence here we can see the length value as  0 even the username value is null.    

var username: String? =null
val length: Int = username?.length ?: 0
println("Length is $length")

Output:

Length is 0

4. Non-Null Assertion Operator: This need to handled very carefully, it is referred by using the double exclamation (!!).   Since you are 100% sure the object is non-null then you can use this else the value is null it will throws the null pointer exception.


var username: String? =null
val length: Int = username!!.length ?: 0
println("Length is $length")

The above code snippet throws the null pointer exception, because username object is null

Saturday, 20 July 2019

Kotlin Code - Get IPV4 & IPV6 Address

The below code helps to get the IPv4 and IPv6 Address using Kotlin.

import java.net.NetworkInterface
import java.util.*

/*
* Author: Rajendhiran E
* Date: 21-Jan-2018
* */

object IPHelper {
    val IPV4Address: String
        get() = getIPAddress(true)

    val IPV6Address: String
        get() = getIPAddress(false)

    /**
     * Get IP address from first non-localhost interface
     * @param userIPV4 true=return ipv4, false=return ipv6
     * @return address or empty string
     */
    private fun getIPAddress(userIPV4: Boolean): String {
        try {
            Collections.list(NetworkInterface.getNetworkInterfaces()).forEach {
                Collections.list(it.inetAddresses).forEach {
                    if (!it.isLoopbackAddress) {
                        val sAddr = it.hostAddress
                        val isIPv4 = sAddr.indexOf(':') < 0
                        if (userIPV4) {
                            if (isIPv4) {
                                return sAddr
                            }
                        } else {
                            if (!isIPv4) {
                                val delim = sAddr.indexOf('%')
                                return if (delim < 0) sAddr.toUpperCase() else sAddr.substring(0, delim).toUpperCase()
                            }
                        }
                    }
                }
            }
        } catch (ignored: Exception) {
        }
        return ""
    }
}


println("IP Address V4 - ${IPHelper.IPV4Address}")
println("IP Address V6 - ${IPHelper.IPV6Address}")


Output  Console
IP Address v4 - 192.168.240.2
IP Address v6 - FE80:0:0:0:4D9:5C92:3433:8A6B

Happy Coding :-)

Saturday, 25 May 2019

Kotlin Lambda Expression & HO Functions - Quick Reference

Lambda Expression: As we know, syntax of Kotlin lambdas is similar to Java Lambdas. A function without name is called anonymous function. For lambda expression we can say that it is anonymous function. A lambda expression is always surrounded by curly braces, argument declarations go inside curly braces and have optional type annotations, the code_body goes after an arrow -> sign. If the inferred return type of the lambda is not Unit, then the last expression inside the lambda body is treated as return value.

Higher-Order Function: In Kotlin, a function which can accept a function as parameter or can return a function is called Higher-Order function. Instead of Integer, String or Array as a parameter to function, we will pass anonymous function or lambdas. Frequently, lambdas are passed as parameter in Kotlin functions for the convenience.

class Operators {
    fun add(a: Int, b: Int) = a + b
    fun inc(a: Int) = a + 1
}

fun calculate(a: Int, b: Int, opr: (Int, Int) -> Int) = opr(a, b)
fun calculate(a: Int, opr: (Int) -> Int) = opr(a)

val addition = { a: Int, b: Int -> Operators().add(a, b) }
fun addition(a: Int, b: Int) = Operators().add(a, b)

val increment = { a: Int -> Operators().inc(a) }
fun increment(a: Int) = Operators().inc(a)

fun main() {
    println("Output: " + calculate(1, 2) { a, b -> Operators().add(a, b) }) // Lambda as param
    println("Output: " + calculate(1, 2, Operators()::add)) // Function as param - reference through its object
    println("Output: " + calculate(1, 2, addition)) // Lambda Expression as param
    println("Output: " + calculate(1, 2, ::addition)) // Function as param
    println("")
    println("Output: " + calculate(1) { a -> Operators().inc(a) }) // Lambda as param
    println("Output: " + calculate(1) { Operators().inc(it) })  //Lambda as param Since it is the only param so, `it` referenced here
    println("Output: " + calculate(1, Operators()::inc)) // Function as param - reference through its object
    println("Output: " + calculate(1, increment)) // Lambda Expression as param
    println("Output: " + calculate(1, ::increment)) // Function as param
}

Output: 3
Output: 3
Output: 3
Output: 3

Output: 2
Output: 2
Output: 2
Output: 2
Output: 2

Happy Coding :-) 

Tuesday, 8 January 2019

View animation Expand and Collapse - Android

This Post helps to animate the android views expand and collapse like Expandable list view.

Find below the code snippet.

ViewAnimationUtils.java







 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class ViewAnimationUtils {

    int animDuration = 600;
 
    public static void expand(final View view) {
        view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        final int targtetHeight = view.getMeasuredHeight();
        view.getLayoutParams().height = 0;
        view.setVisibility(View.VISIBLE);
        Animation animation = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                view.getLayoutParams().height = interpolatedTime == 1
                        ? ViewGroup.LayoutParams.WRAP_CONTENT
                        : (int) (targtetHeight * interpolatedTime);
                view.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };
        animation.setDuration(animDuration);
        view.startAnimation(animation);
    }

    public static void collapse(final View view) {
        final int initialHeight = view.getMeasuredHeight();
        Animation animation = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if (interpolatedTime == 1) {
                    view.setVisibility(View.GONE);
                } else {
                    view.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                    view.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };
        animation.setDuration(animDuration);
        view.startAnimation(animation);
    }
}

Example
TextView description;
Button expand, collapse;
expand.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
  ViewAnimationUtils.expand(description)
 }
});

collapse.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
  ViewAnimationUtils.expand(description)
 }
});

Sunday, 16 December 2018

Http and Https request from Android Pie onwards

Recently I faced a weird situation where my app was working fine in all Android versions except Android Pie.

java.io.IOException: Cleartext HTTP traffic to * not permitted

After lots of debugging I came to know it was because my server was not secure ie it was using HTTP (not HTTPS). Android P uses HTTPS by default. What this means is that if you are using unencrypted HTTP requests in your app, the app will work fine in all versions of Android except Android P.

Let’s consider two situations where your app won’t work properly in Android P. 

1. If your server is on HTTP obviously it won’t work in Android P. 

2. When your server is on HTTPS but it is returning something like an image URL which is HTTP, you won’t be able to load the image in Android P.

From Android 9 Pie now, requests without encryption will never work. The System will expect you to use TLS by default.

The easy way to implement this is to use this attribute to your AndroidManifest.xml where you allow all http for all the requests.

android:usesCleartextTraffic=”true”

We have to add these lines to the application tag like below.

<application android:usesCleartextTraffic="true" />

Cleartext is any transmitted or stored information that is not encrypted or meant to be encrypted.

When an app communicates with servers using a cleartext network traffic, such as HTTP, it could raise a risk of eavesdropping and tampering of content. Third parties can inject unauthorized data or leak information about the users. That is why developers are encouraged to a secure traffic only, such as HTTPS.  Hence the cleartext is inevitable, but we can fix the error at the application end

Going with general fix is not the good solution, We have to fix it on our backend by making the request to support for https, but there is some exceptional cases i.e. If we are allowing http for some domains but not other domains, then we have to do some configurations to make this to work.

We have to create a new file inside our XML folder network_security_config.xml now paste the below code snippet inside the file.

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">abc.com</domain>
	<domain includeSubdomains="true">pqr.com</domain>
    </domain-config>
</network-security-config>

You can add the domain of your choice in place of abc.com / pqr.com

To make this work, we have to define a networkSecurityConfig in the application of our Manifest file tag like this:

<application android:networkSecurityConfig="@xml/network_security_config" />

Thatz It... Happy Coding :-)

Sunday, 23 September 2018

Code Practice: Library Vs Framework

Most of the tyro programmers are every time wants to impress their leads/superiors, also want to show-up their code practices among their teammates, they use few terminologies to explain about their codes, tells they wrote a generic code and some of the dev's tells they have did a code and it is kinda libraries, frameworks and reusable components etc...  but they are not sure about those terminologies.  

In reality, the code which they have written is really a good and consider to be copy and paste into the other projects, and reuse those in other projects, by sure it reduce efforts.  But it is not a library or frameworks. 

Then what is Library and Framework?  Both smells like a same nuts, but it is not right?  It is a nut but the shells were different.


The key difference between a library and a framework is "Inversion of Control". When you call a method from a library, you are in control. But with a framework, the control is inverted: the framework calls you.

Library:
A library is just a collection of class definitions. The reason behind is simply code reuse, i.e. get the code that has already been written by other developers. The classes and methods normally define specific operations in a domain specific area. For example, there are some libraries of mathematics which can let developer just call the function without redo the implementation of how an algorithm works.

Framework:
In framework, all the control flow is already there, and there's a bunch of predefined white spots that you should fill out with your code. A framework is normally more complex. It defines a skeleton where the application defines its own features to fill out the skeleton. In this way, your code will be called by the framework when appropriately. The benefit is that developers do not need to worry about if a design is good or not, but just about implementing domain specific functions.


Courtesy: Programcreek

Tuesday, 3 July 2018

File path too long on windows, keep below 240 characters?



Generally our tyro's might get this kinda of issues because of having a deep || hard folder linking like in a tree hierarchy. For Example: 

D:\user\rajendhiran\personal\training\projects\android_projects\application\........

Code Fix to this issue:
Just do a below code change in your root build directory, since that is where most of the path issues will arise.


1
2
3
4
5
6
allprojects {
    buildDir = "C:/tmp/${rootProject.name}/${project.name}"
    repositories {
       ...
    }
}

Reference Link: http://goo.gl/E6BNoU

Sunday, 18 March 2018

Kotlin: tailrec - Permanent fix for Painful StackOverflowError



Parameters and local variables are allocated on the stack (with reference types the object lives on the heap and a variable references that object). The stack typically lives at the upper end of your address space and as it is used up it heads towards the bottom of the address space (i.e. towards zero).

Your process also has a heap, which lives at the bottom end of your process. As you allocate memory, this heap can grow towards the upper end of your address space. As you can see, there is a potential for the heap to "collide" with the stack (a bit like tectonic plates!!!).

The common cause for a stack overflow is a bad recursive call. Typically, this is caused when your recursive functions doesn't have the correct termination condition, so it ends up calling itself forever. However, with GUI programming, it's possible to generate indirect recursion. For example, your app may be handling paint messages, and, whilst processing them, it may call a function that causes the system to send another paint message. Here you've not explicitly called yourself, but the OS/VM has done it for you.

To deal with them you'll need to examine your code. If you've got functions that call themselves then check that you've got a terminating condition. If you have then check than when calling the function you have at least modified one of the arguments, otherwise there'll be no visible change for the recursively called function and the terminating condition is useless.

If you've got no obvious recursive functions then check to see if you're calling any library functions that indirectly will cause your function to be called (like the implicit case above).

Courtesy: Link1

Example:  This is a demo example which i have used to get the StackOverflowError
Wrote a long run recursive method to sum up-to n numbers.

// Recursive function to find sum of numbers
fun sumOfNumbers(aVal:Int):Int {
    sum+=aVal;
    if (aVal == 0)
        return sum  
    else      
        return sumOfNumbers(aVal-1)
}
print(sumOfNumbers(3)) // 3+2+1=6  - This won't cause StackOverflowError
Output: 6

See, here we have used the smaller number, assume i trying to give a larger number (it may differ based on the system memory), While I'm testing with the below scenario got caught with the StackOverflowError at 1023...1050 (randomly).

print(sumOfNumbers(9000))  // 9000+8999+8998...  - This cause StackOverflowError

Hence, In order to avoid this kind of issue, kotlin provides an option called tailrec, we need to add this keyword before to the recursive method, the rest will taken care by the kotlin internally do the looping kind of approach and facilitates to provide us the solid & valid output with out any crash or error.

// Same Recursive function to find sum of numbers using tailrec 
tailrec fun sumOfNumbers(aVal:Int):Int {
    sum+=aVal;  
    if (aVal == 0)
        return sum  
    else      
        return sumOfNumbers(aVal-1)
}

print(sumOfNumbers(9000))   // The tailrec keyword take care of the app crash or SOF error.
Output: 040504500

Sunday, 28 January 2018

Android Top 10 Important libraries, keep code you with the best practices


Android Top 10 Important libraries which helps us to maintain the good code practices in general.
Gson: Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of. 

Retrofit, OkHTTP, Loopj: Retrofit is a type-safe REST client for Android (or just Java) developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.  OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with call-backs.  Loopj is an Android library for making asynchronous HTTP requests. I like it for its ease of use and simplicity. Created by James Smith, it's also known as "Android Asynchronous HTTP Client", and it's used by companies like Instagram, Pinterest, and many others. It's a good entry point to the world of HTTP libraries, and will help you understand important concepts very easily.

Otto:  Otto is an event bus designed to decouple different parts of your application while still allowing them to communicate efficiently.  Forked from Guava, Otto adds unique functionality to an already refined event bus as well as specializing it to the Android platform.

Realm: Realm is a mobile database and a replacement for SQLite. Although is an OO database it has some differences with other databases. Realm is not using SQLite as its engine. Instead it has own C++ core and aims to provide a mobile-first alternative to SQLite. Realm store data in a universal, table-based format by a C++ core. This is what allows Realm to allow data access from multiple languages as well as a range of ad hoc queries.

Universal Image Loader, Picasso, Glide & Fresco:  These libraries are powerful, flexible and highly customizable instrument for image loading, caching and displaying. It provides a lot of configuration options and good control over the image loading and caching process.

Dagger2, Butterknife: Dagger 2 analyses these dependencies for you and generates code to help wire them together. While there are other Java dependency injection frameworks, many of them suffered limitations in relying on XML, required validating dependency issues at run-time, or incurred performance penalties during start-up. Dagger 2 relies purely on using Java annotation processors and compile-time checks to analyse and verify dependencies. It is one of the most efficient dependency injection frameworks built to date.   Butterknife, Field and method binding for Android views which uses annotation processing to generate boilerplate code for you.

LeakCanary:  The memory leak can be a headache to detect and to resolve, small memory leaks can be hidden and may be seen after a long usage of the application and hunting memory leaks is not a simple task. 

Databinding MVVM: Android offers support to write declarative layouts using data binding. This minimizes the necessary code in your application logic to connect to the user interface elements.

RxJava & RxAndroid: This module adds the minimum classes to RxJava that make writing reactive components in Android applications easy and hassle-free. More specifically, it provides a Scheduler that schedules on the main thread or any given Looper.

MPAndroidChart: Using these libraries, drawing charts on Android could never be simpler. MPAndroidChart library works on Android API 8 and above, but if you are using animations, it works on API 11 and above. Animations is one of the greatest features apart from easy data input, this library could have. Somehow I feel animations give good user experience to an application. Through MPAndroidChart library, we can use more than 25 inbuilt animations, also can define custom animations.

Tuesday, 16 January 2018

Add/Remove View on the Top of Activity or Fragment Android


Add view on to the top of your activity or fragment i.e. in simple to add custom view above the AppCompact/Support Toolbar.

FrameLayout rootLayout = (FrameLayout) findViewById (android.R.id.content);
View v = View.inflate(this, R.layout.overlay_layout, rootLayout);

Then when you want to remove it, below use the below code snippet

FrameLayout rootLayout = (FrameLayout)findViewById(android.R.id.content);
rootLayout.removeViewAt(rootLayout.getChildCount()-1);


Happy Coding :-)

Sunday, 17 December 2017

ExpandableListView - notifyDataSetChanged() - Tricky

In general, we use to call the notifyDataSetChanged() method for updating the list view with our new data sets i.e. objects with either array list or any collections. This data set updations made in course of load more or pull to refresh etc.

While using the listview we can simply update the data-set object and call the notifyDataSetChanged() method from the adapter. It will take care the necessary action of updating the listview.  But this will not been happens in the case of ExpandableListView, hence it requires few thread based handling and again need to set the updated adapter to the ExpandableListView.  Please find below the code snippet for the same.


if (dataList.size() > 0) {
 if (!isShowMore) {
  dataListGlobal = dataList;
  dataListExpandableAdapter = new DataListExpandableAdapter(getActivity(), dataListGlobal);
  expandabaleDataListView.setAdapter(dataListExpandableAdapter);
 } else {
  dataListGlobal.addAll(dataList);
  getActivity().runOnUiThread(new Runnable() {
   public void run() {
    if (dataListExpandableAdapter != null) {
     dataListExpandableAdapter.notifyDataSetChanged();
     expandabaleDataListView.setAdapter(dataListExpandableAdapter);
    }
   }
  });
 }
}

Happy Coding :-)

Sunday, 26 November 2017

Monday, 2 October 2017

Android Resource Layout Sub-folder

Right now, we are probably storing every xml layout file inside the layout/ folder. It is feasible and simple to manage in small projects, but when i'm developing a large and heavy projects/products i.e. more .xml files, we feel difficult in search and finding the files and the things will get messy.

So, is there any way to solve this problem?

Yes, after a long search i found the plugin called "Android File Grouping Plugin" but this not gives me the expected solution, this virtually group the layout files into folder and this can visualized only in the android studio which need to be enabled with the plugin, as like as we have it in the XCode for iOS Projects.

Solution:
Hence after the deep dive into the gradle's ground and found the solution for the same without using any third-party plugins and therefore it also directly reflects on the code and folder hierarchy.

here its go like this, please keenly follow the steps

1. Prepare the folder structure in the below way,  inside the res folder, create your own directory and
inside those folders keep the root folder named as "layout" and then keep on adding your .xml files as to your convenient. For EG: In the below example, i have made the designed the Boarding and Dashboard, under to that created the layout as root directory, then added my .xml files.

res/
  layout/
    boarding/
      layout/
        onboarding_activity.xml
        onboarding_fragment_guest.xml
        onboarding_fragment_user.xml
    dashboard/
      layout/
        dashboard_activity.xml
        dashboard_details.xml

2. The trick is to use gradle’s ability to merge multiple resource folders and set the res/ folder as well as the nested subfolders in the sourceSets block.  The quirk is that you can’t declare a container resource folder before you declare that folder’s child resource folders. Below is the sourceSets block from the build.gradle file. Notice that the subfolders are declared first.

sourceSets {
        main {
            res.srcDirs = [
                    'src/main/res/layout/boarding',
                    'src/main/res/layout/dashboard',
                    'src/main/res/layout',
                    'src/main/res'
            ]
        }
    }

Saturday, 30 September 2017

Android Flags Launch Mode

These flags has been setted programmatically, it can be used depends upon to the situation and it does overrides the behaviour which has defined in the AndroidManifest.xml file.

The following are the list of launch mode flags

FLAG_NEW_TASK
FLAG_CLEAR_TASK
FLAG_SINGLE_TOP
FLAG_CLEAR_TOP



FLAG_NEW_TASK:

Eg 1:
Assume Activity Stack
D
C
B
A

We are starting E from D with flag
Output:
E
-------
D
C
B
A
Note:  A , B , C , D will be in one task and E will be in another task

Eg 2:
Assume Activity Stack
D
C
B
A

We are starting B from D with flag
Output:
B
-------
D
C
B
A
Note:  A , B , C , D will be in one task and and another B will be in another task

FLAG_CLEAR_TASK: It works in conjugation with FLAG_NEW_TASK

Assume Activity Stack
D
C
B
A

We are starting E from D with flag
Output:
E

Note: All other activities will be get destroyed, every time it creates the new instance of the activity. Importantly, even if the activity already exist in the stack, it won't encourage the updating of the same activity with onNewIntent(...)

FLAG_SINGLE_TOP:
This works same as launch mode="singleTop" (Refer this link)

FLAG_CLEAR_TOP: It works similar to the SingleTop Flag, but it has one unique feature of destroying the activities on the top of the stack

Assume Activity Stack
D
C
B
A

We are starting B from D with flag
Output:
B -old instance gets extras data through onNewIntent(Intent intent);
A
Note: All the other activities on top of the B will be destroyed.

Courtesy: Link

Sunday, 20 August 2017

Android RTL Feature

Android provides a feature to make our application bidirectional (LTR & RTL). This feature was introduced in android 4.1 (Jelly Bean) for TextView and EditText elements, allowing apps to display and edit text in both left-to-right (LTR) and right-to-left (RTL).

There was full support for RTL feature in android 4.2 version. It makes the exact mirror image of our existing layout.

Our application will continue to appear as we have set it in default direction. But, with a few simple changes, application will be automatically mirrored when the user switches the system language to a right-to-left script (such as Arabic, Hebrew, or Persian).


Android 4.2 includes the following APIs to help manage View components:
android:layoutDirection — attribute for setting the direction of a component’s layout.
android:textDirection — attribute for setting the direction of a component’s text.
android:textAlignment — attribute for setting the alignment of a component’s text.
getLayoutDirectionFromLocale() — method for getting the Locale-specified direction

Make these changes to support bidirectional feature by android:
  1. Add - android:supportsRtl="true" to the <application>element in manifest file.
  2. Change all of app’s “left/right” layout properties to new “start/end” equivalents.
·        If you are targeting your app to Android 4.2 (the app’s targetSdkVersion or minSdkVersion is 17 or higher), then you should use “start” and “end” instead of “left” and “right”. For example, android:paddingLeft should become android:paddingStart

·        If you want your app to work with versions earlier than Android 4.2 (the app’s targetSdkVersion or minSdkVersion is 16 or less), then you should add “start” and end” in addition to “left” and “right”. For example, you’d use both android:paddingLeft and android:paddingStart

Or

·        If you are using Android studio, then open your project in Android Studio and follow the steps:
                       1. Click on “Refactor” in android studio’s menu bar.
                       2. There will be a pop with options, reach to the end of the menu and click on
“Add RTL Support where possible”.
                       3. Now, you will get a popup. Tick the checkbox accordingly.

Note: If you are not a developer and still want to see the miracle then follow the steps:
  1. In your android phone, tap on “Settings” icon.
  2.   Scroll down the list. You will get “Developer options”, if not then no need to worry follow: Settings > About device > Build number
  3. Once you’ve found the Build number section of the settings, tap on the section 7 times. Now there will be “developer options” before “about phone”
  4.  Now tap on developer options and search for “Force RTL layout direction”.
  5. Tap on it to enable RTL feature.
This RTLUtils class helps us to know given View or Locale is RTL

package com.manakular.rajendhiran.lang;

import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

import android.support.v4.view.ViewCompat;
import android.view.View;

public class RTLUtils
{

    private static final Set<String> RTL;

    static
    {
        Set<String> lang = new HashSet<String>();
        lang.add("ar"); // Arabic
        lang.add("dv"); // Divehi
        lang.add("fa"); // Persian (Farsi)
        lang.add("ha"); // Hausa
        lang.add("he"); // Hebrew
        lang.add("iw"); // Hebrew (old code)
        lang.add("ji"); // Yiddish (old code)
        lang.add("ps"); // Pashto, Pushto
        lang.add("ur"); // Urdu
        lang.add("yi"); // Yiddish
        RTL = Collections.unmodifiableSet(lang);
    }

    public static boolean isRTL(Locale locale)
    {
        if(locale == null)
            return false;

        // Character.getDirectionality(locale.getDisplayName().charAt(0))
        // can lead to NPE (Java 7 bug)
        // https://bugs.openjdk.java.net/browse/JDK-6992272?page=com.atlassian.streams.streams-jira-plugin:activity-stream-issue-tab
        // using hard coded list of locale instead
        return RTL.contains(locale.getLanguage());
    }

    public static boolean isRTL(View view)
    {
        if(view == null)
            return false;

        // config.getLayoutDirection() only available since 4.2
        // -> using ViewCompat instead (from Android support library)
        if (ViewCompat.getLayoutDirection(view) == View.LAYOUT_DIRECTION_RTL)
        {
            return true;
        }
        return false;
    }
}

To Identify RTL in Android:

public static boolean isRTL() {
    return isRTL(Locale.getDefault());
}

public static boolean isRTL(Locale locale) {
    final int directionality = Character.getDirectionality(locale.getDisplayName().charAt(0));
    return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT ||
           directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC;
}

Also, you can takes the Android Lint's help to fix up the RTL.   Please refer and make use of the artifacts or library
Happy Coding :)