2014-09-28 16 views
5

Próbowałem wysłać sms za pośrednictwem zamiar z tym kodem:Wysyłanie wiadomości SMS za pośrednictwem intencyjny i wiedzieć, czy SMS został wysłany lub nie

Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setData(Uri.parse("smsto:" + phoneNumber)); 
intent.putExtra("address", phoneNumber); 
intent.putExtra("sms_body", messageBody); 
intent.putExtra("exit_on_sent", true); 
startActivityForResult(intent, CODE); 

Następnie, chcę wiedzieć, czy SMS został wysłany czy nie i używam tego kodu:

public void onActivityResult(int requestCode, int resultCode, Intent intent) { 

    switch (requestCode) { 

     case CODE: 
     if (resultCode == Activity.RESULT_OK) 
     { 
      //Then do... 
     } 
     elseif(resultCode == Activity.RESULT_CANCELED) 
     { 
      // Do... 
     } 
     break;  
    } 
} 

Chodzi o to, wynik jest zawsze 0 (Activity.RESULT_CANCELED), nawet jeśli SMS został wysłany. Skąd mam wiedzieć, czy SMS został wysłany, czy nie? Chcę korzystać z domyślnej aplikacji SMS telefonu, a nie tworzyć interfejsu do wysyłania SMS-ów.

+0

Tak rzeczywiście trzeba odbiornik do monitorowania stanu wiadomości! – Pavlos

+0

http://mobiforge.com/design-development/sms-messaging-android – Pavlos

+0

Korzystanie z programu BroadcastReceiver, jak pokazano w podanym linku @Pavlos, działa tylko wtedy, gdy aplikacja wysyła SMS sam. Nie zadziała, jeśli użyjesz intencji do uruchomienia innej aplikacji, aby wysłać wiadomość. Możesz jednak zrobić to, co chcesz, używając 'ContentObserver'. –

Odpowiedz

9

W poniższym przykładzie używamy ContentObserver do monitorowania aktualizacji dostawcy SMS. Ten obserwator jest tworzony i uruchamiany przed uruchomieniem zamiaru wiadomości SMS i sprawdza zmiany dostawcy względem adresu docelowego. Aktywność, która tworzy obserwatora, musi implementować interfejs SmsSendObserver.SmsSendListener, aby otrzymać wywołanie zwrotne.

Konstruktor obserwatora zawiera parametr timeout (w milisekundach), aby umożliwić prawidłowe wyrejestrowanie obserwatora, jeśli wiadomość nie zostanie wysłana po upływie odpowiedniego czasu. W razie potrzeby można to ustawić na NO_TIMEOUT. Jednak klasa, jak napisano, jest przeznaczona do użycia "w jednym ujęciu", a sama wyrejestrowuje się i unieważnia członków po oddzwonieniu. Do oczyszczenia można użyć metody stop(), jeśli nie wystąpi oddzwonienie. W obu przypadkach instancja nie jest już użyteczna, a wszelkie odniesienia do niej powinny mieć wartość null.

Przykład aktywny:

public class MainActivity extends Activity 
    implements SmsSendObserver.SmsSendListener { 
    ... 

    private void sendMessage(String phoneNumber, String messageBody) { 
     // This example has a timeout set to 15 seconds 
     new SmsSendObserver(this, phoneNumber, 15000).start(); 

     Intent intent = new Intent(Intent.ACTION_VIEW); 
     intent.setData(Uri.parse("smsto:" + phoneNumber)); 
     intent.putExtra("address", phoneNumber); 
     intent.putExtra("sms_body", messageBody); 
     intent.putExtra("exit_on_sent", true); 
     startActivity(intent); 
    } 

    public void onSmsSendEvent(boolean sent) { 
     Toast.makeText(this, sent ? "Message was sent" : "Timed out", 
         Toast.LENGTH_SHORT).show(); 
    } 
} 

