Android Wear Device вибратор не работает программно все время - PullRequest
0 голосов
/ 23 ноября 2018

Я разрабатываю для часов Huawei 2. Когда приходит смс-сигнал тревоги, часы должны переключиться на экран AlertScreen и начать вибрировать.Это работает как 99% времени, но иногда вибрация не происходит.Я уже много раз рефакторинг кода, но не могу понять, где ошибка.

MainActivity

Я регистрирую слушателя для получения SMS, а затем звонюstartAlert функция для запуска вибрации:

public class MainActivity extends FragmentActivity {

    private final FragmentManager supportFragmentManager = getSupportFragmentManager();
    private final SmsBroadcastReceiver smsBroadcastReceiver = new SmsBroadcastReceiver();
    private final AlertFragment alertFragment = new AlertFragment();
    private static final String SENDER_PHONE_NUMBER = MyApplication.getAppContext().getResources().getString(R.string.sender_phone);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        supportFragmentManager.beginTransaction().replace(R.id.fragment_container, new MainFragment()).commit();

        registerReceiver(smsBroadcastReceiver, new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION));
        smsBroadcastReceiver.setListener(new SmsListener() {
            @Override
            public void messageReceived(final String phoneNumber) {
                startAlert(phoneNumber);
            }
        });
    }

    private void startAlert(final String phoneNumber) {
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (alertFragment.isRunning || phoneNumber.equals(SENDER_PHONE_NUMBER)) {
                    supportFragmentManager.beginTransaction().replace(R.id.fragment_container, alertFragment).commitAllowingStateLoss();
                    alertFragment.startAlert(phoneNumber);
                }
            }
        }, 4000);
    }
}

AlertFragment:

В этом фрагменте в startAlert Im добавляется вспомогательный класс к executorService, который запуститфактическая вибрация.Переменная isRunning здесь, потому что во время работы, если часы получают новое сообщение с другого номера, они обычно останавливают вибрацию.

public class AlertFragment extends Fragment {

    private Button cancelButton;
    private Future longRunningTaskFuture;
    private ConnectionService mService;
    private PowerManager powerManager;
    private FragmentManager supportFragmentManager;
    private PowerManager.WakeLock wakeLock;
    AlertHelper longRunningTask = new AlertHelper();
    public boolean isRunning = false;
    private boolean mBound = false;
    private final String TYPE = "feedback";
    private static final String SENDER_PHONE_NUMBER = MyApplication.getAppContext().getResources().getString(R.string.sender_phone);
    private View.OnClickListener onAlertButtonPressedListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mService.sendMessage(new Message(TYPE, "1").toJson());
            supportFragmentManager.beginTransaction().replace(R.id.fragment_container, new MainFragment()).commit();
            stopAlert();
        }
    };

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();
        supportFragmentManager = getActivity().getSupportFragmentManager();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        wakeUpWatch();
        Intent intent = new Intent(context, ConnectionService.class);
        context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.alert_fragment, container, false);
        if (view != null) {
            cancelButton = (Button) view.findViewById(R.id.stop_button);
            cancelButton.setOnClickListener(onAlertButtonPressedListener);
        }
        ((DrawerLock) getActivity()).setDrawerLocked(true);
        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        //No call for super(). Bug on API Level > 11.
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ((DrawerLock) getActivity()).setDrawerLocked(false);
    }

    public void startAlert(String phoneNumber) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        // submit task to threadpool:
        if (isRunning || phoneNumber.equals(SENDER_PHONE_NUMBER)) {
            longRunningTaskFuture = executorService.submit(longRunningTask);
            isRunning = true;
        }
    }

    public void stopAlert() {
        longRunningTaskFuture.cancel(true);
        longRunningTaskFuture = null;
        isRunning = false;
        longRunningTask.vibrator.cancel();
        releaseWakeLock();
    }

    private void wakeUpWatch() {
        Intent intent = new Intent(getActivity().getApplicationContext(), MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // You need this if starting
        //  the activity from a service
        intent.setAction(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        startActivity(intent);
        powerManager = (PowerManager) MyApplication.getAppContext().getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK,"MyWakelockTag");
        wakeLock.acquire();
    }

    private void releaseWakeLock() {
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder service) {
            ConnectionService.LocalBinder binder = (ConnectionService.LocalBinder) service;
            mService = binder.getServiceInstance();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

И, наконец, класс AlertHelper фактически запустит вибрацию:

public class AlertHelper implements Runnable {

    Vibrator vibrator = (Vibrator) MyApplication.getAppContext().getSystemService(Context.VIBRATOR_SERVICE);
    public volatile boolean isRunning;
    private final long[] mVibratePattern = new long[]{0, 400, 800, 600, 800, 800, 800, 1000};
    private final int[] mAmplitudes = new int[]{0, 255, 0, 255, 0, 255, 0, 255};

    @Override
    public void run() {
        this.isRunning = true;
        if (this.vibrator != null) {
            this.vibrator.vibrate(VibrationEffect.createWaveform(mVibratePattern, mAmplitudes, 0));
        }
    }
}

Так что я понятия не имею, вибрация обычно работает так, как должна, но иногда она простонет.У меня всегда была эта ошибка с каждой реализацией, поэтому я начинаю думать, что это может быть ошибка, о которой я не знаю.Какое здесь может быть решение?

РЕДАКТИРОВАТЬ:

Ошибка не в MainActivity, так как экран всегда меняется, как и должно быть, поэтому проблема должна бытьс оповещением классов

...