如何在iPhone上编程发送短信?

545

请问有人知道如何通过官方的SDK / Cocoa Touch在上以编程方式发送SMS吗?


在iOS 4中,你可以用代码发送短信,但问题是你的应用程序将会被关闭。 - Pankaj Kainthla
如果其他人不需要使用官方SDK,我写了这篇文章来展示如何使用Twilio完成此操作:https://www.twilio.com/blog/2016/11/how-to-send-an-sms-from-ios-in-swift.html - Megan Speir
您可以通过Gmail创建Google电子表格,制定所需字段,然后在“工具”中选择“脚本编辑器”,使用POST请求调用“MailApp.sendEmail” API向手机号发送电子邮件。AT&T的是YOURNUMBER@mms.att.net,T-Mobile的是YOURNUMBER@tmomail.net(全部免费)。 - Coty Embry
18个回答

418

限制

如果你在iPhone程序中发送短信,你将能够编写可以在后台垃圾短信人的游戏。我相信你真的希望收到来自朋友的垃圾邮件,“试试这个新游戏!它非常棒,你的也会是!roxxersboxxers.com!! 如果你现在注册,你将获得3200 RB点!!”

苹果对自动(甚至部分自动化)的短信和拨号操作有限制。(想象一下,如果游戏在特定时间拨打911呢?)

如果您需要完全自动化,则最好在互联网上设置一个中间服务器,该服务器使用在线短信发送服务,并通过该路线发送短信。 (即,您在iPhone上的程序发送UDP数据包到您的服务器,然后服务器发送真正的短信)

iOS 4更新

然而,iOS 4现在提供了您可以导入到应用程序中的viewController。 你预填充SMS字段,然后用户可以在控制器内启动SMS发送。 与使用“SMS:...” URL格式不同,这允许您的应用程序保持打开状态,并允许您填充tobody字段。 您甚至可以指定多个收件人。

这样可以防止应用程序在用户明确知道之前发送自动化的SMS。 您仍然无法从iPhone本身发送完全自动化的SMS,它需要一些用户交互。 但是这至少允许您填充所有内容,并避免关闭应用程序。

MFMessageComposeViewController类有很好的文档,并且教程展示了实现的简单易行。

iOS 5更新

iOS 5 包含 iPod touch 和 iPad 设备的消息功能,因此虽然我还没有亲自测试过,但所有 iOS 设备可能都能通过 MFMessageComposeViewController 发送短信。如果是这种情况,那么苹果正在运行一个短信服务器,代表没有蜂窝调制解调器的设备发送消息。

iOS 6 更新

该类别没有更改。

iOS 7 更新

现在你可以检查你使用的消息媒介是否接受主题或附件,以及它将接受何种类型的附件。在允许的情况下,你可以编辑主题并添加附件到消息中。

iOS 8 更新

该类别没有更改。

iOS 9 更新

该类别没有更改。

iOS 10 更新

该类别没有更改。

iOS 11 更新

该类别没有重大更改

该类别的限制

请注意,这将不适用于没有安装 iOS 4 的手机,并且除了可能的 iOS 5 版本,它也不适用于 iPod touch 或 iPad。在使用此控制器之前,你必须检测设备和 iOS 限制,否则会限制你的应用程序仅适用于最近升级的3G、3GS和4G iPhone。

但是,一个中间服务器发送短信将允许任何和所有这些 iOS 设备发送短信,只要它们有互联网接入,因此对于许多应用程序来说可能仍然是更好的解决方案。或者使用两者,并且仅在设备不支持时回退到在线短信服务。


12
如果你购买了那个域名,我就再也无法以同样的方式看待你了。 - Adam Davis
81
有人将这篇文章标记为垃圾信息,我认为这非常具有讽刺意味。大家要看看行间的含义! - Randolpho
2
-1是因为这个听起来像是推测。另外,可以查看Jus' Wondrin'和rydgaze的回答,了解如何发送应用内短信。 - Frank Shearar
8
@Frank - 我更新了我的写作,以反映新的iOS 4功能。去除了含糊不清的措辞。 - Adam Davis
15
非常感谢您更新此帖以适应新的iOS版本。 :) - Ciryon
显示剩余4条评论

