gpt4 book ai didi

java - 发送短信直至成功

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:05:56 24 4
gpt4 key购买 nike

我正在尝试从我的应用程序发送紧急短信。我必须确保短信发送成功。

短信是在Android系统启动后,正在检查后发送的。

所以我有一个处理 BOOT_COMPLETED intent-filter 的服务类。此类进行检查,如果为真,则它会尝试通过另一个“扩展服务”的类发送 SMS 消息

在确保短信成功发送后,两种服务(处理启动调用的服务和发送短信的服务)都必须退出。

问题 1:如何让我的短信发送功能超时调用,而不让应用程序收到无响应的消息?目前我正在使用这个(我不知道它是否是正确的方法,尽管它有效):

Timer mTimer = new Timer();
//wait a small timeout prior to sending the message.
mTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
this.cancel(); //I don't want to run the timer more than once
sms_sender sms = new sms_sender();
sms.sendSMS(phoneNumber, messageText);
}
}, 30000, 30000); //run sendSMS() after 30 seconds

问题2:如何实现sendSMS功能,在发现上次尝试失败后每30秒重试一次?

问题三:发现短信发送成功后如何停止这两个服务?

这是我的代码,它不起作用:

public class sms_sender extends Service {

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}

final String SENT = "SMS_SENT";

public void sendSMS(final String phoneNumber, final String message, final boolean check_result)
{

PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent(SENT), 0);
registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
if(!check_result)
return;
switch (getResultCode())
{
case Activity.RESULT_OK:
//exit
stopSelf();
return;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
case SmsManager.RESULT_ERROR_NO_SERVICE:
case SmsManager.RESULT_ERROR_NULL_PDU:
case SmsManager.RESULT_ERROR_RADIO_OFF:
//try again in 1 minute
Timer mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
this.cancel(); //no need to run again, if it fails, this exact code will run again
sendSMS(phoneNumber, message, true);
}
}, 60000, 60000);
return;
}
}
}, new IntentFilter(SENT));

SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNumber, null, message, sentPI, null);
}
}

目前程序在 PendingIntent 调用时崩溃。我尝试使用私有(private)成员变量在 onCreate 方法上实现 BroadCastReceiver,以便通过 onReceive 方法再次调用 sendSMS() 函数,但是 onReceive 似乎从未运行。

-- 编辑--

所以,这是我最后的工作代码。我想我的情况很特殊,因为它不适用于 UI 线程。我有一个在启动时运行的广播接收器。我正在尝试发送 SMS 消息,直到发送成功。

这个引导广播接收器启动一个服务。这是其中的一些代码:

public class service extends Service{

static public service serv;
//member variable. Initializing to null so as to know whether to unregister the service or not
private BroadcastReceiver messageSent = null;

...
...
@Override
public void onStart(Intent intent, int startid)
{
serv=this; //will use this static variable in order to shutdown the service when the message is successfully sent
...
...
if(somethingIsTrue()){
//register receiver
messageSent = new sent_message();
registerReceiver(messageSent, new IntentFilter(sms_sender.INTENT_MESSAGE_SENT));
startMessageServiceIntent(messageText, phoneNumber); //function code can be found on accepted answer
}
}
}

sent_message 类如下:

public class sent_message extends BroadcastReceiver {

private Context pubCon;

private void startMessageServiceIntent(String message, String receiver) {
Intent i = new Intent(pubCon, sms_sender.class);
i.putExtra(sms_sender.EXTRA_MESSAGE, message);
i.putExtra(sms_sender.EXTRA_RECEIVERS, new String[] { receiver });
pubCon.startService(i);
}

@Override
public void onReceive(Context context, Intent intent) {
pubCon=context;
switch (getResultCode()) {
case Activity.RESULT_OK:
//all went OK, stop the service where this is called from
service.serv.stopSelf();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
case SmsManager.RESULT_ERROR_NO_SERVICE:
case SmsManager.RESULT_ERROR_NULL_PDU:
case SmsManager.RESULT_ERROR_RADIO_OFF:
//try sending the message again after 30s
new Handler().postDelayed(new Runnable(){
@Override
public void run(){
startMessageServiceIntent(service.messageText, service.phoneNumber);
}
}, 30000);

break;
}

}
}

sms_sender 类的简化(仅接受一个接收者)版本如下:

