Search code examples
javaandroidwear-ossendmessage

WearOS and Android application does not communicate


I want to display the numbers entered in an Android app on a Wearable device, but it's not working as expected. Since MessageApi is deprecated, I'm trying to use MessageClient as a replacement, but it's not working. I've been debugging, but it seems to stop after sending the message, and there are no error logs to help me figure out the issue. If anyone has experience with developing for Wear OS devices, could you please help me?                                                    enter image description hereenter image description here

Android MainActivity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText editText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = findViewById(R.id.editText);

        Button sendButton = findViewById(R.id.sendButton);
        sendButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.sendButton) {
            String text = editText.getText().toString();
            sendMessage(text);
        }
    }

    private void sendMessage(String text) {
        MessageClient messageClient = Wearable.getMessageClient(this);

        
        Task<List<Node>> nodeListTask = Wearable.getNodeClient(this).getConnectedNodes();
        nodeListTask.addOnSuccessListener(nodes -> {
            
            for (Node node : nodes) {
                messageClient.sendMessage(node.getId(), "/data_comm", text.getBytes())
                        .addOnSuccessListener(aVoid -> {
                            
                            Log.d("SendMessage", "Message sent successfully to: " + node.getDisplayName());
                            
                        })
                        .addOnFailureListener(e -> {
                            
                            Log.e("SendMessage", "Failed to send message to: " + node.getDisplayName(), e);
                        });
            }
        }).addOnFailureListener(e -> {
            
            Log.e("SendMessage", "Failed to get connected nodes", e);
        });
    }
}

wear os MainActivity

public class MainActivity extends Activity implements MessageClient.OnMessageReceivedListener {
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView); 
    }

    @Override
    protected void onResume() {
        super.onResume();
        Wearable.getMessageClient(this).addListener(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Wearable.getMessageClient(this).removeListener(this);
    }

    @Override
    public void onMessageReceived(@NonNull final MessageEvent messageEvent) {
        if (messageEvent.getPath().equals("/data_comm")) {
            runOnUiThread(() -> {
                String message = new String(messageEvent.getData());
                textView.setText(message); 
            });
        }
    }

DataListenerService class

public class DataListenerService extends WearableListenerService {
    private Handler handler = new Handler(Looper.getMainLooper());

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                DataItem item = event.getDataItem();

                if (item.getUri().getPath().equals("/data_comm")) {
                    DataMap dataMap = DataMapItem.fromDataItem(item).getDataMap();
                    handler.post(() -> Toast.makeText(getApplicationContext(), dataMap.getString("key_data"),
                            Toast.LENGTH_SHORT).show());
                }
            }
        }
    }

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        if (messageEvent.getPath().equals("/data_comm_2")) {
            handler.post(() -> Toast.makeText(getApplicationContext(),
                    new String(messageEvent.getData()),
                    Toast.LENGTH_SHORT).show());
        }
    }
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Practice_wear"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
    </application>

</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-feature android:name="android.hardware.type.watch" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@android:style/Theme.DeviceDefault">

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

    </application>

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
</manifest>
plugins {
    id 'com.android.application'
}

android {
    namespace 'com.websarva.wings.android.practice_wear'
    compileSdk 33

    defaultConfig {
        applicationId "com.websarva.wings.android.practice_wear"
        minSdk 26
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'com.google.android.gms:play-services-wearable:18.1.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
    implementation 'androidx.core:core:1.6.0'
}
plugins {
    id 'com.android.application'
}

android {
    namespace 'com.websarva.wings.android.wear'
    compileSdk 33

    defaultConfig {
        applicationId "com.websarva.wings.android.wear"
        minSdk 26
        targetSdk 33
        versionCode 1
        versionName "1.0"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.percentlayout:percentlayout:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.3.2'
    implementation 'com.google.android.gms:play-services-wearable:18.1.0'
    implementation 'androidx.wear:wear:1.0.0'
    compileOnly 'com.google.android.wearable:wearable:2.5.0'
}

Solution

  • Please review the following security requirements, otherwise your apps won't communicate to each other:

    • The package name must match across devices.
    • The signature of the package must match across devices.

    It looks like your package names are not matching across the projects:

    • com.websarva.wings.android.practice_wear
    • com.websarva.wings.android.wear

    Other sources of information/tutorial on this subject: