在iOS中以编程方式获取自己的电话号码

338
有没有一种从iPhone SDK的标准API中获取自己电话号码的方法?

可能对于那些不使用私有API的解决方案寻找帮助的人很有用——使用设备名称来捕获用户名称,只需相应修改以捕获电话号码或其他详细信息。 - Nik Burns
davidgyoung提供了一个可行的解决方案。它被埋没了(需要一些赞)。 - P i
9个回答

328

冒着被扣分的风险,我想提出一个建议:目前排名最高的解决方案(当前第一响应)违反了2009年11月5日最新的SDK协议。我们的应用程序刚刚因为使用它而被拒绝了。以下是来自苹果公司的回复:

"出于安全考虑,iPhone OS将应用程序(包括其首选项和数据)限制在文件系统中的唯一位置。这种限制是安全功能的一部分,称为应用程序的“沙箱”。沙箱是一组细粒度控件,限制应用程序对文件、首选项、网络资源、硬件等的访问。"

设备的电话号码不可在您的应用程序容器内使用。您需要修改应用程序,仅在您的目录容器内进行读取,并重新提交二进制文件到iTunes Connect,以便您的应用程序重新考虑加入应用商店。

这真是令人失望,因为我们希望减轻用户输入他们自己的电话号码的负担。


1
我可以获取包含此信息的apple.developer文档链接吗? - Ganesh AB
3
我从未找到关于这方面的任何文件,但很想看到它。这是苹果一直让我感到不透明的领域之一。自此以后我就没有尝试过提交应用程序。 - Dylan
1
@rgbrgb,我不使用Snapchat,你能否请解释一下他们那么神秘的体验是什么? - William Entriken
1
@rgbrgb Snap在注册时要求用户提供他们的电话号码。 - Sam
1
WhatsApp是如何做到的?你不需要手动输入号码,它就知道。 - Ash
显示剩余6条评论

139

不,目前没有合法可靠的方法可以实现这个功能。

即使你找到了一种方法,它也会在不久的将来被禁用,就像以前所有的方法一样。


2
请参考Nik Burn的回答:http://stackoverflow.com/a/8415162/292166 - 有一种(某种程度上的)方法可以实现这个! - JosephH
4
你见过的苹果公司禁止基于授权访问用户电话号码的最好理由是什么?苹果已经允许基于授权访问联系人、照片、位置以及用户的摄像头和麦克风,为什么不能授权访问电话号码?肯定有一个很好的理由,但并不立即清楚。这很不幸,因为禁止访问会导致开发者花费大量时间和金钱在其他验证用户电话号码的方式上。 - Crashalot

86
更新:苹果公司在iOS 4左右似乎已经移除了该功能。

仅仅是为了扩展之前的答案,像这样的东西对我很有用:

NSString *num = [[NSUserDefaults standardUserDefaults] stringForKey:@"SBFormattedPhoneNumber"];

注意: 这会检索在 iPhone 的 iTunes 激活期间输入的“电话号码”,可能为空或者不正确。这不是从 SIM 卡中读取的。

至少在2.1版本中是这样的。NSUserDefaults中还有其他一些有趣的键,也可能不会持久存在(这是在我的应用程序中使用UIWebView的情况下)。

WebKitJavaScriptCanOpenWindowsAutomatically
NSInterfaceStyle
TVOutStatus
WebKitDeveloperExtrasEnabledPreferenceKey

等等其他人是否有做什么,我不确定。


1
最近有一些关于这种能力的安全问题的报道:http://www.theregister.co.uk/2009/09/30/iphone_security/ - JeffH
11
不要这样做。通过键盘或联系人选择器询问用户数字。你应该尽可能明确地向用户收集信息。这可能不是最方便的方式,但很容易保存数字,所以你只需问一次即可。 - David Kanarek
4
被应用程序拒绝的解决方案不是一个解决方案。 - averydev

29

使用私有API,您可以按照以下方式获取用户电话号码:

extern NSString* CTSettingCopyMyPhoneNumber();


+(NSString *) phoneNumber {
NSString *phone = CTSettingCopyMyPhoneNumber();

return phone;
}

同时将CoreTelephony.framework添加到您的项目中。


在阅读了本论坛中其他答案后,我认为这是不可能的,但您已经做得非常好。 - Mehul Thakkar
1
在iOS 7中,它受到授权的保护https://dev59.com/TmIk5IYBdhLWcg3wMLiI#20830611 - creker
当我尝试这个时,phone是空的。 - C0D3

27

即使在使用私有API的私有应用程序中,iOS API本身无法单独捕获电话号码,因为所有已知的方法都在iOS 11中被修补和阻止。即使发现了新的漏洞,苹果也明确表示,他们将拒绝使用私有API来执行此操作的任何应用程序进入应用商店。详见@Dylan的回答。

但是,有一种合法的方式可以捕获电话号码而不需要用户输入任何数据。这类似于Snapchat的做法,但更简单,因为它不需要用户输入自己的电话号码。

