2016-12-05 39 views
1

我需要爲我的用戶準備一個經過驗證的電話號碼,但經過研究,似乎沒有可靠的方法從設備獲取手機號碼。我見過幾次的一個建議是發送一條短信,然後在廣播接收器中捕獲它,並根據意向解析電話號碼。我已經看到這個問題: I could not get data from Intent after broadcast receivedthis one,但他們沒有解決我的問題。如何在廣播接收器中獲取短信數據

目前,我有接收器工作,但我無法獲得關於SMS消息的任何數據,這可能是通過意圖訪問的。

下面是當用戶按下發送按鈕觸發該代碼:

btnSend.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      try { 
       String SENT = "sent"; 
       String DELIVERED = "delivered"; 
       Intent sentIntent = new Intent(SENT); 

       /*Create Pending Intents*/ 
       PendingIntent sentPI = PendingIntent.getBroadcast(
         getApplicationContext(), 0, sentIntent, 
         PendingIntent.FLAG_UPDATE_CURRENT); 

       /* Register for SMS send action */ 
       registerReceiver(new BroadcastReceiver() { 
        @Override 
        public void onReceive(Context context, Intent intent) { 
         try { 
     --->     **SmsMessage[] smsMessage = Telephony.Sms.Intents.getMessagesFromIntent(intent);** 
          String messageBody = smsMessage[0].getMessageBody(); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 
         int resultcode = getResultCode(); 
         Log.d(" RESULT=", Integer.toString(resultcode)); 
        } 

       }, new IntentFilter(SENT)); 

       SmsManager smsManager = SmsManager.getDefault(); 

       if ((ContextCompat.checkSelfPermission(getApplicationContext(), 
         Manifest.permission.SEND_SMS) != 
         PackageManager.PERMISSION_GRANTED) || 
         (ContextCompat.checkSelfPermission(getApplicationContext(), 
           Manifest.permission.RECEIVE_SMS) != 
           PackageManager.PERMISSION_GRANTED)){ 
        ActivityCompat.requestPermissions(SMSActivity.this, 
          new String[] { 
            Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_SMS 
          }, 1); 
       } 
       smsManager.sendTextMessage(phoneNo.getText().toString(), null, 
               msg.getText().toString(), sentPI, null); 
      } catch (Exception ex) { 
       Toast.makeText(getApplicationContext(), 
         ex.getMessage(), Toast.LENGTH_LONG) 
         .show(); 
       ex.printStackTrace(); 
      } 
     } 
    }); 

當調用getMessagesFromIntent()由(粗體線),拋出一個異常作爲「的onReceive這裏列出( SMSActivity.java:60):「Intent不是null,所以看起來」null array「是getMessagesFromIntent的內部。

W/System.err: java.lang.NullPointerException: Attempt to get length of null array 
W/System.err:  at android.provider.Telephony$Sms$Intents.getMessagesFromIntent(Telephony.java:1345) 
W/System.err:  at com.jdot.jsontest.SMSActivity$1$1.onReceive(SMSActivity.java:60) 
W/System.err:  at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:993) 
W/System.err:  at android.os.Handler.handleCallback(Handler.java:739) 
W/System.err:  at android.os.Handler.dispatchMessage(Handler.java:95) 
W/System.err:  at android.os.Looper.loop(Looper.java:158) 
W/System.err:  at android.app.ActivityThread.main(ActivityThread.java:7224) 
W/System.err:  at java.lang.reflect.Method.invoke(Native Method) 
W/System.err:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
W/System.err:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 

我想我可能有相關的問題權限。我把這個添加到我的清單:

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

我也看到了這個清單除了幾次,但我不知道如何命名MyBroadcastListener,因爲它不是像例子類我見過。

<receiver android:name="MyBroadcastListener"> 
<intent-filter> 
<action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
</intent-filter> 
</receiver> 

最後,我在的onReceive的身體試圖下面的代碼塊(作爲替代)()。雖然intent.getExtras()返回一個Bundle,但是調用bundle.get(「pdus」)返回null,所以一切都失敗了。

Bundle bundle = intent.getExtras(); 
SmsMessage[] msgs = null; 
String str = ""; 
if (bundle != null) { 
//---retrieve the SMS message received--- 
Object[] pdus = (Object[]) bundle.get("pdus"); 
msgs = new SmsMessage[pdus.length]; 
for (int i=0; i<msgs.length; i++){ 
     msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]); 
     str += "SMS from " + msgs[i].getOriginatingAddress(); 
       str += " :"; 
       str += msgs[i].getMessageBody().toString(); 
       str += "\n"; 
    } 
//---display the new SMS message--- 
    Toast.makeText(context, str, Toast.LENGTH_SHORT).show(); 
} 

我的問題是:

  1. 我是否需要接收器/意圖濾波器塊在我的表現,如果是這樣,我怎麼命名的第一行聽衆?
  2. 我無法在onReceive()中收到傳入消息的副本的原因是什麼?我該如何糾正?
  3. 我是否需要在onReceive()中發送消息並「捕獲」消息以便可靠地獲取設備的電話號碼,或者我可以請求獲取用戶讀取SMS的權限,並且只需讀取第一條消息以獲取來電號碼?

