短信接收广播接收器似乎不起作用

时间:2014-04-08 10:41:14

标签: android broadcastreceiver smsmanager

我正在准备一个应用程序,要求我拥有用户的电话号码,然后以编程方式将用户的哈希码发送为短信,以便之后将其用作其令牌。

我让用户输入MainActivty中的号码并让我的接收器收听SMS_RECEIVED以便它不会是用户,首先我要确保我发送和接收用户的号码正确地接受它。但是我的接收器似乎没有听到触发器。我可以看到收到的短信通知,我可以听到声音,但广播接收器不听。

我的MainActivity代码

public class MainActivity extends Activity
{    
Button submit;
EditText contact;
static String phNo;
ProgressDialog progress;
static Boolean wasMyOwnNumber;
static Boolean workDone;
final static int SMS_ROUNDTRIP_TIMOUT = 30000;

@Override
protected void onCreate(Bundle savedInstanceState)
{
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  contact = (EditText)findViewById(R.id.mobileNumber);
  submit = (Button) findViewById(R.id.button1);
  wasMyOwnNumber = false;
  workDone = false;
  submit.setOnClickListener(new View.OnClickListener()
  {
          public void onClick(View v)
          {
              phNo = contact.getText().toString();
              new CheckOwnMobileNumber().execute();
          }
  });

}

 private class CheckOwnMobileNumber extends AsyncTask<String, Void, String>
 {
  @Override
  protected void onPostExecute(String result)
  {
      // TODO Auto-generated method stub
      if(progress.isShowing())
      {
          progress.dismiss();
          if(wasMyOwnNumber)
          {
              Toast.makeText(getApplicationContext(), "Number matched.", Toast.LENGTH_LONG).show();
              wasMyOwnNumber = false;
              workDone = false;
          }
          else
          {
              Toast.makeText(getApplicationContext(), "Wrong number.", Toast.LENGTH_LONG).show();
              wasMyOwnNumber = false;
              workDone = false;
              return;
          }
      }
      super.onPostExecute(result);
  }

  @Override
  protected String doInBackground(String... params)
  {
      // TODO Auto-generated method stub
      String msg = phNo;
      try
      {
          SmsManager sms = SmsManager.getDefault();
          sms.sendTextMessage(phNo, null, msg, null, null);
          timeout();
      }
      catch(Exception ex)
      {
          Log.v("Exception :", ""+ex);
      }
      return null;
  }

  @Override
  protected void onPreExecute() 
  {
      // TODO Auto-generated method stub
      progress = ProgressDialog.show(MainActivity.this, "","Checking Mobile Number...");
      progress.setIndeterminate(true);
      progress.getWindow().setLayout(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
      super.onPreExecute();
  }

}

