GenericRemoteMessage

public final class GenericRemoteMessage implements EspressoRemoteMessage.To


Generic implementation of the EspressoRemoteMessage interface, which uses reflection for proto message serialization and deserialization.

Every Espresso matcher, view action or view assertion needs to support proto serialization to participate in any kind of cross process UI interaction using Espresso Remote.

Each serializable type T needs to provide two things. First a proto message declaration of type T. Second an EspressoRemoteMessage class which implements the and EspressoRemoteMessage.From interfaces to serialize/deserialization any state into their proto message equivalent.

This GenericRemoteMessage class is special type of EspressoRemoteMessage, which implements the the EspressoRemoteMessage.To and EspressoRemoteMessage.From interfaces and uses reflection to perform serialisation of an object of type T into its proto message representation.

Espresso Remote uses a global RemoteDescriptorRegistry for RemoteDescriptor lookups. Where a RemoteDescriptor is a descriptor object which contains all the necessary meta information for proto serialization.

Usage:

For a type Foo with fields bar and baz:

public class Foo {
  private final String bar;
  private final int baz;

  protected Foo(String bar, int baz) { // set fields }
}

Note: A protected constructor with serializable fields in declared order is required for proto deserialization.

Create a corresponding proto definition, FooProto.proto for Foo:

message FooProto {
  bytes bar = 1; // Name needs to match Foo#bar
  bytes baz = 2; // Name needs to match Foo#baz
}

The proto type definitions used with GenericRemoteMessage need to be of type byte and the type names must match the variable name of the serializable fields in Foo.java.

The last step is to create a RemoteDescriptor using a , to configure all the meta data required for generic serialization. Finally register the descriptor with the RemoteDescriptorRegistry. A typical descriptor builder looks like this:

new RemoteDescriptor.Builder()
  .setInstanceType(Foo.class)
  .setInstanceFieldDescriptors(
    FieldDescriptor.of(String.class, "bar")),
    FieldDescriptor.of(int.class, 32))
  .setRemoteType(GenericRemoteMessage.class)
  .setProtoType(FooProto.class)
  .build();

First set the instance type, Foo.class. Then specify the serializable fields using a FieldDescriptor. Where a FieldDescriptor represents the name and the type of a reflective field of Foo. Any fields described by the field properties and passed to setInstanceFieldDescriptors will be serialised into FooProto.proto. Next specify that type Foo will use for it's serialization entry point, in this case GenericRemoteMessage and lastly set the proto message class.

Note: The declared field properties order, must match the protected constructor of Foo, which takes the serializable fields in declared order!

Throws
androidx.test.espresso.remote.RemoteProtocolException

if a FieldDescriptors field name does not match any field in the declared type or proto message.

androidx.test.espresso.remote.RemoteProtocolException

if type cannot be serialised or dematerialised

Summary

Constants

static final EspressoRemoteMessage.From<ObjectMessageLite>

This is used to create and deserialize a proto message into an instance type

Public constructors

Creates a new GenericRemoteMessage.

Public methods

MessageLite

Constants

FROM

public static final EspressoRemoteMessage.From<ObjectMessageLiteFROM

This is used to create and deserialize a proto message into an instance type

Public constructors

GenericRemoteMessage

public GenericRemoteMessage(@NonNull Object instance)

Creates a new GenericRemoteMessage.

This constructor is called reflectively and should not be used.

Parameters
@NonNull Object instance

the object that needs to be serialized into a proto

Public methods

toProto

public MessageLite toProto()