首页 文章

我可以将自定义对象发送到Android Wear吗?

提问于
浏览
11

我刚学习如何开发Android Wear,我已经为智能 Watch 创建了一个全屏活动,在我的应用程序的移动部分,我获得了一些JSON数据,并从中创建了一个自定义对象列表 .

在我的移动应用程序中,我在ListView中显示这些对象的信息 .

在我的应用程序的Wear部分,我想显示此列表的限制版本,例如列表中的前3个将显示在Wearable上的全屏应用程序上 .

我的问题是似乎没有办法将Parcelable Objects发送到Android Wear,因此没有选项将putParcelable放在DataItem中 .

看起来唯一的选择是以字节为单位发送对象,如下所示:

public void sendWearableData(GoogleApiClient aGoogleApiClient, ArrayList<MyObject> myObjectList, String path)
{

    googleApiClient = aGoogleApiClient;

    byte[] testBytes = new byte[0];

    if (googleApiClient.isConnected()) {
        PutDataMapRequest dataMapRequest = PutDataMapRequest.create(path);
        try {
            testBytes = BytesUtils.toByteArray(myObjectList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        dataMapRequest.getDataMap().putByteArray(Constants.TEST_KEY, testBytes);
        PutDataRequest request = dataMapRequest.asPutDataRequest();
        Wearable.DataApi.putDataItem(googleApiClient, request);
    }
}

所以我必须将我的对象转换为字节,将其发送到Android Wear并将其转换回来?这意味着我已经实现了Parcelable的对象,所以我现在可以通过Intents发送它们也需要实现Serializable,这是正确的还是有更好的方法呢?

1 回答

  • 15

    类似Bundle的解决方案:

    在我的应用程序中,我创建了一个轻量级的类,专门用于从手机发送到 Watch . 由于代码在应用程序的移动和可穿戴部分之间共享,因此可以在两个设备上轻松打包和恢复,而无需重复代码 . 它提供类似 Bundle 的机制,但使用 DataMap .

    示例实施:

    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;
        }
    }
    

    编写这样的类将让您考虑实际需要在设备之间发送的内容尽可能少地发送 . 当添加或删除任何字段时,它也不会中断(与下一个解决方案相反) .

    回答您的Parcelable问题:

    如果您不想编写新类并希望重用现有代码,可以尝试使用下面的代码 . 它将让你只使用 Parcelable 接口(无需实现 Serializable 接口) . 我没有在跨设备发送时测试它,但它成功地将 marshall()unmarshall() 字节数组发送到/来自Parcel并将其存储在 DataMap 中 .

    NOTE: 我不确切知道Google Play服务如何保存所有这些 DataApi 数据,但我担心在更新此类课程时可能会出现问题 .
    例如,该类将在Android Wear上更新,用户将启动尝试从 DataApi 读取当前数据的应用程序(使用此类的旧版本"serialized")并尝试从 byte[] 读取它,就好像它是更新版本一样 . 应该对这些问题进行测试,但我认为他们并没有如此原始"just because"或者更难以在Wear上开发应用程序 .

    我强烈建议使用 Bundle -like解决方案,不要使用 Parcelable 解决方案 .
    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>
    * DataMapParcelableUtils.putParcelable(dataMap, "KEY", myParcelableObject); * </p><p> * <b>Restore object from DataMap:</b>
    * 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; } }

    该代码也可在GitHub上找到 .

相关问题