init
This commit is contained in:
@@ -16,24 +16,23 @@ class ApiService {
|
||||
if (_token != null) 'Authorization': 'Bearer $_token',
|
||||
};
|
||||
|
||||
Future<String> login(String username, String password) async {
|
||||
Future<bool> verifyToken(String token) async {
|
||||
final res = await http.post(
|
||||
Uri.parse('$_baseUrl/api/auth/login'),
|
||||
Uri.parse('$_baseUrl/api/auth/verify'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: jsonEncode({'username': username, 'password': password}),
|
||||
body: jsonEncode({'token': token}),
|
||||
);
|
||||
if (res.statusCode != 200) throw Exception(_error(res));
|
||||
return jsonDecode(res.body)['token'];
|
||||
return res.statusCode == 200;
|
||||
}
|
||||
|
||||
Future<String> register(String username, String password) async {
|
||||
final res = await http.post(
|
||||
Uri.parse('$_baseUrl/api/auth/register'),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: jsonEncode({'username': username, 'password': password}),
|
||||
Future<List<Map<String, dynamic>>> fetchServerSms() async {
|
||||
final res = await http.get(
|
||||
Uri.parse('$_baseUrl/api/sms?limit=999999'),
|
||||
headers: _headers,
|
||||
);
|
||||
if (res.statusCode != 201) throw Exception(_error(res));
|
||||
return jsonDecode(res.body)['token'];
|
||||
if (res.statusCode != 200) throw Exception(_error(res));
|
||||
final data = jsonDecode(res.body);
|
||||
return List<Map<String, dynamic>>.from(data['messages']);
|
||||
}
|
||||
|
||||
Future<int> uploadSms(List<SmsMessage> messages) async {
|
||||
|
||||
76
app/lib/services/sms_foreground_handler.dart
Normal file
76
app/lib/services/sms_foreground_handler.dart
Normal file
@@ -0,0 +1,76 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
import 'package:telephony/telephony.dart' as tel;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../models/sms_message.dart';
|
||||
|
||||
class SmsForegroundHandler extends TaskHandler {
|
||||
StreamSubscription? _smsSub;
|
||||
int _uploadedCount = 0;
|
||||
|
||||
@override
|
||||
Future<void> onStart(DateTime timestamp, TaskStarter starter) async {
|
||||
_startListening();
|
||||
}
|
||||
|
||||
@override
|
||||
void onRepeatEvent(DateTime timestamp) {}
|
||||
|
||||
@override
|
||||
Future<void> onDestroy(DateTime timestamp) async {
|
||||
_smsSub?.cancel();
|
||||
}
|
||||
|
||||
@override
|
||||
void onNotificationPressed() {
|
||||
FlutterForegroundTask.launchApp('/');
|
||||
}
|
||||
|
||||
void _startListening() async {
|
||||
final telephony = tel.Telephony.instance;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final baseUrl = prefs.getString('server_url') ?? '';
|
||||
final token = prefs.getString('token') ?? '';
|
||||
|
||||
telephony.listenIncomingSms(
|
||||
onNewMessage: (tel.SmsMessage sms) async {
|
||||
final msg = SmsMessage(
|
||||
phoneNumber: sms.address ?? '',
|
||||
contactName: sms.address,
|
||||
content: sms.body ?? '',
|
||||
type: 'received',
|
||||
smsDate: DateTime.now().toUtc().toIso8601String(),
|
||||
);
|
||||
|
||||
if (baseUrl.isNotEmpty && token.isNotEmpty) {
|
||||
try {
|
||||
await http.post(
|
||||
Uri.parse('$baseUrl/api/sms/upload'),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
},
|
||||
body: jsonEncode([msg.toJson()]),
|
||||
);
|
||||
_uploadedCount++;
|
||||
FlutterForegroundTask.updateService(
|
||||
notificationText: '已自动上传 $_uploadedCount 条短信',
|
||||
);
|
||||
} catch (_) {
|
||||
FlutterForegroundTask.updateService(
|
||||
notificationText: '上传失败,等待重试... (已上传 $_uploadedCount 条)',
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
listenInBackground: false,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void startCallback() {
|
||||
FlutterForegroundTask.setTaskHandler(SmsForegroundHandler());
|
||||
}
|
||||
@@ -1,36 +1,60 @@
|
||||
import 'dart:async';
|
||||
import 'package:sms_maintained/sms_maintained.dart';
|
||||
import 'package:telephony/telephony.dart' as tel;
|
||||
import '../models/sms_message.dart';
|
||||
|
||||
class SmsReaderService {
|
||||
final _telephony = tel.Telephony.instance;
|
||||
|
||||
Future<List<SmsMessage>> queryAllSms() async {
|
||||
final messages = <SmsMessage>[];
|
||||
final all = await SmsQuery().querySms(
|
||||
kinds: [SmsQueryKind.Inbox, SmsQueryKind.Sent],
|
||||
|
||||
final inbox = await _telephony.getInboxSms(
|
||||
columns: [tel.SmsColumn.ADDRESS, tel.SmsColumn.BODY, tel.SmsColumn.DATE],
|
||||
);
|
||||
for (final s in all) {
|
||||
for (final s in inbox) {
|
||||
messages.add(SmsMessage(
|
||||
phoneNumber: s.address ?? '',
|
||||
contactName: s.sender ?? s.address,
|
||||
contactName: s.address,
|
||||
content: s.body ?? '',
|
||||
type: s.kind == SmsQueryKind.Sent ? 'sent' : 'received',
|
||||
smsDate: DateTime.fromMillisecondsSinceEpoch(s.date!).toUtc().toIso8601String(),
|
||||
type: 'received',
|
||||
smsDate: s.date != null
|
||||
? DateTime.fromMillisecondsSinceEpoch(s.date!).toUtc().toIso8601String()
|
||||
: DateTime.now().toUtc().toIso8601String(),
|
||||
));
|
||||
}
|
||||
|
||||
final sent = await _telephony.getSentSms(
|
||||
columns: [tel.SmsColumn.ADDRESS, tel.SmsColumn.BODY, tel.SmsColumn.DATE],
|
||||
);
|
||||
for (final s in sent) {
|
||||
messages.add(SmsMessage(
|
||||
phoneNumber: s.address ?? '',
|
||||
contactName: s.address,
|
||||
content: s.body ?? '',
|
||||
type: 'sent',
|
||||
smsDate: s.date != null
|
||||
? DateTime.fromMillisecondsSinceEpoch(s.date!).toUtc().toIso8601String()
|
||||
: DateTime.now().toUtc().toIso8601String(),
|
||||
));
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
Stream<SmsMessage> listenToIncoming() {
|
||||
final controller = StreamController<SmsMessage>.broadcast();
|
||||
SmsReceiver().onSmsReceived!.listen((SmsMessage sms) {
|
||||
controller.add(SmsMessage(
|
||||
phoneNumber: sms.address ?? '',
|
||||
contactName: sms.sender ?? sms.address,
|
||||
content: sms.body ?? '',
|
||||
type: 'received',
|
||||
smsDate: DateTime.now().toUtc().toIso8601String(),
|
||||
));
|
||||
});
|
||||
_telephony.listenIncomingSms(
|
||||
onNewMessage: (tel.SmsMessage sms) {
|
||||
controller.add(SmsMessage(
|
||||
phoneNumber: sms.address ?? '',
|
||||
contactName: sms.address,
|
||||
content: sms.body ?? '',
|
||||
type: 'received',
|
||||
smsDate: DateTime.now().toUtc().toIso8601String(),
|
||||
));
|
||||
},
|
||||
listenInBackground: false,
|
||||
);
|
||||
return controller.stream;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user