Can I send custom objects to Android Wear?

前端 未结 1 1844
梦如初夏
梦如初夏 2021-02-04 10:59

I am just learning how to develop for Android Wear, I have created a full screen Activity for Smart Watches and in my mobile part of the application I get some JSON data and cre

相关标签:
1条回答
  • 2021-02-04 11:32

    Bundle-like solution:

    In my app I've created a lightweight class, specially for sending it from phone to watch. Because the code is shared between mobile and wearable parts of app it can be easily packed and restored on both devices without code duplication. It provides Bundle-like mechanism, but using DataMap.

    Sample implementation:

    public class MyObject {
    
        public final long itemId;
        public final long sortOrder;
        public final String priceString;
    
        public MyObject(long itemId, long sortOrder, String priceString) {
            this.itemId = itemId;
            this.sortOrder = sortOrder;
            this.priceString = priceString;
        }
    
        public MyObject(DataMap map) {
            this(map.getLong("itemId"),
                 map.getLong("sortOrder"),
                 map.getString("priceString")
                );
        }
    
        public DataMap putToDataMap(DataMap map) {
            map.putLong("itemId", itemId);
            map.putLong("sortOrder", sortOrder);
            map.putString("priceString", priceString);
            return map;
        }
    }
    

    Writing such class will let you consider the what actually needs to be send between devices to send as little as possible. It will also not break when any field will be added or removed (in oppose to the next solution).

    Answering to your Parcelable concerns:

    If you don't want to write the new class and want to reuse your existing code you can try to use the code below. It will let you stay with only Parcelable interface (without need to implement Serializable interface). I haven't tested it while sending across devices but it successes to marshall() and unmarshall() byte array to/from Parcel and store it in DataMap.

    NOTE: I don't know exactly how Google Play Services hold all these DataApi data, but I'm afraid that something may break when such class will be updated.
    For example the class will be updated on Android Wear, user will launch the app that would try to read the current data from DataApi (that was "serialized" using old version of this class) and try to read it from byte[] as if it was updated version. These concerns should be tested, but I don't think that they made DataApi so primitive "just because" or to make harder to develop apps on Wear.

    I strongly recommend to use Bundle-like solution and to not use the Parcelable solution.
    Use this at your own risk.

    import android.os.Parcel;
    import android.os.Parcelable;
    
    import com.google.android.gms.wearable.DataMap;
    
    /**
     * <p>Allows to put and get {@link Parcelable} objects into {@link DataMap}</p>
     * <b>USAGE:</b>
     * <p>
     * <b>Store object in DataMap:</b><br/>
     * DataMapParcelableUtils.putParcelable(dataMap, "KEY", myParcelableObject);
     * </p><p>
     * <b>Restore object from DataMap:</b><br/>
     * myParcelableObject = DataMapParcelableUtils.getParcelable(dataMap, "KEY", MyParcelableObject.CREATOR);
     * </p>
     * I do <b>not recommend</b> to use this method - it may fail when the class that implements {@link Parcelable} would be updated. Use it at your own risk.
     * @author Maciej Ciemięga
     */
    public class DataMapParcelableUtils {
    
        public static void putParcelable(DataMap dataMap, String key, Parcelable parcelable) {
            final Parcel parcel = Parcel.obtain();
            parcelable.writeToParcel(parcel, 0);
            parcel.setDataPosition(0);
            dataMap.putByteArray(key, parcel.marshall());
            parcel.recycle();
        }
    
        public static <T> T getParcelable(DataMap dataMap, String key, Parcelable.Creator<T> creator) {
            final byte[] byteArray = dataMap.getByteArray(key);
            final Parcel parcel = Parcel.obtain();
            parcel.unmarshall(byteArray, 0, byteArray.length);
            parcel.setDataPosition(0);
            final T object = creator.createFromParcel(parcel);
            parcel.recycle();
            return object;
        }
    }
    

    The code is also available on GitHub.

    0 讨论(0)
提交回复
热议问题