Added People to the Notification API
In order to support people without a URI and further changes in MessagingStyle, a new person API is introduced that allows for a richer presentation. In addition are we now properly supporting people without a URI, which is useful for non-handheld clients Test: runtest -x tests/app/src/android/app/cts/NotificationTest.java Bug: 63708826 Change-Id: I496c893273803a2ec4fd3a5b731a6b4d483801ea
This commit is contained in:
@@ -5207,7 +5207,8 @@ package android.app {
|
||||
field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
|
||||
field public static final java.lang.String EXTRA_NOTIFICATION_ID = "android.intent.extra.NOTIFICATION_ID";
|
||||
field public static final java.lang.String EXTRA_NOTIFICATION_TAG = "android.intent.extra.NOTIFICATION_TAG";
|
||||
field public static final java.lang.String EXTRA_PEOPLE = "android.people";
|
||||
field public static final deprecated java.lang.String EXTRA_PEOPLE = "android.people";
|
||||
field public static final java.lang.String EXTRA_PEOPLE_LIST = "android.people.list";
|
||||
field public static final java.lang.String EXTRA_PICTURE = "android.picture";
|
||||
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
|
||||
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
|
||||
@@ -5353,7 +5354,8 @@ package android.app {
|
||||
method public deprecated android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
|
||||
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
|
||||
method public android.app.Notification.Builder addExtras(android.os.Bundle);
|
||||
method public android.app.Notification.Builder addPerson(java.lang.String);
|
||||
method public deprecated android.app.Notification.Builder addPerson(java.lang.String);
|
||||
method public android.app.Notification.Builder addPerson(android.app.Notification.Person);
|
||||
method public android.app.Notification build();
|
||||
method public android.widget.RemoteViews createBigContentView();
|
||||
method public android.widget.RemoteViews createContentView();
|
||||
@@ -5501,6 +5503,22 @@ package android.app {
|
||||
method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
|
||||
}
|
||||
|
||||
public static final class Notification.Person implements android.os.Parcelable {
|
||||
ctor protected Notification.Person(android.os.Parcel);
|
||||
ctor public Notification.Person();
|
||||
method public int describeContents();
|
||||
method public android.graphics.drawable.Icon getIcon();
|
||||
method public java.lang.String getKey();
|
||||
method public java.lang.CharSequence getName();
|
||||
method public java.lang.String getUri();
|
||||
method public android.app.Notification.Person setIcon(android.graphics.drawable.Icon);
|
||||
method public android.app.Notification.Person setKey(java.lang.String);
|
||||
method public android.app.Notification.Person setName(java.lang.CharSequence);
|
||||
method public android.app.Notification.Person setUri(java.lang.String);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.app.Notification.Person> CREATOR;
|
||||
}
|
||||
|
||||
public static abstract class Notification.Style {
|
||||
ctor public Notification.Style();
|
||||
method public android.app.Notification build();
|
||||
|
||||
@@ -1022,9 +1022,17 @@ public class Notification implements Parcelable
|
||||
/**
|
||||
* {@link #extras} key: A String array containing the people that this notification relates to,
|
||||
* each of which was supplied to {@link Builder#addPerson(String)}.
|
||||
*
|
||||
* @deprecated the actual objects are now in {@link #EXTRA_PEOPLE_LIST}
|
||||
*/
|
||||
public static final String EXTRA_PEOPLE = "android.people";
|
||||
|
||||
/**
|
||||
* {@link #extras} key: An arrayList of {@link Person} objects containing the people that
|
||||
* this notification relates to.
|
||||
*/
|
||||
public static final String EXTRA_PEOPLE_LIST = "android.people.list";
|
||||
|
||||
/**
|
||||
* Allow certain system-generated notifications to appear before the device is provisioned.
|
||||
* Only available to notifications coming from the android package.
|
||||
@@ -2819,7 +2827,7 @@ public class Notification implements Parcelable
|
||||
private Bundle mUserExtras = new Bundle();
|
||||
private Style mStyle;
|
||||
private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
|
||||
private ArrayList<String> mPersonList = new ArrayList<String>();
|
||||
private ArrayList<Person> mPersonList = new ArrayList<>();
|
||||
private NotificationColorUtil mColorUtil;
|
||||
private boolean mIsLegacy;
|
||||
private boolean mIsLegacyInitialized;
|
||||
@@ -2910,8 +2918,9 @@ public class Notification implements Parcelable
|
||||
Collections.addAll(mActions, mN.actions);
|
||||
}
|
||||
|
||||
if (mN.extras.containsKey(EXTRA_PEOPLE)) {
|
||||
Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE));
|
||||
if (mN.extras.containsKey(EXTRA_PEOPLE_LIST)) {
|
||||
ArrayList<Person> people = mN.extras.getParcelableArrayList(EXTRA_PEOPLE_LIST);
|
||||
mPersonList.addAll(people);
|
||||
}
|
||||
|
||||
if (mN.getSmallIcon() == null && mN.icon != 0) {
|
||||
@@ -3621,13 +3630,41 @@ public class Notification implements Parcelable
|
||||
* URIs. The path part of these URIs must exist in the contacts database, in the
|
||||
* appropriate column, or the reference will be discarded as invalid. Telephone schema
|
||||
* URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
|
||||
* It is also possible to provide a URI with the schema {@code name:} in order to uniquely
|
||||
* identify a person without an entry in the contacts database.
|
||||
* </P>
|
||||
*
|
||||
* @param uri A URI for the person.
|
||||
* @see Notification#EXTRA_PEOPLE
|
||||
* @deprecated use {@link #addPerson(Person)}
|
||||
*/
|
||||
public Builder addPerson(String uri) {
|
||||
mPersonList.add(uri);
|
||||
addPerson(new Person().setUri(uri));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a person that is relevant to this notification.
|
||||
*
|
||||
* <P>
|
||||
* Depending on user preferences, this annotation may allow the notification to pass
|
||||
* through interruption filters, if this notification is of category {@link #CATEGORY_CALL}
|
||||
* or {@link #CATEGORY_MESSAGE}. The addition of people may also cause this notification to
|
||||
* appear more prominently in the user interface.
|
||||
* </P>
|
||||
*
|
||||
* <P>
|
||||
* A person should usually contain a uri in order to benefit from the ranking boost.
|
||||
* However, even if no uri is provided, it's beneficial to provide other people in the
|
||||
* notification, such that listeners and voice only devices can announce and handle them
|
||||
* properly.
|
||||
* </P>
|
||||
*
|
||||
* @param person the person to add.
|
||||
* @see Notification#EXTRA_PEOPLE_LIST
|
||||
*/
|
||||
public Builder addPerson(Person person) {
|
||||
mPersonList.add(person);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -4968,8 +5005,7 @@ public class Notification implements Parcelable
|
||||
mActions.toArray(mN.actions);
|
||||
}
|
||||
if (!mPersonList.isEmpty()) {
|
||||
mN.extras.putStringArray(EXTRA_PEOPLE,
|
||||
mPersonList.toArray(new String[mPersonList.size()]));
|
||||
mN.extras.putParcelableArrayList(EXTRA_PEOPLE_LIST, mPersonList);
|
||||
}
|
||||
if (mN.bigContentView != null || mN.contentView != null
|
||||
|| mN.headsUpContentView != null) {
|
||||
@@ -7102,6 +7138,176 @@ public class Notification implements Parcelable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Person associated with this Notification.
|
||||
*/
|
||||
public static final class Person implements Parcelable {
|
||||
@Nullable private CharSequence mName;
|
||||
@Nullable private Icon mIcon;
|
||||
@Nullable private String mUri;
|
||||
@Nullable private String mKey;
|
||||
|
||||
protected Person(Parcel in) {
|
||||
mName = in.readCharSequence();
|
||||
if (in.readInt() != 0) {
|
||||
mIcon = Icon.CREATOR.createFromParcel(in);
|
||||
}
|
||||
mUri = in.readString();
|
||||
mKey = in.readString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new person.
|
||||
*/
|
||||
public Person() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Give this person a name.
|
||||
*
|
||||
* @param name the name of this person
|
||||
*/
|
||||
public Person setName(@Nullable CharSequence name) {
|
||||
this.mName = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an icon for this person.
|
||||
* <br />
|
||||
* This is currently only used for {@link MessagingStyle} notifications and should not be
|
||||
* provided otherwise, in order to save memory. The system will prefer this icon over any
|
||||
* images that are resolved from the URI.
|
||||
*
|
||||
* @param icon the icon of the person
|
||||
*/
|
||||
public Person setIcon(@Nullable Icon icon) {
|
||||
this.mIcon = icon;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a URI associated with this person.
|
||||
*
|
||||
* <P>
|
||||
* Depending on user preferences, adding a URI to a Person may allow the notification to
|
||||
* pass through interruption filters, if this notification is of
|
||||
* category {@link #CATEGORY_CALL} or {@link #CATEGORY_MESSAGE}.
|
||||
* The addition of people may also cause this notification to appear more prominently in
|
||||
* the user interface.
|
||||
* </P>
|
||||
*
|
||||
* <P>
|
||||
* The person should be specified by the {@code String} representation of a
|
||||
* {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
|
||||
* </P>
|
||||
*
|
||||
* <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema
|
||||
* URIs. The path part of these URIs must exist in the contacts database, in the
|
||||
* appropriate column, or the reference will be discarded as invalid. Telephone schema
|
||||
* URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
|
||||
* </P>
|
||||
*
|
||||
* @param uri a URI for the person
|
||||
*/
|
||||
public Person setUri(@Nullable String uri) {
|
||||
mUri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a key to this person in order to uniquely identify it.
|
||||
* This is especially useful if the name doesn't uniquely identify this person or if the
|
||||
* display name is a short handle of the actual name.
|
||||
*
|
||||
* <P>If no key is provided, the name serves as as the key for the purpose of
|
||||
* identification.</P>
|
||||
*
|
||||
* @param key the key that uniquely identifies this person
|
||||
*/
|
||||
public Person setKey(@Nullable String key) {
|
||||
mKey = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the uri provided for this person or {@code null} if no Uri was provided
|
||||
*/
|
||||
@Nullable
|
||||
public String getUri() {
|
||||
return mUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name provided for this person or {@code null} if no name was provided
|
||||
*/
|
||||
@Nullable
|
||||
public CharSequence getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the icon provided for this person or {@code null} if no icon was provided
|
||||
*/
|
||||
@Nullable
|
||||
public Icon getIcon() {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key provided for this person or {@code null} if no key was provided
|
||||
*/
|
||||
@Nullable
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the URI associated with this person, or "name:mName" otherwise
|
||||
* @hide
|
||||
*/
|
||||
public String resolveToLegacyUri() {
|
||||
if (mUri != null) {
|
||||
return mUri;
|
||||
}
|
||||
if (mName != null) {
|
||||
return "name:" + mName;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, @WriteFlags int flags) {
|
||||
dest.writeCharSequence(mName);
|
||||
if (mIcon != null) {
|
||||
dest.writeInt(1);
|
||||
mIcon.writeToParcel(dest, 0);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeString(mUri);
|
||||
dest.writeString(mKey);
|
||||
}
|
||||
|
||||
public static final Creator<Person> CREATOR = new Creator<Person>() {
|
||||
@Override
|
||||
public Person createFromParcel(Parcel in) {
|
||||
return new Person(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Person[] newArray(int size) {
|
||||
return new Person[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// When adding a new Style subclass here, don't forget to update
|
||||
// Builder.getNotificationStyleClass.
|
||||
|
||||
|
||||
@@ -890,6 +890,8 @@ public abstract class NotificationListenerService extends Service {
|
||||
createLegacyIconExtras(notification);
|
||||
// populate remote views for older clients.
|
||||
maybePopulateRemoteViews(notification);
|
||||
// populate people for older clients.
|
||||
maybePopulatePeople(notification);
|
||||
} catch (IllegalArgumentException e) {
|
||||
if (corruptNotifications == null) {
|
||||
corruptNotifications = new ArrayList<>(N);
|
||||
@@ -1178,6 +1180,25 @@ public abstract class NotificationListenerService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates remote views for pre-P targeting apps.
|
||||
*/
|
||||
private void maybePopulatePeople(Notification notification) {
|
||||
if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P) {
|
||||
ArrayList<Notification.Person> people = notification.extras.getParcelableArrayList(
|
||||
Notification.EXTRA_PEOPLE_LIST);
|
||||
if (people != null && people.isEmpty()) {
|
||||
int size = people.size();
|
||||
String[] peopleArray = new String[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
Notification.Person person = people.get(i);
|
||||
peopleArray[i] = person.resolveToLegacyUri();
|
||||
}
|
||||
notification.extras.putStringArray(Notification.EXTRA_PEOPLE, peopleArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
protected class NotificationListenerWrapper extends INotificationListener.Stub {
|
||||
@Override
|
||||
|
||||
@@ -278,7 +278,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
||||
|
||||
// VisibleForTesting
|
||||
public static String[] getExtraPeople(Bundle extras) {
|
||||
Object people = extras.get(Notification.EXTRA_PEOPLE);
|
||||
Object people = extras.get(Notification.EXTRA_PEOPLE_LIST);
|
||||
if (people instanceof String[]) {
|
||||
return (String[]) people;
|
||||
}
|
||||
@@ -305,6 +305,16 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
||||
return array;
|
||||
}
|
||||
|
||||
if (arrayList.get(0) instanceof Notification.Person) {
|
||||
ArrayList<Notification.Person> list = (ArrayList<Notification.Person>) arrayList;
|
||||
final int N = list.size();
|
||||
String[] array = new String[N];
|
||||
for (int i = 0; i < N; i++) {
|
||||
array[i] = list.get(i).resolveToLegacyUri();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -459,7 +469,9 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
|
||||
lookupResult = searchContacts(mContext, uri);
|
||||
} else {
|
||||
lookupResult = new LookupResult(); // invalid person for the cache
|
||||
Slog.w(TAG, "unsupported URI " + handle);
|
||||
if (!"name".equals(uri.getScheme())) {
|
||||
Slog.w(TAG, "unsupported URI " + handle);
|
||||
}
|
||||
}
|
||||
if (lookupResult != null) {
|
||||
synchronized (mPeopleCache) {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
public void testSingleString() throws Exception {
|
||||
String[] expected = { "foobar" };
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(Notification.EXTRA_PEOPLE, expected[0]);
|
||||
bundle.putString(Notification.EXTRA_PEOPLE_LIST, expected[0]);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("string should be in result[0]", expected, result);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
public void testSingleCharArray() throws Exception {
|
||||
String[] expected = { "foobar" };
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putCharArray(Notification.EXTRA_PEOPLE, expected[0].toCharArray());
|
||||
bundle.putCharArray(Notification.EXTRA_PEOPLE_LIST, expected[0].toCharArray());
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("char[] should be in result[0]", expected, result);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
public void testSingleCharSequence() throws Exception {
|
||||
String[] expected = { "foobar" };
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putCharSequence(Notification.EXTRA_PEOPLE, new SpannableString(expected[0]));
|
||||
bundle.putCharSequence(Notification.EXTRA_PEOPLE_LIST, new SpannableString(expected[0]));
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("charSequence should be in result[0]", expected, result);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
public void testStringArraySingle() throws Exception {
|
||||
Bundle bundle = new Bundle();
|
||||
String[] expected = { "foobar" };
|
||||
bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
|
||||
bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("wrapped string should be in result[0]", expected, result);
|
||||
}
|
||||
@@ -83,7 +83,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
public void testStringArrayMultiple() throws Exception {
|
||||
Bundle bundle = new Bundle();
|
||||
String[] expected = { "foo", "bar", "baz" };
|
||||
bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
|
||||
bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testStringArrayMultiple", expected, result);
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
public void testStringArrayNulls() throws Exception {
|
||||
Bundle bundle = new Bundle();
|
||||
String[] expected = { "foo", null, "baz" };
|
||||
bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
|
||||
bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testStringArrayNulls", expected, result);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
charSeqArray[i] = new SpannableString(expected[i]);
|
||||
}
|
||||
bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE, charSeqArray);
|
||||
bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE_LIST, charSeqArray);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testCharSequenceArrayMultiple", expected, result);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
charSeqArray[i] = new SpannableString(expected[i]);
|
||||
}
|
||||
}
|
||||
bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE, charSeqArray);
|
||||
bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE_LIST, charSeqArray);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testMixedCharSequenceArrayList", expected, result);
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
stringArrayList.add(expected[i]);
|
||||
}
|
||||
bundle.putStringArrayList(Notification.EXTRA_PEOPLE, stringArrayList);
|
||||
bundle.putStringArrayList(Notification.EXTRA_PEOPLE_LIST, stringArrayList);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testStringArrayList", expected, result);
|
||||
}
|
||||
@@ -149,11 +149,24 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase {
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
stringArrayList.add(new SpannableString(expected[i]));
|
||||
}
|
||||
bundle.putCharSequenceArrayList(Notification.EXTRA_PEOPLE, stringArrayList);
|
||||
bundle.putCharSequenceArrayList(Notification.EXTRA_PEOPLE_LIST, stringArrayList);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testCharSequenceArrayList", expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPeopleArrayList() throws Exception {
|
||||
Bundle bundle = new Bundle();
|
||||
String[] expected = { "name:test" , "tel:1234" };
|
||||
final ArrayList<Notification.Person> arrayList =
|
||||
new ArrayList<>(expected.length);
|
||||
arrayList.add(new Notification.Person().setName("test"));
|
||||
arrayList.add(new Notification.Person().setUri(expected[1]));
|
||||
bundle.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, arrayList);
|
||||
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
|
||||
assertStringArrayEquals("testPeopleArrayList", expected, result);
|
||||
}
|
||||
|
||||
private void assertStringArrayEquals(String message, String[] expected, String[] result) {
|
||||
String expectedString = Arrays.toString(expected);
|
||||
String resultString = Arrays.toString(result);
|
||||
|
||||
Reference in New Issue
Block a user