我们能够检测到哪个iOS应用程序正在使用我的自定义键盘吗?

11
我希望在我的自定义键盘扩展应用中检测使用我的扩展的应用程序。我们能否在键盘扩展中检测有关使用我的扩展的应用程序的任何信息?我认为这是不可能的。如果有人对此有了解,请分享一下。
谢谢。

据我所知是不可能的,在扩展中你无法检测类型或其他任何东西,但你的问题很好。 - Anbu.Karthik
我还没有尝试在扩展中是否有效,但请查看此链接:https://dev59.com/D2sy5IYBdhLWcg3w2Bo6 - NeonBerry
4个回答

15

您可以在您的UIInputViewController中尝试此代码

override public func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    if let parentViewController = self.parentViewController {
        var hostBundleID = parentViewController.valueForKey("_hostBundleID")
        println(hostBundleID)
    }
}

但我不确定当你发布到App Store时,苹果是否会批准。


1
_hostBundleID 的官方文档在哪里? - Pang
在iOS 16中,valueForKey("_hostBundleID")返回nil - Daniel Saidi

1

Swift 5 版本

适用于 iOS 16 及更早版本

import Foundation
import UIKit

extension UIInputViewController {
    
    func hostBundleId() -> String? {
        if let parentViewController = parent {
            if let hostBundleId = parentViewController.value(forKey: "_hostBundleID") as? String,
               hostBundleId != "<null>" {
                return hostBundleId
            } else if let hostPID = parentViewController.value(forKey: "_hostPID") {
                let selector = NSSelectorFromString("defaultService")
                if let anyClass: AnyObject = NSClassFromString("PKService"),
                   let pkService = anyClass as? NSObjectProtocol,
                   pkService.responds(to: selector),
                   let serverInis = pkService.perform(selector).takeUnretainedValue() as? NSObjectProtocol {
                    let lities = serverInis.perform(NSSelectorFromString("personalities")).takeUnretainedValue()
                    let bundleId = Bundle.main.bundleIdentifier ?? ""
                    if let infos = lities.object(forKey: bundleId) as? AnyObject,
                       let info = infos.object(forKey: hostPID) as? AnyObject,
                       let con = info.perform(NSSelectorFromString("connection")).takeUnretainedValue() as? NSObjectProtocol {
                        let xpcCon = con.perform(NSSelectorFromString("_xpcConnection")).takeUnretainedValue()
                        let handle = dlopen("/usr/lib/libc.dylib", RTLD_NOW)
                        let sym = dlsym(handle, "xpc_connection_copy_bundle_id")
                        typealias xpcFunc = @convention(c) (AnyObject) -> UnsafePointer<CChar>
                        let cFunc = unsafeBitCast(sym, to: xpcFunc.self)
                        let response = cFunc(xpcCon)
                        let hostBundleId = NSString(utf8String: response)
                        return hostBundleId as String?
                    }
                }
            }
        }
        return nil
    }
    
}

很不幸的是,在iOS 17中似乎停止工作了。 - Daniel Saidi
谢谢兄弟..在iOS 17上工作,太棒了! - undefined

1

适用于iOS 16+

#import <dlfcn.h>

+ (nullable NSString *)hostBundleIDWithInputVC:(UIInputViewController *)vc {
    
    NSString *bundleID = nil;
    
    @try {
        bundleID = [vc.parentViewController valueForKey:@"_hostBundleID"];
    } @catch (NSException *exception) {
        NSLog(@"hostBundleID Get Failure 1 %@", exception);
    } @finally {
        
    }
    
    if(XMUtils.validString(bundleID) && ![bundleID isEqual:@"<null>"]) {
        return bundleID;
    }
    
    // 云控禁止xpc取法

    // xpc取法 逆向自xx输入法 主要解决iOS16上获取不到的问题
    @try {
        id hostPid = [vc.parentViewController valueForKey:@"_hostPID"];
        
        if (hostPid) {
            
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            
            id serverIns = [NSClassFromString(@"PKService") performSelector:NSSelectorFromString(@"defaultService")];
            id lities = [serverIns performSelector:NSSelectorFromString(@"personalities")];

            id infos = [lities objectForKey:[NSBundle mainBundle].bundleIdentifier];
            
            id info = [infos objectForKey:hostPid];
            id con = [info performSelector:NSSelectorFromString(@"connection")];
            id xpcCon = [con performSelector:NSSelectorFromString(@"_xpcConnection")];
            
    #pragma clang diagnostic pop
            
            const char * (* cfunc)(id) = dlsym(RTLD_DEFAULT, "xpc_connection_copy_bundle_id");
            
            if (cfunc != nil && xpcCon != nil) {
                const char *res = cfunc(xpcCon);
                bundleID = [NSString stringWithUTF8String:res];
                return  bundleID;
            }
        }
    } @catch (NSException *exception) {
        NSLog(@"hostBundleID Get Failure 2 %@", exception);
    } @finally {
        
    }
   
    return nil;
}

{{链接1:来自博客}}


目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0

要求iOS系统版本为16或以上,"_hostBundleID"的值为nil。


目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接