Различение отчетов о доставке двух отдельных СМС
В сервисе, когда отправка smses в цикле с приемником широковещания прослушивает отчеты о доставке, как отличить отчет о доставке каждой отправленной смс? Это похоже на: Как получить отчет о доставке каждого SMS, отправленного в цикле Android?
за исключением того, что я думаю, что он использует это в действии, и я использую это в сервисе, где getIntent() бесполезен.
Редактировать 2: размещение моего кода
public class CheckServer extends Service
{
public String snumber[] = new String[10];
public JSONArray array;
public int onStartCommand(Intent intent,int flags, int startid)
{
// Do useful things.
ServiceAction SA = new ServiceAction();
SA.execute();
try
{
SA.get();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
new startSending().execute();
scheduleNextUpdate();
return START_STICKY;
}
public class startSending extends AsyncTask<Void,Void,Void>
{
@Override
protected Void doInBackground(Void... params)
{
String no,message;
try
{
for (int i = 0; i < array.length(); i++)
{
JSONObject row;
row = array.getJSONObject(i);
snumber[i] = row.getString("sno");
no = row.getString("no");
message = row.getString("message");
sendSMS(no,message,snumber[i]);
}
}
catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (JSONException e)
{
e.printStackTrace();
}
return null;
}
}
private void scheduleNextUpdate()
{
Intent intent = new Intent(this, this.getClass());
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// The update frequency should often be user configurable. This is not.
long currentTimeMillis = System.currentTimeMillis();
long nextUpdateTimeMillis = currentTimeMillis + 1 * DateUtils.MINUTE_IN_MILLIS;
Time nextUpdateTime = new Time();
nextUpdateTime.set(nextUpdateTimeMillis);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, nextUpdateTimeMillis, pendingIntent);
}
public class ServiceAction extends AsyncTask<Void,Void,Void>
{
@Override
protected Void doInBackground(Void... arg0)
{
HttpResponse response = null;
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
try
{
request.setURI(new URI("http://www.somesite.com/sms/getsms"));
response = client.execute(request);
String result = convertStreamToString(response.getEntity().getContent());
array = new JSONArray(result);
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (JSONException e)
{
e.printStackTrace();
}
return null;
}
}
public static String convertStreamToString(InputStream inputStream) throws IOException
{
if (inputStream != null)
{
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try
{
Reader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"),1024);
int n;
while ((n = reader.read(buffer)) != -1)
{
writer.write(buffer, 0, n);
}
}
finally
{
inputStream.close();
}
return writer.toString();
}
else
{
return "";
}
}
public void sendSMS(String number,String message,String serialnum)
{
String SENT = "SMS_SENT";
PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
new Intent(SENT), 0);
//---when the SMS has been sent---
registerReceiver(new BroadcastReceiver()
{
@Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "SMS sent",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(getBaseContext(), "Generic failure",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(getBaseContext(), "No service",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(getBaseContext(), "Null PDU",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(getBaseContext(), "Radio off",
Toast.LENGTH_SHORT).show();
break;
}
unregisterReceiver(this);
}
}, new IntentFilter(SENT));
String DELIVERED = "SMS_DELIVERED";
Intent delivered = new Intent(DELIVERED);
delivered.putExtra("MsgNum", serialnum);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this, Integer.parseInt(serialnum), delivered, 0);
//---when the SMS has been delivered---
registerReceiver(new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "SMS delivered",Toast.LENGTH_SHORT).show();
updateSMSStatus USS = new updateSMSStatus();
USS.execute(intent.getStringExtra("Msgnum"));
break;
case Activity.RESULT_CANCELED:
Toast.makeText(getBaseContext(), "SMS not delivered",Toast.LENGTH_SHORT).show();
break;
}
unregisterReceiver(this);
}
},
new IntentFilter(DELIVERED));
ContentValues values = new ContentValues();
values.put("address", number);
values.put("body", message);
getContentResolver().insert(Uri.parse("content://sms/sent"), values);
SmsManager smsMngr = SmsManager.getDefault();
smsMngr.sendTextMessage(number, null, message, sentPI, deliveredPI);
}
public class updateSMSStatus extends AsyncTask<String,Void,Void>
{
@Override
protected Void doInBackground(String... params) {
HttpResponse response = null;
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
try
{
Log.i("SMS APP", "MyClass.getView() — Serial Number = " + params[0]);
request.setURI(new URI("http://www.somesite.com/sms/updatesmsstatus?uname=someone&sno="+params[0]));
response = client.execute(request);
String result = convertStreamToString(response.getEntity().getContent());
Log.i("SMS APP","Update SMS Status is :"+result);
}
catch (URISyntaxException e)
{
e.printStackTrace();
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
}
1 ответ
Вы добавляете дополнительный номер сообщения в Intent следующим образом:
delivered.putExtra("MsgNum", serialnum);
и вы пытаетесь извлечь это так:
USS.execute(intent.getStringExtra("Msgnum"));
В putExtra()
у вас есть заглавная буква "N", в getStringExtra()
Вы используете строчную букву "n".
Вот почему вы должны всегда использовать константы для подобных вещей. Это мешает вам часами пытаться найти ошибки, вызванные опечатками.
Попробуй это:
public static final String EXTRA_MSGNUM = "MsgNum";
затем используйте:
delivered.putExtra(EXTRA_MSGNUM, serialnum);
а также:
USS.execute(intent.getStringExtra(EXTRA_MSGNUM));
РЕДАКТИРОВАТЬ: добавить что-то о создании различных PendingIntent
на основе комментария ОП
ОП написал в комментарии:
Моя ошибка для опечатки, чувствовала себя как овца из-за этого, я проверил ее, теперь она не дает нулевого значения, вместо этого она дает мне серийный номер первого сообщения, отправленного в цикле для всех сообщений, если я отправляю 17 20 24 21 25 27, это дает мне только 17 для всех отчетов о доставке
Ваша проблема - это путь PendingIntent
работает. Система управляет пулом PendingIntent
s. Когда ваш код делает:
String DELIVERED = "SMS_DELIVERED";
Intent delivered = new Intent(DELIVERED);
delivered.putExtra("MsgNum", serialnum);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
Integer.parseInt(serialnum), delivered, 0);
Это заставляет систему искать PendingIntent
соответствует параметрам, которые вы передали (в этом случае ваш Intent
). Тем не менее, алгоритм сопоставления, который PendingIntent
использует только сравнение определенных полей Intent
определить, является ли это тот, который вы ищете. В частности, он не сравнивает дополнения. Так что это означает, что после того, как вы создали первый PendingIntent
Призыв к PendingIntent.getBroadcast()
всегда будет возвращаться одинаково PendingIntent
из пула (а не создавать новый, который вам нужен).
Для того, чтобы позвонить PendingIntent.getBroadcast()
создать новый PendingIntent
каждый раз, когда вы вызываете его, попробуйте сделать параметры, передаваемые вызову, уникальными (например, сделав ДЕЙСТВИЕ в Intent
уникальный). Кроме того, так как каждый из этих PendingIntent
s будет использоваться только после установки FLAG_ONE_SHOT при получении PendingIntent
как это:
String DELIVERED = "SMS_DELIVERED" + serialnum; // Unique ACTION every time
Intent delivered = new Intent(DELIVERED);
delivered.putExtra("MsgNum", serialnum);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
Integer.parseInt(serialnum), delivered,
PendingIntent.FLAG_ONE_SHOT);
Поскольку ДЕЙСТВИЕ будет отличаться для каждого звонка PendingIntent.getBroadcast()
, это должно решить вашу проблему.
РЕДАКТИРОВАТЬ 2: Добавить альтернативный метод регистрации приемников вещания на основе обсуждения в комментариях
Если вы создаете класс, который расширяет BroadcastReceiver, вы можете добавить его в манифест, и тогда вам вообще не нужно явно регистрировать широковещательный получатель. Что-то вроде этого:
public class MessageStatusReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// This is called when the status of your SMS changes (delivery or send status)
// .. put your code here ..
}
}
Объявите получателя в своем манифесте:
<receiver android:name=".MessageStatusReceiver" />
В своем коде, который отправляет SMS, сделайте это:
String DELIVERED = "SMS_DELIVERED" + serialnum; // Unique ACTION every time
Intent delivered = new Intent(context, MessageStatusReceiver.class);
delivered.setAction(DELIVERED ); // Set action to ensure unique PendingIntent
delivered.putExtra("MsgNum", serialnum);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
Integer.parseInt(serialnum), delivered,
PendingIntent.FLAG_ONE_SHOT);