請注意,我已經通讀了所有類似的問題,但沒有找到答案。


回答

2

這是你的問題:

registerReceiver(..., new IntentFilter(SENT)); 

你註冊該接收器爲您所使用的行動派確認,不爲SMS_RECEIVED行動,這是什麼時候播出一條消息到達。

發送PendingIntent用於確認消息已成功離開設備。從所得到的Intent不會對任何消息的PDU,這就是爲什麼你崩潰。

如果您使用API​​ 19或更高版本進行編譯,您需要註冊入站SMS Receiver的操作是"android.provider.Telephony.SMS_RECEIVED"或常量Telephony.Sms.Intents.SMS_RECEIVED_ACTION


要解決的具體問題:

  1. 我需要在我的清單中的接收器/意向過濾塊,如果是這樣,我怎麼命名的第一行聽衆?

註冊在清單的接收器可以讓您的應用程序來接收,即使它尚未運行,或者在前臺的消息。如果您不需要這樣做,您不一定需要在清單中註冊。但是,如果用戶接收的消息之前導航從Activity之遙,暫停Activity不會得到廣播。

「最安全」的方法來處理它會在清單中註冊,但你要註冊一個類,而不是一個動態的實例。您將需要創建一個MyBroadcastListener類,並以某種方式在收到通知從該Activity;例如,使用startActivity(),或LocalBroadcastManager,或一些其它事件總線實施等

  • 什麼是可能的原因我不能在的onReceive接收傳入的消息的副本( ),我應該怎麼做才能糾正它?
  • 如上所述,在sendTextMessage()呼叫傳遞的PendingIntent發送確認。它導致Intent並不會對它收到的消息。你只需要聽正確的廣播。

  • 是否需要爲了可靠地獲得該裝置的電話號碼發送消息和「抓住它」中的onReceive(),或我可以請求許可從讀取短信用戶,並剛剛閱讀第一條消息來獲取傳入的電話號碼?
  • 您需要實際發送消息。傳入消息將不會附加收件人號碼。

    +0

    非常感謝您的幫助!我會給你一槍,讓你知道。 –

    +0

    沒問題。如果可以的話,我只是意識到我忽略了提及應該堅持'getMessagesFromIntent()'方法。即,至少在API 19或以上。在API 23中爲不同的PDU格式增加了一個新的'SmsMessage#createFromPdu()'重載,並且使用'getMessagesFromIntent()'將調用正確的API層次的適當參數,所以你不必你自己。 –

    +0

    我不能告訴你我多麼感激解釋。我按照你的建議修改了這個意圖,它的效果非常好。有一個問題,如果我想支持API 18,我認爲我應該使用bundle.get(「pdus」)方法來解析消息,並且「android.provider.Telephony.SMS_RECEIVED」仍然可以工作?我無法從你的評論中得知它是API-19特有的常數還是兩者。 –

    -2

    試試這個。希望它能幫助你。

    public class IncomingSMSReceiver extends BroadcastReceiver { 
    
    @Override 
    public void onReceive(Context context, Intent intent) { 
        // TODO Auto-generated method stub 
        Bundle b = intent.getExtras(); 
        try { 
         if (b != null) { 
          Object[] pdusObj = (Object[]) b.get("pdus"); 
    
          for (int i = 0; i < pdusObj.length; i++) { 
           SmsMessage currentMessage = SmsMessage 
             .createFromPdu((byte[]) pdusObj[i]); 
           String phoneNumber = currentMessage 
             .getDisplayOriginatingAddress(); 
           String senderNum = phoneNumber; 
           String message = currentMessage.getDisplayMessageBody(); 
    
           if (senderNum .equals("VK-VERIFY")) 
           { 
             MainActivity Sms = new MainActivity(); 
             Log.d("TAG",""+message); 
             Sms.recivedSms(message); 
           } 
          } 
         } 
    
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
    }} 
    

    AndroidManifest

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.nitish.incomingsms" 
    android:versionCode="1" 
    android:versionName="1.0" > 
    
    <uses-permission android:name="android.permission.RECEIVE_SMS" > 
    </uses-permission> 
    <uses-permission android:name="android.permission.READ_SMS" /> 
    <uses-permission android:name="android.permission.SEND_SMS" > 
    </uses-permission>  
    
    <uses-sdk 
        android:minSdkVersion="16" 
        android:targetSdkVersion="16" /> 
    
    <application 
        android:allowBackup="true" 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" 
        android:theme="@style/AppTheme" > 
        <activity 
         android:name=".MainActivity" 
         android:label="@string/app_name" > 
         <intent-filter> 
          <action android:name="android.intent.action.MAIN" /> 
    
          <category android:name="android.intent.category.LAUNCHER" /> 
         </intent-filter> 
        </activity> 
    
        <receiver android:name=".IncomingSMSReceiver" > 
         <intent-filter> 
          <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
         </intent-filter> 
        </receiver> 
    </application> 
    

    在消息的變量,你會得到整個消息體。

    +0

    感謝您的代碼示例。這對我目前的問題沒有幫助,但在未來可能會有用。 –

    相關問題