 private boolean timeout()
 {
     int waited = 0;
     while (waited < SMS_ROUNDTRIP_TIMOUT)
     {
        try
        {
          Thread.sleep(100);
        }
        catch (InterruptedException e)
        {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
        waited += 100;
        if(phoneNumberConfirmationReceived())
        {
            waited=SMS_ROUNDTRIP_TIMOUT;
            workDone = true;
        }
     }
     /*Log.v("MainActivity:timeout2: Waited: " , ""+waited);
     Log.v("MainActivity:timeout2:Comparision: ", ""+ phoneNumberConfirmationReceived());
     Log.v("MainActivity:timeout2: WorkDone value after wait complete : ", ""+workDone);*/
  return workDone;

}

 private boolean phoneNumberConfirmationReceived()
 {
  if(wasMyOwnNumber)
  {
      workDone = true;
  }
  return workDone;

} SMSReceiver的MyCode

public class SMSReceiver extends BroadcastReceiver
{
private static final String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
Context mContext;
private Intent mIntent;
static String address, str = null;
boolean isSame;

// Retrieve SMS
public void onReceive(Context context, Intent intent)
{
    Log.v("ONMESSAGE", "RECEIVED");
    mContext = context;
    mIntent = intent;
    String action = intent.getAction();       
        SmsMessage[] msgs = getMessagesFromIntent(mIntent);
        if (msgs != null)
        {
            for (int i = 0; i < msgs.length; i++)
            {
                address = msgs[i].getOriginatingAddress();
                str = msgs[i].getMessageBody().toString();
            }
        }
        Log.v("Originating Address : Sender :", ""+address);
        Log.v("Message from sender :", ""+str);
        isSame = PhoneNumberUtils.compare(str, MainActivity.phNo);
        Log.v("Comparison :", "Yes this true. "+isSame);
        if(isSame)
        {
             MainActivity.wasMyOwnNumber = isSame;
             MainActivity.workDone=true;
        }

        // ---send a broadcast intent to update the SMS received in the
        // activity---
        Intent broadcastIntent = new Intent();
        broadcastIntent.setAction("SMS_RECEIVED_ACTION");
        broadcastIntent.putExtra("sms", str);
        context.sendBroadcast(broadcastIntent);

   }

public static SmsMessage[] getMessagesFromIntent(Intent intent)
{
    Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
    byte[][] pduObjs = new byte[messages.length][];

    for (int i = 0; i < messages.length; i++)
    {
        pduObjs[i] = (byte[]) messages[i];
    }

    byte[][] pdus = new byte[pduObjs.length][];
    int pduCount = pdus.length;
    SmsMessage[] msgs = new SmsMessage[pduCount];
    for (int i = 0; i < pduCount; i++)
    {
        pdus[i] = pduObjs[i];
        msgs[i] = SmsMessage.createFromPdu(pdus[i]);
    }
    return msgs;
}
}  

* 我在Manifest中的条目是*

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.getphonenumber"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/> 
<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.getphonenumber.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="com.example.getphonenumber.SMSReceiver">  
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>
</application>

</manifest>

3 个答案:

答案 0 :(得分:1)

为意图提供优先级值。

<intent-filter>更改为以下

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

试试..

还添加接收短信的权限

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

答案 1 :(得分:1)

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

   write in manifest: 
       <receiver
            android:name="yourpackagename.SmsReceive"
            android:enabled="true" >
            <intent-filter android:priority="1000" >
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>




SmsReceive class:

public void onReceive(Context context, Intent intent) {

        Bundle bundle = intent.getExtras();
        SmsMessage[] msgs = null;
        if (bundle != null) {

            str = "";
            substr = null;
            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();
                sender=msgs[i].getOriginatingAddress();
                str += msgs[i].getMessageBody().toString();


                if(str.length()!=0)
                {

                //write the logic 
                }
            }
        }
    }

答案 2 :(得分:1)

在大部分时间呆在这里之后,我想我会分享我的经验,以防有人被困在同一条船上。我花了几个小时来解决无法获取任何短信通知的问题,最终我通过致电获取权限解决了该通知。我相信这与最近sdk版本中权限的更改有关。

如上所述,我在androidmanifest.xml中设置了接收器,并且我也以编程方式添加了接收器,没有任何运气。

我在androidmanifest.xml中具有权限:

<uses-feature android:name="android.permission.RECEIVE_SMS" android:required="true"></uses-feature>
<uses-feature android:name="android.permission.READ_SMS" android:required="true"></uses-feature>

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

我是否将接收器放在androidmanifest.xml中(在应用程序块下的接收器块中)还是以编程方式如下进行操作,都是同样的问题:

private void InstallFunction () {
        final YourActivity activity = this;

        this.smsReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                activity.onReceiveIntent(context, intent);
            }
        };
        filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); // tried 0, 999, Integer.MaxValue, etc.
        filter.addAction(Telephony.Sms.Intents.SMS_RECEIVED_ACTION); // SMS
        this.registerReceiver(smsReceiver, filter);

它没有给出错误,也没有记录任何警告,但从未在模拟器或手机上使用短信调用过onReceive。

打一个电话,检查我是否拥有下面所述权限,说我同时拥有这两个权限。

    canReadSMS = ActivityCompat.checkSelfPermission(this,
            Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED;
canReceiveSMS = ActivityCompat.checkSelfPermission(this,
    Manifest.permission.Manifest.permission.RECEIVE_SMS) == PackageManager.PERMISSION_GRANTED);

canReadSMS和canReceiveSMS都是真的。

尽管如此,没有事件发生。重写几次后,尝试了上百万种方式,我最终决定忽略权限响应,反而要求获得许可。

        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.RECEIVE_SMS) ||
            ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.READ_SMS)) {
            new AlertDialog.Builder(this)
                    .setMessage("Would you like TheApp to handle confirmation codes text messages for you to make registration easier?")
                    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            ActivityCompat.requestPermissions(activity,
                                    new String[]{
                                            Manifest.permission.RECEIVE_SMS,
                                            Manifest.permission.READ_SMS
                                    },
                                    SMS_PERMISSIONS_REQUEST_ID);
                        }
                    })
                    .setNegativeButton("No", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    })
                    .create()
                    .show();

