jjzjj

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

coder 2023-11-19 原文

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

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

在我的应用程序的 Wear 部分,我想显示此列表的一个有限版本,例如,列表中的前 3 个将显示在我的可穿戴设备上的全屏应用程序中。

我的问题是似乎没有办法将 Parcelable 对象发送到 Android Wear,没有在 DataItem 中放置 Parcelable 的选项。

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

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,这是正确的还是有更好的方法?

最佳答案

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 接口(interface)(无需实现 Serializable 接口(interface))。我没有在跨设备发送时测试过它,但它成功地将 marshall()unmarshall() 字节数组发送到/从 Parcel 并将其存储在 DataMap.

注意:我不知道 Google Play 服务如何保存所有这些 DataApi 数据,但我担心更新此类时可能会出现问题.
例如,类将在 Android Wear 上更新,用户将启动应用程序,尝试从 DataApi 读取当前数据(使用此类的旧版本“序列化”)并尝试读取它来自 byte[] 就好像它是更新版本一样。应该测试这些问题,但我认为它们使 DataApi 如此原始“只是因为”或使在 Wear 上开发应用程序变得更加困难。

我强烈建议使用类似Bundle的解决方案,不要使用Parcelable解决方案。
使用它需要您自担风险。

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

代码也可以在 GitHub 上找到.

关于android - 我可以将自定义对象发送到 Android Wear 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25938273/

有关android - 我可以将自定义对象发送到 Android Wear 吗?的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  3. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  4. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  5. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  6. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  9. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  10. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

随机推荐