6

在一个服务中,当广播接收器在一个循环中发送短信时,监听发送报告,如何区分每个发送的短信的发送报告?这类似于: How to get Delivery Report of each SMS sent in loop 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;
  }

}
4

1 回答 1

12

您将消息编号额外添加到 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根据 OP 的评论添加一些关于生成不同 s 的内容

OP 在评论中写道:

我对错字不利,因此感觉像一只羊,我对其进行了测试,它现在没有给出空值,相反,它给了我在循环中发送的所有消息的第一条消息的序列号,如果我发送17 20 24 21 25 27,它只给我 17 的所有交货报告

你的问题是工作方式PendingIntent。系统管理一个PendingIntents 池。当您的代码执行以下操作时:

String DELIVERED = "SMS_DELIVERED";
Intent delivered = new Intent(DELIVERED);
delivered.putExtra("MsgNum", serialnum);
PendingIntent deliveredPI = PendingIntent.getBroadcast(this,
                    Integer.parseInt(serialnum), delivered, 0);

这会导致系统搜索PendingIntent与您传入的参数匹配的 a(在本例中为您的Intent)。但是,PendingIntent使用的匹配算法仅比较 的某些字段Intent以确定它是否是您要查找的字段。特别是,它不比较 extras。所以这意味着在你创建了第一个PendingIntent之后,调用PendingIntent.getBroadcast()总是会PendingIntent从池中返回相同的(而不是创建一个新的,这是你想要的)。

为了使每次调用都PendingIntent.getBroadcast()创建一个新的调用,请尝试使您传递给调用的参数唯一(例如:通过使 ACTION 中的唯一)。此外,由于这些s 中的每一个都只会在你应该设置 FLAG_ONE_SHOT 时使用,所以当你获得这样的:PendingIntentIntentPendingIntentPendingIntent

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);

由于每次调用的 ACTION 都会有所不同PendingIntent.getBroadcast(),这应该可以解决您的问题。

EDIT2:根据评论中的讨论添加注册广播接收器的替代方法

如果您创建一个扩展 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);
于 2012-10-10T10:43:48.670 回答