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

React Native结合Wear OS:如何实现杀死状态下的数据传输?

解决方案:React Native + Wear OS 离线/杀进程状态下通信保障

核心思路

利用Android原生WearableListenerService(系统级监听服务,不受应用进程状态影响)捕获Wear Data Layer的消息/数据变更,结合Headless JS任务或本地持久化实现离线数据处理,同时确保应用重启后能读取未处理的消息。


步骤1:创建Android原生监听服务

在Android项目src/main/java/[你的包名]/下新建WearDataListenerService.java,负责监听Wear Data Layer事件:

package com.yourapppackage;

import android.content.Intent;
import android.util.Log;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.WearableListenerService;
import org.json.JSONException;
import org.json.JSONObject;

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

    // 监听实时消息
    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        super.onMessageReceived(messageEvent);
        String messageContent = new String(messageEvent.getData());
        Log.d(TAG, "Received offline message: " + messageContent);

        // 方案1:启动Headless JS处理消息
        try {
            JSONObject messageJson = new JSONObject(messageContent);
            Intent intent = new Intent(this, HeadlessJsTaskService.class);
            intent.putExtra(HeadlessJsTaskService.EXTRA_TASK_CONFIG,
                    new HeadlessJsTaskConfig(
                            WEAR_TASK_NAME,
                            Arguments.createMapFromJson(messageJson.toString()),
                            5000, // 任务超时时间(ms)
                            false // 禁止前台执行(避免显示应用界面)
                    ));
            startService(intent);
        } catch (JSONException e) {
            Log.e(TAG, "Parse message failed", e);
        }

        // 方案2:持久化到SharedPreferences(备选,用于App重启后读取)
        // SharedPreferences prefs = getSharedPreferences("WearOfflineData", MODE_PRIVATE);
        // prefs.edit().putString("lastMessage", messageContent).apply();
    }

    // 监听数据项变更(适合需要同步的离线数据)
    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        super.onDataChanged(dataEvents);
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                String path = event.getDataItem().getUri().getPath();
                String dataContent = new String(event.getDataItem().getData());
                Log.d(TAG, "Data changed: " + path + " -> " + dataContent);
                // 同样可以触发Headless任务或持久化
            }
        }
        dataEvents.close();
    }
}

步骤2:注册服务到AndroidManifest.xml

添加权限和服务声明,确保系统能唤醒监听服务:

<manifest ...>
    <!-- 必要权限 -->
    <uses-permission android:name="com.google.android.gms.permission.WEARABLE_MESSAGE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <!-- 应对API30+后台限制 -->

    <application ...>
        <!-- 注册Wear数据监听服务 -->
        <service
            android:name=".WearDataListenerService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
                <data
                    android:host="*"
                    android:pathPrefix="/"
                    android:scheme="wear" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
                <data
                    android:host="*"
                    android:pathPrefix="/"
                    android:scheme="wear" />
            </intent-filter>
        </service>

        <!-- 注册Headless JS服务 -->
        <service
            android:name="com.facebook.react.HeadlessJsTaskService"
            android:enabled="true"
            android:exported="true" />
    </application>
</manifest>

步骤3:修复React Native Headless任务逻辑

修改index.js,让任务能接收并处理原生传递的消息:

import {AppRegistry, AsyncStorage} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

const wearTaskHandler = async (taskData) => {
    console.log('[HeadlessJS] Process offline message:', taskData);
    // 持久化消息,供App重启后读取
    try {
        await AsyncStorage.setItem('pendingWearMessages', JSON.stringify(taskData));
        // 可选:用react-native-push-notification发送通知提醒用户
    } catch (e) {
        console.error('[HeadlessJS] Save message failed:', e);
    }
};

AppRegistry.registerHeadlessTask('WearConnectivityTask', () => wearTaskHandler);
AppRegistry.registerComponent(appName, () => App);

步骤4:App重启后读取未处理消息

修改App.tsx,在组件挂载时读取持久化的离线消息并更新UI:

import React, {useEffect, useState} from 'react';
import {View, StyleSheet, Text, Button, AsyncStorage} from 'react-native';
import {sendMessage, watchEvents} from 'react-native-wear-connectivity';
import type {ReplyCallback, ErrorCallback} from 'react-native-wear-connectivity';

function CounterScreen() {
    const [disabled, setDisabled] = useState(false);
    const [count, setCount] = useState(0);

    useEffect(() => {
        // 读取应用杀进程期间收到的消息
        const loadPendingMessages = async () => {
            try {
                const pendingMsg = await AsyncStorage.getItem('pendingWearMessages');
                if (pendingMsg) {
                    console.log('Load pending message:', pendingMsg);
                    setCount(prev => prev + 1);
                    // 处理完成后清除缓存
                    await AsyncStorage.removeItem('pendingWearMessages');
                }
            } catch (e) {
                console.error('Load pending messages failed:', e);
            }
        };
        loadPendingMessages();

        // 监听前台状态下的实时消息
        const unsubscribe = watchEvents.on('message', message => {
            console.log('Foreground message:', message);
            setCount(prev => prev + 1);
        });

        return () => unsubscribe();
    }, []);

    const onSuccess: ReplyCallback = result => {
        setDisabled(false);
        console.log('Send success:', result);
    };
    const onError: ErrorCallback = error => console.log('Send error:', error);

    const sendMessageToWear = () => {
        setDisabled(true);
        sendMessage({text: 'hello from mobile'}, onSuccess, onError);
    };

    return (
        <View style={styles.container}>
            <Text style={styles.counter}>{count}</Text>
            <Button
                disabled={disabled}
                title="Increase Counter"
                onPress={sendMessageToWear}
            />
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        padding: 8,
    },
    counter: {
        height: 100,
        width: 400,
        textAlign: 'center',
        fontSize: 50,
        fontWeight: 'bold',
    },
});

export default CounterScreen;

关键注意事项

  1. API30+后台限制:Android 11+对后台启动有严格限制,需引导用户关闭应用的电池优化,或申请REQUEST_IGNORE_BATTERY_OPTIMIZATIONS权限。
  2. 数据同步选型:如果需要确保数据不丢失,优先使用Data Items而非Message API,Data Items会自动同步,设备重连后可获取最新数据。
  3. Headless JS限制:Headless任务不能执行UI操作,仅能处理数据、持久化或发送通知。
  4. 签名一致性:手机和手表端应用必须使用相同的签名(调试/发布签名需对应),否则无法建立Data Layer连接。

内容的提问来源于stack exchange,提问作者Nishit Chauhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 11:42:13