Password AutoFill APP Extensions 密碼自動(dòng)填充 iOS12

????? 剛開始接到這個(gè)需求的時(shí)候第一感覺就是做不到,怎么可能把自己APP內(nèi)的賬號(hào)密碼填充到其他APP登錄的輸入框內(nèi),但是客戶找出了類似的APP說是別人的APP是可以的,相信你也可以。這時(shí)我就有些沒有頭緒了,我在網(wǎng)上找資料,可是無果。最后拿出我的神器,用谷歌搜,剛開始搜的也是一些沒有用的。但是隨后還是找到了一些資料。都是一些零零散散的。而且都是一些英文的文檔,我一邊翻譯一邊看,還是沒有頭緒。我想著這是在APP以外用到的,不會(huì)啟動(dòng)APP,所以我就想到了用APP拓展。我就按照APP拓展的方式去打開果然真的有賬號(hào)密碼填充。

點(diǎn)擊加號(hào)就會(huì)出現(xiàn)應(yīng)用拓展的選項(xiàng),直接選擇密碼填充
接下來就是跟正常的APP拓展是一樣的,需要配置一下配置文件

這里就不多說了,新建完之后有一個(gè)文件夾,里面有一個(gè)CredentialProviderViewController控制器和一個(gè)MainInterface.storyboard,這兩個(gè)類就是應(yīng)用拓展的入口,入口也是可以改變的需要在info.plist里面

NSExtensionPrincipalClass 添加這個(gè)鍵對(duì)應(yīng)的就是APP拓展的入口,NSExtensionAttributes下面的ASCredentialProviderExtensionShowsConfigurationUI的屬性對(duì)應(yīng)的就是在設(shè)置的時(shí)候是否彈出APP拓展的入口,

一般來說在設(shè)置點(diǎn)擊的時(shí)候是需要驗(yàn)證一下,此應(yīng)用的密碼,或者是指紋之類的。但是如果點(diǎn)擊了設(shè)置里面的選項(xiàng),彈出APP拓展的驗(yàn)證,這時(shí)取消驗(yàn)證,設(shè)置里面的選項(xiàng)還是被勾選的,不能被取消。如果讀者有更好的方法,可以在下面留言,可以相互學(xué)習(xí)一下。

接下來先簡(jiǎn)單的介紹一下CredentialProviderViewController.m里的

- (void)prepareCredentialListForServiceIdentifiers:(NSArray<ASCredentialServiceIdentifier *> *)serviceIdentifiers

這個(gè)是如果輸入框設(shè)置為蘋果的賬號(hào)類型就會(huì)有返回,這個(gè)方法進(jìn)入之后就會(huì)走這個(gè)方法。展示Credentials List讓用戶選擇,系統(tǒng)會(huì)觸發(fā)該方法,并傳入serviceIdentifiers數(shù)組,以便用戶過濾或者對(duì)數(shù)據(jù)排序。如果serviceIdentifiers數(shù)組存在多個(gè),那么越靠前的數(shù)據(jù)價(jià)值越大。當(dāng)然數(shù)組也可能是空的。

- (void)provideCredentialWithoutUserInteractionForIdentity:(ASPasswordCredentialIdentity *)credentialIdentity;

這個(gè)方法會(huì)被觸發(fā)是點(diǎn)擊鍵盤上面的賬號(hào)密碼,這個(gè)賬號(hào)密碼如何顯示到鍵盤上,需要存儲(chǔ)到ASCredentialIdentityStore里面,我是在點(diǎn)擊具體的密碼返回到上一界面的時(shí)候

ASPasswordCredentialIdentity * credent = [[ASPasswordCredentialIdentity alloc] initWithServiceIdentifier:self.service

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? user:accout

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? recordIdentifier:nil];


? ? [[ASCredentialIdentityStore sharedStore] saveCredentialIdentities:@[credent]

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? completion:^(BOOL success, NSError * _Nullable error) {

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"%@", error);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }];

self.service是prepareCredentialListForServiceIdentifiers:方法返回的,這里會(huì)有問題,可以自己創(chuàng)建一個(gè)ASCredentialServiceIdentifier類型的對(duì)象進(jìn)行存儲(chǔ)。如果用戶可信則直接返回?cái)?shù)據(jù),否則可以觸發(fā)ASExtensionErrorCodeUserInteractionRequest讓用戶進(jìn)行身份驗(yàn)證。該方法觸發(fā)時(shí)ViewController并沒有展示,所以不要做任何的UI操作。

- (void)prepareInterfaceToProvideCredentialForIdentity:(ASPasswordCredentialIdentity *)credentialIdentity;

該方法是驗(yàn)證,比如提供一個(gè)解鎖頁面,當(dāng)用戶輸入密碼正確則調(diào)用[ASCredentialProviderExtensionContext completeRequestWithSelectedCredential:completionHandler:]對(duì)外提供數(shù)據(jù);如果輸入錯(cuò)誤,則調(diào)用[ASCredentialProviderExtensionContext cancelRequestWithError:]錯(cuò)誤類型選用ASExtensionErroCode中的ASExtensionErroDomain,如果Extension無法為外部提供數(shù)據(jù)則選用ASExtensionErrorCodeCredentialIdentityNotFound。

- (void)prepareInterfaceForExtensionConfiguration;

系統(tǒng)Setting打開Extension時(shí)觸發(fā)。這時(shí)會(huì)展示ViewController。該方法觸發(fā)需要配置。


走到這里基本上完成了百分之50。有一個(gè)最重要的還沒有解決,就是要讀取主APP的數(shù)據(jù),APP拓展的數(shù)據(jù)跟主APP的數(shù)據(jù)是獨(dú)立的。所以這里就需要的用到APP GROUP https://blog.csdn.net/allangold/article/details/54890555這里介紹的很全面,我這里就不細(xì)說了。

我在這里遇到了一個(gè)問題,就是主APP中的數(shù)據(jù)是存儲(chǔ)在數(shù)據(jù)庫里面。需要把這些數(shù)據(jù)存儲(chǔ)到共享的空間當(dāng)中。我的數(shù)據(jù)庫文件是個(gè).db文件。所以我在初始化數(shù)據(jù)庫的時(shí)候直接把數(shù)據(jù)庫copy到共享空間,其他的在那個(gè)博客里面也寫到,這里就不多做解釋

- (BOOL)saveDataFromPath:(NSString *)originPath toFile:(NSString *)filename

{

? ? NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"這里是共享空間的ID"];

? ? NSURL *fileURL = [url URLByAppendingPathComponent:filename];


? ? NSFileManager *fileManager =[NSFileManager defaultManager];

? ? return [[NSFileManager defaultManager] copyItemAtPath:originPath toPath:[fileURL path] error:nil];

}

用這個(gè)方法

NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"這里是共享空間的ID"];? ? ??

NSURL *fileURL = [url URLByAppendingPathComponent:@"mypass.db"];

? _queue = [FMDatabaseQueue databaseQueueWithPath:fileURL.path];

到這里大部分的工作做得差不多了。第一次寫寫文章,有些地方寫的不是很全面。也有些落下的可以多多指正。邏輯可能有些亂,不動(dòng)的可以留言,或者加我wx: jiangdong00000000,大家共同學(xué)習(xí),一起進(jìn)步,謝謝

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容