β Android SMS log reader (inbox/sent/etc)
β Real-time incoming SMS listener (stream)
β OTP read (User Consent API) β Play-safe
Platforms: β Android | β iOS (not supported by iOS APIs)
- Read SMS logs:
- Inbox / Sent / Draft / Outbox / Failed / Queued / All
- Filters:
address,bodyContains,threadId, date rangefrom/to
- Pagination:
limit+offset
- Best-effort SIM info:
subId(if available on device/ROM)
- Incoming SMS events:
- Works while your app process is alive
- Uses BroadcastReceiver for
SMS_RECEIVED
- Optional store change watcher:
- ContentObserver on
content://sms - Emits
store_changedevents (and can fetch latest message ifREAD_SMSgranted)
- ContentObserver on
- Send SMS through this plugin (uses
SmsManager) - Get
sent/deliveredcallbacks via events stream
(Status callbacks are only guaranteed for messages sent via this plugin.)
- OTP via SMS User Consent API
- No
READ_SMS/RECEIVE_SMSruntime permission required - Provide a regex like
\b\d{4,8}\b
Google Play restricts use of SMS permissions (like READ_SMS, RECEIVE_SMS).
If your app does not qualify under Play policies, do not include those permissions.
Use OTP via User Consent / SMS Retriever instead.
dependencies:
advanced_sms_log: ^1.0.1Add to your app android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<!-- Only if you send SMS via plugin -->
<uses-permission android:name="android.permission.SEND_SMS" />If you publish on Google Play, ensure policy compliance before requesting SMS permissions.
This plugin uses Google Play Services Auth API Phone for OTP consent.
The dependency is already included in the plugin's Android Gradle config.
import 'package:advanced_sms_log/advanced_sms_log.dart';
final ok = await AdvancedSmsLog.requestSmsLogPermission();
if (!ok) return;
final items = await AdvancedSmsLog.getSms(
box: SmsBox.inbox,
limit: 50,
offset: 0,
bodyContains: 'otp',
);
for (final m in items) {
print('${m.address} ${m.date} ${m.body}');
}await AdvancedSmsLog.startIncomingListener(
useBroadcast: true,
useObserver: true,
);
final sub = AdvancedSmsLog.events.listen((e) {
if (e.type == SmsEventType.received) {
final sms = e.sms;
print('Incoming: ${sms?.address} -> ${sms?.body}');
}
});
// later...
// await AdvancedSmsLog.stopIncomingListener();
// await sub.cancel();await AdvancedSmsLog.startOtpUserConsent(
otpRegex: r'\b\d{4,8}\b',
);
AdvancedSmsLog.events.listen((e) {
if (e.type == SmsEventType.otp) {
print('OTP: ${e.otp}');
print('Message: ${e.message}');
}
});final ok = await AdvancedSmsLog.requestSendPermission();
if (!ok) return;
final sent = await AdvancedSmsLog.sendSms(
to: '+919999999999',
message: 'Hello from advanced_sms_log',
);
print('sendSms(): $sent');SmsBox:inbox,sent,draft,outbox,failed,queued,all
SmsLogid,address,body,date,dateSent,threadId,type,read,seen,subId
receivedβSmsLogstore_changedβSmsLog?(ifREAD_SMSgranted, we include latest)sent_statusβ{messageId, kind, status, resultCode}otpβ{otp, message}errorβ{error}
doc/USAGE.mddoc/ARCHITECTURE.md
If this package saves you development time, consider supporting my work.
https://github.com/sponsors/nousath
See CHANGELOG.md.
