diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 1f2b3429f3f8b..5caea2b38c962 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -34,6 +34,7 @@ import android.database.Cursor; import android.database.DatabaseUtils; import android.graphics.Rect; import android.net.Uri; +import android.os.Bundle; import android.os.RemoteException; import android.text.TextUtils; import android.util.DisplayMetrics; @@ -44,6 +45,9 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** *
@@ -166,6 +170,22 @@ public final class ContactsContract {
*/
public static final String STREQUENT_PHONE_ONLY = "strequent_phone_only";
+ /**
+ * A key to a boolean in the "extras" bundle of the cursor.
+ * The boolean indicates that the provider did not create a snippet and that the client asking
+ * for the snippet should do it (true means the snippeting was deferred to the client).
+ *
+ * @hide
+ */
+ public static final String DEFERRED_SNIPPETING = "deferred_snippeting";
+
+ /**
+ * Key to retrieve the original query on the client side.
+ *
+ * @hide
+ */
+ public static final String DEFERRED_SNIPPETING_QUERY = "deferred_snippeting_query";
+
/**
* @hide
*/
@@ -4857,6 +4877,19 @@ public final class ContactsContract {
* @hide
*/
public static final String SNIPPET_ARGS_PARAM_KEY = "snippet_args";
+
+ /**
+ * A key to ask the provider to defer the snippeting to the client if possible.
+ * Value of 1 implies true, 0 implies false when 0 is the default.
+ * When a cursor is returned to the client, it should check for an extra with the name
+ * {@link ContactsContract#DEFERRED_SNIPPETING} in the cursor. If it exists, the client
+ * should do its own snippeting using {@link ContactsContract#snippetize}. If
+ * it doesn't exist, the snippet column in the cursor should already contain a snippetized
+ * string.
+ *
+ * @hide
+ */
+ public static final String DEFERRED_SNIPPETING_KEY = "deferred_snippeting";
}
/**
@@ -8054,4 +8087,138 @@ public final class ContactsContract {
public static final String DATA_SET = "com.android.contacts.extra.DATA_SET";
}
}
+
+ /**
+ * Creates a snippet out of the given content that matches the given query.
+ * @param content - The content to use to compute the snippet.
+ * @param displayName - Display name for the contact - if this already contains the search
+ * content, no snippet should be shown.
+ * @param query - String to search for in the content.
+ * @param snippetStartMatch - Marks the start of the matching string in the snippet.
+ * @param snippetEndMatch - Marks the end of the matching string in the snippet.
+ * @param snippetEllipsis - Ellipsis string appended to the end of the snippet (if too long).
+ * @param snippetMaxTokens - Maximum number of words from the snippet that will be displayed.
+ * @return The computed snippet, or null if the snippet could not be computed or should not be
+ * shown.
+ *
+ * @hide
+ */
+ public static String snippetize(String content, String displayName, String query,
+ char snippetStartMatch, char snippetEndMatch, String snippetEllipsis,
+ int snippetMaxTokens) {
+
+ String lowerQuery = query != null ? query.toLowerCase() : null;
+ if (TextUtils.isEmpty(content) || TextUtils.isEmpty(query) ||
+ TextUtils.isEmpty(displayName) || !content.toLowerCase().contains(lowerQuery)) {
+ return null;
+ }
+
+ // If the display name already contains the query term, return empty - snippets should
+ // not be needed in that case.
+ String lowerDisplayName = displayName != null ? displayName.toLowerCase() : "";
+ List