设备app共享和通讯

APP间通讯。


介绍一下,同一个设备上,app之间实现数据共享和通讯的技术方法。


一、app之间的数据共享策略(Sharing File Data Between Applications in Swift/iOS )

先介绍三个东西:

App Extensions (app 扩展)

Shared Keychain Access(共享钥匙链接口)

Custom Pasteboards(用户粘贴板)



1. app Extensions(Widget /Today Extension 都是app拓展的类型)是个iOS8之后出现的功能。

(1)它其实是一个附属进程,显示在通知中心视图中,可以为用户快速执行一些比较简单独立的任务。但是说到共享数据,因为app进程之间默认的安全域(security domains)是不一样的,默认情况下一个app和它的扩展是不能共享相同数据的。为了解决app和其拓展之间的数据共享问题,就需要使用到 App Group。可以理解为一个App Group提供了共享句柄和共享容器,app和它的扩展可以共同使用这个句柄来存储数据。

(2)具体使用大概有这么几个步骤 :

a. 为一个APP和它的扩展创建App Group :group.com.yourdomain.YourAwesomeGroup

b. 将需要共享的数据库放置在共享容器中,一般使用CoreData,

c. 在 App 扩展中使用 Core Data。创建App 扩展的时候Xcode并没有提供CoreData选项框,所以需要手动添加。

d. 共享其他的数据。 在共享容器中使用Core Data的好处是能搞保证数据的同步,避免数据崩溃。


以使用CoreData为例,下面分别是惯常用法和使用App Group情况下的数据路径获取方法:

// 惯常,方法会返会一个文件路径url,权限是 App bundle可持有

- (NSURL *)applicationDocumentsDirectory {

    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

}

// 要共享,使用App Group,则需要一个共享句柄(Share Bundle),方法如下:

