How can I autolink #mentions in my adapter itemview? - java

I'm using Linkify to search for strings that come after the #symbol. Why don't they turn into links in my TextView? Do I have to set something else in the XML like android:linksClickable="true"?
feedItemView.messageText.setText(message.getString("messageText"));
Pattern userMatcher = Pattern.compile("\\B#[^:\\s]+");
String userViewURL = ".activity.UserProfileActivity://";
Linkify.addLinks(feedItemView.messageText, userMatcher, userViewURL);

I used the following code:
feedItemView.messageText.setText(yeet.getString(ParseConstants.KEY_NOTIFICATION_TEXT));
Linkify.TransformFilter filter = (match, url) -> match.group();
Pattern mentionPattern = Pattern.compile("#([A-Za-z0-9_-]+)");
String mentionScheme = "http://www.twitter.com/";
Linkify.addLinks(feedItemView.messageText, mentionPattern, mentionScheme, null, filter);
I also made sure to remove android:autoLink="all" from that TextView's XML. This will remove auto link functionality for web links so then you'd want to add this to method that handles displaying that TextView:
Pattern urlPattern = Patterns.WEB_URL;
Linkify.addLinks(tweet, urlPattern, null, null, filter);

Related

Make link inside of string clickable: Java

I am creating a messaging system in Java using android studio.
People can send messages back and forth. But if they send a link, it just shows up as regular text. I want the part that is the link to show up as a clickable link and the rest just text.
I checked all day on this site and others but no seems to do this in the way I'm trying too. Most of the answers I see are people using a TexView to accomplish their goal. I'm using a string. Can someone please help me figure this out ?
private void showMessages(){
DatabaseReference userMessageKeyRef = RootRef.child("Messages").child(messageSenderID).child(messageReceiverID);
userMessageKeyRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot snapshot1 : snapshot.getChildren()) {
Messages messages = new Messages();
String strMessage = snapshot1.child("message").getValue().toString();
String strFrom = snapshot1.child("from").getValue().toString();
String strType = snapshot1.child("type").getValue().toString();
messages.setMessage(strMessage);
messages.setFrom(strFrom);
messages.setType(strType);
messagesList.add(messages);
// Pattern for recognizing a URL, based off RFC 3986
final Pattern urlPattern = Pattern.compile(
"(?:^|[\\W])((ht|f)tp(s?):\\/\\/|www\\.)"
+ "(([\\w\\-]+\\.){1,}?([\\w\\-.~]+\\/?)*"
+ "[\\p{Alnum}.,%_=?&#\\-+()\\[\\]\\*$~#!:/{};']*)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
// separate input by spaces ( URLs don't have spaces )
String [] parts = strMessage.split("\\s+");
// get every part
for( String item : parts ) {
if(urlPattern.matcher(item).matches()) {
//it's a good url
System.out.print(""+ item + " " );
} else {
// it isn't a url
System.out.print(item + " ");
}
}
}
messageAdapter = new MessageAdapter(ChatActivity.this,messagesList);
userMessagesList.setAdapter(messageAdapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
There are two common ways to do this. One, like you have done, is to add html to the string. The second is to use the TextView's auto link mask feature.
Using HTML
Once you have identified URLs in your incoming string and added the appropriate html tags to turn them into links, you just need to use HtmlCompat when you go to actually display it in the TextView. You also need to make sure to call setMovementMethod or you won't be able to click the link. The advantage of using HTML is that you can have the link text be a readable phrase instead of a URL.
String txt = "This is www.google.com";
TextView link = findViewById(R.id.link);
link.setMovementMethod(LinkMovementMethod.getInstance());
link.setText(HtmlCompat.fromHtml(txt,HtmlCompat.FROM_HTML_MODE_LEGACY));
If you choose to go this route, your existing code just needs to be modified a bit to save the HTML string in the messages list passed to the adapter, then add the TextView calls above inside the adapter when you set the text.
String [] parts = strMessage.split("\\s+");
// replace URL parts with html links
for( int i = 0; i < parts.length; ++i ) {
if(urlPattern.matcher(parts[i]).matches()) {
parts[i] = "" + parts[i] + "";
}
}
// re-join parts back into a single string
String htmlMessage = String.join(" ", parts);
// save a list of html strings to pass to your adapter
htmlMessageStrings.add(htmlMessage);
Using Link Mask
This method doesn't require you to edit the string at all. If you use Linkify.ALL it also recognizes things like web links, emails, phone numbers, and physical addresses - not just web links. If you only want it to recognize web links use Linkify.WEB_URLS instead. This requires a lot less code on your part - you no longer have to try to parse the string for links.
String txt = "This is www.google.com"; // no need to modify the string
TextView link = findViewById(R.id.link);
link.setAutoLinkMask(Linkify.ALL); // or Linkify.WEB_URLS
link.setText(txt);
You can also add android:autoLink="all" to the TextView XML definition instead of calling it in-code.
Both methods produce this output

CSS validation with AntiSamy

I have a String, and I want to validate whether it is a valid CSS value or not. In the documentation of AntiSamy, I found that I might be able to use CSSValidator.isValidProperty (http://javadox.com/org.owasp/antisamy/1.4/org/owasp/validator/css/CssValidator) to do so. However, the type of the second param requires LexicalUnit.
Is there another way to validate a String with AnitSamy?
I think what you want is the CssScanner.
/****** pull out style tag from html *****/
Pattern p = Pattern.compile("<style>([\\s\\S]+?)</style>");
Matcher m = p.matcher(validHTML);
// if we find a match, get the group
if (m.find()) {
// get the matching group
codeGroup = m.group(1);
}
/****** block for checking all css for validity *****/
InternalPolicy policy = null;
try {
policy = (InternalPolicy) InternalPolicy.getInstance("antisamy-ebay.xml");
} catch (PolicyException e) {
e.printStackTrace();
}
ResourceBundle messages = ResourceBundle.getBundle("AntiSamy", Locale.getDefault());
CssScanner scanner = new CssScanner(policy, messages);
CleanResults results = scanner.scanStyleSheet(codeGroup, Integer.MAX_VALUE);
validCSS = results.getCleanHTML().toString();
That is the part of the code that worked for me. Let me know if any of this does not work for you, I have variables declared at the top of the code because I am also handling html validation in here too. So some variables are not in this code. But it should point you in the right direction. Also, you need a policy in place, I chose the ebay policy, this guides the whitelist of what the css will allow for the resulting output. I have not used the CssValidator, so I am not sure how they compare, but CssScanner does a great job of giving back clean css.

Android: TextView with url end with -/\n Linkify wrongly

Currently, I have a String like
http://www.example.com/defg-/\nletters
I put this String into a TextView, and make the url clickable by setAutoLinkMask(Linkify.WEB_URLS) and setMovementMethod(LinkMovementMethod.getInstance())
However, the link is recognize wrongly, where only
http://www.example.com/defg   <--missing "-/"
is highlighted but not
http://www.example.com/defg-/  <--I want this
, and results in a wrong url.
What should I do such that the url can be recognized correctly?
The Sample Result (2nd link is wrongly recognized)
Code Implementation
txtNorm = (TextView) findViewById(R.id.txtNorm);
txtNorm.setText("http://www.example.com/defg-/");
txtNorm.setAutoLinkMask(Linkify.WEB_URLS);
txtNorm.setMovementMethod(LinkMovementMethod.getInstance());
txtCustom = (TextView) findViewById(R.id.txtCustom);
txtCustom.setText("http://www.example.com/defg-/\nletters");
txtCustom.setAutoLinkMask(Linkify.WEB_URLS);
txtCustom.setMovementMethod(LinkMovementMethod.getInstance());
i found a way you can try this.. at first you need to know that if you add -/ at the end of url this is not common format of standard Web Url. so i made a custom pattern ..
String urlRegex="[://.a-zA-Z_-]+-/"; // carefully set your pattern.
Pattern pattern = Pattern.compile(urlRegex);
String url1="press http://www.example.com/defg-/\\ or on Android& to search it on google";
text.setText(url1);
Matcher matcher1=Pattern.compile(urlRegex).matcher(url1);
while (matcher1.find()) {
final String tag = matcher1.group(0);
Linkify.addLinks(text, pattern, tag);
}
text.setMovementMethod(LinkMovementMethod.getInstance());

twitter linkify android all #mentions

I want to give a link all twitter #mentions on mytweets app in android. If I click on #mentions I want to open another page about of the #mentions.
This code do not work. Firstly I want to search #mentions in tweet and I give link this #mentions and if I click this #mentions in tweet I want to open another page about of the this #mentions.
TextView bt = (TextView) v.findViewById(R.id.bottomtext);
Pattern atMentionPattern = Pattern.compile("#([A-Za-z0-9_]+)");
String atMentionScheme = "http://twitter.com/";
TransformFilter transformFilter = new TransformFilter() {
public String transformUrl(final Matcher match, String url) {
return match.group(1);
}
};
Linkify.addLinks(bt, Linkify.ALL);
Linkify.addLinks(bt, atMentionPattern, atMentionScheme, null, transformFilter);
try like this
textView.setAutoLinkMask(0);
// Recognize phone numbers and web URLs
Linkify.addLinks(text, Linkify.PHONE_NUMBERS | Linkify.WEB_URLS);
// Recognize all of the default link text patterns
Linkify.addLinks(text, Linkify.ALL);
// Disable all default link detection
Linkify.addLinks(text, 0);
see here is documentation
http://polamreddyn.blogspot.in/2013/01/android-text-links-using-linkify.html

Java : replacing text URL with clickable HTML link

I am trying to do some stuff with replacing String containing some URL to a browser compatible linked URL.
My initial String looks like this :
"hello, i'm some text with an url like http://www.the-url.com/ and I need to have an hypertext link !"
What I want to get is a String looking like :
"hello, i'm some text with an url like http://www.the-url.com/ and I need to have an hypertext link !"
I can catch URL with this code line :
String withUrlString = myString.replaceAll(".*://[^<>[:space:]]+[[:alnum:]/]", "HereWasAnURL");
Maybe the regexp expression needs some correction, but it's working fine, need to test in further time.
So the question is how to keep the expression catched by the regexp and just add a what's needed to create the link : catched string
Thanks in advance for your interest and responses !
Try to use:
myString.replaceAll("(.*://[^<>[:space:]]+[[:alnum:]/])", "HereWasAnURL");
I didn't check your regex.
By using () you can create groups. The $1 indicates the group index.
$1 will replace the url.
I asked a simalir question: my question
Some exemples: Capturing Text in a Group in a regular expression
public static String textToHtmlConvertingURLsToLinks(String text) {
if (text == null) {
return text;
}
String escapedText = HtmlUtils.htmlEscape(text);
return escapedText.replaceAll("(\\A|\\s)((http|https|ftp|mailto):\\S+)(\\s|\\z)",
"$1$2$4");
}
There may be better REGEXs out there, but this does the trick as long as there is white space after the end of the URL or the URL is at the end of the text. This particular implementation also uses org.springframework.web.util.HtmlUtils to escape any other HTML that may have been entered.
For anybody who is searching a more robust solution I can suggest the Twitter Text Libraries.
Replacing the URLs with this library works like this:
new Autolink().autolink(plainText)
Belows code replaces links starting with "http" or "https", links starting just with "www." and finally replaces also email links.
Pattern httpLinkPattern = Pattern.compile("(http[s]?)://(www\\.)?([\\S&&[^.#]]+)(\\.[\\S&&[^#]]+)");
Pattern wwwLinkPattern = Pattern.compile("(?<!http[s]?://)(www\\.+)([\\S&&[^.#]]+)(\\.[\\S&&[^#]]+)");
Pattern mailAddressPattern = Pattern.compile("[\\S&&[^#]]+#([\\S&&[^.#]]+)(\\.[\\S&&[^#]]+)");
String textWithHttpLinksEnabled =
"ajdhkas www.dasda.pl/asdsad?asd=sd www.absda.pl maiandrze#asdsa.pl klajdld http://dsds.pl httpsda http://www.onet.pl https://www.onsdas.plad/dasda";
if (Objects.nonNull(textWithHttpLinksEnabled)) {
Matcher httpLinksMatcher = httpLinkPattern.matcher(textWithHttpLinksEnabled);
textWithHttpLinksEnabled = httpLinksMatcher.replaceAll("$0");
final Matcher wwwLinksMatcher = wwwLinkPattern.matcher(textWithHttpLinksEnabled);
textWithHttpLinksEnabled = wwwLinksMatcher.replaceAll("$0");
final Matcher mailLinksMatcher = mailAddressPattern.matcher(textWithHttpLinksEnabled);
textWithHttpLinksEnabled = mailLinksMatcher.replaceAll("$0");
System.out.println(textWithHttpLinksEnabled);
}
Prints:
ajdhkas www.dasda.pl/asdsad?asd=sd www.absda.pl maiandrze#asdsa.pl klajdld http://dsds.pl httpsda http://www.onet.pl https://www.onsdas.plad/dasda
Assuming your regex works to capture the correct info, you can use backreferences in your substitution. See the Java regexp tutorial.
In that case, you'd do
myString.replaceAll(....., "\1")
In case of multiline text you can use this:
text.replaceAll("(\\s|\\^|\\A)((http|https|ftp|mailto):\\S+)(\\s|\\$|\\z)",
"$1<a href='$2'>$2</a>$4");
And here is full example of my code where I need to show user's posts with urls in it:
private static final Pattern urlPattern = Pattern.compile(
"(\\s|\\^|\\A)((http|https|ftp|mailto):\\S+)(\\s|\\$|\\z)");
String userText = ""; // user content from db
String replacedValue = HtmlUtils.htmlEscape(userText);
replacedValue = urlPattern.matcher(replacedValue).replaceAll("$1$2$4");
replacedValue = StringUtils.replace(replacedValue, "\n", "<br>");
System.out.println(replacedValue);

Categories