Can we detect which ios application is using my Custom keyboard
Asked Answered
B

4

11

I want to detect in my custom keyboard extension app which application is using my extension. Can we detect any information in keyboard extension about application which is using my extension.I dont think it is possible .if any body have have knowledge about this kindly share it.

Thanks

Builder answered 15/4, 2015 at 6:6 Comment(2)
in my knowledge is not possible, in extension you can't detect the type or anything, but your question is fine,Bowles
I have not tried if it works in an extension, but check this: stackoverflow.com/questions/8275578Jesse
D
15

You can try this code in your UIInputViewController

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

But I'm not sure that Apple will approved when you release to App Store

Dysentery answered 28/5, 2015 at 10:7 Comment(2)
Where's _hostBundleID officially documented?Harber
valueForKey("_hostBundleID") returns nil in iOS 16.Antecedent
E
1

for 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;
}

from blog

Esker answered 3/3, 2023 at 12:44 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Giovanna
S
1

Swift 5 Version

This works for iOS 16 and older

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
    }
    
}
Stinker answered 20/3, 2023 at 14:6 Comment(2)
This unfortunately seems to have stopped working in iOS 17.Antecedent
thanks broo.. work in ios 17 guys wohhooooAzelea
G
0

ios 16+, "_hostBundleID" the value is nil

Goulette answered 5/9, 2022 at 6:58 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Giovanna

© 2022 - 2024 — McMap. All rights reserved.