ios app、H5、safari、appstore应用主页评分页之间拉起调用、打开手机某些系统功能、app打开文档

定义打开URL的方法

- (void)openURL:(NSString *)urlStr {
    NSURL *url = [NSURL URLWithString:urlStr];
    UIApplication *app = [UIApplication sharedApplication];
    if ([app canOpenURL:url]) {
#ifdef __IPHONE_10_0
    [app openURL:url options:[NSDictionary dictionary] completionHandler:nil];
#else
    [app openURL:url];
#endif
    }
}

调用方法为:

    NSString *url = @"xxxxxx";
    [xx openURL:url];

1.打开email

    NSString *url = [NSString stringWithFormat:@"mailto://admin@hzlzh.com"];

2.打开appstore 某应用的主页

NSString *appID = @"xxxxxxx";
NSString *url = [NSString stringWithFormat:@"https://itunes.apple.com/cn/app/id%@?mt=8", appID];

3.打电话

 NSString *url = @"tel://8008808888";

4.调用 SMS

 NSString *url = @"sms://800888";

5.自带safari打开网页

 NSString *url = @"https://www.baidu.com";

6. 代开Remote

 NSString *url = @"remote://xxx";

7.app之间拉起调用

1)在被调用app的plist文件中,注册对外接口
在TARGETS --> Info找到URL Types,然后展开URL types,增加一项,URLSchemes为:myapp,这个myapp就是对外接口,其它应用可以通过它

image.png

2)调用app方法

 NSString *url = @"myapp:";

通过上述两个步骤,你可以在你的应用中,让用户打开你的其它应用。如果加参数的话,最好写成"myapp://login?account=xxx&password=123456",就好比http请求的“http”换成“myapp”.

3)处理URL请求
应用程序委托在application:handleOpenURL:方法中处理传递给应用程序的URL请求。如果您已经为自己的应用程序注册了定制的URL模式,则务必在委托中实现这个方法。
application:handleOpenURL:方法实现 中,传入的URL对象在其请求和片断部分带有具体应用程序的信息。

- (BOOL)application: (UIApplication * )application handleOpenURL: (NSURL *)url {
 if ([[url scheme] isEqualToString:@"myapp"]) {
 //处理链接
return YES;
}
 return NO;
}

第二种处理URL请求方法

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  {
 //被其他应用调用
 NSURL *url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
 if(url) {//做出相应的判断
 if ([[url scheme] isEqualToString:@"myapp"]) {
 //处理链接
}
}
 return YES;
}

说明:iOS 程序启动时总会调用application:didFinishLaunchingWithOptions:,其中第二个参数launchOptions为NSDictionary类型的对象,里面存储有此程序启动的原因。

4).快速测试外部调用
1.回到Home屏幕,启动Safari(在iPhone仿真器上,在菜单上选择Hardware->Home命令就可以回到Home屏幕)。
2.在Safari的地址栏中,键入使用定制模式的URL,即“myapp:”,加参数的话则为“myapp://........”
3.确认您的应用程序是否启动,以及应用程序委托是否收到application:handleOpenURL:消息。

8. H5拉起调用app

[Mobile Safari 调用本地APP,否则进入App Store下载]

<!DOCTYPE html">
<html>
<body>
<body>
    <div>
        <a onClick="javascript:try_to_open_app();" href="mqq:open://">打开QQ
</a>
        <a onClick="javascript:try_to_open_app();" href="myapp://">打开myapp
</a>
    </div>
    <script language="javascript">
        var timeout;
        function open_appstore() {
            window.location='itms-apps://itunes.apple.com/cn/app/qq-2011/
id444934666?mt=8';
        }

    function try_to_open_app() {
        timeout = setTimeout('open_appstore()', 300);
    }
    </script>
</body>
</html>

1.window.location连接的指向为打开应用
2.延时打开App Store下载应用页面

具体来说:
当你打开链接时,Mobile Safari通过window.location指向URL Scheme,直接打开本地应用,否则30ms后打开下载页面。如果应用成功打开,生命周期就是激活状态,那么浏览器的状态是进入后台,页面里的所有操作都被注销了,显然timeout会被clear掉,但如果你没成功打开应用即返回404,那么30ms后页面当然会自动跳转了。

这种方式使用有个缺点:如果应用没有安装的话页面在跳转至App Store的同时会弹出打不开网址的提示。
当然将连接协议改成itms-apps://可以避免。即:
itms-apps://itunes.apple.com/cn/app/qq-2011/id444934666?mt=8

一篇完整的代码,可针对PC 和 Mobile单独做调整:

<!DOCTYPE html">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width,minimum-scale=1.0">
    <title>Mobile Safari 调用本地APP,否则进入App Store下载</title>
    <meta name="keywords" content="Mobile Safari 调用本地APP,否则进入App 
