You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Android Wearable设备中的数据以文本文件形式后台传输至配对手机?

解答:WearOS 数据文件静默传输到配对手机的实现方案

首先明确回答你的第一个疑问:WearOS 完全支持与配对手机进行这类数据传输,Google 提供的 Data Layer API 就是专门用于跨穿戴设备和手机同步数据(包括文件类数据)的核心方案,完全能满足你的需求。下面结合你的现有代码,一步步实现完整流程:


一、核心思路梳理

  1. 整合所有需要传输的日志数据(日期时间、UUID、地理位置、所选参数)为结构化内容(文本或 JSON)
  2. 使用 Data Layer API 的 Asset 类封装文件数据(适合传输二进制/文本文件)
  3. 通过 DataClient 从穿戴设备后台发送数据
  4. 在配对手机端监听 Data Layer 数据变化,接收并保存文件
  5. 用 WorkManager 确保传输任务在后台静默执行(即使穿戴设备的 Activity 被销毁)

二、穿戴设备端代码改造

1. 整合日志数据为统一内容

先新增一个方法,把你现有 getDateTime()、getUUID()、getSelections()、getLocation() 获取的数据整合为可保存的文本内容:

private String generateReportContent() {
    // 1. 日期时间
    SimpleDateFormat sdf_date = new SimpleDateFormat("dd/MM/yyyy");
    SimpleDateFormat sdf_time = new SimpleDateFormat("HH:mm:ss z");
    String currentDate = sdf_date.format(new Date());
    String currentTime = sdf_time.format(new Date());
    String dateTimeStr = "Date: " + currentDate + "\nTime: " + currentTime + "\n";

    // 2. UUID
    SharedPreferences sh = getSharedPreferences("UUID_File", MODE_APPEND);
    String theUUID = sh.getString(PREF_UNIQUE_ID, uniqueID);
    String uuidStr = "UUID: " + theUUID + "\n";

    // 3. 所选参数
    String selectionsStr = "Tool No.: " + c.getToolNo() +
            "\nTool Size: " + c.getToolSizeStr() +
            "\nFrom Mode: " + c.getCurrentModeStr() +
            "\nGoto Mode: " + c.getModeStr() +
            "\nMethod: " + c.getMethodStr() +
            "\nBit Duration: " + c.getBitDuration() +
            "\nUpper bound: " + c.getUpStageValue() +
            "\nLower bound: " + c.getDownStageValue() + "\n";

    // 4. 地理位置(假设你已经在 getLocation() 中保存了 location 对象)
    String locationStr = "";
    if (location != null) {
        locationStr = "Latitude: " + location.getLatitude() + "\nLongitude: " + location.getLongitude() + "\n";
    }

    // 整合所有内容
    return dateTimeStr + uuidStr + selectionsStr + locationStr;
}

2. 用 Data Layer API 发送文件数据

首先在 MainActivity 中初始化 DataClient:

private DataClient dataClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 初始化 DataClient
    dataClient = Wearable.getDataClient(this);
    // 其他初始化代码...
}

然后新增传输文件的方法,将整合后的内容封装为 Asset 发送:

private void sendReportToPhone() {
    String reportContent = generateReportContent();
    try {
        // 将文本转成字节数组,创建 Asset(适合传输文件类数据)
        byte[] reportBytes = reportContent.getBytes(StandardCharsets.UTF_8);
        Asset reportAsset = Asset.createFromBytes(reportBytes);

        // 创建数据请求,添加时间戳确保 Data Layer 识别数据变化
        PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/wear_report");
        putDataMapReq.getDataMap().putAsset("report_asset", reportAsset);
        putDataMapReq.getDataMap().putLong("timestamp", System.currentTimeMillis());

        PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
        // 发送数据
        dataClient.putDataItem(putDataReq)
                .addOnSuccessListener(dataItem -> Log.d("WearData", "日志报告已成功发送"))
                .addOnFailureListener(e -> Log.e("WearData", "发送失败: ", e));
    } catch (Exception e) {
        Log.e("WearData", "生成报告出错: ", e);
    }
}

3. 修改按钮点击事件,触发传输

在你的按钮点击逻辑中,获取完所有数据后调用传输方法:

gps_btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (Build.VERSION.SDK_INT >= 26) {
            getLocation();
            getDateTime();
            getUUID();
            getSelections();
            // 调用传输方法
            sendReportToPhone();
        } else {
            Toast.makeText(get_location.this,"Build SDK 版本过低",Toast.LENGTH_SHORT).show();
        }
    }
});

