【问题标题】:Why would sendTextMessage require READ_PHONE_STATE permission?为什么 sendTextMessage 需要 READ_PHONE_STATE 权限?
【发布时间】:2011-01-04 23:17:25
【问题描述】:

我的应用程序将这个堆栈跟踪发送回了主页,这看起来好像在后台发生了一些非常错误的事情。

phone_model=SKY IM-A630K, android_version=2.1-update1

java.lang.SecurityException: Requires READ_PHONE_STATE: Neither user 10089 nor current process has android.permission.READ_PHONE_STATE.

   at android.os.Parcel.readException(Parcel.java:1218)
   at android.os.Parcel.readException(Parcel.java:1206)
   at com.android.internal.telephony.IPhoneSubInfo$Stub$Proxy.getLine1Number(IPhoneSubInfo.java:223)
   at android.telephony.TelephonyManager.getLine1Number(TelephonyManager.java:764)
   at android.telephony.SmsManager.sendTextMessage(SmsManager.java:129)
   at android.telephony.SmsManager.sendTextMessage(SmsManager.java:108)
   at com.emergency.button.SMSSender.safeSendSMS(SMSSender.java:91)
   at com.emergency.button.EmergencyActivity$EmergencyThread.sendSMS(EmergencyActivity.java:294)
   at com.emergency.button.EmergencyActivity$EmergencyThread.sendMessages(EmergencyActivity.java:386)
   at com.emergency.button.EmergencyActivity$EmergencyThread.run(EmergencyActivity.java:266)

所以我应该只捕获 sendTextMessage 周围的所有异常吗?这是谁的错?

【问题讨论】:

    标签: android permissions sms


    【解决方案1】:

    我现在看到在 Lollipop (API 21) 中,即使使用像 SmsManager.getDefault().divideMessage(String) 这样的良性函数 - 也需要 READ_PHONE_STATE 权限。我确信以前不需要它,这是一个操作系统问题,因为我之前和升级到 Lollipop 之后在 Nexus 5 设备上测试过它。之前,在运行 KitKat 时,SMS 在没有 READ_PHONE_STATE 权限的情况下也能正常工作。之后,它是必需的。

    我想,原因是电话功能试图对所有事情做出明智的决定。因此,像拆分 SMS(甚至不发送)这样的简单任务一直运行到 SmsManager 以查询手机状态。

    我认为这是一个设计错误。正如你上面所说,它可以而且应该吓到用户。为什么他们在 Android 上有这么多模棱两可的权限?

    这是我的堆栈跟踪,只是为了好玩:

    java.lang.SecurityException: Requires READ_PHONE_STATE: Neither user 10078 nor current process has android.permission.READ_PHONE_STATE.
    at android.os.Parcel.readException(Parcel.java:1540)
    at android.os.Parcel.readException(Parcel.java:1493)
    at com.android.internal.telephony.IPhoneSubInfo$Stub$Proxy.getGroupIdLevel1(IPhoneSubInfo.java:465)
    at android.telephony.TelephonyManager.getGroupIdLevel1(TelephonyManager.java:1666)
    at android.telephony.SmsMessage.hasEmsSupport(SmsMessage.java:776)
    at com.android.internal.telephony.gsm.SmsMessage.calculateLength(SmsMessage.java:808)
    at android.telephony.SmsMessage.fragmentText(SmsMessage.java:322)
    at android.telephony.SmsManager.divideMessage(SmsManager.java:328)
    at mobi.chatfish.utils.CFCommunications.sendSMSDirect(CFCommunications.java:138)
    

    【讨论】:

    • 是的,我在运行 Loolipop 的 OnePlus One 上看到了类似的堆栈跟踪(行号略有不同)。举报为code.google.com/p/android/issues/detail?id=81758请star :)
    • 我在 Y550 上收到此错误,但我的应用确实在清单中将 READ_PHONE_STATE 声明为权限??
    • 我对棒棒糖需​​要 READ_PHONE_STATE 的 SmsManager.getDefault().divideMessage(String) 有完全相同的问题。这很烦人!
    • 这似乎在 Android 6 中已修复
    • 我在 Y625-U21 (HWY625-U) 上遇到了同样的 SecurityException 并需要 READ_PHONE_STATE 来调用 android.text.format.DateFormat.getDateFormat(context)
    【解决方案2】:

    我的应用程序将这个堆栈跟踪发送回了主页,这看起来好像在后台发生了一些非常错误的事情。

    你这么说,我想这是你第一次看到这个问题,而且它不会发生在其他手机上。

    是否有可能在此手机型号的 Android 实现中,SmsManager 在尝试发送 SMS 消息之前尝试检查手机“状态”。这纯粹是一种猜测,但它似乎并不是一件不合理的事情,尽管 SMS Manager 的 Telephony API 文档没有提及它。也许不是,我不确定。

    由于在您的应用中发送 SMS 消息非常重要,因此您当然应该尽一切努力捕捉任何可能与发送消息相关的异常(并尽可能从异常状态中恢复)。

    由于似乎无法从这个特定问题中恢复,为什么不在清单中声明 READ_PHONE_STATE 的使用权限?

    【讨论】:

    • 我认为 READ_PHONE_STATE 可能会吓跑不想让我知道他们电话号码的用户。哦,好吧......我想我会抓住并忽略这个异常(我会向用户报告),因为它在整个应用程序的生命周期中只发生过一次......
    • @ubershmekel:是的,如果可以避免的话,我理解不使用 READ_PHONE_STATE。也许这只是一次性的,希望捕捉异常会有所帮助。
    【解决方案3】:

    我在使用 HTC 手机 (Desire 728G) Dual Sim 时遇到了同样的问题,我必须添加“READ_PHONE_STATE”,但现在 Google 要求提供隐私政策,因为我懒得这样做:) 我做了一些研究,发现了一种不使用“READ_PHONE_STATE”的更好方法。 问题是某些设备(主要是双卡)需要“READ_PHONE_STATE”权限来查找默认的“SubscriptionId”,这就是您调用“SmsManager.getDefault()”时发生的情况。 下面是我用来避免此问题的代码,如果发生任何异常,则将值 (1) 分配给 SubscriptionId:

                SmsManager smsManager = SmsManager.getDefault();
    
                if (android.os.Build.VERSION.SDK_INT >= 22){
                    Log.e("Alert","Checking SubscriptionId");
                try {
                    Log.e("Alert","SubscriptionId is " + smsManager.getSubscriptionId());
                } catch (Exception e) {
                    Log.e("Alert",e.getMessage());
                    Log.e("Alert","Fixed SubscriptionId to 1");
                    smsManager = SmsManager.getSmsManagerForSubscriptionId(1);
                }
                }
    
                smsManager.sendTextMessage(mobileNumber, null, msgStr, null, null);
    

    【讨论】:

      猜你喜欢
      • 2018-08-31
      • 2019-10-25
      • 2017-10-13
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      • 2012-09-06
      • 1970-01-01
      相关资源
      最近更新 更多