Hola amigos 馃憢 Bienvenidos a un nuevo tutorial de Universo Android. Hoy aprenderemos a programar para Wear OS, el sistema operativo de Google para smartwatches y dispositivos wearables, creando aplicaciones optimizadas para pantallas peque帽as y circulares.
Al finalizar este tutorial tendr谩s una aplicaci贸n que incluir谩:
- Configuraci贸n completa de proyecto Wear OS
- Dise帽os adaptados a pantallas circulares
- Notificaciones en smartwatch
- Complicaciones para watch faces
- Sensores y monitoreo de actividad f铆sica
- Sincronizaci贸n con dispositivo m贸vil
- Interfaz optimizada para wearables
馃煩 1. ¿Qu茅 es Wear OS?
Wear OS es el sistema operativo de Google dise帽ado espec铆ficamente para smartwatches y dispositivos wearables. Permite crear aplicaciones que aprovechan las caracter铆sticas 煤nicas de estos dispositivos: pantallas peque帽as, interacci贸n r谩pida, sensores de salud y notificaciones instant谩neas.
馃煩 2. Requisitos Previos
Antes de comenzar necesitas:
- Android Studio (versi贸n actualizada)
- SDK de Android API 30 o superior
- Smartwatch con Wear OS o emulador configurado
- Conocimientos b谩sicos de Android
馃煩 3. Crear el Proyecto Wear OS en Android Studio
Paso 1: Nuevo Proyecto
- Abre Android Studio
- Selecciona New Project
- En la pesta帽a Wear OS, selecciona Empty Wear App
- Configura el nombre y paquete
- Selecciona API 30: Android 11.0 (Wear OS 3) como m铆nimo
- Finaliza la creaci贸n
馃煩 4. Configurar build.gradle
Abre el archivo build.gradle (Module: app) y verifica las dependencias:
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.wearosapp'
compileSdk 34
defaultConfig {
applicationId "com.example.wearosapp"
minSdk 30
targetSdk 34
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 {
// Wear OS dependencies
implementation 'androidx.wear:wear:1.3.0'
implementation 'com.google.android.support:wearable:2.9.0'
compileOnly 'com.google.android.wearable:wearable:2.9.0'
// Material Design para Wear OS
implementation 'androidx.wear:wear-input:1.1.0'
implementation 'androidx.wear:wear-ongoing:1.0.0'
// Core dependencies
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
// Play Services para sensores
implementation 'com.google.android.gms:play-services-wearable:18.1.0'
}Sincroniza el proyecto despu茅s de agregar las dependencias.
馃煩 5. Dise帽o XML para Wear OS
Crea un archivo llamado:
馃搫 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.wear.widget.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:padding="16dp"
app:boxedEdges="all">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- T铆tulo de la App -->
<TextView
android:id="@+id/txtTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wear OS App"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="20dp" />
<!-- Contador de Pasos -->
<TextView
android:id="@+id/txtStepCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="#4CAF50"
android:textSize="48sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/txtTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/txtStepLabel"
android:layout_marginTop="20dp" />
<!-- Etiqueta de Pasos -->
<TextView
android:id="@+id/txtStepLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pasos hoy"
android:textColor="#AAAAAA"
android:textSize="16sp"
app:layout_constraintTop_toBottomOf="@id/txtStepCount"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/btnStart" />
<!-- Bot贸n Iniciar -->
<Button
android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Iniciar"
android:textColor="#FFFFFF"
android:backgroundTint="#2196F3"
app:layout_constraintTop_toBottomOf="@id/txtStepLabel"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/btnNotification"
android:layout_marginTop="20dp" />
<!-- Bot贸n Notificaci贸n -->
<Button
android:id="@+id/btnNotification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Notificaci贸n"
android:textColor="#FFFFFF"
android:backgroundTint="#FF5722"
app:layout_constraintTop_toBottomOf="@id/btnStart"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginTop="12dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.wear.widget.BoxInsetLayout>馃煩 6. Dise帽o XML con Lista Circular (WearableRecyclerView)
Crea un archivo llamado:
馃搫 activity_list.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.wear.widget.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
app:boxedEdges="all">
<androidx.wear.widget.WearableRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layoutManager="androidx.wear.widget.WearableLinearLayoutManager" />
</androidx.wear.widget.BoxInsetLayout>馃煩 7. L贸gica Java Principal
馃搫 MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private static final String CHANNEL_ID = "wear_channel";
private static final int NOTIFICATION_ID = 1;
TextView txtStepCount, txtTitle;
Button btnStart, btnNotification;
SensorManager sensorManager;
Sensor stepCounterSensor;
int stepCount = 0;
boolean isTracking = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Inicializar vistas
txtTitle = findViewById(R.id.txtTitle);
txtStepCount = findViewById(R.id.txtStepCount);
btnStart = findViewById(R.id.btnStart);
btnNotification = findViewById(R.id.btnNotification);
// Configurar sensor de pasos
setupStepCounter();
// Crear canal de notificaci贸n
createNotificationChannel();
// Configurar botones
btnStart.setOnClickListener(v -> toggleTracking());
btnNotification.setOnClickListener(v -> sendNotification());
}
private void setupStepCounter() {
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
stepCounterSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
if (stepCounterSensor == null) {
Toast.makeText(this, "Sensor de pasos no disponible", Toast.LENGTH_SHORT).show();
}
}
}
private void toggleTracking() {
if (!isTracking) {
startTracking();
} else {
stopTracking();
}
}
private void startTracking() {
if (stepCounterSensor != null) {
sensorManager.registerListener(this, stepCounterSensor, SensorManager.SENSOR_DELAY_NORMAL);
isTracking = true;
btnStart.setText("Detener");
btnStart.setBackgroundTintList(getColorStateList(android.R.color.holo_red_dark));
Toast.makeText(this, "Seguimiento iniciado", Toast.LENGTH_SHORT).show();
}
}
private void stopTracking() {
sensorManager.unregisterListener(this);
isTracking = false;
btnStart.setText("Iniciar");
btnStart.setBackgroundTintList(getColorStateList(android.R.color.holo_blue_dark));
Toast.makeText(this, "Seguimiento detenido", Toast.LENGTH_SHORT).show();
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_STEP_COUNTER) {
stepCount = (int) event.values[0];
txtStepCount.setText(String.valueOf(stepCount));
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// No se requiere implementaci贸n
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Wear Channel";
String description = "Canal de notificaciones para Wear OS";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
}
private void sendNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentTitle("Wear OS App")
.setContentText("¡Has caminado " + stepCount + " pasos hoy!")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setVibrate(new long[]{0, 500, 200, 500})
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(NOTIFICATION_ID, builder.build());
Toast.makeText(this, "Notificaci贸n enviada", Toast.LENGTH_SHORT).show();
}
@Override
protected void onPause() {
super.onPause();
if (isTracking) {
sensorManager.unregisterListener(this);
}
}
@Override
protected void onResume() {
super.onResume();
if (isTracking && stepCounterSensor != null) {
sensorManager.registerListener(this, stepCounterSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
}馃煩 8. Crear Adaptador para Lista Circular
馃搫 WearListAdapter.java
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class WearListAdapter extends RecyclerView.Adapter<WearListAdapter.ViewHolder> {
private List<String> items;
private OnItemClickListener listener;
public interface OnItemClickListener {
void onItemClick(String item);
}
public WearListAdapter(List<String> items, OnItemClickListener listener) {
this.items = items;
this.listener = listener;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
String item = items.get(position);
holder.textView.setText(item);
holder.itemView.setOnClickListener(v -> listener.onItemClick(item));
}
@Override
public int getItemCount() {
return items.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
TextView textView;
ViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(android.R.id.text1);
textView.setTextColor(0xFFFFFFFF);
}
}
}馃煩 9. Actividad con Lista Circular
馃搫 ListActivity.java
import androidx.appcompat.app.AppCompatActivity;
import androidx.wear.widget.WearableLinearLayoutManager;
import androidx.wear.widget.WearableRecyclerView;
import android.os.Bundle;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class ListActivity extends AppCompatActivity {
WearableRecyclerView recyclerView;
WearListAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
recyclerView = findViewById(R.id.recyclerView);
// Configurar LayoutManager para pantalla curva
WearableLinearLayoutManager layoutManager = new WearableLinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setEdgeItemsCenteringEnabled(true);
// Crear lista de items
List<String> items = new ArrayList<>();
items.add("Correr");
items.add("Caminar");
items.add("Ciclismo");
items.add("Nataci贸n");
items.add("Yoga");
items.add("Gimnasio");
items.add("F煤tbol");
items.add("Baloncesto");
// Configurar adaptador
adapter = new WearListAdapter(items, item ->
Toast.makeText(this, "Seleccionado: " + item, Toast.LENGTH_SHORT).show()
);
recyclerView.setAdapter(adapter);
}
}馃煩 10. Configurar AndroidManifest.xml
馃搫 AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Permisos para Wear OS -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Declarar que es una app Wear OS -->
<uses-feature android:name="android.hardware.type.watch" />
<!-- Sensor de pasos -->
<uses-feature
android:name="android.hardware.sensor.stepdetector"
android:required="false" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault"
tools:targetApi="26">
<!-- Metadata para identificar como app Wear -->
<meta-data
android:name="com.google.android.wearable.standalone"
android:value="true" />
<!-- Actividad Principal -->
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@android:style/Theme.DeviceDefault">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Actividad de Lista -->
<activity
android:name=".ListActivity"
android:exported="false"
android:label="Actividades"
android:theme="@android:style/Theme.DeviceDefault" />
</application>
</manifest>馃煩 11. Sensores Disponibles en Wear OS
| Sensor | Descripci贸n |
|---|---|
TYPE_STEP_COUNTER | Contador de pasos acumulados |
TYPE_STEP_DETECTOR | Detecta cada paso individual |
TYPE_HEART_RATE | Monitor de frecuencia card铆aca |
TYPE_ACCELEROMETER | Aceler贸metro para movimiento |
TYPE_GYROSCOPE | Giroscopio para rotaci贸n |
TYPE_AMBIENT_TEMPERATURE | Temperatura ambiente |
TYPE_PRESSURE | Presi贸n barom茅trica |
馃煩 12. Crear Complicaci贸n para Watch Face
馃搫 ComplicationService.java
import android.app.PendingIntent;
import android.content.Intent;
import androidx.wear.watchface.complications.data.ComplicationData;
import androidx.wear.watchface.complications.data.ComplicationType;
import androidx.wear.watchface.complications.data.PlainComplicationText;
import androidx.wear.watchface.complications.data.ShortTextComplicationData;
import androidx.wear.watchface.complications.datasource.ComplicationDataSourceService;
import androidx.wear.watchface.complications.datasource.ComplicationRequest;
public class StepComplicationService extends ComplicationDataSourceService {
@Override
public void onComplicationRequest(ComplicationRequest request, ComplicationRequestListener listener) {
// Obtener conteo de pasos (simulado)
int steps = 5432;
// Crear Intent para abrir la app
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(
this, 0, intent, PendingIntent.FLAG_IMMUTABLE
);
// Crear complicaci贸n
ShortTextComplicationData complicationData = new ShortTextComplicationData.Builder(
PlainComplicationText.Builder(steps + " pasos").build(),
PlainComplicationText.Builder("Pasos").build()
)
.setTapAction(pendingIntent)
.build();
listener.onComplicationData(complicationData);
}
@Override
public void onComplicationActivated(int complicationInstanceId, ComplicationType type) {
// Complicaci贸n activada
}
@Override
public void onComplicationDeactivated(int complicationInstanceId) {
// Complicaci贸n desactivada
}
@Override
public ComplicationType[] getSupportedComplicationTypes(int complicationInstanceId) {
return new ComplicationType[]{
ComplicationType.SHORT_TEXT,
ComplicationType.LONG_TEXT
};
}
}馃煩 13. Configurar Emulador Wear OS
- Abre AVD Manager en Android Studio
- Clic en Create Virtual Device
- Selecciona categor铆a Wear OS
- Elige un dispositivo (Wear OS Square o Round)
- Selecciona API 30 o superior
- Finaliza y ejecuta el emulador
▶️ C贸mo Ejecutar tu Aplicaci贸n
- Abre Android Studio
- Conecta tu smartwatch o inicia el emulador Wear OS
- Presiona Run para ejecutar el proyecto
- La aplicaci贸n se instalar谩 en tu dispositivo Wear OS
- Ver谩s la interfaz optimizada para smartwatch funcionando
馃И Resultado Final
Tu aplicaci贸n Wear OS mostrar谩:
- Interfaz adaptada a pantallas circulares y cuadradas
- Contador de pasos en tiempo real
- Botones optimizados para smartwatch
- Notificaciones con vibraci贸n
- Lista circular con desplazamiento curvo
- Sensores de actividad f铆sica funcionando
馃摜 Descargar Proyecto de Ejemplo
Puedes descargar el proyecto completo desde el siguiente enlace:
馃憠 Estamos trabajando en ello!
馃檶 Gracias por Visitar mi Blog
Si este tutorial te fue 煤til:
✔️ Comp谩rtelo
✔️ D茅jame un comentario
✔️ S铆gueme para m谩s contenido sobre Android y programaci贸n
¡Estoy aqu铆 para ayudarte!
❓ Preguntas Frecuentes (FAQ)
1. ¿Puedo desarrollar para Wear OS sin tener un smartwatch f铆sico?
S铆, Android Studio incluye emuladores de Wear OS que simulan tanto pantallas circulares como cuadradas para desarrollo y testing.
2. ¿Qu茅 diferencias hay entre una app normal de Android y una de Wear OS?
Las apps de Wear OS tienen interfaces m谩s compactas, dise帽os adaptados a pantallas peque帽as y circulares, enfoque en notificaciones r谩pidas y acceso a sensores espec铆ficos de wearables.
3. ¿Puedo sincronizar datos entre mi app m贸vil y mi app Wear OS?
S铆, puedes usar la Wearable Data Layer API de Google Play Services para sincronizar datos entre dispositivos m贸viles y smartwatches.
4. ¿Qu茅 sensores est谩n disponibles en Wear OS?
Los smartwatches Wear OS incluyen sensores como contador de pasos, monitor de frecuencia card铆aca, aceler贸metro, giroscopio, GPS y algunos modelos incluyen sensores adicionales de salud.

No hay comentarios:
Publicar un comentario