为什么sendTextMessage需要READ_PHONE_STATE权限?

12

我的应用程序发送了这个堆栈跟踪,似乎底层发生了非常严重的问题。

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周围捕获所有异常?这是谁的错?

3个回答

9
在Lollipop(API 21)中,即使使用类似于SmsManager.getDefault().divideMessage(String)这样无害的函数也需要READ_PHONE_STATE权限。我确定之前不需要该权限,并且这是一个操作系统问题,因为我之前在Nexus 5上测试过,并且升级到Lollipop后再次进行了测试。在运行KitKat时,短信可以正常工作而无需READ_PHONE_STATE权限。但是,在升级后,就必须要有该权限。
我猜原因是电话功能试图做出明智的决策,以应对所有情况。因此,即使只是将SMS分割成几条(甚至没有发送),也需要一直运行到SmsManager,以查询有关电话状态的信息。
我认为这是一个设计漏洞。正如您上面所说,它可能会吓到用户。为什么安卓系统会拥有这么多含糊不清的权限呢?
以下是我的堆栈跟踪,仅供娱乐:
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)

2
是的,我在运行Loolipop的OnePlus One上看到了类似的堆栈跟踪(略有不同的行号)。已报告为https://code.google.com/p/android/issues/detail?id=81758 请点赞 :) - Flow
1
我在Y550上遇到了这个错误,但我的应用程序在清单中确实声明了READ_PHONE_STATE权限? - LairdPleng
1
我也遇到了与SmsManager.getDefault().divideMessage(String)在Lollipop上需要READ_PHONE_STATE权限的完全相同的问题。这真的很烦人! - goseib
1
这个问题似乎在Android 6中已经被修复了。 - 1615903
我在Y625-U21 (HWY625-U)上调用android.text.format.DateFormat.getDateFormat(context)时遇到了相同的SecurityException并需要READ_PHONE_STATE。 - josue.0
显示剩余5条评论

3
我曾经遇到过与HTC手机(Desire 728G)双卡相同的问题,我不得不包括“READ_PHONE_STATE”,但现在谷歌要求提供隐私政策,因为我太懒了 :) 我做了一些研究,找到了一种更好的方法,而不需要使用“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);

2
我的应用程序发送了这个堆栈跟踪,似乎底层出现了一些非常严重的问题。从你的说法来看,我猜测这是你第一次遇到这个问题,在其他手机上不会发生。 在这种手机型号的Android实现中,SmsManager是否尝试在尝试发送短信消息之前检查手机“状态”可能性?这只是一个猜测,但似乎并不是一件不合理的事情,即使SMS Manager的电话API文档没有提到它。也许不是,我不确定。 因为在您的应用程序中发送短信是非常关键的,所以您应该尽力捕捉任何可能与发送消息有关的异常(并在可能的情况下从异常状态中恢复)。 由于似乎这个特定的问题无法恢复,为什么不将READ_PHONE_STATE用途权限声明到您的清单中呢?

1
我认为READ_PHONE_STATE可能会吓到那些不想让我知道他们电话号码的用户。哦,算了...我想我只需要捕获并忽略这个异常(我会向用户报告),因为在整个应用程序的生命周期中只发生了一次... - ubershmekel
2
@ubershmekel:是的,如果你能避免使用READ_PHONE_STATE,我理解这一点。也许这只是一个例外情况,希望捕获异常可以有所帮助。 - Squonk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接