运行此命令后,通知开始到达,我非常兴奋。最初,我没有调用“ shouldShowRequestPermissionRationale”,这似乎导致崩溃或最终导致输入不允许我输入数据的活动出现问题。经过一番研究,我遇到了上面代码中的ActivityCompat.shouldShowRequestPermissionRationale(...。在用户授予了短信的应用权限之后,该函数似乎不再返回true,最终结果是要求他们输入新的权限方案给我带来的另一个麻烦是,如果我在确认页面上请求权限,那么他们可能会在文本到达时响应权限查询-在这种情况下文本不会到达消息处理程序。我在打开确认页面之前先在注册页面上请求权限。

注意:SMS_PERMISSIONS_REQUEST_ID是分配了特定整数值的正义变量。给它分配任何您喜欢的合理名称和号码。

通常,您可以实现重写“ onRequestPermissionsResult”功能来确定您是否获得许可,但是在我的情况下,许可是可选的-如果应用无法读取短信,则用户仍然可以手动输入或跳过码。在这种情况下,我可以忽略该替代。根据您的实现,您可能需要它-该处理程序可以使用许多示例。在该处理程序中使用上面定义的ID来确定您正在获取刚刚提出的权限请求的结果。

还有许多处理短信的示例,但是如果有人登陆,我将包括处理传入SMS的代码。我在寻找问题时,特意写了一点罗word且易于理解的内容。

private void onReceiveIntent (Context context, Intent intent) {
    if (context == this &&
            intent != null) {
        if (intent.getAction ().toString ().equals (Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
            Bundle bundle;

            bundle = intent.getExtras ();
            if (bundle != null) {
                Object[] pdus;
                String format;

                format = bundle.getString ("format");
                pdus = (Object[]) bundle.get("pdus");
                if (pdus != null &&
                        pdus.length > 0) {
                    StringBuilder body;
                    SmsMessage header;
                    SmsMessage sms;

                    body = new StringBuilder();
                    header = SmsMessage.createFromPdu((byte[]) pdus[0],
                            format);
                    for (Object pdu : pdus) {
                        //sms = SmsMessage.createFromPdu ((byte[]) pdu); <-- has been deprecated
                        sms = SmsMessage.createFromPdu ((byte[]) pdu,
                                format); // <-- the new way -- get the format as per above.
                        if (sms != null) {
                            body.append (sms.getDisplayMessageBody());
                        }
                    }
                    ProcessSmsMessage (header,
                            body.toString ());
                }
            }
        }
    }
}

private void ProcessSmsMessage(SmsMessage header,
                               String message) {
    if (header != null &&
            message != null) {
        String originator;

        originator = header.getOriginatingAddress();
        ProcessSmsMessage(originator,
                message);
    }
}

private void ProcessSmsMessage(String originator,
                               String message) {
    if (originator != null &&
        originator.equals ("##########")) { // does it come from my twilio sms number?
        if (message.startsWith("$TheApp$ Device Verification Code:")) {
            final DeviceConfirmationActivity confirmationActivity = this;
            final String code;

            code = message.substring (##); // past the name and text message above
            this.mConfirmationCodeView.setText (code); // <-- the manual entry box now filled for them

    // now you can do some work.  I use a custom timer to do this work on main thread
    // per much research, you should avoid doing lengthy operation in this thread
    // You can also set up a job.
            confirmationActivity.DoDeviceConfirmation(code);
        }
    }
}

如代码中所述,

sms = SmsMessage.createFromPdu ((byte[]) pdu);
现在已不推荐大多数示例代码中使用的

。幸运的是,找到了一些显示新版本的示例:

sms = SmsMessage.createFromPdu ((byte[]) pdu,
                format);

并且该格式来自:bundle.getString(“ format”);按照上面的代码。

特别感谢Shirish Herwade:SmsMessage.createFromPdu is deprecated in android API level 23

希望可以帮助某人坚持我的方式。我对过去使用cordova的Android编程很陌生,因此即使权限检查返回的值使人认为我已经已经使用过,所以其他人也许可以更好地了解为何在获得通知之前必须进行该权限调用表示同意。