Store下载" />
    <meta name="description" content="Mobile Safari 调用本地APP,否则进入App
 Store下载" />
    <script type="text/javascript">
    /**  
    浏览器版本信息
    * @type {Object} 
    * @return {Boolean}  返回布尔值     
    */
    function browser() {
        var u = navigator.userAgent.toLowerCase();
        var app = navigator.appVersion.toLowerCase();
        return {
            txt: u, // 浏览器版本信息
            version: (u.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || 
[])[1], // 版本号       
            msie: /msie/.test(u) && !/opera/.test(u), // IE内核
            mozilla: /mozilla/.test(u) && !/(compatible|webkit)/
.test(u), // 火狐浏览器
            safari: /safari/.test(u) && !/chrome/.test(u), //是否为safair
            chrome: /chrome/.test(u), //是否为chrome
            opera: /opera/.test(u), //是否为oprea
            presto: u.indexOf('presto/') > -1, //opera内核
            webKit: u.indexOf('applewebkit/') > -1, //苹果、谷歌内核
            gecko: u.indexOf('gecko/') > -1 && u.indexOf('khtml') == -1,
 //火狐内核
            mobile: !!u.match(/applewebkit.*mobile.*/), //是否为移动终端
            ios: !!u.match(/\(i[^;]+;( u;)? cpu.+mac os x/), //ios终端
            android: u.indexOf('android') > -1, //android终端
            iPhone: u.indexOf('iphone') > -1, //是否为iPhone
            iPad: u.indexOf('ipad') > -1, //是否iPad
            webApp: !!u.match(/applewebkit.*mobile.*/) && u.indexOf('s
afari/') == -1 //是否web应该程序,没有头部与底部
        };
    }
    var timeout;
    function open_appstore() {
        var b=browser();
        if(b.ios||b.iPhone||b.iPad){
            window.location="itms-apps://itunes.apple.com/cn/app
/qq-2011/id444934666?mt=8";
        }else if(b.android){
            // 
        }
    } 
    function try_to_open_app() {
        var b=browser();
        if(b.ios||b.iPhone||b.iPad){
            window.location="mqq:open";
        }else if(b.android){
            // 
        }
        timeout = setTimeout('open_appstore()', 30);
    }
    try_to_open_app();
    </script>
</head>
<body>
</body>
</html>

9.用我们的app打开word、pdf之类的文档,即点击word、pdf可以选用我们的app打开

概要点:
1. 注册申明app能够打开某种类型的文档,这样其他app才可能通过DIC(document interaction interface)把文件转给你app来打开

2. 注册就要在plist里声明CFBundleDocumentTypes

<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>文档类型名称
<string>pdf</string>
<key>LSHandlerRank</key> //是拥有此类型文档,还是仅用于打开
<string>Default</string>
</dict>
</array

一般而言一个文档类型和一个文件类型对应,当然也可以是多个文件类型例如。doc和docx是word文档在两个不同版本下的文件后缀。这样你可以把这两个文件类型组合在一个文档类型中

A uniform type identifier (UTI) is a string that identifies a class of entities with a type. UTIs are typically used to identify the format for files or in-memory data types and to identify the hierarchical layout of directories, volumes or packages

这里有个基本的对照表,文件后缀和UTI的串

https://developer.apple.com/library/mac/#documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html

更多的对应可以参考:
Apple's Uniform Type Identifiers Overview

<key>LSItemContentTypes</key>
<array>
<string>com.sunsetlakesoftware.molecules.pdb</string> //app id+.pdb
<string>org.gnu.gnu-zip-archive</string>
</array>

这里我们使用了一个系统定义的。org。gnu。。。。另外一个是程序定义的UTI,程序定义的UTI需要导出,系统其他程序才能知道

3. 需要为自定义的UtI在plist中申明:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.plain-text</string>
            <string>public.text</string>
        </array>
        <key>UTTypeDescription</key>
        <string>Molecules Structure File</string>
        <key>UTTypeIdentifier</key>
        <string>com.sunsetlakesoftware.molecules.pdb</string> // 自定义的type identifier
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key> //关键点
            <string>pdb</string>
            <key>public.mime-type</key>  //关键点
            <string>chemical/x-pdb</string>
        </dict>
    </dict>
</array>

关键是说明 com.sunsetlakesoftware.molecules.pdb UTI 是和.pdb后缀文件关联,且mime类型是 chemical/x-pdb.

这样一来,在邮件程序中,tap且hold等待弹出候选程序列表,可以打开特定的文件。

当附件被打开,你的app就启动了。一般而言,至少要在application:didfinishelaunchingwithoptions中处理文件路径等,看起来就像是文件被copy到你app目录下,然后打开了:

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];

再看另外一个例子,注释在其中

<dict>
<key>CFBundleTypeName</key>
<string>My File Format</string> //任意定义
<key>CFBundleTypeIconFiles</key>  //icon图标资源,当用于显示此类文件的时候<array>
<string>MySmallIcon.png</string>  //resource in bundle
<string>MyLargeIcon.png</string>
</array>
<key>LSItemContentTypes</key>  //使用了UTI格式的,关联到文件格式</pre>
 <array>
<string>com.example.myformat</string>
</array>
<key>LSHandlerRank</key></pre>
<string>Owner</string> //非默认,而是owner
</dict>

也可以通过MIME来指定文件类型CFBundleTypeMIMETypes

更多信息:
https://developer.apple.com/library/ios/#documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-SW1

案例: 在iOS app中导入/导出文档

我们经常会用到的文件操作,又希望本地有文档保存,可以离线操作,其实ibook/iannotation之类多有类似的东西,就是本地library;有时候,还希望可以导出文件去另g外一个地方

新建一个项目view based application:

打开nib文件,增加两控件:

  • WebView

  • Button

    1. 通过拖拽,完成outlet action的声明;
    增加一些message例如opendocument/handledocumentopenUrL

    2.注意到要实现protocol:UIDocumentInteractionControllerDelegate

@interface flyViewController : UIViewController<UIDocumentInteractionControllerDelegate>
{
 
    IBOutlet UIWebView *webview;
 
}
 
-(void)openDocumentIn;
-(void)handleDocumentOpenURL:(NSURL *)url;
-(void)displayAlert:(NSString *) str;
-(void)loadFileFromDocumentsFolder:(NSString *) filename;
-(void)listFilesFromDocumentsFolder;
- (IBAction)btnDisplayFiles:(id)sender;
 
@end
-(void)openDocumentIn {    
    NSString * filePath = 
        [[NSBundle mainBundle] 
        pathForResource:@"Courses for Q2 2011" ofType:@"pdf"];    
    documentController = 
        [UIDocumentInteractionController 
            interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
    documentController.delegate = self;
    [documentController retain];
    documentController.UTI = @"com.adobe.pdf";
    [documentController presentOpenInMenuFromRect:CGRectZero 
                                                   inView:self.view 
                                                 animated:YES];
}
 
-(void)documentInteractionController:(UIDocumentInteractionController *)controller 
         willBeginSendingToApplication:(NSString *)application {
 
}
 
-(void)documentInteractionController:(UIDocumentInteractionController *)controller 
             didEndSendingToApplication:(NSString *)application {
 
}
 
-(void)documentInteractionControllerDidDismissOpenInMenu:
(UIDocumentInteractionController *)controller {
 
}

10. 文档共享

1.通过itunes
Info.plist增加如下声明:

<key>UIFileSharingEnabled</key>
<true/>

当文件拖动到app后,会存储在default document目录下

-(void) displayAlert:(NSString *) str {
    UIAlertView *alert = 
        [[UIAlertView alloc] initWithTitle:@"Alert" 
                                   message:str 
                                  delegate:self
                         cancelButtonTitle:@"OK"
                         otherButtonTitles:nil];
    [alert show];
    [alert release];    
}
 
- (void)handleDocumentOpenURL:(NSURL *)url {
    NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];        
    [webView setUserInteractionEnabled:YES];    
    [webView loadRequest:requestObj];
}
 
-(void)loadFileFromDocumentsFolder:(NSString *) filename {
    //---get the path of the Documents folder---   
    NSArray *paths = NSSearchPathForDirectoriesInDomains(  
        NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0];     
    NSString *filePath = [documentsDirectory 
        stringByAppendingPathComponent:filename];    
    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];        
    [self handleDocumentOpenURL:fileUrl];
}
 
