一碗暗、系統(tǒng)應(yīng)用
在開發(fā)某些應(yīng)用時(shí)颈将,我們可能希望能夠調(diào)用iOS系統(tǒng)內(nèi)置的電話、短信言疗、郵件晴圾、瀏覽器應(yīng)用,或者直接調(diào)用安裝的第三方應(yīng)用噪奄,這個(gè)要怎么實(shí)現(xiàn)呢死姚?
這里統(tǒng)一使用UIApplication的一個(gè)對(duì)象方法來實(shí)現(xiàn):
//打開不同的系統(tǒng)應(yīng)用
- (void)openUrl:(NSURL *)url;
那怎么區(qū)分我是要打電話還是發(fā)短信等等呢?
之前我們學(xué)習(xí)網(wǎng)絡(luò)的時(shí)候勤篮,是不是URL最前面使用的是http://
都毒,使用本地文件是不是前面就變成file://
了,這就是URL的協(xié)議碰缔,我們就是控制URL的協(xié)議账劲,來打開不同應(yīng)用。
下面列出了一些系統(tǒng)應(yīng)用URL協(xié)議:
tel://
和tel:
:打電話手负,沒有提示直接撥打
-
telprompt://
和telprompt:
:打電話涤垫,撥打電話前有提示用戶是否撥打電話 -
sms://
和sms:
:發(fā)短信 -
mailto://
和mailto:
:發(fā)郵件 -
http://
和http:
:打開瀏覽器
下面就是具體實(shí)例演示:
1. 有提示的打電話
//打電話
- (void)telpromptTest{
//電話號(hào)碼
NSString *phoneNumber = @"18500138888";
//1.創(chuàng)建打電話URL路徑,這種方式會(huì)提示用戶確認(rèn)是否撥打電話
NSString *urlStr = [NSString stringWithFormat:@"telprompt://%@",phoneNumber];
//2.生成URL
NSURL *url = [NSURL URLWithString:urlStr];
//3.打開系統(tǒng)應(yīng)用
UIApplication *application = [UIApplication sharedApplication];
[application openURL:url];
}
2. 發(fā)短信
//發(fā)送短信
- (void)sendMessageTest{
//電話號(hào)碼
NSString *phoneNumber = @"18500138888";
//1.創(chuàng)建發(fā)短信URL路徑
NSString *urlStr = [NSString stringWithFormat:@"sms://%@",phoneNumber];
//2.生成URL
NSURL *url = [NSURL URLWithString:urlStr];
//3.打開系統(tǒng)應(yīng)用
UIApplication *application = [UIApplication sharedApplication];
[application openURL:url];
}
3. 發(fā)郵件
//發(fā)送郵件
- (void)sendEmailTest {
NSString *mailAddress = @"850192964@qq.com";
//1.創(chuàng)建發(fā)郵件URL路徑
NSString *urlStr = [NSString stringWithFormat:@"mailto://%@",mailAddress];
//2.生成URL
NSURL *url = [NSURL URLWithString:urlStr];
//3.打開系統(tǒng)應(yīng)用
UIApplication *application = [UIApplication sharedApplication];
[application openURL:url];
}
4. 打開瀏覽器
//瀏覽網(wǎng)頁
- (void)browserTest {
//1.創(chuàng)建打開瀏覽器URL路徑
NSString *urlStr = @"http://www.baidu.com";
//2.生成URL
NSURL *url = [NSURL URLWithString:urlStr];
//3.打開系統(tǒng)應(yīng)用
UIApplication *application = [UIApplication sharedApplication];
[application openURL:url];
}
上面打開的是系統(tǒng)應(yīng)用竟终,實(shí)際上openUrl
的功能是只要是系統(tǒng)安裝了的應(yīng)用程序蝠猬,都可以打開,比如假設(shè)你現(xiàn)在開發(fā)了一個(gè)應(yīng)用A统捶,如果用戶機(jī)器上已經(jīng)安裝了此應(yīng)用榆芦,并且在應(yīng)用B中希望能夠直接打開A,也是可以用openUrl
實(shí)現(xiàn)喘鸟,不過要進(jìn)行一些配置匆绣。
配置第三方應(yīng)用步驟:
- 修改應(yīng)用A的
info.plist
文件,添加URL types
節(jié)點(diǎn)
- 在該節(jié)點(diǎn)下什黑,配置具體協(xié)議
URL Schemas
以及應(yīng)用A的唯一標(biāo)識(shí)URL identifier
崎淳,如下圖:
- 在應(yīng)用A的
AppDelegate
文件中處理AppDelegate
的一個(gè)代理方法
/*
當(dāng)被其他應(yīng)用程序通過URL打開時(shí)就會(huì)調(diào)用,
這里可以接收參數(shù)并解析愕把,返回是否能被其他應(yīng)用程序打開
*/
-(BOOL)application:(UIApplication *)application //當(dāng)前應(yīng)用程序
openURL:(NSURL *)url //其他應(yīng)用使用的URL
sourceApplication:(NSString *)sourceApplication //其他應(yīng)用的應(yīng)用標(biāo)識(shí)
annotation:(id)annotation
{
NSLog(@"url:%@",url);
NSLog(@"source:%@",sourceApplication);
NSLog(@"params:%@",[url host]);
return YES;//是否打開
}
配置應(yīng)用A完成拣凹,然后我們就可以在應(yīng)用B中使用openUrl
打開應(yīng)用A了
//打開第三方應(yīng)用
- (void)thirdPartyApplicationTest
{
//使用第三方應(yīng)用協(xié)議
NSString *urlStr = @"cmj://myparams";
NSURL *url = [NSURL URLWithString:urlStr];
//判斷該應(yīng)用是否能打開
UIApplication *application = [UIApplication sharedApplication];
if(![application canOpenURL:url]){
NSLog(@"無法打開\"%@\"森爽,請(qǐng)確保此應(yīng)用已經(jīng)正確安裝.",url);
return;
}
[application openURL:url];
}
二、系統(tǒng)服務(wù)
調(diào)用系統(tǒng)內(nèi)置的應(yīng)用來發(fā)送短信嚣镜、郵件相當(dāng)簡(jiǎn)單爬迟,但是這么操作也存在著一些弊端:
當(dāng)你點(diǎn)擊了發(fā)送短信(或郵件)操作之后,直接啟動(dòng)了系統(tǒng)的短信(或郵件)應(yīng)用程序菊匿,我們的應(yīng)用其實(shí)此時(shí)已經(jīng)處于一種掛起狀態(tài)付呕,發(fā)送完(短信或郵件)之后無法自動(dòng)回到應(yīng)用界面。
如果想要在應(yīng)用程序內(nèi)部完成這些操作跌捆,則可以利用iOS中的MessageUI.framework
徽职,它提供了關(guān)于短信和郵件的UI接口供開發(fā)者在應(yīng)用程序內(nèi)部調(diào)用。
MessageUI.framework
提供了有現(xiàn)成的短信和郵件的編輯界面疹蛉,開發(fā)人員只需要通過編程的方式給短信和郵件控制器設(shè)置對(duì)應(yīng)的參數(shù)即可活箕。
1、短信
在MessageUI.framework
中使用MFMessageComposeViewController
來發(fā)短信
下面是使用步驟:
- 導(dǎo)入
MessageUI.framework
可款,并添加頭文件
#import <MessageUI/MessageUI.h>
- 創(chuàng)建
MFMessageComposeViewController
對(duì)象 - 設(shè)置收件人育韩、信息正文等內(nèi)容屬性,設(shè)置代理
messageComposeDelegate
- 以模態(tài)彈出該視圖控制器
- 處理代理方法闺鲸,獲取發(fā)送狀態(tài):
/* 發(fā)送完成會(huì)調(diào)用筋讨,不管成功與否 */
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result;/*發(fā)送結(jié)果*/
下面是使用實(shí)例:
#import "KCSendMessageViewController.h"
#import <MessageUI/MessageUI.h>
@interface KCSendMessageViewController ()<MFMessageComposeViewControllerDelegate>
@property (weak, nonatomic) IBOutlet UITextField *receivers;//收信人文本框
@property (weak, nonatomic) IBOutlet UITextField *body;//信息正文文本框
@property (weak, nonatomic) IBOutlet UITextField *subject;//主題文本框
@property (weak, nonatomic) IBOutlet UITextField *attachments;//附件文本框
@end
@implementation KCSendMessageViewController
#pragma mark - 控制器視圖方法
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - UI事件
- (IBAction)sendMessageClick:(UIButton *)sender {
//如果不能發(fā)送文本信息,就直接返回
if(![MFMessageComposeViewController canSendText]){
return;
}
//創(chuàng)建短信發(fā)送視圖控制器
MFMessageComposeViewController *messageController =
[[MFMessageComposeViewController alloc] init];
//設(shè)置收件人
messageController.recipients = [self.receivers.text componentsSeparatedByString:@","];
//設(shè)置信息正文
messageController.body = self.body.text;
//設(shè)置代理,注意這里不是delegate而是messageComposeDelegate
messageController.messageComposeDelegate = self;
//判斷是否支持主題
if([MFMessageComposeViewController canSendSubject]){
//設(shè)置主題
messageController.subject = self.subject.text;
}
//判斷是否支持附件
if ([MFMessageComposeViewController canSendAttachments]) {
//添加附件摸恍,請(qǐng)務(wù)必指定附件文件的后綴悉罕,否則在發(fā)送后無法正確識(shí)別文件類別
NSArray *attachments = [self.attachments.text componentsSeparatedByString:@","];
if (attachments.count > 0) {
for(NSString *attachment in attachments){
NSString *path = [[NSBundle mainBundle] pathForResource:attachment
ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
//添加附件具體方法,需要設(shè)置附件URL和附件的標(biāo)識(shí)
[messageController addAttachmentURL:url
withAlternateFilename:attachment];
};
}
}
//以模態(tài)彈出界面
[self presentViewController:messageController animated:YES completion:nil];
}
#pragma mark - MFMessageComposeViewController代理方法
/* 發(fā)送完成立镶,不管成功與否 */
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MessageComposeResultSent:
NSLog(@"發(fā)送成功.");
break;
case MessageComposeResultCancelled:
NSLog(@"取消發(fā)送.");
break;
default:
NSLog(@"發(fā)送失敗.");
break;
}
//彈回界面
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
2. 郵件
在MessageUI.framework
中使用MFMailComposeViewController
來發(fā)郵件
使用步驟【和發(fā)短信相似】:
- 導(dǎo)入
MessageUI.framework
,并添加頭文件
#import <MessageUI/MessageUI.h>
- 創(chuàng)建
MFMailComposeViewController
對(duì)象 - 設(shè)置收件人缭召、抄送人栈顷、正文等內(nèi)容屬性,設(shè)置代理
mailComposeDelegate
- 以模態(tài)彈出該視圖控制器
- 處理代理方法嵌巷,獲取發(fā)送狀態(tài):
/* 發(fā)送完成會(huì)調(diào)用萄凤,不管成功與否 */
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result /* 發(fā)送結(jié)果 */
error:(NSError *)error;/* 錯(cuò)誤信息 */
下面是實(shí)例:
#import "KCSendEmailViewController.h"
#import <MessageUI/MessageUI.h>
@interface KCSendEmailViewController ()<MFMailComposeViewControllerDelegate>
@property (weak, nonatomic) IBOutlet UITextField *toTecipients;//收件人文本框
@property (weak, nonatomic) IBOutlet UITextField *ccRecipients;//抄送人文本框
@property (weak, nonatomic) IBOutlet UITextField *bccRecipients;//密送人文本框
@property (weak, nonatomic) IBOutlet UITextField *subject; //主題文本框
@property (weak, nonatomic) IBOutlet UITextField *body;//正文文本框
@property (weak, nonatomic) IBOutlet UITextField *attachments;//附件文本框
@end
@implementation KCSendEmailViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - UI事件
- (IBAction)sendEmailClick:(UIButton *)sender {
//判斷當(dāng)前是否能夠發(fā)送郵件
if ([MFMailComposeViewController canSendMail]) {
return;
}
//創(chuàng)建發(fā)送郵件視圖控制器
MFMailComposeViewController *mailController =
[[MFMailComposeViewController alloc] init];
//設(shè)置代理,注意這里不是delegate搪哪,而是mailComposeDelegate
mailController.mailComposeDelegate = self;
//設(shè)置收件人
NSArray *recipients = [self.toTecipients.text componentsSeparatedByString:@","];
[mailController setToRecipients:recipients];
//設(shè)置抄送人
if (self.ccRecipients.text.length > 0) {
NSArray *ccRecipients = [self.ccRecipients.text componentsSeparatedByString:@","];
[mailController setCcRecipients:ccRecipients];
}
//設(shè)置密送人
if (self.bccRecipients.text.length > 0) {
NSArray *bccRecipients = [self.bccRecipients.text componentsSeparatedByString:@","];
[mailController setBccRecipients:bccRecipients];
}
//設(shè)置主題
[mailController setSubject:self.subject.text];
//設(shè)置主體內(nèi)容
[mailController setMessageBody:self.body.text isHTML:YES];
//添加附件
if (self.attachments.text.length > 0) {
NSArray *attachments = [self.attachments.text componentsSeparatedByString:@","] ;
for(NSString *attachment in attachments) {
NSString *file = [[NSBundle mainBundle] pathForResource:attachment
ofType:nil];
NSData *data = [NSData dataWithContentsOfFile:file];
//第一個(gè)參數(shù)是附件數(shù)據(jù)靡努,第二個(gè)參數(shù)是mimeType類型,jpg圖片對(duì)應(yīng)image/jpeg
[mailController addAttachmentData:data
mimeType:@"image/jpeg"
fileName:attachment];
};
}
//彈出視圖
[self presentViewController:mailController animated:YES completion:nil];
}
#pragma mark - MFMailComposeViewController代理方法
/* 發(fā)送完成會(huì)調(diào)用,不管成功與否 */
-(void)mailComposeController:(MFMailComposeViewController *)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError *)error
{
switch (result) {
case MFMailComposeResultSent:
NSLog(@"發(fā)送成功.");
break;
case MFMailComposeResultSaved:
//點(diǎn)取消會(huì)提示是否存儲(chǔ)為草稿颤难,存儲(chǔ)后可以到系統(tǒng)郵件應(yīng)用的對(duì)應(yīng)草稿箱找到
NSLog(@"郵件已保存.");
break;
case MFMailComposeResultCancelled:
NSLog(@"取消發(fā)送.");
break;
default:
NSLog(@"發(fā)送失敗.");
break;
}
if (error) {
NSLog(@"發(fā)送郵件過程中發(fā)生錯(cuò)誤神年,錯(cuò)誤信息:%@",error.localizedDescription);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
上面的代碼Demo點(diǎn)這里:LearnDemo里面的MessageUITest