feat(android): track sms sent, delivered, and failed status

This commit is contained in:
isra el
2025-06-02 20:42:14 +03:00
parent f355065bfb
commit 64859b38ad
7 changed files with 626 additions and 33 deletions

View File

@@ -44,6 +44,15 @@
</intent-filter>
</receiver>
<receiver
android:name=".receivers.SMSStatusReceiver"
android:exported="true">
<intent-filter>
<action android:name="SMS_SENT" />
<action android:name="SMS_DELIVERED" />
</intent-filter>
</receiver>
<receiver android:enabled="true"
android:name=".receivers.BootCompletedReceiver"
android:exported="true"

View File

@@ -7,6 +7,15 @@ public class SMSDTO {
private String message = "";
private long receivedAtInMillis;
private String smsId;
private String smsBatchId;
private String status;
private long sentAtInMillis;
private long deliveredAtInMillis;
private long failedAtInMillis;
private String errorCode;
private String errorMessage;
public SMSDTO() {
}
@@ -34,4 +43,68 @@ public class SMSDTO {
public void setReceivedAtInMillis(long receivedAtInMillis) {
this.receivedAtInMillis = receivedAtInMillis;
}
public String getSmsId() {
return smsId;
}
public void setSmsId(String smsId) {
this.smsId = smsId;
}
public String getSmsBatchId() {
return smsBatchId;
}
public void setSmsBatchId(String smsBatchId) {
this.smsBatchId = smsBatchId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public long getSentAtInMillis() {
return sentAtInMillis;
}
public void setSentAtInMillis(long sentAtInMillis) {
this.sentAtInMillis = sentAtInMillis;
}
public long getDeliveredAtInMillis() {
return deliveredAtInMillis;
}
public void setDeliveredAtInMillis(long deliveredAtInMillis) {
this.deliveredAtInMillis = deliveredAtInMillis;
}
public long getFailedAtInMillis() {
return failedAtInMillis;
}
public void setFailedAtInMillis(long failedAtInMillis) {
this.failedAtInMillis = failedAtInMillis;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

View File

@@ -1,25 +1,236 @@
package com.vernu.sms.helpers;
import android.Manifest;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsManager;
import android.os.Build;
import android.telephony.SubscriptionManager;
import android.util.Log;
import com.vernu.sms.ApiManager;
import com.vernu.sms.AppConstants;
import com.vernu.sms.TextBeeUtils;
import com.vernu.sms.dtos.SMSDTO;
import com.vernu.sms.dtos.SMSForwardResponseDTO;
import com.vernu.sms.receivers.SMSStatusReceiver;
import com.vernu.sms.services.GatewayApiService;
import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class SMSHelper {
public static void sendSMS(String phoneNo, String message) {
SmsManager smsManager = SmsManager.getDefault();
//for sms with more than 160 chars
ArrayList<String> parts = smsManager.divideMessage(message);
if (parts.size() > 1) {
smsManager.sendMultipartTextMessage(phoneNo, null, parts, null, null);
} else {
smsManager.sendTextMessage(phoneNo, null, message, null, null);
private static final String TAG = "SMSHelper";
/**
* Sends an SMS message and returns whether the operation was successful
*
* @param phoneNo The recipient's phone number
* @param message The SMS message to send
* @param smsId The unique ID for this SMS
* @param smsBatchId The batch ID for this SMS
* @param context The application context
* @return boolean True if sending was initiated, false if permissions aren't granted
*/
public static boolean sendSMS(String phoneNo, String message, String smsId, String smsBatchId, Context context) {
// Check if we have permission to send SMS
if (!TextBeeUtils.isPermissionGranted(context, Manifest.permission.SEND_SMS)) {
Log.e(TAG, "SMS permission not granted. Unable to send SMS.");
// Report failure to API
reportPermissionError(context, smsId, smsBatchId);
return false;
}
try {
SmsManager smsManager = SmsManager.getDefault();
// Create pending intents for status tracking
PendingIntent sentIntent = createSentPendingIntent(context, smsId, smsBatchId);
PendingIntent deliveredIntent = createDeliveredPendingIntent(context, smsId, smsBatchId);
// For SMS with more than 160 chars
ArrayList<String> parts = smsManager.divideMessage(message);
if (parts.size() > 1) {
ArrayList<PendingIntent> sentIntents = new ArrayList<>();
ArrayList<PendingIntent> deliveredIntents = new ArrayList<>();
for (int i = 0; i < parts.size(); i++) {
sentIntents.add(sentIntent);
deliveredIntents.add(deliveredIntent);
}
smsManager.sendMultipartTextMessage(phoneNo, null, parts, sentIntents, deliveredIntents);
} else {
smsManager.sendTextMessage(phoneNo, null, message, sentIntent, deliveredIntent);
}
return true;
} catch (Exception e) {
Log.e(TAG, "Exception when sending SMS: " + e.getMessage());
// Report exception to API
reportSendingError(context, smsId, smsBatchId, e.getMessage());
return false;
}
}
/**
* Sends an SMS message from a specific SIM slot and returns whether the operation was successful
*
* @param phoneNo The recipient's phone number
* @param message The SMS message to send
* @param simSubscriptionId The specific SIM subscription ID to use
* @param smsId The unique ID for this SMS
* @param smsBatchId The batch ID for this SMS
* @param context The application context
* @return boolean True if sending was initiated, false if permissions aren't granted
*/
public static boolean sendSMSFromSpecificSim(String phoneNo, String message, int simSubscriptionId,
String smsId, String smsBatchId, Context context) {
// Check for required permissions
if (!TextBeeUtils.isPermissionGranted(context, Manifest.permission.SEND_SMS) ||
!TextBeeUtils.isPermissionGranted(context, Manifest.permission.READ_PHONE_STATE)) {
Log.e(TAG, "SMS or Phone State permission not granted. Unable to send SMS from specific SIM.");
// Report failure to API
reportPermissionError(context, smsId, smsBatchId);
return false;
}
try {
// Get the SmsManager for the specific SIM
SmsManager smsManager;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
smsManager = SmsManager.getSmsManagerForSubscriptionId(simSubscriptionId);
} else {
// Fallback to default SmsManager for older Android versions
smsManager = SmsManager.getDefault();
Log.w(TAG, "Using default SIM as specific SIM selection not supported on this Android version");
}
public static void sendSMSFromSpecificSim(String phoneNo, String message, int simSlot) {
SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(simSlot);
smsManager.sendMultipartTextMessage(phoneNo, null, smsManager.divideMessage(message), null, null);
// Create pending intents for status tracking
PendingIntent sentIntent = createSentPendingIntent(context, smsId, smsBatchId);
PendingIntent deliveredIntent = createDeliveredPendingIntent(context, smsId, smsBatchId);
// For SMS with more than 160 chars
ArrayList<String> parts = smsManager.divideMessage(message);
if (parts.size() > 1) {
ArrayList<PendingIntent> sentIntents = new ArrayList<>();
ArrayList<PendingIntent> deliveredIntents = new ArrayList<>();
for (int i = 0; i < parts.size(); i++) {
sentIntents.add(sentIntent);
deliveredIntents.add(deliveredIntent);
}
smsManager.sendMultipartTextMessage(phoneNo, null, parts, sentIntents, deliveredIntents);
} else {
smsManager.sendTextMessage(phoneNo, null, message, sentIntent, deliveredIntent);
}
return true;
} catch (Exception e) {
Log.e(TAG, "Exception when sending SMS from specific SIM: " + e.getMessage());
// Report exception to API
reportSendingError(context, smsId, smsBatchId, e.getMessage());
return false;
}
}
private static void reportPermissionError(Context context, String smsId, String smsBatchId) {
SMSDTO smsDTO = new SMSDTO();
smsDTO.setSmsId(smsId);
smsDTO.setSmsBatchId(smsBatchId);
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(System.currentTimeMillis());
smsDTO.setErrorCode("PERMISSION_DENIED");
smsDTO.setErrorMessage("SMS permission not granted");
updateSMSStatus(context, smsDTO);
}
private static void reportSendingError(Context context, String smsId, String smsBatchId, String errorMessage) {
SMSDTO smsDTO = new SMSDTO();
smsDTO.setSmsId(smsId);
smsDTO.setSmsBatchId(smsBatchId);
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(System.currentTimeMillis());
smsDTO.setErrorCode("SENDING_EXCEPTION");
smsDTO.setErrorMessage(errorMessage);
updateSMSStatus(context, smsDTO);
}
private static void updateSMSStatus(Context context, SMSDTO smsDTO) {
String deviceId = SharedPreferenceHelper.getSharedPreferenceString(context, AppConstants.SHARED_PREFS_DEVICE_ID_KEY, "");
String apiKey = SharedPreferenceHelper.getSharedPreferenceString(context, AppConstants.SHARED_PREFS_API_KEY_KEY, "");
if (deviceId.isEmpty() || apiKey.isEmpty()) {
Log.e(TAG, "Device ID or API key not found");
return;
}
GatewayApiService apiService = ApiManager.getApiService();
Call<SMSForwardResponseDTO> call = apiService.updateSMSStatus(deviceId, apiKey, smsDTO);
call.enqueue(new Callback<SMSForwardResponseDTO>() {
@Override
public void onResponse(Call<SMSForwardResponseDTO> call, Response<SMSForwardResponseDTO> response) {
if (response.isSuccessful()) {
Log.d(TAG, "SMS status updated successfully - ID: " + smsDTO.getSmsId() + ", Status: " + smsDTO.getStatus());
} else {
Log.e(TAG, "Failed to update SMS status. Response code: " + response.code());
}
}
@Override
public void onFailure(Call<SMSForwardResponseDTO> call, Throwable t) {
Log.e(TAG, "API call failed: " + t.getMessage());
}
});
}
private static PendingIntent createSentPendingIntent(Context context, String smsId, String smsBatchId) {
// Create explicit intent (specify the component)
Intent intent = new Intent(context, SMSStatusReceiver.class);
intent.setAction(SMSStatusReceiver.SMS_SENT);
intent.putExtra("sms_id", smsId);
intent.putExtra("sms_batch_id", smsBatchId);
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags |= PendingIntent.FLAG_MUTABLE;
}
// Use a unique request code to avoid PendingIntent collisions
int requestCode = (smsId + "_sent").hashCode();
return PendingIntent.getBroadcast(context, requestCode, intent, flags);
}
private static PendingIntent createDeliveredPendingIntent(Context context, String smsId, String smsBatchId) {
// Create explicit intent (specify the component)
Intent intent = new Intent(context, SMSStatusReceiver.class);
intent.setAction(SMSStatusReceiver.SMS_DELIVERED);
intent.putExtra("sms_id", smsId);
intent.putExtra("sms_batch_id", smsBatchId);
int flags = PendingIntent.FLAG_UPDATE_CURRENT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags |= PendingIntent.FLAG_MUTABLE;
}
// Use a unique request code to avoid PendingIntent collisions
int requestCode = (smsId + "_delivered").hashCode();
return PendingIntent.getBroadcast(context, requestCode, intent, flags);
}
}

View File

@@ -4,6 +4,8 @@ public class SMSPayload {
private String[] recipients;
private String message;
private String smsId;
private String smsBatchId;
// Legacy fields that are no longer used
private String[] receivers;
@@ -27,4 +29,20 @@ public class SMSPayload {
public void setMessage(String message) {
this.message = message;
}
public String getSmsId() {
return smsId;
}
public void setSmsId(String smsId) {
this.smsId = smsId;
}
public String getSmsBatchId() {
return smsBatchId;
}
public void setSmsBatchId(String smsBatchId) {
this.smsBatchId = smsBatchId;
}
}

View File

@@ -0,0 +1,180 @@
package com.vernu.sms.receivers;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsManager;
import android.util.Log;
import com.vernu.sms.ApiManager;
import com.vernu.sms.AppConstants;
import com.vernu.sms.dtos.SMSDTO;
import com.vernu.sms.dtos.SMSForwardResponseDTO;
import com.vernu.sms.helpers.SharedPreferenceHelper;
import com.vernu.sms.services.GatewayApiService;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class SMSStatusReceiver extends BroadcastReceiver {
private static final String TAG = "SMSStatusReceiver";
public static final String SMS_SENT = "SMS_SENT";
public static final String SMS_DELIVERED = "SMS_DELIVERED";
@Override
public void onReceive(Context context, Intent intent) {
String smsId = intent.getStringExtra("sms_id");
String smsBatchId = intent.getStringExtra("sms_batch_id");
String action = intent.getAction();
SMSDTO smsDTO = new SMSDTO();
smsDTO.setSmsId(smsId);
smsDTO.setSmsBatchId(smsBatchId);
if (SMS_SENT.equals(action)) {
handleSentStatus(context, getResultCode(), smsDTO);
} else if (SMS_DELIVERED.equals(action)) {
handleDeliveredStatus(context, getResultCode(), smsDTO);
}
}
private void handleSentStatus(Context context, int resultCode, SMSDTO smsDTO) {
long timestamp = System.currentTimeMillis();
String errorMessage = "";
switch (resultCode) {
case Activity.RESULT_OK:
smsDTO.setStatus("SENT");
smsDTO.setSentAtInMillis(timestamp);
Log.d(TAG, "SMS sent successfully - ID: " + smsDTO.getSmsId());
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
errorMessage = "Generic failure";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
errorMessage = "Radio off";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
errorMessage = "Null PDU";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
errorMessage = "No service";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
case SmsManager.RESULT_ERROR_LIMIT_EXCEEDED:
errorMessage = "Sending limit exceeded";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
case SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED:
errorMessage = "Short code not allowed";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
case SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED:
errorMessage = "Short code never allowed";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
default:
errorMessage = "Unknown error";
smsDTO.setStatus("FAILED");
smsDTO.setFailedAtInMillis(timestamp);
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS failed to send - ID: " + smsDTO.getSmsId() + ", Unknown error code: " + resultCode);
break;
}
updateSMSStatus(context, smsDTO);
}
private void handleDeliveredStatus(Context context, int resultCode, SMSDTO smsDTO) {
long timestamp = System.currentTimeMillis();
String errorMessage = "";
switch (resultCode) {
case Activity.RESULT_OK:
smsDTO.setStatus("DELIVERED");
smsDTO.setDeliveredAtInMillis(timestamp);
Log.d(TAG, "SMS delivered successfully - ID: " + smsDTO.getSmsId());
break;
case Activity.RESULT_CANCELED:
errorMessage = "Delivery canceled";
smsDTO.setStatus("DELIVERY_FAILED");
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS delivery failed - ID: " + smsDTO.getSmsId() + ", Error code: " + resultCode + ", Error: " + errorMessage);
break;
default:
errorMessage = "Unknown delivery error";
smsDTO.setStatus("DELIVERY_FAILED");
smsDTO.setErrorCode(String.valueOf(resultCode));
smsDTO.setErrorMessage(errorMessage);
Log.e(TAG, "SMS delivery failed - ID: " + smsDTO.getSmsId() + ", Unknown error code: " + resultCode);
break;
}
updateSMSStatus(context, smsDTO);
}
private void updateSMSStatus(Context context, SMSDTO smsDTO) {
String deviceId = SharedPreferenceHelper.getSharedPreferenceString(context, AppConstants.SHARED_PREFS_DEVICE_ID_KEY, "");
String apiKey = SharedPreferenceHelper.getSharedPreferenceString(context, AppConstants.SHARED_PREFS_API_KEY_KEY, "");
if (deviceId.isEmpty() || apiKey.isEmpty()) {
Log.e(TAG, "Device ID or API key not found");
return;
}
GatewayApiService apiService = ApiManager.getApiService();
Call<SMSForwardResponseDTO> call = apiService.updateSMSStatus(deviceId, apiKey, smsDTO);
call.enqueue(new Callback<SMSForwardResponseDTO>() {
@Override
public void onResponse(Call<SMSForwardResponseDTO> call, Response<SMSForwardResponseDTO> response) {
if (response.isSuccessful()) {
Log.d(TAG, "SMS status updated successfully - ID: " + smsDTO.getSmsId() + ", Status: " + smsDTO.getStatus());
} else {
Log.e(TAG, "Failed to update SMS status. Response code: " + response.code());
}
}
@Override
public void onFailure(Call<SMSForwardResponseDTO> call, Throwable t) {
Log.e(TAG, "API call failed: " + t.getMessage());
}
});
}
}

View File

@@ -19,6 +19,12 @@ import com.vernu.sms.activities.MainActivity;
import com.vernu.sms.helpers.SMSHelper;
import com.vernu.sms.helpers.SharedPreferenceHelper;
import com.vernu.sms.models.SMSPayload;
import com.vernu.sms.dtos.RegisterDeviceInputDTO;
import com.vernu.sms.dtos.RegisterDeviceResponseDTO;
import com.vernu.sms.ApiManager;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class FCMService extends FirebaseMessagingService {
@@ -27,33 +33,94 @@ public class FCMService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, remoteMessage.getData().toString());
Gson gson = new Gson();
SMSPayload smsPayload = gson.fromJson(remoteMessage.getData().get("smsData"), SMSPayload.class);
try {
// Parse SMS payload data
Gson gson = new Gson();
SMSPayload smsPayload = gson.fromJson(remoteMessage.getData().get("smsData"), SMSPayload.class);
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
int preferedSim = SharedPreferenceHelper.getSharedPreferenceInt(this, AppConstants.SHARED_PREFS_PREFERRED_SIM_KEY, -1);
for (String receiver : smsPayload.getRecipients()) {
if(preferedSim == -1) {
SMSHelper.sendSMS(receiver, smsPayload.getMessage());
continue;
}
// Check if message contains a data payload
if (remoteMessage.getData().size() > 0) {
sendSMS(smsPayload);
}
// Handle any notification message
if (remoteMessage.getNotification() != null) {
// sendNotification("notif msg", "msg body");
}
} catch (Exception e) {
Log.e(TAG, "Error processing FCM message: " + e.getMessage());
}
}
/**
* Send SMS to recipients using the provided payload
*/
private void sendSMS(SMSPayload smsPayload) {
if (smsPayload == null) {
Log.e(TAG, "SMS payload is null");
return;
}
// Get preferred SIM
int preferredSim = SharedPreferenceHelper.getSharedPreferenceInt(
this, AppConstants.SHARED_PREFS_PREFERRED_SIM_KEY, -1);
// Check if SMS payload contains valid recipients
String[] recipients = smsPayload.getRecipients();
if (recipients == null || recipients.length == 0) {
Log.e(TAG, "No recipients found in SMS payload");
return;
}
// Send SMS to each recipient
boolean atLeastOneSent = false;
int sentCount = 0;
int failedCount = 0;
for (String recipient : recipients) {
boolean smsSent;
// Try to send using default or specific SIM based on preference
if (preferredSim == -1) {
// Use default SIM
smsSent = SMSHelper.sendSMS(
recipient,
smsPayload.getMessage(),
smsPayload.getSmsId(),
smsPayload.getSmsBatchId(),
this
);
} else {
// Use specific SIM
try {
SMSHelper.sendSMSFromSpecificSim(receiver, smsPayload.getMessage(), preferedSim);
} catch(Exception e) {
Log.d("SMS_SEND_ERROR", e.getMessage());
smsSent = SMSHelper.sendSMSFromSpecificSim(
recipient,
smsPayload.getMessage(),
preferredSim,
smsPayload.getSmsId(),
smsPayload.getSmsBatchId(),
this
);
} catch (Exception e) {
Log.e(TAG, "Error sending SMS from specific SIM: " + e.getMessage());
smsSent = false;
}
}
// Track sent and failed counts
if (smsSent) {
sentCount++;
atLeastOneSent = true;
} else {
failedCount++;
}
}
// TODO: Handle FCM Notification Messages
if (remoteMessage.getNotification() != null) {
// sendNotification("notif msg", "msg body");
}
// Log summary
Log.d(TAG, "SMS sending complete - Batch: " + smsPayload.getSmsBatchId() +
", Sent: " + sentCount + ", Failed: " + failedCount);
}
@Override
@@ -62,7 +129,39 @@ public class FCMService extends FirebaseMessagingService {
}
private void sendRegistrationToServer(String token) {
// Check if device ID and API key are saved in shared preferences
String deviceId = SharedPreferenceHelper.getSharedPreferenceString(this, AppConstants.SHARED_PREFS_DEVICE_ID_KEY, "");
String apiKey = SharedPreferenceHelper.getSharedPreferenceString(this, AppConstants.SHARED_PREFS_API_KEY_KEY, "");
// Only proceed if both device ID and API key are available
if (deviceId.isEmpty() || apiKey.isEmpty()) {
Log.d(TAG, "Device ID or API key not available, skipping FCM token update");
return;
}
// Create update payload with new FCM token
RegisterDeviceInputDTO updateInput = new RegisterDeviceInputDTO();
updateInput.setFcmToken(token);
// Call API to update the device with new token
Log.d(TAG, "Updating FCM token for device: " + deviceId);
ApiManager.getApiService()
.updateDevice(deviceId, apiKey, updateInput)
.enqueue(new Callback<RegisterDeviceResponseDTO>() {
@Override
public void onResponse(Call<RegisterDeviceResponseDTO> call, Response<RegisterDeviceResponseDTO> response) {
if (response.isSuccessful()) {
Log.d(TAG, "FCM token updated successfully");
} else {
Log.e(TAG, "Failed to update FCM token. Response code: " + response.code());
}
}
@Override
public void onFailure(Call<RegisterDeviceResponseDTO> call, Throwable t) {
Log.e(TAG, "Error updating FCM token: " + t.getMessage());
}
});
}
/* build and show notification */

View File

@@ -21,4 +21,7 @@ public interface GatewayApiService {
@POST("gateway/devices/{deviceId}/receive-sms")
Call<SMSForwardResponseDTO> sendReceivedSMS(@Path("deviceId") String deviceId, @Header("x-api-key") String apiKey, @Body() SMSDTO body);
@PATCH("gateway/devices/{deviceId}/sms-status")
Call<SMSForwardResponseDTO> updateSMSStatus(@Path("deviceId") String deviceId, @Header("x-api-key") String apiKey, @Body() SMSDTO body);
}