0

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

我让用户在 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>
4

3 回答 3

2

为意图赋予优先级值..

改变你<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" />
于 2014-04-08T10:47:30.793 回答
2

在这里呆了一天的大部分时间后,我想我会分享我的经验,以防有人被困在同一条船上。我花了几个小时对未能获得任何短信通知进行故障排除,我最终通过调用获取权限解决了这个问题。我相信这与最近的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 在该处理程序中用于确定您正在获取刚刚发出的权限请求的结果。

还有许多处理短信的例子,但如果有人登陆这里,我将包括我处理传入短信的代码。当我正在寻找问题时,它故意写得有点罗嗦且易于消化。

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在 android API 级别 23 中已弃用

希望这有助于有人坚持我的方式。我对 Android 编程相当陌生,过去曾使用过 Cordova,因此其他人可能能够更好地了解为什么必须在收到通知之前进行权限调用,即使权限检查返回的值会让人们认为我已经说了许可。

于 2018-11-21T05:24:38.640 回答
1

添加权限:

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

写在清单中:

       <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 
                }
            }
        }
    }
于 2014-04-08T11:02:26.210 回答