其思想是:应用程序以编程方式向服务器发送一个SMS消息并附带应用程序的唯一安装代码。然后,应用程序可以查询同一服务器,以查看最近是否从具有此唯一应用程序安装代码的设备接收到SMS消息。如果有,则可以读取发送它的电话号码。以下是展示该过程的演示视频。正如你所见,它非常有效!

这不是非常容易设置的,但是可以使用教程提供的示例代码在免费的AWS层上在几小时内配置完成而无需支付任何费用。


抱歉,视频意外设为私人状态了。现在已经公开了。 - davidgyoung
1
这是一个很好的方法,但您能否丰富一下您的回答,至少涵盖基本的实现细节?如何在不知道您的电话号码的情况下从iOS设备发送短信?如何设置一个SMS接收服务器,使其可以访问发送者的电话号码?有哪些工具?兼容性如何? - Motti Shneor
@MottiShneor,你看到答案中的教程链接了吗?其中包含有关设置此解决方案的完整教程以及在Github存储库中的工作示例应用程序代码。 - davidgyoung
有人实施过这种方法并部署到应用商店吗?好奇App Store审核(或更新的Play Store审核)是否会对此有问题。 - Alexander Wallace Matchneer
1
我将此用于企业应用程序,因此没有提交审核。但由于用户通过他们看到的对话框控制发送短信消息,所以我怀疑无论是苹果还是谷歌都不会有问题,只要您披露您正在发送短信以验证其电话号码。 - davidgyoung
1
这太聪明了,2023年我可能会在应用商店的应用中尝试一下,看看是否成功 - Jonovono

23

如果你使用以下这行代码,你可能已经知道你的应用会被苹果拒绝

NSString *num = [[NSUserDefaults standardUserDefaults] stringForKey:@"SBFormattedPhoneNumber"];

这里有一个参考链接:

http://ayeapi.blogspot.com/2009/12/sbformatphonenumber-is-lie.html

您可以使用以下信息代替。

NSString *phoneName = [[UIDevice currentDevice] name];

NSString *phoneUniqueIdentifier = [[UIDevice currentDevice] uniqueIdentifier];

等等,等等

@property(nonatomic,readonly,retain) NSString    *name;              // e.g. "My iPhone"
@property(nonatomic,readonly,retain) NSString    *model;             // e.g. @"iPhone", @"iPod Touch"
@property(nonatomic,readonly,retain) NSString    *localizedModel;    // localized version of model
@property(nonatomic,readonly,retain) NSString    *systemName;        // e.g. @"iPhone OS"
@property(nonatomic,readonly,retain) NSString    *systemVersion;     // e.g. @"2.0"
@property(nonatomic,readonly) UIDeviceOrientation orientation;       // return current device orientation
@property(nonatomic,readonly,retain) NSString    *uniqueIdentifier;  // a string unique to each device based on various hardware info.

希望这能帮到你!


9
uniqueIdentifier在iOS5中已经废弃,请使用MAC地址代替。 - Raptor
15
MAC地址在iOS 7中已被弃用,请改用[UIDevice identifierForVendor] - jab

2
没有官方API可以实现这个功能。使用私有API,您可以使用以下方法:
-(NSString*) getMyNumber {
    NSLog(@"Open CoreTelephony");
    void *lib = dlopen("/Symbols/System/Library/Framework/CoreTelephony.framework/CoreTelephony",RTLD_LAZY);
    NSLog(@"Get CTSettingCopyMyPhoneNumber from CoreTelephony");
    NSString* (*pCTSettingCopyMyPhoneNumber)() = dlsym(lib, "CTSettingCopyMyPhoneNumber");
    NSLog(@"Get CTSettingCopyMyPhoneNumber from CoreTelephony");

    if (pCTSettingCopyMyPhoneNumber == nil) {
        NSLog(@"pCTSettingCopyMyPhoneNumber is nil");
        return nil;
    }
    NSString* ownPhoneNumber = pCTSettingCopyMyPhoneNumber();
    dlclose(lib);
    return ownPhoneNumber;
}

它可以在未越狱和特殊签名的iOS 6上运行。
creker所述,在iOS 7中需要越狱,您需要使用权限才能使其正常工作。
关于如何使用权限,请参见此处: iOS 7:如何通过私有API获取自己的号码?

2

要获取您的电话号码,您可以读取一个plist文件。这在非越狱的iDevices上不起作用:

NSString *commcenter = @"/private/var/wireless/Library/Preferences/com.apple.commcenter.plist";
    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:commcenter];
    NSString *PhoneNumber = [dict valueForKey:@"PhoneNumber"];
    NSLog([NSString stringWithFormat:@"Phone number: %@",PhoneNumber]);

我不确定苹果是否允许这样做,但是在iPhone上可以使用。


苹果公司会取消越狱手机的保修,并且一个应用程序需要具备所有用户的普遍能力。 - Cosmtar

1

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