146

这里有一篇教程可以完全满足你的需求: MFMessageComposeViewController

http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/

本质上:

MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
    controller.body = @"SMS message here";
    controller.recipients = [NSArray arrayWithObjects:@"1(234)567-8910", nil];
    controller.messageComposeDelegate = self;
    [self presentModalViewController:controller animated:YES];
}

还有一个链接到文档。

https://developer.apple.com/documentation/messageui/mfmessagecomposeviewcontroller


仍然需要弹出短信表单。有没有办法在后台发送? - Raptor
5
您可以使用 Twilio 等服务在后台发送短信,但如果您想从用户的电话号码发送短信,则需要通过上述方法获得他们的批准。请注意,不能改变原文的意思。 - Daniel Amitay
3
дҢүз”ЁдёЉиү°д»Әз Ѓзљ„д»»дҢ•дғғйѓҢеЏҮд»ӨиЂѓи™‘е°†MFMessageComposeViewController *controller = ...ж”ңењЁifеқ—е†…гЂ‚пә€з±»ж–№жі•дёҚйњЂи¦Ѓе®һдң‹жқӨиү›иҰЊжµ‹иҮ•пә‰ - unsynchronized
链接 http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/ 在我的笔记本电脑上显示“502 Bad Gateway”。也许链接已经失效了。 - Nikita Vlasenko

100
  1. 你必须将MessageUI.framework添加到你的Xcode项目中
  2. 在你的头文件中包含#import <MessageUI/MessageUI.h>
  3. 将这些委托添加到你的头文件:MFMessageComposeViewControllerDelegateUINavigationControllerDelegate
  4. 在你的IBAction方法中声明一个MFMessageComposeViewController的实例,例如messageInstance
  5. 为了检查你的设备是否可以发送短信,在if条件语句中使用[MFMessageComposeViewController canSendText],它将返回Yes/No
  6. if条件语句中执行以下操作:

    1. 首先设置messageInstance的正文内容:

      messageInstance.body = @"Hello from Shah";
      
      然后,根据以下方式确定消息的接收者:
      messageInstance.recipients = [NSArray arrayWithObjects:@"12345678", @"87654321",         nil];
      
    2. 将一个委托对象分配给你的messageInstance,示例如下:

      messageInstance.messageComposeDelegate = self;
      
      在最后一行做这个:
      [self presentModalViewController:messageInstance animated:YES];
      

2
版本说明:presentModalViewController:animated:已被弃用,请使用presentViewController:animated:completion:代替。另外,如果您想要了解结果,请记得定义委托方法- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result - Raptor
请将测试代码放在这里或Github上,@Najeebullah Shah。 - user285594

49
您可以使用sms:[目标电话号码] URL打开短信应用程序,但没有任何指示如何预填短信正文。

react-native-communications使用&body=参数来预先填充文本,当打开sms:targetphonenumber&body=textyouwanttoprefillwith的时候,适用于iOS。 - Doug Voss
我刚在我的 iPhone 8 上尝试了一下,效果非常好...谢谢! - Brad Parks
我需要向一个特定的号码发送短信,但是要预先填写好正文内容。这些正文内容应该是从4个可能选项中手动选择的。例如,应用程序打开并弹出“选择原因”的窗口。然后提供4个选项。接下来,用户选择其中一个选项,然后自动发送一条短信,其正文内容为用户的选择。有什么提示吗? - seralouk

25

在MacOS中,一种进程间通信系统是XPC。该系统层已经基于使用libSystem和launchd传输plist结构的进程间通信进行了开发。实际上,它是一种接口,允许通过交换诸如字典之类的结构来管理进程。由于遗传关系,iOS 5也拥有此机制。