-(void)listFilesFromDocumentsFolder {    
    //---get the path of the Documents folder---    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(     
    NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
 
    NSFileManager *manager = [NSFileManager defaultManager];
    NSArray *fileList =   
        [manager contentsOfDirectoryAtPath:documentsDirectory error:nil];
    NSMutableString *filesStr = 
        [NSMutableString stringWithString:@"Files in Documents folder \n"];
    for (NSString *s in fileList){    
        [filesStr appendFormat:@"%@ \n", s];
    }
    [self displayAlert:filesStr];    
    [self loadFileFromDocumentsFolder:@"0470918020.pdf"];
}
 
- (IBAction) btnDisplayFiles {
    [self listFilesFromDocumentsFolder];    
}

第二中方法就是自己作为一个文档接受方:主要是通过注册,在plist中声明通过CFBundledocumenttypes


image.png

其实当文档触发app起来后,文档会被复制到一个inbox的目录,在documents目录下的一个子目录,可以通过url来看到路径

#import "OfflineReaderAppDelegate.h"
#import "OfflineReaderViewController.h"
 
@implementation OfflineReaderAppDelegate
 
@synthesize window;
@synthesize viewController;
 
-(BOOL)application:(UIApplication *)application 
           openURL:(NSURL *)url 
 sourceApplication:(NSString *)sourceApplication 
        annotation:(id)annotation {    
    if (url != nil && [url isFileURL]) {
        [self.viewController handleDocumentOpenURL:url];
    }    
    return YES;
}
image.png

如果觉得可以就点个👍吧,欢迎粉丝收藏,土豪打赏,您的关注就是我们创作的动力!

读者有什么想看的相关技术篇章,欢迎评论留言!

QQ交流群:908058499

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容