系统应用和第三方应用跳转

前言:

iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如在应用中拨打电话,一些第三方软件会在应用内发送短信等。今天将和大家一起学习如何使用系统应用、使用系统服务完成上述功能。

事实上,我们在前面学习的内容中就有调用过系统内置的应用。比如我们在点击textView的超链接文本时,默认使用系统浏览器来访问连接,还有前面学习到地图服务,我们也可以通过打开系统内置的地图应用来完成地图服务。在开发某些应用时,如果希望能够调用iOS系统内置的电话、短信、邮件、浏览器应用,此时你可以直接使用UIApplication的OpenURL:方法指定特定的协议来打开不同的系统应用。常用的协议如下:

  • 打电话:tel:或者tel://、telprompt:或telprompt://(拨打电话前有提示)。
  • 发短信:sms:或者sms://
  • 发送邮件:mailto:或者mailto://
  • 启动浏览器:http:或者http://

但是实际开发中我们发现,调用系统内置的应用来完成上述系统服务也存在着一些弊端:除了打电话之外,当你点击了发送短信(或邮件)操作之后直接启动了系统的短信(或邮件)应用程序,我们的应用其实此时已经处于一种挂起状态,打完电话或是发送完短信(或邮件)之后无法自动回到应用界面。而且不能在我们自己开发的应用中制定短信(或邮件)的内容。这显然不符合我们的需求,我们需要在应用程序内部完成这些操作。


1. 拨打电话

拨打电话的功能实现相对简单,直接使用UIApplication的OpenURL:的方法并制定对应的协议就可以,打完电话后我们任然留在当前的应用界面。下面以一个简单的demo演示如何完成拨打电话的功能:

示例代码:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

// 打电话 tel: 或tel:// 协议
- (IBAction)callPhone1:(id)sender {
    // 使用这个协议会直接拨打电话
    NSString *phoneNumber=@"10010";// 拨打的电话

    NSString *url=[NSString stringWithFormat:@"tel://%@",phoneNumber];

    [self openUrl:url];
}

// 打电话 telprompt:或telprompt:// 协议
- (IBAction)callPhone2:(id)sender {
    // 这个协议在打电话前会先弹出一个对话框,提醒你是否打电话,然后在打完电话之后会回到程序中
    NSString *phoneNumber=@"10010";// 拨打的电话
    NSString *url=[NSString stringWithFormat:@"telprompt://%@",phoneNumber];

    [self openUrl:url];
}

#pragma mark - 私有方法
-(void)openUrl:(NSString *)urlStr {

    // 注意url中包含协议名称,iOS根据协议确定调用哪个应用,例如发送邮件是“tel://”其中“//”可以省略写成“tel:”(其他协议也是如此)
    NSURL *url=[NSURL URLWithString:urlStr];
    UIApplication *application=[UIApplication sharedApplication];
    if(![application canOpenURL:url]){
        NSLog(@"无法打开\"%@\",请确保此应用已经正确安装.",url);
        return;
    }
    // 打开对应协议的应用
    [[UIApplication sharedApplication] openURL:url];
}
@end

2. 发送短信

如果我们在应用中直接调用发送短信的系统应用,在完成发送任务后,我们停留在了系统应用当中,当然我们也可以在程序内部完成短信的编辑和发送任务。利用iOS中的MessageUI.framework,它提供了关于短信的UI接口供开发者在应用程序内部调用。从框架名称不难看出这是一套UI接口,提供有现成的短信的编辑界面,开发人员只需要通过编程的方式给短信控制器设置对应的参数即可。

在MessageUI.framework中用于发送短信的类是MFMessageComposeViewController。它继承于UINavigationController。下面介绍一下MFMessageComposeViewController使用步骤:

  • 创建MFMessageComposeViewController对象。
  • 设置收件人recipients、信息正文body,如果运行商支持主题和附件的话可以设置主题subject、附件attachments(可以通过canSendSubject、canSendAttachments方法判断运行商是否支持)
  • 设置代理messageComposeDelegate,注意这里不是delegate属性,因为delegate属性已经留给UINavigationController,MFMessageComposeViewController没有覆盖此属性而是重新定义了一个代理,实现代理方法获得发送状态。

