iOS 12は、アプリケーションがインストールされているか否かを判断する

2950 ワード

一般に,アプリケーションがインストールされているか否かを判断するのはURL schemesによる判断であるが,この方式には2つの明らかな問題がある.
  • iOS 9以上は、infoでホワイトリストの設定が必要である.plistに
  • を追加
  • も重要な点であり、別のappに同じURL schemesを構成する方法で詐欺を行うことができます.例えば、別のappに微信のURL schemes weixin://を付けると、微信appがインストールされていない場合でも、システムに微信がインストールされていると判断します.

  • 一般的にURL schemesでは大きな問題はないと判断されますが、セキュリティレベルが高い場合、正確な判定のためにプライベートAPIの方法が必要になります.
    ネット上では、プライベートAPIでインストールするかどうかを判断する方法が多く紹介されています.iOS 10より前にLSApplicationWorkspacにてインストールアプリケーションリストを取得することにより全てのアプリケーションのbundleIDを取得する
    Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
    
    NSObject* workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
    NSArray *allApplications = [workspace performSelector:@selector(allApplications)];
    for (NSString *appStr in allApplications) {
          NSString *app = [NSString stringWithFormat:@"%@",appStr];
            NSRange range = [app rangeOfString:@"    App bundle ID"];
             if (range.length > 1) {
                NSLog(@"   ");
            }
    }
    

    iOS 11では、この方式は失効しており、プライベートクラスMCMAPpContainerでbundIDがインストールされているかどうかを判断する
    NSBundle *container = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"]; 
    if ([container load]) 
    { 
      Class appContainer = NSClassFromString(@"MCMAppContainer"); 
      id test = [appContainer performSelector:@selector(containerWithIdentifier:error:) withObject:bundleId withObject:nil]; 
      if (test) { 
        return YES; 
      }else{ 
        return NO; 
      } 
    } 
    return NO;
    

    残念ながらiOS 12では、この方式は権限の問題で禁止されています.他に判断できる方法はありますか?
    研究の結果、LSApplicationWorkspaceクラスのallApplicationsメソッドはiOS 10以降では使用できません.しかし、もう一つの方法はinstalledPluginsで使用できます.この方法は、現在のシステムにインストールされているすべてのextensionプラグインを返すために使用されます.具体的なコードは次のとおりです.
    Class lsawsc = objc_getClass("LSApplicationWorkspace");   
    NSObject* workspace = [lsawsc performSelector:NSSelectorFromString(@"defaultWorkspace")];
    NSArray *plugins = [workspace performSelector:NSSelectorFromString(@"installedPlugins")]; //    plugins
    [plugins enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSString *pluginID = [obj performSelector:(@selector(pluginIdentifier))];
        NSLog(@"%@",pluginID);
    }];
    

    例えば、微信:iOS 12の場合、3つのプラグインcomを返すことができる.tencent.xin.siriext com.tencent.xin.siriextensionui com.tencent.xin.sharetimeline名前から見ると、1つの共有プラグインと2つのsiriプラグインがあります.
    これでアプリケーションがインストールされているかどうかを判断できますが、まだ2つの小さな問題があります.
  • いくつかの古いバージョンのアプリケーションにプラグインがあるかどうか、例えばシステムにインストールされている微信バージョンが古いかどうか、この3つのプラグインがあるかどうか.実はこの問題はまあまあですが、iOS 12のシステムでしか判断されていませんが、元のシステムバージョンは以前の方法で判断されています.システムバージョンが更新されてアプリが更新されていない人はいないでしょう.
  • のもっと主要な問題はやはり私有APIの問題で、もちろん元のバージョンの判断方法も私有APIで、依然として方法名の混同などの方式で処理します.

  • iOS 12の新しいバージョンでは、アプリケーションのインストールでこのようなサイドクリックの方法しか見つからないと判断しています.何かもっと良い方法があれば教えてください.