public class sms_sender extends IntentService {

public static final String INTENT_MESSAGE_SENT = "message.sent";
public static final String INTENT_MESSAGE_DELIVERED = "message.delivered";

public static final String EXTRA_MESSAGE = "extra.message";
public static final String EXTRA_RECEIVERS = "extra.receivers";

public sms_sender() {
super("sms_sender");
}

private static class IDGenerator {

private static final AtomicInteger counter = new AtomicInteger();

public static int nextValue() {
return counter.getAndIncrement();
}
}

public void sendSMS(String message, String receiver) {
SmsManager sm = SmsManager.getDefault();

PendingIntent sentPI = null;

Intent sentIntent = new Intent(INTENT_MESSAGE_SENT);

int sentID = IDGenerator.nextValue();
sentPI = PendingIntent.getBroadcast(sms_sender.this, sentID, sentIntent,
PendingIntent.FLAG_CANCEL_CURRENT);

try {
sm.sendTextMessage(receiver, null, message, sentPI, null);
} catch (IllegalArgumentException e) {
System.out.println("Illegal argument");
}
}

protected void onHandleIntent(Intent intent) {
String message = intent.getStringExtra(EXTRA_MESSAGE);
String[] receivers = intent.getStringArrayExtra(EXTRA_RECEIVERS);
sendSMS(message, receivers[0]);
}
}

最佳答案

这是我所做的:

public class SMSSender extends IntentService {

public static final String INTENT_MESSAGE_SENT = "message.sent";
public static final String INTENT_MESSAGE_DELIVERED = "message.delivered";

public static final String EXTRA_MESSAGE = "extra.message";
public static final String EXTRA_RECEIVERS = "extra.receivers";

public SMSSender() {
super("SMSSender");
}

private final String TAG = "SendSMS";


private static class IDGenerator {

private static final AtomicInteger counter = new AtomicInteger();

public static int nextValue() {
return counter.getAndIncrement();
}
}

private void sendSMS(String message, String[] receivers) {

SmsManager sm = SmsManager.getDefault();

ArrayList<String> parts = sm.divideMessage(message);

PendingIntent sentPI = null;
PendingIntent deliveredPI = null;

Intent sentIntent = new Intent(INTENT_MESSAGE_SENT);

int sentID = IDGenerator.nextValue();
sentPI = PendingIntent.getBroadcast(SMSSender.this, sentID, sentIntent,
PendingIntent.FLAG_CANCEL_CURRENT);

Intent deliveryIntent = new Intent(INTENT_MESSAGE_DELIVERED);

int deliveredID = IDGenerator.nextValue();
deliveredPI = PendingIntent.getBroadcast(SMSSender.this, deliveredID,
deliveryIntent, PendingIntent.FLAG_CANCEL_CURRENT);

Log.i(TAG, "sending SMS: parts: " + parts.size() + " message: "
+ message);

if (parts.size() > 1) {
ArrayList<PendingIntent> sentIntents = null;
ArrayList<PendingIntent> deliveredIntents = null;

sentIntents = new ArrayList<PendingIntent>();
deliveredIntents = new ArrayList<PendingIntent>();

for (int i = 0; i < parts.size(); i++) {
sentIntents.add(sentPI);
deliveredIntents.add(deliveredPI);
}

for (String receiver : receivers) {
try {
sm.sendMultipartTextMessage(receiver, null, parts,
sentIntents, deliveredIntents);
} catch (IllegalArgumentException e) {
Log.e(TAG, "illegal receiver: " + receiver);
}

}
} else {
for (String receiver : receivers) {
try {
sm.sendTextMessage(receiver, null, parts.get(0), sentPI,
deliveredPI);
} catch (IllegalArgumentException e) {
Log.e(TAG, "illegal receiver: " + receiver);
}
}
}
}

@Override
protected void onHandleIntent(Intent intent) {
String message = intent.getStringExtra(EXTRA_MESSAGE);
String[] receivers = intent.getStringArrayExtra(EXTRA_RECEIVERS);

sendSMS(message, receivers);

}

并使用它:

