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

Android Wear OS 2.0应用振动偶尔失效问题排查求助

Hey there! Let's dig into this tricky vibration issue you're facing with your first Android Wear app—resource constraints and lifecycle quirks on Wear OS can throw some unexpected curveballs, so let's break down what's likely going wrong and how to fix it.

What's Probably Causing the One-Time Vibration Glitch

Looking at your code, a few key patterns stand out as potential culprits:

  • Multiple AlarmActivity Instances Clashing
    When your SmsReceiver detects a new message while AlarmActivity is already active, it launches a new instance of the activity (thanks to Android's default standard launch mode). This triggers the old instance to enter onStop()/onPause() (setting active to false), while the new instance starts fresh. The system might interrupt the existing vibration during this switch, or overlapping vibrator calls could cause unexpected behavior that stops the vibration prematurely.

  • Unreliable Static active Flag
    The static active boolean is shared across all AlarmActivity instances. When an old instance is stopped, it sets active to false—even if a new instance is already running. This can break your SmsReceiver logic and lead to missed vibration restarts.

  • WakeLock Leaks
    You only release the wake lock when the stop button is clicked. If AlarmActivity gets destroyed unexpectedly (e.g., due to low memory on Wear OS), the wake lock stays held, straining system resources and potentially causing the vibrator service to misbehave.


Fixes to Try (Start with the First One!)

Let's tackle these issues step by step:

1. Use singleTop Launch Mode to Avoid Multiple Instances

First, update your AndroidManifest.xml to set AlarmActivity to singleTop mode—this ensures only one instance runs at the top of the stack, and new launch requests trigger onNewIntent() instead of creating a duplicate:

<activity
    android:name=".AlarmActivity"
    android:launchMode="singleTop">
</activity>

Then add onNewIntent() to AlarmActivity to reactivate vibration if it's interrupted, plus clean up resource lifecycle:

private Vibrator vibrator;
private PowerManager.WakeLock wakeLock;
private boolean isVibrating = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_alarm);
    
    // Initialize vibrator and wake lock once
    vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(
        PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, 
        "MyWakelockTag"
    );
    wakeLock.acquire();
    
    // Start vibration on first launch
    startVibration();
    
    // Stop button logic (update to track vibration state)
    Button stopButton = findViewById(R.id.stop_button);
    stopButton.setOnClickListener(v -> {
        if (isVibrating) {
            vibrator.cancel();
            isVibrating = false;
        }
        if (wakeLock.isHeld()) {
            wakeLock.release();
        }
        new SendEmail().execute();
        startActivity(new Intent(AlarmActivity.this, MainActivity.class));
    });
    
    setAmbientEnabled();
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    // Reactivate vibration if it stopped unexpectedly
    startVibration();
    // Refresh wake lock to keep screen on
    if (!wakeLock.isHeld()) {
        wakeLock.acquire();
    }
}

private void startVibration() {
    if (!isVibrating && vibrator.hasVibrator()) {
        long[] mVibratePattern = new long[]{0, 400, 800, 600, 800, 800, 800, 1000};
        int[] mAmplitudes = new int[]{0, 255, 0, 255, 0, 255, 0, 255};
        vibrator.vibrate(VibrationEffect.createWaveform(mVibratePattern, mAmplitudes, 0));
        isVibrating = true;
    }
}

// Clean up resources when the activity is destroyed
@Override
protected void onDestroy() {
    super.onDestroy();
    if (wakeLock.isHeld()) {
        wakeLock.release();
    }
    if (isVibrating) {
        vibrator.cancel();
    }
}

2. Replace the Static active Flag with a Foreground Check

Instead of relying on a static boolean, use ActivityManager to check if AlarmActivity is actually in the foreground in your SmsReceiver:

private boolean isAlarmActivityActive(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        return topActivity.getClassName().equals("hu.asd.watchtest.AlarmActivity");
    }
    return false;
}

Then update your receiver's else-if branch:

else if (isAlarmActivityActive(context)) {
    Intent intent1 = new Intent();
    intent1.setClassName("hu.asd.watchtest", "hu.asd.watchtest.AlarmActivity");
    intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    context.startActivity(intent1);
}

3. Add Lifecycle Hooks for Vibration State

Update your AlarmActivity lifecycle methods to track vibration state properly:

@Override
protected void onPause() {
    super.onPause();
    // Pause vibration when the activity is hidden (prevents background vibration)
    if (isVibrating) {
        vibrator.cancel();
        isVibrating = false;
    }
}

@Override
protected void onResume() {
    super.onResume();
    // Resume vibration when the activity comes back to foreground
    startVibration();
}

Why These Fixes Should Work

By using singleTop, you eliminate duplicate activity instances that were causing conflicting vibrator calls. The isVibrating flag ensures you don't start overlapping vibrations, and proper wake lock cleanup prevents resource leaks that could destabilize the system on Wear OS.

Give these changes a shot—they should resolve the random one-time vibration stops you're seeing!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:32:59