4. 后台静默传输优化(可选)

如果需要在穿戴设备 Activity 销毁后仍能完成传输,建议用 WorkManager 调度任务:

  • 先创建一个 Worker 类:
public class ReportSendWorker extends Worker {
    private DataClient dataClient;

    public ReportSendWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
        dataClient = Wearable.getDataClient(context);
    }

    @NonNull
    @Override
    public Result doWork() {
        // 从 SharedPreferences 读取预存的报告内容
        SharedPreferences sh = getApplicationContext().getSharedPreferences("ReportData", MODE_PRIVATE);
        String reportContent = sh.getString("report_content", "");

        try {
            byte[] reportBytes = reportContent.getBytes(StandardCharsets.UTF_8);
            Asset reportAsset = Asset.createFromBytes(reportBytes);

            PutDataMapRequest putDataMapReq = PutDataMapRequest.create("/wear_report");
            putDataMapReq.getDataMap().putAsset("report_asset", reportAsset);
            putDataMapReq.getDataMap().putLong("timestamp", System.currentTimeMillis());

            PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
            Tasks.await(dataClient.putDataItem(putDataReq));
            return Result.success();
        } catch (ExecutionException | InterruptedException e) {
            Log.e("ReportWorker", "发送失败,将重试", e);
            return Result.retry();
        } catch (Exception e) {
            Log.e("ReportWorker", "出错", e);
            return Result.failure();
        }
    }
}
  • 修改按钮点击事件,先保存数据再调度 Worker:
// 在按钮点击事件中,获取完数据后:
String reportContent = generateReportContent();
// 保存到 SharedPreferences
SharedPreferences.Editor editor = getSharedPreferences("ReportData", MODE_PRIVATE).edit();
editor.putString("report_content", reportContent);
editor.apply();
// 调度后台任务
OneTimeWorkRequest sendRequest = new OneTimeWorkRequest.Builder(ReportSendWorker.class).build();
WorkManager.getInstance(this).enqueue(sendRequest);

三、配对手机端接收并保存文件

1. 创建数据监听 Service

手机端需要监听 Data Layer 的数据变化,创建一个 WearableListenerService:

public class WearDataListenerService extends WearableListenerService {
    private static final String TAG = "WearDataListener";

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        super.onDataChanged(dataEvents);
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                DataItem item = event.getDataItem();
                // 匹配穿戴设备发送的路径
                if (item.getUri().getPath().equals("/wear_report")) {
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                    Asset reportAsset = dataMap.getAsset("report_asset");
                    if (reportAsset != null) {
                        // 读取 Asset 内容
                        Task<InputStream> inputStreamTask = Wearable.getDataClient(this).getFdForAsset(reportAsset);
                        inputStreamTask.addOnSuccessListener(inputStream -> {
                            try {
                                String reportContent = new String(IOUtils.toByteArray(inputStream), StandardCharsets.UTF_8);
                                // 保存到手机文件系统
                                saveReportToFile(reportContent);
                                Log.d(TAG, "报告已接收并保存");
                            } catch (IOException e) {
                                Log.e(TAG, "读取 Asset 出错", e);
                            } finally {
                                try {
                                    inputStream.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }).addOnFailureListener(e -> Log.e(TAG, "获取 Asset 输入流失败", e));
                    }
                }
            }
        }
    }

    // 保存报告到手机下载目录
    private void saveReportToFile(String content) {
        File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        File reportFile = new File(downloadsDir, "wear_report_" + System.currentTimeMillis() + ".txt");
        try (FileWriter writer = new FileWriter(reportFile)) {
            writer.write(content);
            Toast.makeText(this, "报告已保存到: " + reportFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            Log.e(TAG, "保存文件出错", e);
            Toast.makeText(this, "保存报告失败", Toast.LENGTH_SHORT).show();
        }
    }
}

2. 在 AndroidManifest 中注册 Service

<service
    android:name=".WearDataListenerService"
    android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
        <data android:scheme="wear" android:host="*" android:pathPrefix="/wear_report" />
    </intent-filter>
</service>

四、关键注意事项

  1. 确保穿戴设备和手机已配对且处于连接状态,Data Layer 会自动处理离线同步(离线时数据会暂存,联网后自动发送)
  2. 手机端需要申请 WRITE_EXTERNAL_STORAGE 权限(Android 10+ 可使用 scoped storage)
  3. Data Layer 只会同步数据变化,所以每次发送时添加时间戳是必要的,确保数据能被识别为新内容

内容的提问来源于stack exchange,提问作者Mohamed El Kayal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 14:47:29