    private void startMessageServiceIntent(String message, String receiver) {
Intent i = new Intent(context, SMSSender.class);
i.putExtra(SMSSender.EXTRA_MESSAGE, message);
i.putExtra(SMSSender.EXTRA_RECEIVERS, new String[] { receiver });
startService(i)
}

注意它支持多个接收器,此方法未演示/使用。

请记住在您的 list 中:

<uses-permission android:name="android.permission.SEND_SMS" />

<service android:name="your.package.SMSSender" android:enabled="true" />

您可以选择监听消息何时发送和/或传递:

@Override
protected void onCreate() {

...

// ---when the SMS has been sent---
private BroadcastReceiver messageSent; // <- stored as a field
messageSent = new SentMessage();
registerReceiver(messageSent, new IntentFilter(SMSSender.INTENT_MESSAGE_SENT));

// ---when the SMS has been delivered---
private BroadcastReceiver messageDelivered; // <- stored as a field
messageDelivered = new MessageDelivered();
registerReceiver(messageDelivered, new IntentFilter(
SMSSender.INTENT_MESSAGE_DELIVERED));
}

@Override
protected void onDestroy() { // remember to unregister
unregisterReceiver(messageSent);
unregisterReceiver(messageDelivered );
}

我知道这并不能说明您所有问题的答案,但我希望这已经足够了。

编辑:添加了我对 messageSent 和 messageDelivered 的实现

这些是针对我的实现的,所以包含一些你不能使用的代码,只是为了演示。

消息已发送:

public class SentMessage extends BroadcastReceiver {

private final String TAG = "SentMessage";

@Override
public void onReceive(Context context, Intent intent) {
long _id = intent.getLongExtra(EXTRA_ID, -1);
long protocol_id = intent.getLongExtra(EXTRA_PROTOCOL, -1);
Log.d(TAG, "SentMessage");
switch (getResultCode()) {
case Activity.RESULT_OK:
Log.d(TAG, "RESULT_OK");
if (MessageData.sentMessage(_id, protocol_id)) {
try {
Database.messageSent(_id);
} catch (DatabaseRowNotFoundException e) {
Log.e(TAG, e.toString(), e);
}
}
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Log.d(TAG, "RESULT_ERROR_GENERIC_FAILURE");
MessageData.postponeMessage(_id);
ApplicationData.hasSignal(false);
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Log.d(TAG, "RESULT_ERROR_NO_SERVICE");
MessageData.postponeMessage(_id);
ApplicationData.hasSignal(false);
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Log.d(TAG, "RESULT_ERROR_NULL_PDU");
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Log.d(TAG, "RESULT_ERROR_RADIO_OFF");
MessageData.postponeMessage(_id);
ApplicationData.hasSignal(false);
break;
}

}

消息传递:

public class DeliveredMessage extends BroadcastReceiver {

private final String TAG = "DeliveredMessage ";


@Override
public void onReceive(Context context, Intent intent) {

long _id = intent.getLongExtra(EXTRA_ID, -1);
long protocol_id = intent.getLongExtra(EXTRA_PROTOCOL, -1);
switch (getResultCode()) {
case Activity.RESULT_OK:
if (_id != -1 && MessageData.deliveredMessage(_id, protocol_id)) {
try {
Database.messageDelivered(_id);
Cursor messageCursor = Database.getCursorByID(MessageOutboxContentProvider.CONTENT_URI, MessageOutboxContentProvider._ID, _id);
messageCursor.close();
} catch (DatabaseRowNotFoundException e) {
Log.e(TAG, e.toString(), e);
}
}
break;
case Activity.RESULT_CANCELED:
break;
}
}

我也需要可靠的发送,所以在数据库中保留对所有未决消息的引用,我会经常扫描这些消息以查找延迟的消息。如果没有 radio ,消息将被推迟,或者发送由于任何原因而失败。

我还将 GCM 与 SMS 结合使用,以尽可能快地传递消息,同时使用两个 channel 发送消息。

Edit2:哦,好吧,不妨解决一下问题,反正我们快到了:

问题 1:由于使用 IntentService,发送是在后台完成的。

您只希望在延迟后发送一次,因此您应该这样做:

    new Handler().postDelayed(new Runnable() {

@Override
public void run() {
// send sms
}
}, delay);

问题 2:很简单,当您发送的消息广播检测到错误时,请执行上述方法。除了接收者和消息之外,您还可以添加额外的信息,计算到目前为止的重试次数,以便您有机会停止发送/重试循环。

问题 3:发送自行停止,因为它是 Intent 服务。至于其他服务,我认为最简单的方法是发送一个公共(public)广播,由您的主要 Activity 接收。这样您就可以在正确的位置获取服务并停止它。

关于java - 发送短信直至成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19083158/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com