下面自定义一个发送短信的界面演示MFMessageComposeViewController的使用:我们可以定制短息控制器的相关参数,当我们弹出MFMessageComposeViewController的实例对象时,看到的就是短息的系统编辑界面,点击MFMessageComposeViewController 界面中的“发送”来完成短信发送工作,当然用户也可能点击“取消”按钮回到当前应用。当然,在我们完成发送任务之后还是可以回到当前应用的。

示例代码:

#import "ViewController.h"
#import 

@interface ViewController ()<MFMessageComposeViewControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

// 发短信
- (IBAction)snedMessage1:(id)sender {

    NSString *phoneNumber = @"10010";
    NSString *urlString = [NSString stringWithFormat:@"sms://%@",phoneNumber];

    NSURL *url = [NSURL URLWithString:urlString];
    UIApplication *application = [UIApplication sharedApplication];
    if(![application canOpenURL:url]){
        NSLog(@"无法打开\"%@\",请确保此应用已经正确安装.",url);
        return;
    }
    // 打开对应协议的应用
    [[UIApplication sharedApplication] openURL:url];
}

- (IBAction)sendMessage2:(id)sender {

    // 判断运营商是否能够发送文本
    if(![MFMessageComposeViewController canSendText]) {

        //显示提示框
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示信息" message:@"该设备不支持短信功能" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *alertAC = [UIAlertAction actionWithTitle:@"YES" style:UIAlertActionStyleCancel handler:nil];
        [alertVC addAction:alertAC];
        [self presentViewController:alertVC animated:YES completion:nil];
        return;
    }

    // 1.初始化一个控制器MFMessageComposeViewController用来发送短信
    MFMessageComposeViewController *messageVC = [[MFMessageComposeViewController alloc] init];

    // 2.设置短信内容
    // 收件人,可以设置多个
    messageVC.recipients = @[@"10086",@"10010"];
    // componentsSeparatedByString:根据某个字符将字符串分开成为不同的字符串,并存放到一个数组中。

    // 短信内容
    messageVC.body = @"恭喜发财,红包拿来";

    // 判断运营商是否支持主题设置
    if ([MFMessageComposeViewController canSendSubject]) {
        NSLog(@"can send subject");
        // 添加主题到消息控制器
        messageVC.subject = @"我的主题";
    }
    // 判断硬件是否支持附件设置
    if ([MFMessageComposeViewController canSendAttachments]) {
        NSLog(@"can send attachments");

        // 注意,不能直接给attachments赋值,系统将其看作只读性质对象
        //        messageVC.attachments = @[];

        // 添加附件到消息控制器
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"attachment.png" ofType:nil];
        NSURL *fileURL = [NSURL fileURLWithPath:filePath];

        // 方法一:可以看到我们给文件的命名
        [messageVC addAttachmentURL:fileURL withAlternateFilename:@"attachment"];

        // 方法二:可以看到指定的文件类型,比如看到一个图片
        /**
         *  attatchData:文件数据
         *  typeIdentifier:统一类型标识,标识具体文件类型,详情查看:帮助文档中System-Declared Uniform Type Identifiers
         *  fileName:展现给用户看的文件名称
         */
        [messageVC addAttachmentData:[NSData dataWithContentsOfURL:fileURL] typeIdentifier:@"public.image" filename:@"attachment.png"];
        /* 常用的类型标识
         public.movie:Base type for movies (video with optional audio or other tracks).
         public.audio:Base type for audio (no video).
         public.image:Base type for images.
         */
    }

    // 3. 设置代理,通过代理监听短信的发送状态,并且释放短信控制器,
    messageVC.messageComposeDelegate = self;//注意这里不是delegate而是messageComposeDelegate

    // 4. 弹出消息布局控制器
    [self presentViewController:messageVC animated:YES completion:nil];

    // MessageUI.framework框架功能强大,除了可以支持发送短信给多人之外,自定义的消息可以为图片,并且消息支持HTML格式。最重要的是,如果彼此的手机都是iOS设备,并且都开通了iMessage功能,彼此之间的短信走的是网络通道,而不是走运营商通道!
}