您可能已经明白我在介绍什么。是的,在iOS中有包括用于XPC通信的工具的系统服务。我想通过一个用于短信发送的守护进程来说明这项工作。但应该提到的是,此功能已在iOS 6中固定,但对于iOS 5.0-5.1.1仍然有效。其利用无需越狱、私有框架或其他非法工具,只需要从目录/usr/include/xpc/*获取一组头文件。

iOS中用于短信发送的一个元素是系统服务com.apple.chatkit,其任务包括生成、管理和发送短文本消息。为了方便控制,它具有公开可用的通信端口com.apple.chatkit.clientcomposeserver.xpc。使用XPC子系统,您可以生成并发送消息而无需用户批准。

好的,让我们尝试创建连接。

xpc_connection_t myConnection;

dispatch_queue_t queue = dispatch_queue_create("com.apple.chatkit.clientcomposeserver.xpc", DISPATCH_QUEUE_CONCURRENT);

myConnection = xpc_connection_create_mach_service("com.apple.chatkit.clientcomposeserver.xpc", queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);

现在,我们已经将XPC连接myConnection设置为短信发送服务。然而,XPC配置提供了创建暂停连接的功能,我们需要再迈出一步以进行激活。

xpc_connection_set_event_handler(myConnection, ^(xpc_object_t event){
xpc_type_t xtype = xpc_get_type(event);
if(XPC_TYPE_ERROR == xtype)
{
NSLog(@"XPC sandbox connection error: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
}
// Always set an event handler. More on this later.

NSLog(@"Received a message event!");

});

xpc_connection_resume(myConnection);

连接已激活。此时iOS 6将在电话日志中显示一条消息,指出此类通信是被禁止的。现在我们需要生成一个类似于xpc_dictionary的字典,其中包含发送消息所需的数据。

NSArray *recipient = [NSArray arrayWithObjects:@"+7 (90*) 000-00-00", nil];

NSData *ser_rec = [NSPropertyListSerialization dataWithPropertyList:recipient format:200 options:0 error:NULL];

xpc_object_t mydict = xpc_dictionary_create(0, 0, 0);
xpc_dictionary_set_int64(mydict, "message-type", 0);
xpc_dictionary_set_data(mydict, "recipients", [ser_rec bytes], [ser_rec length]);
xpc_dictionary_set_string(mydict, "text", "hello from your application!");

剩下很少了:将消息发送到XPC端口并确保其被传递。

xpc_connection_send_message(myConnection, mydict);
xpc_connection_send_barrier(myConnection, ^{
NSLog(@"The message has been successfully delivered");
});

就这些。短信已发送。


1
你不应该使用XPC发送短信。这样制作的应用程序将无法通过苹果公司的审核。应改用MessageUI框架。 - Raptor
如果您正在为您的组织使用此技术,并且该应用程序未通过应用商店发布,那么您就不必担心。 - Martin Berger
在iOS 12上出现“XPC沙盒连接错误:连接无效” - Martin Berger

24

添加MessageUI.Framework并使用以下代码

#import <MessageUI/MessageUI.h> 

然后:

if ([MFMessageComposeViewController canSendText]) {
  MFMessageComposeViewController *messageComposer =
  [[MFMessageComposeViewController alloc] init];
  NSString *message = @"Your Message here";
  [messageComposer setBody:message];
  messageComposer.messageComposeDelegate = self;
  [self presentViewController:messageComposer animated:YES completion:nil];
}

并且委托方法 -

- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
             didFinishWithResult:(MessageComposeResult)result {
      [self dismissViewControllerAnimated:YES completion:nil];
 }

嘿,那很棒,但我们能在后台完成这个功能吗? - Raj
3
苹果不允许您未经用户批准发送信息。用户必须通过手动按按钮来发送消息/邮件。或者,您可以通过将电子邮件/号码发送到后端,然后再发送,使用自定义服务。但是,在iPhone上无法直接执行此操作。 - Bharat Gulati

21

您可以采用这种方法:

[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"sms:MobileNumber"]]


iOS将自动从您的应用程序导航到消息应用程序的消息撰写页面。由于URL的方案以sms:开头,因此被识别为一种被消息应用程序识别并启动的类型。


14

按照以下步骤操作

1. 添加MessageUI.Framework到项目中enter image description here

2. 在.h文件中导入#import <MessageUI/MessageUI.h>

3. 复制此代码以发送消息。

 if ([MFMessageComposeViewController canSendText]) {
    MFMessageComposeViewController *messageComposer =
    [[MFMessageComposeViewController alloc] init];
    NSString *message = @"Message!!!";
    [messageComposer setBody:message];
    messageComposer.messageComposeDelegate = self;
    [self presentViewController:messageComposer animated:YES completion:nil];
}

4. 如果您想要,可以实现delegate方法。

- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result{


   ///your stuff here 

    [self dismissViewControllerAnimated:YES completion:nil];
}

跑起来吧!


值得一提的是,您可能希望在 messageComposeViewController: didFinishWithResult: 回调方法中运行 [self dismissViewControllerAnimated:YES completion:nil];。否则它将会一直挂在那里。 - SaltyNuts

12
//Add the Framework in .h file

#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>

//Set the delegate methods

UIViewController<UINavigationControllerDelegate,MFMessageComposeViewControllerDelegate>

//add the below code in .m file


- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];

    MFMessageComposeViewController *controller = 
    [[[MFMessageComposeViewController alloc] init] autorelease];

    if([MFMessageComposeViewController canSendText])
    { 
        NSString *str= @"Hello";
        controller.body = str;
        controller.recipients = [NSArray arrayWithObjects:
                                 @"", nil];
        controller.delegate = self;
        [self presentModalViewController:controller animated:YES];  
    }


}

- (void)messageComposeViewController:
(MFMessageComposeViewController *)controller
                 didFinishWithResult:(MessageComposeResult)result 
{
    switch (result)
    {
        case MessageComposeResultCancelled:  
            NSLog(@"Cancelled");    
            break; 
        case MessageComposeResultFailed:
            NSLog(@"Failed");
            break;   
        case MessageComposeResultSent:      
            break; 
        default:  
            break;  
    }  
    [self dismissModalViewControllerAnimated:YES]; 
}

你应该看一下这个链接:http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/,它会对你有所帮助。 - Banker Mittal

6

这是在iOS中发送短信的Swift版本代码。请注意它只能在真实设备上运行,经测试可用于iOS 7以上版本。您可以点击此处了解更多信息。

1)创建一个继承自MFMessageComposeViewControllerDelegate和NSObject的新类:

import Foundation
import MessageUI

class MessageComposer: NSObject, MFMessageComposeViewControllerDelegate {
    // A wrapper function to indicate whether or not a text message can be sent from the user's device
    func canSendText() -> Bool {
        return MFMessageComposeViewController.canSendText()
    }

    // Configures and returns a MFMessageComposeViewController instance
    func configuredMessageComposeViewController(textMessageRecipients:[String] ,textBody body:String) -> MFMessageComposeViewController {
        let messageComposeVC = MFMessageComposeViewController()
        messageComposeVC.messageComposeDelegate = self  //  Make sure to set this property to self, so that the controller can be dismissed!
        messageComposeVC.recipients = textMessageRecipients
        messageComposeVC.body = body
        return messageComposeVC
    }

    // MFMessageComposeViewControllerDelegate callback - dismisses the view controller when the user is finished with it
    func messageComposeViewController(controller: MFMessageComposeViewController!, didFinishWithResult result: MessageComposeResult) {
        controller.dismissViewControllerAnimated(true, completion: nil)
        }
}

2) 如何使用这个类:

func openMessageComposerHelper(sender:AnyObject ,withIndexPath indexPath: NSIndexPath) {
    var recipients = [String]()

    //modify your recipients here

    if (messageComposer.canSendText()) {
        println("can send text")
        // Obtain a configured MFMessageComposeViewController
        let body = Utility.createInvitationMessageText()

        let messageComposeVC = messageComposer.configuredMessageComposeViewController(recipients, textBody: body)

        // Present the configured MFMessageComposeViewController instance
        // Note that the dismissal of the VC will be handled by the messageComposer instance,
        // since it implements the appropriate delegate call-back
        presentViewController(messageComposeVC, animated: true, completion: nil)
    } else {
        // Let the user know if his/her device isn't able to send text messages
        self.displayAlerViewWithTitle("Cannot Send Text Message", andMessage: "Your device is not able to send text messages.")
    }
}

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