Files
jinzhi/lib/common/push/device_push_registrar.dart
T
2026-08-24 19:07:31 +08:00

96 lines
2.6 KiB
Dart

import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:package_info_plus/package_info_plus.dart';
import '../network/dio_provider.dart';
import 'notification_permission.dart';
import 'umeng_push_service.dart';
class DevicePushRegistrar {
DevicePushRegistrar(this._read);
final T Function<T>(ProviderListenable<T>) _read;
StreamSubscription<String>? _subscription;
String? _lastToken;
bool? _lastPermission;
int _attempt = 0;
void start() {
_subscription ??= UmengPushService.onDeviceToken.listen(_register);
UmengPushService.emitCachedToken();
}
Future<void> stop() async => _subscription?.cancel();
Future<void> refresh() => UmengPushService.refreshDeviceToken();
void forceRegisterCurrentToken() {
_lastToken = null;
_lastPermission = null;
UmengPushService.emitCachedToken();
}
Future<void> _register(String token) async {
final permission = await NotificationPermission.isGranted();
if (token == _lastToken && permission == _lastPermission) return;
try {
final package = await PackageInfo.fromPlatform();
await _read(dioProvider).post<List<int>>(
'/api/v1/push/devices',
data: _PushRegisterRequest(
token: token,
platform: defaultTargetPlatform == TargetPlatform.iOS ? 1 : 2,
version: package.version,
permission: permission,
).toBytes(),
options: protobufOptions(),
);
_lastToken = token;
_lastPermission = permission;
_attempt = 0;
} catch (_) {
if (_attempt++ >= 3) return;
await Future<void>.delayed(Duration(seconds: 1 << (_attempt - 1)));
await _register(token);
}
}
}
class _PushRegisterRequest {
const _PushRegisterRequest({
required this.token,
required this.platform,
required this.version,
required this.permission,
});
final String token;
final int platform;
final String version;
final bool permission;
Uint8List toBytes() {
final bytes = BytesBuilder(copy: false);
void putInt(int value) {
while (value > 0x7f) {
bytes.addByte((value & 0x7f) | 0x80);
value >>= 7;
}
bytes.addByte(value);
}
void putString(int tag, String value) {
final raw = value.codeUnits;
putInt((tag << 3) | 2);
putInt(raw.length);
bytes.add(raw);
}
putString(1, token);
putInt(2 << 3);
putInt(platform);
putString(3, version);
putInt(4 << 3);
putInt(permission ? 1 : 0);
return bytes.toBytes();
}
}