6

サービスで、配信レポートをリッスンするブロードキャスト レシーバーを使用してループで SMS を送信する場合、送信された各 SMS の配信レポートを区別するにはどうすればよいですか? これは次のようなものです: ループ android で送信された各 SMS の配信レポートを取得する方法は?

ただし、彼はアクティビティで使用していると思いますが、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"));

では大文字の "N"を使用しputExtra()ますが、小文字の "n"を使用します。getStringExtra()

これが、このようなものには常に定数を使用する必要がある理由です。タイプミスが原因のエラーを探すのに何時間も費やす必要がなくなります。

これを試して:

public static final String EXTRA_MSGNUM = "MsgNum";

次に使用します:

delivered.putExtra(EXTRA_MSGNUM, serialnum);

と:

USS.execute(intent.getStringExtra(EXTRA_MSGNUM));

PendingIntent編集: OPのコメントに基づいて異なる s を生成することについて何かを追加します

OP はコメントに次のように書いています。

タイプミスのせいで、羊のように感じました。テストしましたが、現在はnull値を返さず、代わりに、すべてのメッセージのループで送信された最初のメッセージのシリアル番号を取得します。 17 20 24 21 25 27、すべての配信レポートに対して 17 しか表示されません

あなたの問題は、PendingIntent仕組みです。システムは のプールを管理しますPendingIntent。コードが次の場合:

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()に新しいを作成する呼び出しを行うには、呼び出しに渡すパラメーターを一意にしてみてください (たとえば、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 に答える