public static Spannable extendedLinkify(String text,boolean lastDitchGeo){
  Spannable spanText=SpannableString.valueOf(text);
  String defaultPhoneRegion=System.getProperty("user.region","US");
  if (!defaultPhoneRegion.equals("US")) {
    Linkify.addLinks(spanText,Linkify.ALL);
    URLSpan[] spans=spanText.getSpans(0,spanText.length(),URLSpan.class);
    if (spans.length == 1) {
      int linkStart=spanText.getSpanStart(spans[0]);
      int linkEnd=spanText.getSpanEnd(spans[0]);
      if (linkStart <= indexFirstNonWhitespaceChar(spanText) && linkEnd >= indexLastNonWhitespaceChar(spanText) + 1) {
        return spanText;
      }
    }
    spanText=SpannableString.valueOf(text);
    if (lastDitchGeo && !text.isEmpty()) {
      Linkify.addLinks(spanText,mWildcardPattern,"geo:0,0?q=");
    }
    return spanText;
  }
  boolean linkifyFoundLinks=Linkify.addLinks(spanText,Linkify.ALL & ~(Linkify.PHONE_NUMBERS));
  URLSpan[] existingSpans=spanText.getSpans(0,spanText.length(),URLSpan.class);
  Matcher coordMatcher=COORD_PATTERN.matcher(spanText);
  int coordCount=0;
  while (coordMatcher.find()) {
    int start=coordMatcher.start();
    int end=coordMatcher.end();
    if (spanWillOverlap(spanText,existingSpans,start,end)) {
      continue;
    }
    URLSpan span=new URLSpan("geo:0,0?q=" + coordMatcher.group());
    spanText.setSpan(span,start,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    coordCount++;
  }
  existingSpans=spanText.getSpans(0,spanText.length(),URLSpan.class);
  int[] phoneSequences=findNanpPhoneNumbers(text);
  int phoneCount=0;
  for (int match=0; match < phoneSequences.length / 2; match++) {
    int start=phoneSequences[match * 2];
    int end=phoneSequences[match * 2 + 1];
    if (spanWillOverlap(spanText,existingSpans,start,end)) {
      continue;
    }
    StringBuilder dialBuilder=new StringBuilder();
    for (int i=start; i < end; i++) {
      char ch=spanText.charAt(i);
      if (ch == '+' || Character.isDigit(ch)) {
        dialBuilder.append(ch);
      }
    }
    URLSpan span=new URLSpan("tel:" + dialBuilder.toString());
    spanText.setSpan(span,start,end,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    phoneCount++;
  }
  if (lastDitchGeo && !text.isEmpty() && !linkifyFoundLinks&& phoneCount == 0 && coordCount == 0) {
    if (Log.isLoggable(TAG,Log.VERBOSE)) {
      Log.v(TAG,"No linkification matches, using geo default");
    }
    Linkify.addLinks(spanText,mWildcardPattern,"geo:0,0?q=");
  }
  return spanText;
}

public static Spannable extendedLinkify ( String text , boolean lastDitchGeo ) { Spannable spanText = SpannableString . valueOf ( text ) ; String defaultPhoneRegion = System . getProperty ( "user.region" , "US" ) ; if ( ! defaultPhoneRegion . equals ( "US" ) ) { Linkify . addLinks ( spanText , Linkify . ALL ) ; URLSpan [ ] spans = spanText . getSpans ( 0 , spanText . length ( ) , URLSpan . class ) ; if ( spans . length == 1 ) { int linkStart = spanText . getSpanStart ( spans [ 0 ] ) ; int linkEnd = spanText . getSpanEnd ( spans [ 0 ] ) ; if ( linkStart <= indexFirstNonWhitespaceChar ( spanText ) && linkEnd >= indexLastNonWhitespaceChar ( spanText ) + 1 ) { return spanText ; } } spanText = SpannableString . valueOf ( text ) ; if ( lastDitchGeo && ! text . isEmpty ( ) ) { Linkify . addLinks ( spanText , mWildcardPattern , "geo:0,0?q=" ) ; } return spanText ; } boolean linkifyFoundLinks = Linkify . addLinks ( spanText , Linkify . ALL & ~ ( Linkify . PHONE_NUMBERS ) ) ; URLSpan [ ] existingSpans = spanText . getSpans ( 0 , spanText . length ( ) , URLSpan . class ) ; Matcher coordMatcher = COORD_PATTERN . matcher ( spanText ) ; int coordCount = 0 ; while ( coordMatcher . find ( ) ) { int start = coordMatcher . start ( ) ; int end = coordMatcher . end ( ) ; if ( spanWillOverlap ( spanText , existingSpans , start , end ) ) { continue ; } URLSpan span = new URLSpan ( "geo:0,0?q=" + coordMatcher . group ( ) ) ; spanText . setSpan ( span , start , end , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ; coordCount ++ ; } existingSpans = spanText . getSpans ( 0 , spanText . length ( ) , URLSpan . class ) ; int [ ] phoneSequences = findNanpPhoneNumbers ( text ) ; int phoneCount = 0 ; for ( int match = 0 ; match < phoneSequences . length / 2 ; match ++ ) { int start = phoneSequences [ match * 2 ] ; int end = phoneSequences [ match * 2 + 1 ] ; if ( spanWillOverlap ( spanText , existingSpans , start , end ) ) { continue ; } StringBuilder dialBuilder = new StringBuilder ( ) ; for ( int i = start ; i < end ; i ++ ) { char ch = spanText . charAt ( i ) ; if ( ch == '+' || Character . isDigit ( ch ) ) { dialBuilder . append ( ch ) ; } } URLSpan span = new URLSpan ( "tel:" + dialBuilder . toString ( ) ) ; spanText . setSpan ( span , start , end , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ; phoneCount ++ ; } if ( lastDitchGeo && ! text . isEmpty ( ) && ! linkifyFoundLinks && phoneCount == 0 && coordCount == 0 ) { if ( Log . isLoggable ( TAG , Log . VERBOSE ) ) { Log . v ( TAG , "No linkification matches, using geo default" ) ; } Linkify . addLinks ( spanText , mWildcardPattern , "geo:0,0?q=" ) ; } return spanText ; }
replaces stretches of text that look like addresses and phone numbers with clickable links . if lastditchgeo is true , then if no links are found in the textview , the entire string will be converted to a single geo link . any spans that may have previously been in the text will be cleared out . < p > this is really just an enhanced version of linkify . addlinks ( ) .