SmsSendObserver klasa:

public class SmsSendObserver extends ContentObserver { 
    public static final int NO_TIMEOUT = -1; 

    private static final Handler handler = new Handler(); 
    private static final Uri uri = Uri.parse("content://sms/"); 

    private static final String COLUMN_ADDRESS = "address"; 
    private static final String COLUMN_TYPE = "type"; 
    private static final String[] PROJECTION = { COLUMN_ADDRESS, COLUMN_TYPE }; 
    private static final int MESSAGE_TYPE_SENT = 2; 

    private Context context = null; 
    private ContentResolver resolver = null; 

    private String phoneNumber = null; 
    private long timeout = NO_TIMEOUT; 
    private boolean wasSent = false; 
    private boolean timedOut = false; 

    public SmsSendObserver(Context context, String phoneNumber, long timeout) { 
     super(handler); 

     if (context instanceof SmsSendListener) {  
      this.context = context; 
      this.resolver = context.getContentResolver(); 
      this.phoneNumber = phoneNumber; 
      this.timeout = timeout; 
     } 
     else { 
      throw new IllegalArgumentException(
       "Context must implement SmsSendListener interface"); 
     } 
    } 

    private Runnable runOut = new Runnable() { 
     @Override 
     public void run() { 
      if (!wasSent) { 
       timedOut = true; 
       callBack(); 
      } 
     } 
    }; 

    public void start() { 
     if (resolver != null) { 
      resolver.registerContentObserver(uri, true, this); 

      if (timeout > NO_TIMEOUT) { 
       handler.postDelayed(runOut, timeout); 
      } 
     } 
     else { 
      throw new IllegalStateException(
       "Current SmsSendObserver instance is invalid"); 
     } 
    } 

    public void stop() { 
     if (resolver != null) { 
      resolver.unregisterContentObserver(this); 

      resolver = null; 
      context = null; 
     } 
    } 

    private void callBack() { 
     ((SmsSendListener) context).onSmsSendEvent(wasSent); 
     stop(); 
    } 

    @Override 
    public void onChange(boolean selfChange) { 
     if (wasSent || timedOut) 
      return; 

     Cursor cursor = null; 

     try { 
      cursor = resolver.query(uri, PROJECTION, null, null, null); 

      if (cursor != null && cursor.moveToFirst()) { 
       final String address = 
        cursor.getString(cursor.getColumnIndex(COLUMN_ADDRESS)); 
       final int type = 
        cursor.getInt(cursor.getColumnIndex(COLUMN_TYPE)); 

       if (PhoneNumberUtils.compare(address, phoneNumber) && 
         type == MESSAGE_TYPE_SENT) { 

        wasSent = true; 
        callBack(); 
       } 
      } 
     } 
     finally { 
      if (cursor != null) { 
       cursor.close(); 
      } 
     } 
    } 

    public interface SmsSendListener { 
     // Passes true if the message was sent 
     // Passes false if timed out 
     public void onSmsSendEvent(boolean sent); 
    } 
} 
+0

Nie jestem w stanie nazwać tego fragmentem, czy możesz mi pomóc? – MilapTank

+0

@Milap Nie polecam używania tego dokładnego rozwiązania. Zamierzałem to zaktualizować na jakiś czas, ale wciąż zapominam. Klasa 'SmsSendObserver' jest nadal w pełni użyteczna, ale jest całkiem możliwe, że inicjująca instancja' Activity' - nawet ta, w której znajduje się twój "Fragment" - zostanie zabita przed wywołaniem wywołania zwrotnego. Sugerowałbym użycie 'usługi' - być może pierwszoplanowej' usługi' - do zainicjowania obserwatora i odebrania wywołania zwrotnego, i uzyskania wyniku do "działania" w inny sposób; np. magistrala zdarzeń, zapisywanie/pobieranie wyniku przez trwałe przechowywanie itp. –

Powiązane problemy