#pragma mark MFMessageComposeViewControllerDelegate
// 发送完成,不管成功与否
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
    switch (result) {
        case MessageComposeResultCancelled:
            NSLog(@"取消发送");
            break;
        case MessageComposeResultSent:
            NSLog(@"发送成功");
            break;
        case MessageComposeResultFailed:
            NSLog(@"发送失败");
            break;
        default:
            break;
    }

    // 应该用下面的方法释放消息控制器,因为在面向对象程序开发中,有一个原则,谁申请,谁释放!
    [self dismissViewControllerAnimated:YES completion:nil];

    // 当然,此方法也可以正常工作,因为系统会将关闭消息发送给self
//    [controller dismissViewControllerAnimated:YES completion:nil];
}

@end

这里需要强调一下:

  • MFMessageComposeViewController的代理不是通过delegate属性指定的而是通过messageComposeDelegate指定的。
  • 可以通过两种方式来指定发送的附件,当然实现的效果也是不一样的,但是在这个过程中请务必指定文件的后缀,否则在发送后无法正确识别文件类别(例如如果发送的是一张jpg图片,在发送后无法正确查看图片)。
  • 无论发送成功与否代理方法都会执行,通过代理参数中的result来获得发送状态。
  • 释放消息控制器不能使用消息控制器本身调用dismiss的方法,因为在面向对象程序开发中,有一个原则,谁申请,谁释放!所以我们使用退出消息控制器的试图控制器来完成释放的任务。

3. 发送邮件

那么,熟悉了MFMessageComposeViewController之后,我们来看一下如何在应用中发送邮件。 邮件的发送实现起来和短信功能相类似,是由MessageUI.framework的另外一个类MFMailComposeViewController 来实现的。MFMailComposeViewController用法和步骤和MFMessageComposeViewController完全一致,只是功能不同。下面看一下MFMailComposeViewController的使用:

示例代码:

#import "ViewController.h"
#import 

@interface ViewController ()<MFMailComposeViewControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

// 发邮件 mailto: 或 mailto:// 协议
- (IBAction)sendEmail1:(id)sender {

    NSString *mailAddress = @"[email protected]";
    NSString *urlStr = [NSString stringWithFormat:@"mailto://%@",mailAddress];

    NSURL *url = [NSURL URLWithString:urlStr];
    UIApplication *application = [UIApplication sharedApplication];
    if(![application canOpenURL:url]){
        NSLog(@"无法打开\"%@\",请确保此应用已经正确安装.",url);
        return;
    }

    // 打开对应协议的应用
    [[UIApplication sharedApplication] openURL:url];
}

