我的应用程序通过SmsManager.sendMultipartTextMessage发送SMS,然后通知服务器SMS发送的状态。
一切正常,但是Yota运算符存在问题。 SMS未通过MTS运营商传递到电话。 Yota运营商的员工声称MTS运营商阻止从Yota接收消息。
这不是我们的问题,但是Android系统表示成功发送了此类SMS。我们无法从另一部电话重新发送这样的SMS,因为我们的系统认为它们已经成功发送。
如果应用尝试发送此类SMS,则系统会先发出有关成功发送SMS的信号,然后发出有关成功SMS传递的信号。听起来不错,但实际上SMS没有发送。这不是孤立的情况。在不同的设备上测试。还尝试通过MTS运营商将SMS发送到其他电话。
我尝试通过标准的“消息”应用程序发送相同的SMS,并注意到以下内容:
从我的应用程序发送的SMS在不同设备上的标准“消息”应用程序中的显示方式有所不同。例如,ZTE BLADE L110(API 22)显示发送消息时发生错误,而Xiaomi Redmi 3S(API 23)没有显示。但是在两款智能手机上,当我尝试通过标准应用程序发送此类SMS时,都会显示错误消息(在显示Toast“ SMS成功发送”之前,中兴通讯)。
谁可以提供帮助?是否可以通过其他方式检查SMS是否已发送?标准的“消息”应用程序如何在系统生成带有已成功发送和传递消息的信号的意图时注册SMS发送错误的事实?
这是我的代码:
发送短信作业:
public class SendSMSJob extends SimpleJobService {
public static final String EXTRA_SMS_LIST_JSON = "sms_list";
public static final String TAG = "send_sms_job";
private static final String ACTION_SENT = "ru.sp2all.smsgate.SMS_SENT";
private static final String ACTION_DELIVERED = "ru.sp2all.smsgate.SMS_DELIVERED";
private int startId;
@Override
public void onCreate() {
super.onCreate();
MyLog.i(getLogTag(), "onCreate()");
}
@Override
public int onRunJob(JobParameters parameters) {
try {
this.startId = startId;
String json = parameters.getExtras().getString(EXTRA_SMS_LIST_JSON);
Gson gson = new Gson();
SMSDataList smsDataList = gson.fromJson(json, SMSDataList.class);
MyLog.d(getLogTag(), "Sending " + String.valueOf(smsDataList.items.length) + " messages");
boolean complete = true;
boolean needRetry = true;
for (SMSData sms: smsDataList.items) {
Integer subscriptionId = SimsHelper.getSimSubscriptionIdForIndex(getApplicationContext(), sms.simIndex);
SmsManager smsManager = null;
if (subscriptionId != null) {
smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
} else {
smsManager = SmsManager.getDefault();
}
ArrayList<String> parts = smsManager.divideMessage(sms.message);
MyLog.i(getLogTag(), "parts.size=" + parts.size());
insertSmsToDB(sms, parts);
ArrayList<PendingIntent> deliveryIntents = new ArrayList<>(parts.size());
ArrayList<PendingIntent> sentIntents = new ArrayList<>(parts.size());
try {
for (int part = 0; part < parts.size(); part++) {
Intent sentIntent = new Intent(ACTION_SENT);
sentIntent.putExtra("id", sms.smsId + "_" + Integer.toString(part));
sentIntent.putExtra("sms_id", sms.smsId);
sentIntent.putExtra("parts", Integer.toString(parts.size()));
sentIntent.putExtra("part", Integer.toString(part));
sentIntent.putExtra("phone", sms.phone);
sentIntent.putExtra("msg", sms.message);
PendingIntent sentPI = PendingIntent.getBroadcast(this,
Integer.parseInt(sms.smsId) * 100 + part,
sentIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
sentIntents.add(sentPI);
Intent deliveredIntent = new Intent(ACTION_DELIVERED);
deliveredIntent.putExtra("id", sms.smsId + "_" + Integer.toString(part));
deliveredIntent.putExtra("sms_id", sms.smsId);
deliveredIntent.putExtra("parts", Integer.toString(parts.size()));
deliveredIntent.putExtra("part", Integer.toString(part));
deliveredIntent.putExtra("phone", sms.phone);
deliveredIntent.putExtra("msg", sms.message);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
Integer.parseInt(sms.smsId) * 100 + part,
deliveredIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
deliveryIntents.add(deliveredPI);
}
MyLog.i(getLogTag(), "Sending to " + sms.phone);
smsManager.sendMultipartTextMessage(sms.phone, null, parts,
sentIntents, deliveryIntents);
} catch (Exception e) {
ErrorReporter.exception(this, getLogTag(), e, new ErrorReporter.ReporterHandler(e));
complete = true;
}
}
if (complete) {
return RESULT_SUCCESS;
} else if (needRetry) {
return RESULT_FAIL_RETRY;
} else {
return RESULT_FAIL_NORETRY;
}
} catch (Exception e) {
ErrorReporter.exception(this, getLogTag(), e, new ErrorReporter.ReporterHandler(e));
return RESULT_FAIL_RETRY;
}
}
private String getLogTag() {
return getClass().getSimpleName();
}
}
已在AndroidManifest Broadcast接收器中注册以处理SMS状态:
<receiver android:name=".SMSSentReceiver">
<intent-filter>
<action android:name="ru.sp2all.smsgate.SMS_SENT" />
</intent-filter>
</receiver>
<receiver android:name=".SMSDeliveredReceiver">
<intent-filter>
<action android:name="ru.sp2all.smsgate.SMS_DELIVERED" />
</intent-filter>
</receiver>
SMS发送了BroadcastReceiver:
public class SMSSentReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
String sms_id = intent.getStringExtra("sms_id");
int part = Integer.parseInt(intent.getStringExtra("part"));
MyLog.d(getLogTag(), "br_sent " + sms_id);
int status = 0;
int code = getResultCode();
switch (code) {
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
status = 400;
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
status = 401;
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
status = 402;
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
status = 403;
break;
case Activity.RESULT_OK:
updateDBWithNewSentPartsCount();
status = 202; // 202 is SMS sent Server status
break;
default:
status = 404; break;
}
if (status == 202) {
int sent = getSentPartsFromDB();
int parts = getAllPartsFromDB();
MyLog.d(getLogTag(), "DB sent:" + sms_id + " - : sent:" + sent + " parts: " + parts);
if (sent >= parts) {
MyLog.d(getLogTag(), "DB sent all parts");
Network.sendSMSStatus(context, sms_id, status);
}
} else {
Network.sendSMSStatus(context, sms_id, status);
}
} catch (Exception e) {
ErrorReporter.exception(context, getLogTag(), e, new ErrorReporter.ReporterHandler(e));
}
}
private String getLogTag() {
return getClass().getSimpleName();
}
}
SMS交付了广播接收器:
public class SMSDeliveredReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
String sms_id = intent.getStringExtra("sms_id");
int part = Integer.parseInt(intent.getStringExtra("part"));
MyLog.d(getLogTag(), "br_delivered " + sms_id);
int resultCode = getResultCode();
switch (resultCode) {
case Activity.RESULT_OK:
updateDBWithNewDeliveredPartsCount();
int delivered = getDeliveredPartsFromDB();
int parts = getAllPartsFromDB();
MyLog.i(getLogTag(), "DB delivered: " + sms_id + ", " + delivered + " parts of " + parts);
if (delivered >= parts) {
MyLog.i(getLogTag(), "DB delivered all parts");
Network.sendSMSStatus(context, sms_id, 200); // 200 is SMS delivered Server status
}
break;
case Activity.RESULT_CANCELED:
MyLog.w(getLogTag(), "DB delivered: CANCELLED " + sms_id);
Network.sendSMSStatus(context, sms_id, 405);
break;
default:
MyLog.w(getLogTag(), "DB delivered: unknown code " + resultCode);
Network.sendSMSStatus(context, sms_id, resultCode);
}
} catch (Exception e) {
ErrorReporter.exception(context, getLogTag(), e, new ErrorReporter.ReporterHandler(e));
}
}
private String getLogTag() {
return getClass().getSimpleName();
}
}
当我尝试发送SMS和未实际发送的SMS时,从设备登录:
SendSMSJob: onCreate()
SendSMSJob: Sending 1 messages
SendSMSJob: parts.size=1
SendSMSJob: Sending to +7988*******
SMSSentReceiver: br_sent 704402
SMSSentReceiver: DB sent:704402 - : sent:1 parts: 1
SMSSentReceiver: DB sent all parts
Network: sendSMSStatus status: 202
Network: get: https://{SERVER_NAME}/result.php?status=202&smsId=704402
Network: got: {"status":200}
SMSDeliveredReceiver: br_delivered 704402
SMSDeliveredReceiver: DB delivered: 704402, 1 parts of 1
SMSDeliveredReceiver: DB delivered all parts
Network: sendSMSStatus status: 200
Network: get: https://{SERVER_NAME}/result.php?status=200&smsId=704402
Network: got: {"status":200}
用于测试的SMS文本:gate4
答案 0 :(得分:0)
SMS不是公认的协议。您不知道它是否已从发送端发送。发件人只能知道何时发送消息。发送数据时,发送已正确报告,但另一端被阻止。
如果您需要确认的SMS,则可以从接收方回复,但这将涉及开发您自己的确认协议。
我只是从设备轮询网络服务。无论如何,数据比SMS消息便宜很多。
祝你好运。