Я разрабатываю для часов 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, так как экран всегда меняется, как и должно быть, поэтому проблема должна бытьс оповещением классов