- (IBAction)sendEmail2:(id)sender {

    // 判断用户设备是否能够发送邮件
    if(![MFMailComposeViewController canSendMail]) {

        //显示提示框
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"提示信息" message:@"提醒用户设置邮箱" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *alertAC = [UIAlertAction actionWithTitle:@"YES" style:UIAlertActionStyleCancel handler:nil];
        [alertVC addAction:alertAC];
        [self presentViewController:alertVC animated:YES completion:nil];
        return;
    }

    // 1.初始化化一个邮件控制器MFMailComposeViewController用来编辑和发送邮件
    MFMailComposeViewController *mailVC = [[MFMailComposeViewController alloc] init];
    // 设置代理
    mailVC.mailComposeDelegate = self;

    // 2.设置邮件内容
    // 收件人,可以设置多个
    [mailVC setToRecipients:@[@"[email protected]"]];
    // 抄送人
    [mailVC setCcRecipients:@[@"[email protected]"]];
    // 密送人
    [mailVC setBccRecipients:@[@"[email protected]"]];

    // 邮件主题
    [mailVC setSubject:@"我的工作日报"];
    // 邮件正文
    [mailVC setMessageBody:@"这是我的工作报告,请审阅!
P.S. 我的头像牛X吗?"
isHTML:YES]; // 附件 NSString *filePath = [[NSBundle mainBundle] pathForResource:@"头像.png" ofType:nil]; NSData *data = [NSData dataWithContentsOfFile:filePath]; [mailVC addAttachmentData:data mimeType:@"image/png" fileName:@"头像.png"];//第二个参数是mimeType类型,jpg图片对应image/jpeg // 3. 弹出邮件控制器 [self presentViewController:mailVC animated:YES completion:nil]; } #pragma mark MFMailComposeViewControllerDelegate - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { switch (result) { case MFMailComposeResultSent: NSLog(@"发送成功."); break; case MFMailComposeResultSaved://如果存储为草稿(点取消会提示是否存储为草稿,存储后可以到系统邮件应用的对应草稿箱找到) NSLog(@"邮件已保存."); break; case MFMailComposeResultCancelled: NSLog(@"取消发送."); break; default: NSLog(@"发送失败."); break; } if (error) { NSLog(@"发送邮件过程中发生错误,错误信息:%@",error.localizedDescription); } [self dismissViewControllerAnimated:YES completion:nil]; } @end

4. 网页浏览

网页的浏览相对比较简单,我们使用application的openURL:方法打开一个合法连接就可以直接进入系统的内置浏览器,在应用内部浏览可以使用UIWebView加载网络请求,UIWebView的使用前文中也有介绍,在这里就不多做赘述了。

示例代码:

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

// 调用浏览器
- (IBAction)browser1:(id)sender {

    NSString *urlStr = @"http://www.baidu.com";
    NSURL *url = [NSURL URLWithString:urlStr];
    UIApplication *application = [UIApplication sharedApplication];
    if(![application canOpenURL:url]){
        NSLog(@"无法打开\"%@\",请确保此应用已经正确安装.",url);
        return;
    }
    // 打开对应协议的应用
    [[UIApplication sharedApplication] openURL:url];
}

- (IBAction)browser2:(id)sender {

    UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [webView loadRequest:request];

    [self.view addSubview:webView];
}
@end

5. 第三方应用跳转

从上面的几个示例中不难发现当openURL:方法只要指定一个URL Schame并且已经安装了对应的应用程序就可以打开此应用。当然,如果是自己开发的应用也可以调用openURL方法来打开。假设你现在开发了一个应用A,如果用户机器上已经安装了此应用,并且在应用B中希望能够直接打开A。那么首先需要确保应用A已经配置了Url Types,具体方法就是在plist文件中添加URL types节点并配置URL Schemas作为具体协议,配置URL identifier作为这个URL的唯一标识,如下图:
这里写图片描述
然后就可以调用openURL方法像打开系统应用一样打开第三方应用程序了:

// 打开第三方应用
- (IBAction)thirdPartyApplicationClick:(UIButton *)sender {

    NSString *urlStr = @"thirdParty://myparams";
    NSURL *url = [NSURL URLWithString:urlStr];
    // 打开对应协议的应用
    [[UIApplication sharedApplication] openURL:url];
}

注意:

  • 官方内置应用是默认授权跳转的,但是第三方应用的跳转需要用户额外给予授权,所以我们看到[[UIApplication sharedApplication] canOpenURL:url]反馈结果一直为NO,所以我们省掉了判断,首次打开第三方应用时系统会弹出一个AlertView获取第三方应用跳转的授权。
  • 从结果看出app的地址构成是: URL Scheme://URL identifier,但是单用URL Scheme 即可打开程序, 即URL identifier是可选的
  • myapp://后面的字可以为点”.”和等号”=” 不可以为空格和问号
  • stackoverflow上有人指出这是apple禁止的功能, 所以请谨慎使用, 但如果是客户问”设备能力”这方面的问题, 那么答案是”可以”, 但 不建议那么做.

就像调用系统应用一样,协议后面可以传递一些参数,这样一来在应用中可以在AppDelegate的
- (BOOL)application:(UIApplication )app openURL:(NSURL )url options:(NSDictionary

/** @pramas  当用户通过其它应用启动本应用时,会回调这个方法
 *
 *  prams:   url //其它应用调用openURL:方法时传过来的
 *           app //打开本应用的应用程序
 *           options // 应用的配置参数
 *
 *  return:  bool // 是否允许打开本程序
 */
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options {

    NSLog(@"url:%@,source application:%@,params:%@",url,app,[url host]);

    return YES;// 是否打开
}

下面是常用APP的Url Scheme 前缀

QQ mqq://
微信是 weixin://
网易新闻 newsapp://
淘宝 taobao://
点评 dianping:// dianping://search
微博 sinaweibo://
weico微博 weico://
支付宝 alipay://
豆瓣fm: doubanradio://
微盘 sinavdisk://
网易公开课 ntesopen://
美团 imeituan://
人人 renren://
我查查 wcc://
1号店 wccbyihaodian://
有道词典 yddictproapp://
知乎 zhihu://
优酷 youku://
ZAKER zakeripad://
京东hd openApp.jdiPad://
易迅 icson://;yixunipad://
wunderlist wunderlist://
支付宝 alipay://
查找朋友 grenada://;findmyfriends://;fmf1://
查找iphone fmip1://
触宝拨号:dialer://
蜂窝网络:prefs:root=MOBILE_DATA_SETTINGS_ID
WIFI:prefs:root=WIFI(WIFI这几个字母一定要大写)
定位服务:prefs:root=LOCATION_SERVICES
备忘录:mobilenotes://
高德地图:iosamap://
今日头条 snssdk141://
挖财记账 wacai://
QQ音乐 :QQmusic://
酷我音乐 com.kuwo.kwmusic.kwmusicForKwsing://
酷狗音乐 kugouURL://
京东 openApp.jdMobile://
QQ音乐 qqmusic://
QQ斗地主 tencent382://
QQ浏览器 mttbrowser://
QQ安全中心 qmtoken://
QQ国际版 mqqiapi://
搜狗输入法 com.sogou.sogouinput://
搜狐视频 sohuvideo-iphone:// 或 sohuvideo://
搜狐新闻 sohunews://
设置 prefs:root=SETTING
定位服务 prefs:root=LOCATION_SERVICES
E-Mail MESSAGE://
ifttt ifttt://
名片全能王hd camcard://;CamCardHDOpenAPI://
拉手团购hd LaShouGroupHDPay://
美团hd iMeituan://
evermemo evermemo://
网易云课堂 wangyiyunketang://
网易公开课 ntesopen://
订票助手2 trainassistfree://
pcalc lite pcalc://
爱奇艺视频 QIYIHD-iPad://
三国kill sgk://
TuneIn Radio tunein:// 或 tuneinpro://
OfficeSuite mobisystemsofficesuite://
WPS Office KingsoftOfficeApp://
Line line://
1Password onepassword://
mdict mdict://
名片全能王camcard://
支付宝alipay://
豆瓣fm:doubanradio://
微盘 sinavdisk://
网易公开课ntesopen://
我查查 wcc://
1号店wccbyihaodian://
有道词典yddictproapp://
知乎zhihu://
墨客 com.moke.moke-1://
名片全能王 camcard://
扫描全能王 camscanner://
12306订票助手 trainassist://
金山词霸 com.kingsoft.powerword.6://
节奏大师 tencentrm://
凤凰新闻 comIfeng3GifengNews://
高铁管家 gtgj://
飞信 fetion://
豆瓣FM doubanradio://
大智慧 dzhiphone://
布卡漫画 buka://
爱奇艺PPS ppstream://
哔哩哔哩动画 bilibili://
56视频 com.56Video://
365日历 rili365://
58同城 wbmain://
遇见 iaround://
陌陌 momochat://
旺旺卖家版 wangwangseller://
蜻蜓FM qtfmp://
浦发银行 wx1cb534bb13ba3dbd://
招商银行 cmbmobilebank://
支付宝 alipay://
建设银行 wx2654d9155d70a468://
工商银行 com.icbc.iphoneclient://
随手记 FDMoney://
腾讯企业邮箱 qqbizmailDistribute2://
腾讯手机管家 mqqsecure://
腾讯视频 tenvideo:// 或 tenvideo2:// 或 tenvideo3://
腾讯微博 TencentWeibo://
天猫 tmall://
天天星连萌 tencent100689806://
天天爱消除 tencent100689805://
天天酷跑 tencent100692648://
天天飞车 tencent100695850://
天天动听 ttpod://扇贝新闻 shanbaynews://
扇贝单词 shanbay://
扇贝单词hd shanbaywordshd://
skype skype://
搜狐视频hd sohu-SViPad://;sohuvideohd://
teamviewer:teamviewer8://
格志 griddiary://;sumi-interactive://
淘宝hd taobao://;itaobao://;taobaohd://
天猫 tmall://
腾讯视频hd tenvideohd://;tenvideo2://
同步推正版HD tbtui://;tuihd://
航旅纵横pro umetrippro://
mathpad myscriptmathpad://
雅虎天气! yweather://
一号店 ipadstore://
优酷hd youkuhd://
知乎 zhihu://
欧陆词典pro eudic://
拓词 towordsp://
Clear(著名的Todo应用) clearapp://
电话 mobilephone://
猎豹浏览器:sinaweibosso.422729959://
UC浏览器:ucbrowser://
支付宝:alipay://
新浪微博:weibo://
优酷:youku://
节奏大师:节奏大师tencentrm://
刀塔传奇:刀塔传奇teiron2273://
天天动听:ttpod://
淘宝taobao://有道词典 yddict://
掌阅iReader iReader://
艺龙旅行 elongIPhone://
迅雷+迅雷云播 thunder://
熊猫公交 wb1405365637://
携程无线 CtripWireless://
无线苏州 SuZhouTV://
唯品会 vipshop://
微视 weishiiosscheme://
微拍 wpweipai://
旺信 wangxin://
网易公开课 ntesopen://
网易将军令 netease-mkey://
万年历 youloft.419805549://
土豆视频 tudou://
同花顺 amihexin://
天涯社区 tianya://
天气通Pro sinaweatherpro://
天气通 sinaweather://
墨迹天气 rm434209233MojiWeather://
腾讯新闻 qqnews://
腾讯微云 weiyun://
腾讯地图 sosomap://
淘宝旅行 taobaotravel://
人人 renrenios://PPTV pptv://
爱奇艺视频 qiyi-iphone://
暴风影音 com.baofeng.play://
保卫萝卜2 wb2217954495://
保卫萝卜 wb1308702128://
百度云 baiduyun://
百度音乐 baidumusic://
百度视频 baiduvideoiphone:// 或 bdviphapp://
百度糯米 bainuo://
百度魔图 photowonder://
百度魔拍 wondercamera://
百度地图 baidumap://
百度导航 bdNavi://
百度视频hd BaiduVideoiPad://;baiduvideoipadapp://
百度相册hd BaiDuCloudAlbumHD://
百度浏览器hd bdbrowser://
百度文库hd bdwenku://
威锋网 com.weiphone.forum://
新浪微博 weibo:// 或 sinaweibo://
网易邮箱 neteasemail://
百度输入法 BaiduIMShop://
C浏览器 ucbrowser://
一个one clover-one://
当当hd dangdanghd://;ddhd://
大众点评hd dianpinghd://
多看阅读 duokan-reader://
艺龙旅行hd elongiPad://
圈点hd skitch://
印象笔记hd enx://
备忘录 mobilenotes://
qq通讯录 tencentappqqpim://
Chrome谷歌浏览器 googlechrome://
Calendars 5 calendars://
PDF Expert 5 pdfexpert5presence://
Documents 5 rdocs://
nPlayer nplayer-http://
GPlayer gplayer://
AVPlayer HD AVPlayerHD://
AVPlayer AVPlayer://
Ace Player aceplayer://

你可能感兴趣的:(系统服务)