Extract hyperlinks and emails from a text and perform actions in Android (Kotlin)

Anant Raman
3 min readNov 4, 2020
Adding hypertext within a text using spannable string

We often come across situations where we need to extract links and emails from a given string. I recently faced a similar situation and handled it using REGEX and Spannable String.

Using Regex, we can identify a string of a given pattern

Let us write the Regex for identifying a hyperlink of a website (www.abc.com or https//:www.abc.com) :

private val urlPattern: Pattern = Pattern.compile(
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
+ "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
+ "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~@!:/{};']*)",
Pattern.CASE_INSENSITIVE or Pattern.MULTILINE or Pattern.DOTALL
)

Now let us define the regex for identifying emails :

private val emailPattern: Pattern = Pattern.compile(
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
"\\@" +
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
"(" +
"\\." +
"[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
")+"
)

Once we are done with defining our regex, let us get started with our functions for extracting hyperlinks and emails from the string and customize it.

//Function to extract hyperlinks from a given stringprivate fun getHyperLinks(s: String): List<Pair<Int, Int>> {
val urlList = mutableListOf<Pair<Int, Int>>()
val urlMatcher = urlPattern.matcher(s)
var matchStart: Int
var matchEnd: Int
while (urlMatcher.find()) {
matchStart = urlMatcher.start(1)
matchEnd = urlMatcher.end()
urlList.add(Pair(matchStart, matchEnd))
val url = s.substring(matchStart, matchEnd)
}
return urlList
}
//Function to extract emails from a given stringprivate fun getEmailLists(s: String): List<Pair<Int, Int>> {
val emailList = mutableListOf<Pair<Int, Int>>()

val emailMatcher = emailPattern.matcher(s)
while (emailMatcher.find()) {
val email = emailMatcher.group()
emailList.add(Pair(emailMatcher.start(), emailMatcher.start() + email.length))
}
return emailList
}
//Function to customise texts which are identifed as a hyperlink or an emailprivate fun customiseText(
spanStr: SpannableString,
start: Int,
end: Int
): SpannableString {
val clickSpan = object : ClickableSpan() {
override fun onClick(widget: View) {
// Write the actions you want to be performed on click of the particular hyperlink or email
}
}
}
spanStr.setSpan(clickSpan, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)//Change the colour of the hyperlink or the email spanStr.setSpan(
ForegroundColorSpan(Color.BLUE),
start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)

return spanStr
}

Now we are done with our functions to extract the list of hyperlinks and emails and customize it. Now let us use the above methods on our string. Let us assume we have string str from which we need to extract our links and emails.

val listOfUrls = getHyperLinks(str)
val listOfEmails = getEmailLists(str)
val spanPoint = SpannableString(str)
var point: SpannableString? = null
for (url in listOfUrls) {
point = customiseText(spanPoint, url.first, url.second)
}
for (email in listOfEmails) {
point = customiseText(spanPoint, email.first, email.second)
}
binding.point.movementMethod = LinkMovementMethod.getInstance()//If our string doesnot contain any hyperlink we will set out textview with original string ortherwise with our new customised string.if (point != null) {
binding.pointTv.text = point
} else {
binding.pointTv.text = str
}

You can further go through these links for detail:

https://medium.com/androiddevelopers/spantastic-text-styling-with-spans-17b0c16b4568
https://medium.com/@jerryhanksokafor/string-manipulation-using-spannablestring-regular-expression-and-custom-textview-part1-24e4bd3eda92

You can connect with me on LinkedIn https://www.linkedin.com/in/anantramanindia/

--

--