- (NSURL *)applicationDocumentsDirectory {

    return [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.com.yourdomain.YourAwesomeGroup"];

}

(3)注意:如果是大量数据的,使用CoreData无疑是很好的,当时如果你只是想要存储共享很少的数据,比如一些偏好设置,则可以考虑使用NSUserDefaults。自然与惯常的实例化方法是有区别的,下面是演示代码:

// 实例化NSUserdefaults 对象,得到共享接口

NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.yourdomain.YourAwesomeGroup"];


// 使用共享的NSUserdefaults对象,更新参数。

[sharedDefaults setObject:anObject forKey:@"anObjectKey"];

let sharedDefaults = NSUserDefaults(suiteName: "group.com.yourdomain.YourAwesomeGroup")

sharedDefaults?.setObject(anObject, forKey: "anObjectKey")


(4)因为数据共享,安全该如何保证呢? 其实不用担心,App Group策略和揭晓来介绍的钥匙链共享接口的安全原理是一样的,他们都是需要实现了与开发者账号的唯一绑定的(每一个工程的target 中有一个plist配置文件<Enabling App Sandbox>,其中的开关设置都需要开发者账号权限),App Group 号或者 ID号 都是唯一的,就像你的开发者账号一样安全,只有持有者可以得到对应的修改权限。


 2. Shared Keychain Access

(1)钥匙链存储策略适合一些简短重要的讯息数据,比如站好密码,信用卡号等,当然惯常这些数据只存在一个app中。如果需要将之在一个设备中共享,是不同app可以使用(比如多个应用使用同一个账号登录),那么就可以使用钥匙链组(Keychain Groups)来实现。

(2)具体步骤大致如下:

a. Xcode中打开应用Target下的钥匙链开关(target >> Capabilities >> 打开Keychain Sharing)

b. Xocde出现开发者登录弹框,选择开发者

c. 指定钥匙链组的名字,如(myKeychainGroup1)

d. 组合 App ID前缀+要是组名($(AppIdentifierPrefix)myKeychainGroup1 格式:AB123CDE45.myKeychainGroup1

e. 可以进行使用了,(主要是共享钥匙链选项成员(shared Keychain item)的Add、Delete和Find操作)

3. Custom Pasteboards(纸板控件UIPasteboard)

(1)剪切板并不只能存放字符串数据,其还可以进行图片数据与网址URL数据的存放。这个剪切板就是UIPasteboard类,开发者也可以直接通过它来操作数据进行应用内或应用间传值

(2)UIPastebord类有三个初始化方法

a. + (UIPasteboard *)generalPasteboard;

b. + (UIPasteboard *)pasteboardWithName:(NSString *)pasteboardName create:(BOOL)create;

c. + (UIPasteboard *)pasteboardWithUniqueName;

(3)如果用于应用之间的传值,建议使用第二个实例的纸板,不过他们也是存在局限的,对已名字或标记同一的纸板,如果进行了第二次使用,可能就会覆盖上一次的值,这个需要应用中做注意,第三个方法的在其对应的程序退出之后纸板上的内容会被抹掉,也需注意。一般手法可能是UIPasteboard + URL Scheme 通过URL scheme传递UIPasteboard的名称,然后通过UIPasteboard共享数据。



4. app之间数据共享方法不只是以上三种,

· UIDocumentInteractionController

· UIActivityViewController

·Web Service 通过dropbox或者其他第三方的服务来共享数据。

·……



二、app如何知道存在数据共享数据

先介绍点东西,上文有提到

iOS 中的 URL Scheme

通知  Notification


1.  上文中描述数据共享的方法解决的主要问题是找到一个共享容器,然而当共享之后我们需要通知另外一个app让它知晓,这个时候就需要用到 URL Scheme 或者 Notification。

2. 在iOS的SDK中提供了一个非常有意思的功能,它能将iOS的Application同自定义的URL Schema绑定,同时可以通过URL Scheme在浏览器或者是其他应用中启动这个Application。本文主要介绍如何通过URL Scheme的方式启动应用和参数的传递。

3. 通知,使用苹果提供通知技术,告知一个指定的app,并可以传送少许讯息( < 256 byte).



参考文档:

https://www.invasivecode.com/weblog/sharing-data-between-apps-and-their-extenstions/

http://stackoverflow.com/questions/35299044/sharing-file-data-between-applications-in-swift-ios

http://wufawei.com/2013/06/iOS-inter-app-communication/

http://code.tutsplus.com/tutorials/previewing-and-opening-documents-with-uidocumentinteractioncontroller--mobile-15130

http://sspai.com/31500

———————

See the section "Sharing Data with Your Containing App"

Also see "Adding an App to an App Group":

https://github.com/mutualmobile/MMWormhole



Keep coding and making awesome apps.

Vicente



钥匙链内建有一些API,主要使用规则是,通过组名,配合队列(kSecAttrAccessGroup)键值函数(SecItemAdd,SecItemDeleteSecItemCopyMatching)来实现。使用代码展示如下:

Delete a shared Keychain item

let itemKey = "My key"

let itemValue = "My secretive bee "

let keychainAccessGroupName = "AB123CDE45.myKeychainGroup1"


let queryDelete: [String: AnyObject] = [

  kSecClass as String: kSecClassGenericPassword,

  kSecAttrAccount as String: itemKey,

  kSecAttrAccessGroup as String: keychainAccessGroupName

]


let resultCodeDelete = SecItemDelete(queryDelete as CFDictionaryRef)


if resultCodeDelete != noErr {

  print("Error deleting from Keychain: \(resultCodeDelete)")

}

Add a shared Keychain item

guard let valueData = itemValue.dataUsingEncoding(NSUTF8StringEncoding)else {

  print("Error saving text to Keychain")

  return

}


let queryAdd: [String: AnyObject] = [

  kSecClass as String: kSecClassGenericPassword,

  kSecAttrAccount as String: itemKey,

  kSecValueData as String: valueData,

  kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked,

  kSecAttrAccessGroup as String: keychainAccessGroupName

]


let resultCode = SecItemAdd(queryAdd as CFDictionaryRef, nil)


if resultCode != noErr {

  print("Error saving to Keychain: \(resultCode)")

}

Find a shared Keychain item 

let queryLoad: [String: AnyObject] = [

  kSecClass as String: kSecClassGenericPassword,

  kSecAttrAccount as String: itemKey,

  kSecReturnData as String: kCFBooleanTrue,

  kSecMatchLimit as String: kSecMatchLimitOne,

  kSecAttrAccessGroup as String: keychainAccessGroupName

]


var result: AnyObject?


let resultCodeLoad = withUnsafeMutablePointer(&result) {

  SecItemCopyMatching(queryLoad, UnsafeMutablePointer($0))

}


if resultCodeLoad == noErr {

  if let result = result as? NSData,

    keyValue = NSString(data: result,

      encoding: NSUTF8StringEncoding) as? String {


    // Found successfully

    print(keyValue)

  }

} else {

  print("Error loading from Keychain: \(resultCodeLoad)")

}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值