Messaging: Handle geo uri scheme

Change-Id: I19f1039d18441cb2bd013577c41e279327f806e6
This commit is contained in:
Michael W
2025-01-01 18:56:09 +01:00
parent 7f639e3652
commit 66d57e98a3
2 changed files with 84 additions and 2 deletions
@@ -28,7 +28,6 @@ import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Gravity;
@@ -67,6 +66,7 @@ import com.android.messaging.util.Assert;
import com.android.messaging.util.AvatarUriUtil;
import com.android.messaging.util.ContentType;
import com.android.messaging.util.ImageUtils;
import com.android.messaging.util.LinkifyHelper;
import com.android.messaging.util.OsUtil;
import com.android.messaging.util.PhoneUtils;
import com.android.messaging.util.UiUtils;
@@ -642,7 +642,7 @@ public class ConversationMessageView extends FrameLayout implements View.OnClick
mMessageTextView.setText(text);
// Linkify phone numbers, web urls, emails, and map addresses to allow users to
// click on them and take the default intent.
mMessageTextHasLinks = Linkify.addLinks(mMessageTextView, Linkify.ALL);
mMessageTextHasLinks = LinkifyHelper.addLinks(mMessageTextView);
mMessageTextView.setVisibility(View.VISIBLE);
} else {
mMessageTextView.setVisibility(View.GONE);
@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2025 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
package com.android.messaging.util;
import android.text.SpannableString;
import android.text.style.URLSpan;
import android.text.util.Linkify;
import android.util.Log;
import android.widget.TextView;
import androidx.core.util.Pair;
import java.util.ArrayList;
import java.util.regex.Pattern;
/*
* Helper class to support Linkify-ing the geo uri scheme, see
* https://en.wikipedia.org/wiki/Geo_URI_scheme
*/
public class LinkifyHelper {
public final static String TAG = "LinkifyHelper";
public final static boolean VERBOSE = false;
private final static Pattern GEO_URL_PATTERN =
Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?",
Pattern.CASE_INSENSITIVE);
// This could have been simpler, but Linkify.addLinks() removes existing links
// and PHONE_NUMBERS also matches parts of the geo-url
public static boolean addLinks(TextView text) {
boolean ret;
// We need to add and know the geo spans first since Linkify will replace them with
// phone numbers - therefore we remove those later and replace them with the geo ones
// again
Linkify.addLinks(text, GEO_URL_PATTERN, null);
SpannableString geoSpannable = SpannableString.valueOf(text.getText());
final URLSpan[] geoSpans = geoSpannable.getSpans(0, geoSpannable.length(), URLSpan.class);
ArrayList<Pair<Integer, Integer>> geoSpanPairs = new ArrayList<>();
for (URLSpan geoSpan : geoSpans) {
geoSpanPairs.add(new Pair<>(geoSpannable.getSpanStart(geoSpan),
geoSpannable.getSpanEnd(geoSpan)));
}
// We want "ALL" but that's deprecated due to Linkify.MAP_ADDRESSES
int mask = Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS;
// This will remove our existing spans
ret = Linkify.addLinks(text, mask);
SpannableString s = SpannableString.valueOf(text.getText());
if (geoSpans.length > 0) {
ret = true;
final URLSpan[] allSpans = s.getSpans(0, s.length(), URLSpan.class);
for (int i = allSpans.length - 1; i >= 0; i--) {
int spanStart = s.getSpanStart(allSpans[i]);
int spanEnd = s.getSpanEnd(allSpans[i]);
for (Pair<Integer, Integer> pair : geoSpanPairs) {
if (spanStart >= pair.first && spanStart <= pair.second) {
// We have found a span within a geo span
if (VERBOSE) {
Log.d(TAG, "Removing span between " + spanStart + " and " + spanEnd +
" since it's in range of a geo span (" + pair.first + ", " +
pair.second + ")");
}
s.removeSpan(allSpans[i]);
}
}
}
text.setText(s);
// Add the geo spans again
Linkify.addLinks(text, GEO_URL_PATTERN, null);
}
return ret;
}
}