generated from Grigo/AndroidTemplate
Подготовка к крупным изменениям: карта, AIS и UI
- Яндекс/MapForge: правки в менеджерах и обёртках маркеров (улучшена отрисовка/логика) - NMEAParser: корректировки парсинга и стабильности - Модель AISVessel: уточнение полей/логики - Настройки: правки в SettingsActivity и SettingsManager, актуализация AppController - UI: обновлены activity_main, activity_settings, bottom_sheet_ais_vessel; меню main_menu - Ресурсы: добавлен drawable/targetclassa.xml, обновлён drawable/target.xml - Конфигурация: правки AndroidManifest и app/build.gradle - Прочее: изменения в .idea (не влияют на сборку)
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
package com.grigowashere.aismap.services;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.media.ToneGenerator;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.os.VibratorManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import com.grigowashere.aismap.MainActivity;
|
||||
import com.grigowashere.aismap.R;
|
||||
import com.grigowashere.aismap.utils.SettingsManager;
|
||||
|
||||
/**
|
||||
* Сервис для обработки уведомлений о новых AIS целях
|
||||
* Поддерживает вибрацию и звуковые уведомления
|
||||
*/
|
||||
public class NotificationService {
|
||||
|
||||
private static final String TAG = "NotificationService";
|
||||
private static final String ALERT_CHANNEL_ID = "aismap_alerts";
|
||||
private static final int SAFETY_NOTIFICATION_ID_BASE = 2000;
|
||||
|
||||
private Context context;
|
||||
private SettingsManager settingsManager;
|
||||
private Vibrator vibrator;
|
||||
private ToneGenerator toneGenerator;
|
||||
private boolean isInitialized = false;
|
||||
|
||||
public NotificationService(Context context) {
|
||||
this.context = context;
|
||||
this.settingsManager = new SettingsManager(context);
|
||||
initializeService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализирует сервис уведомлений
|
||||
*/
|
||||
private void initializeService() {
|
||||
try {
|
||||
createAlertChannel();
|
||||
// Инициализация вибратора
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
|
||||
VibratorManager vibratorManager = (VibratorManager) context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE);
|
||||
vibrator = vibratorManager.getDefaultVibrator();
|
||||
} else {
|
||||
vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
}
|
||||
|
||||
// Инициализация генератора тонов
|
||||
toneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
|
||||
|
||||
isInitialized = true;
|
||||
Log.i(TAG, "Сервис уведомлений инициализирован успешно");
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Ошибка инициализации сервиса уведомлений: " + e.getMessage(), e);
|
||||
isInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает канал уведомлений для предупреждений (Android O+)
|
||||
*/
|
||||
private void createAlertChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(
|
||||
ALERT_CHANNEL_ID,
|
||||
"AIS Alerts",
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
);
|
||||
channel.setDescription("Сообщения безопасности AIS и предупреждения");
|
||||
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (nm != null) nm.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Воспроизводит уведомление о новой AIS цели
|
||||
*/
|
||||
public void notifyNewAISTarget() {
|
||||
if (!isInitialized) {
|
||||
Log.w(TAG, "Сервис уведомлений не инициализирован");
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверяем настройки и воспроизводим соответствующие уведомления
|
||||
if (settingsManager.isVibrationEnabled()) {
|
||||
playVibration();
|
||||
}
|
||||
|
||||
if (settingsManager.isSoundEnabled()) {
|
||||
playSound();
|
||||
}
|
||||
|
||||
Log.i(TAG, "Уведомление о новой AIS цели воспроизведено");
|
||||
}
|
||||
|
||||
/**
|
||||
* Воспроизводит вибрацию
|
||||
*/
|
||||
private void playVibration() {
|
||||
try {
|
||||
if (vibrator != null && vibrator.hasVibrator()) {
|
||||
// Паттерн вибрации: короткая пауза, длинная вибрация, короткая пауза, короткая вибрация
|
||||
long[] pattern = {0, 200, 100, 100};
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
VibrationEffect effect = VibrationEffect.createWaveform(pattern, -1);
|
||||
vibrator.vibrate(effect);
|
||||
} else {
|
||||
vibrator.vibrate(pattern, -1);
|
||||
}
|
||||
|
||||
Log.d(TAG, "Вибрация воспроизведена");
|
||||
} else {
|
||||
Log.w(TAG, "Вибратор недоступен");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Ошибка воспроизведения вибрации: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Воспроизводит звуковое уведомление
|
||||
*/
|
||||
private void playSound() {
|
||||
try {
|
||||
if (toneGenerator != null) {
|
||||
// Воспроизводим тон уведомления (TONE_CDMA_ALERT_CALL_GUARD)
|
||||
toneGenerator.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 500);
|
||||
|
||||
Log.d(TAG, "Звуковое уведомление воспроизведено");
|
||||
} else {
|
||||
Log.w(TAG, "Генератор тонов недоступен");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Ошибка воспроизведения звука: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, включены ли уведомления
|
||||
*/
|
||||
public boolean areNotificationsEnabled() {
|
||||
return settingsManager.isVibrationEnabled() || settingsManager.isSoundEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, включена ли вибрация
|
||||
*/
|
||||
public boolean isVibrationEnabled() {
|
||||
return settingsManager.isVibrationEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, включен ли звук
|
||||
*/
|
||||
public boolean isSoundEnabled() {
|
||||
return settingsManager.isSoundEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Уведомление о сообщении безопасности (AIS 14)
|
||||
*/
|
||||
public void notifySafetyMessage(String mmsi, String text) {
|
||||
if (!isInitialized) {
|
||||
Log.w(TAG, "Сервис уведомлений не инициализирован");
|
||||
return;
|
||||
}
|
||||
// Подаем сигнал по настройкам (вибро/звук)
|
||||
if (settingsManager.isVibrationEnabled()) {
|
||||
playVibration();
|
||||
}
|
||||
if (settingsManager.isSoundEnabled()) {
|
||||
playSound();
|
||||
}
|
||||
|
||||
// Показ системного уведомления в шторке
|
||||
try {
|
||||
createAlertChannel();
|
||||
Intent intent = new Intent(context, MainActivity.class);
|
||||
int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT : 0;
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, flags);
|
||||
|
||||
String title = "AIS Safety message";
|
||||
String content = (text != null && !text.isEmpty()) ? text : ("Сообщение от " + mmsi);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, ALERT_CHANNEL_ID)
|
||||
.setSmallIcon(R.mipmap.ic_launcher)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(content))
|
||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setAutoCancel(true);
|
||||
|
||||
int notificationId = SAFETY_NOTIFICATION_ID_BASE + (mmsi != null ? (mmsi.hashCode() & 0x0FFF) : 0);
|
||||
NotificationManagerCompat.from(context).notify(notificationId, builder.build());
|
||||
|
||||
Log.i(TAG, "Показано системное уведомление о safety-сообщении: MMSI=" + mmsi);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Ошибка показа системного уведомления: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Освобождает ресурсы сервиса
|
||||
*/
|
||||
public void cleanup() {
|
||||
try {
|
||||
if (toneGenerator != null) {
|
||||
toneGenerator.release();
|
||||
toneGenerator = null;
|
||||
}
|
||||
|
||||
if (vibrator != null) {
|
||||
vibrator.cancel();
|
||||
}
|
||||
|
||||
isInitialized = false;
|
||||
Log.i(TAG, "Ресурсы сервиса уведомлений освобождены");
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Ошибка при освобождении ресурсов сервиса уведомлений: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user