Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Modeler   Code  
»áÔ±   
 
   
 
 
     
   
 ¶©ÔÄ
  ¾èÖú
ÈçºÎʹÓÃKeyChain±£´æºÍ»ñÈ¡UDID
 
×÷Õߣºfocusjava À´Ô´£ºCSDN ·¢²¼ÓÚ£º 2015-05-29
  3932  次浏览      29
 

±¾ÎÄÊÇiOS7ϵÁÐÎÄÕµÚһƪÎÄÕ£¬Ö÷Òª½éÉÜʹÓÃKeyChain±£´æºÍ»ñÈ¡APPÊý¾Ý£¬½â¾öiOS7ÉÏ»ñÈ¡²»±äUDIDµÄÎÊÌâ¡£²¢¸ø³öÒ»¸ö»ñÈ¡UDIDµÄ¹¤¾ßÀ࣬ʹÓ÷½±ã£¬Ö»ÐèÒªÌæ»»Á½¸öµØ·½¼´¿É¡£

Ò»¡¢iOS²»Óð汾»ñÈ¡UDIDµÄ·½·¨±È½Ï

1£©iOS 5.0

iOS 2.0°æ±¾ÒÔºóUIDeviceÌṩһ¸ö»ñÈ¡É豸Ψһ±êʶ·ûµÄ·½·¨uniqueIdentifier£¬Í¨¹ý¸Ã·½·¨ÎÒÃÇ¿ÉÒÔ»ñÈ¡É豸µÄÐòÁкţ¬Õâ¸öÒ²ÊÇĿǰΪֹΨһ¿ÉÒÔÈ·ÈÏΨһµÄ±êʾ·û¡£ºÃ¾°²»³¤£¬ÒòΪ¸ÃΨһ±êʶ·ûÓëÊÖ»úÒ»Ò»¶ÔÓ¦£¬Æ»¹û¾õµÃ¿ÉÄÜ»áй¶Óû§Òþ˽£¬ËùÒÔÔÚ iOS 5.0Ö®ºó¸Ã·½·¨¾Í±»·ÏÆúµôÁË¡£
¡¡¡¡¶øÇÒÆ»¹û×öµÄ¸üºÝ£¬½ñÄê5Ô·ÝÒÔºóÌá½»App StoreµÄ²úÆ·¶¼²»ÔÊÐíÔÙÓÃuniqueIdentifier½Ó¿Ú£¬ÉõÖÁÓÐЩÅóÓÑÒòΪ´úÂëÖÐÓÐUDID»¹±»´ò»ØÀ´£¬¿´À´ÕâÌõ·ÊDZ»·âËÀÁË¡£

2£©iOS 6.0

iOS 6.0ϵͳÐÂÔöÁËÁ½¸öÓÃÓÚÌæ»»uniqueIdentifierµÄ½Ó¿Ú£¬·Ö±ðÊÇ£ºidentifierForVendor£¬advertisingIdentifier¡£

identifierForVendor½Ó¿ÚµÄ¹Ù·½Îĵµ½éÉÜÈçÏÂ:

The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps on the same device that come from different vendors, and for apps on different devices regardless of vendor.

The value of this property may be nil if the app is running in the background, before the user has unlocked the device the first time after the device has been restarted. If the value is nil, wait and get the value again later.

The value in this property remains the same while the app (or another app from the same vendor) is installed on the iOS device. The value changes when the user deletes all of that vendor¡¯s apps from the device and subsequently reinstalls one or more of them. Therefore, if your app stores the value of this property anywhere, you should gracefully handle situations where the identifier changes.

´ó¸ÅÒâ˼¾ÍÊÇ¡°Í¬Ò»¿ª·¢É̵ÄAPPÔÚÖ¸¶¨»úÆ÷É϶¼»á»ñµÃͬһ¸öID¡£µ±ÎÒÃÇɾ³ýÁËijһ¸öÉ豸ÉÏij¸ö¿ª·¢É̵ÄËùÓÐAPPÖ®ºó£¬Ï´λñÈ¡½«»á»ñÈ¡µ½²»Í¬µÄID¡£¡± Ò²¾ÍÊÇ˵ÎÒÃÇͨ¹ý¸Ã½Ó¿Ú²»ÄÜ»ñÈ¡ÓÃÀ´Î¨Ò»±êʶÉ豸µÄID£¬ÎÊÌâ×ÜÊÇÄѲ»µ¹´ÏÃ÷µÄ³ÌÐòÔ±£¬ÓÚÊÇ´ó¼ÒÏëµ½ÁËʹÓÃWiFiµÄmacµØÖ·À´È¡´úÒѾ­·ÏÆúÁ˵ÄuniqueIdentifier·½·¨¡£¾ßÌåµÄ·½·¨ÍíÉÏÓкܶ࣬´ó¼Ò¸ÐÐËȤµÄ¿ÉÒÔ×Ô¼ºÕÒÕÒ£¬Õâ¶ùÌṩһ¸öÍøÖ·: http://stackoverflow.com/questions/677530/how-can-i-programmatically-get-the-mac-address-of-an-iphone

3£©iOS 7.0

iOS 7ÖÐÆ»¹ûÔÙÒ»´ÎÎÞÇéµÄ·âɱmacµØÖ·£¬Ê¹ÓÃ֮ǰµÄ·½·¨»ñÈ¡µ½µÄmacµØÖ·È«²¿¶¼±ä³ÉÁË02:00:00:00:00:00¡£ÓÐÎÊÌâ×ܵĽâ¾ö°¡£¬ÓÚÊÇËÄ´¦²é×ÊÁÏ£¬ÖÕÓÚÓÐÁË˼·ÊÇ·ñ¿ÉÒÔʹÓÃKeyChainÀ´±£´æ»ñÈ¡µ½µÄΨһ±êʾ·ûÄØ£¬ÕâÑùÒÔºó¼´Ê¹APPɾÁËÔÙ×°»ØÀ´£¬Ò²¿ÉÒÔ´ÓKeyChainÖжÁÈ¡»ØÀ´¡£ÓÐÁË·½ÏòÒÔºó¾Í¿ªÊ¼×ö£¬¿´¹ØÓÚKeyChainµÄ¹Ù·½Îĵµ£¬¿´¹Ù·½Ê¹ÓÃKeyChainµÄDemo£¬´ó¸Å»¨ÁËÒ»ÏÂÎçʱ¼ä£¬ÎÊÌâÖÕÓÚ½â¾öÁË¡£

¶þ¡¢KeyChain½éÉÜ

ÎÒÃǸãiOS¿ª·¢£¬Ò»¶¨¶¼ÖªµÀOS XÀïÃæµÄKeyChain(Ô¿³×´®)£¬Í¨³£ÒªÏçÕò¼°µ÷ÊԵϰ£¬¶¼µÃ°²×°Ö¤ÊéÖ®ÀàµÄ£¬ÕâЩ֤Êé¾ÍÊDZ£´æÔÚKeyChainÖУ¬»¹ÓÐÎÒÃÇÆ½Ê±ä¯ÀÀÍøÒ³¼Ç¼µÄÕ˺ÅÃÜÂëÒ²¶¼ÊǼǼÔÚKeyChainÖС£iOSÖеÄKeyChainÏà±ÈOS X±È½Ï¼òµ¥£¬Õû¸öϵͳֻÓÐÒ»¸öKeyChain£¬Ã¿¸ö³ÌÐò¶¼¿ÉÒÔÍùKeyChainÖмǼÊý¾Ý£¬¶øÇÒÖ»ÄܶÁÈ¡µ½×Ô¼º³ÌÐò¼Ç¼ÔÚKeyChainÖеÄÊý¾Ý¡£iOSÖÐSecurity.framework¿ò¼ÜÌṩÁËËĸöÖ÷ÒªµÄ·½·¨À´²Ù×÷KeyChain:

// ²éѯ
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);

// Ìí¼Ó
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result);

// ¸üÐÂKeyChainÖеÄItem
OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);

// ɾ³ýKeyChainÖеÄItem
OSStatus SecItemDelete(CFDictionaryRef query)

ÕâËĸö·½·¨²ÎÊý±È½Ï¸´ÔÓ£¬Ò»µ©´«´í¾Í»áµ¼Ö²Ù×÷KeyChainʧ°Ü£¬Õâ¿é¶ùÎĵµÖнéÉܵıȽÏÏêϸ£¬´ó¼Ò¿ÉÒÔ²é²é¹Ù·½ÎĵµKeychain Services Reference¡£

Ç°ÃæÌáµ½ÁËÿ¸öAPPÖ»ÔÊÐí·ÃÎÊ×Ô¼ºÔÚKeyChainÖмǼµÄÊý¾Ý£¬ÄÇôÊDz»ÊǾÍûÓбðµÄ°ì·¨·ÃÎÊÆäËûAPP´æÔÚKeyChainµÄÊý¾ÝÁË£¿

Æ»¹ûÌṩÁËÒ»¸ö·½·¨ÔÊÐíͬһ¸ö·¢É̵Ķà¸öAPP·ÃÎʸ÷APPÖ®¼äµÄ;¾¶£¬¼´ÔÚµ÷SecItemAddÌí¼ÓÊý¾ÝµÄʱºòÖ¸¶¨AccessGroup£¬¼´·ÃÎÊ×é¡£Ò»¸öAPP¿ÉÒÔÊôÓÚͬÊÂÊôÓÚ¶à¸ö·Ö×飬Ìí¼ÓKeyChainÊý¾Ý·ÃÎÊ×éÐèÒª×öÒ»ÏÂÁ½¼þÊÂÇé:

a¡¢ÔÚAPP targetµÄbulibSettingÀïÃæÉèÖÃCode Signing Entitlements£¬Ö¸Ïò°üº¬AceessGroupµÄ·Ö×éÐÅÏ¢µÄplistÎļþ¡£¸ÃÎļþ±ØÐëºÍ¹¤³ÌÎļþÔÚͬһ¸öĿ¼Ï£¬ÎÒÔÚÌí¼Ó·ÃÎÊ·Ö×éµÄʱºò¾ÍÒòΪplistÎļþλÖÃÎÊÌ⣬²Ù×÷KeyChainʧ°Ü£¬²éÕÒÕâ¸öÎÊÌ⻹»¨Á˺þõÄʱ¼ä¡£

b¡¢ÔÚ¹¤³ÌĿ¼ÏÂн¨Ò»¸öKeychainAccessGroups.plistÎļþ£¬¸ÃÎļþµÄ½á¹¹ÖÐ×î¶¥²ãµÄ½Úµã±ØÐëÊÇÒ»¸öÃûΪ¡°keychain-access-groups¡±µÄArray£¬²¢ÇÒ¸ÃArrayÖÐÿһÏî¶¼ÊÇÒ»¸öÃèÊö·Ö×éµÄNSString¡£¶ÔÓÚStringµÄ¸ñʽҲÓÐÏàÓ¦ÒªÇ󣬸ñʽΪ:"AppIdentifier.com.***"£¬ÆäÖÐAPPIdentifier¾ÍÊÇÄãµÄ¿ª·¢ÕßÕʺŶÔÓ¦µÄID¡£

c¡¢ÔÚ´úÂëÖÐÍùKeyChainÖÐAddÊý¾ÝµÄʱºò£¬ÉèÖÃkSecAttrAccessGroup£¬´úÂëÈçÏÂ:

NSString *accessGroup = [NSString stringWithUTF8String:"APPIdentifier.com.cnblogs.smileEvday"];
    if (accessGroup != nil)
    {
#if TARGET_IPHONE_SIMULATOR
        // Ignore the access group if running on the iPhone simulator.
        //
        // Apps that are built for the simulator aren't signed, so there's no keychain access group
        // for the simulator to check. This means that all apps can see all keychain items when run
        // on the simulator.
        //
        // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
        // simulator will return -25243 (errSecNoAccessForItem).
#else
        [dictForQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
    }

Õâ¶Î´úÂëÊÇ´Ó¹Ù·½µÄDemoÖÐÖ±½Ó¿½±´¹ýÀ´µÄ£¬¸ù¾Ý×¢ÊÍÎÒÃÇ¿ÉÒÔ¿´µ½£¬Ä£ÄâÆ÷ÊDz»Ö§³ÖAccessGroupµÄ£¬ËùÒÔ²ÅÐÐÁËÔ¤±àÒëºêÀ´Ñ¡ÔñÐÔÌí¼Ó¡£

×¢£ºappIdentifer¾ÍÊÇ¿ª·¢ÕßÕʺŵÄÄÇÒ»´®±êʶ£¬ÈçÏÂͼËùʾ£º

´ò¿ªxcodeµÄOrganizer£¬Ñ¡ÔñDeviceÑ¡Ï£¬Á¬½ÓÉ豸¾Í¿ÉÒÔ¿´µ½É豸Éϰ²×°µÄ¿ª·¢ÕßÕ˺ÅÃèÊöÎļþÁÐ±í£¬ÆäÖеÚÎåÁÐ×ʼµÄ10¸ö×Ö·û¼´ÎªApp Identifier£¬Õâ¿é¶ùÇ°ÃæÐ´µÄ²»ÊǺÜÇå³þ£¬ºÃ¶àÅóÓѼÓÎÒqqÎÊÎÒ£¬½ñÌìÌØµØ²¹ÉÏ¡£

Èý¡¢Ê¹ÓÃKeyChain±£´æºÍ»ñÈ¡UDID

˵ÁËÕâô¶àÖÕÓÚ½øÈëÕýÌâÁË£¬ÈçºÎÔÚiOS 7ÉÏÃæ»ñÈ¡µ½²»±äµÄUDID¡£ÎÒÃǽ«µÚ¶þ²¿·ÖËù½²µÄ֪ʶֱ½ÓÓ¦ÓýøÀ´¾Í¿ÉÒÔÁËÇáËÉ´ïµ½ÎÒÃÇÒªµÄЧ¹ûÁË£¬ÏÂÃæÎÒÃÇÏÈ¿´¿´ÍùÈçºÎ½«»ñÈ¡µ½µÄidentifierForVendorÌí¼Óµ½KeyChainÖеĴúÂë¡£

+ (BOOL)settUDIDToKeyChain:(NSString*)udid
{
    NSMutableDictionary *dictForAdd = [[NSMutableDictionary alloc] init];
    
    [dictForAdd setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    [dictForAdd setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier] forKey:kSecAttrDescription];
    
    [dictForAdd setValue:@"UUID" forKey:(id)kSecAttrGeneric];
    
    // Default attributes for keychain item.
    [dictForAdd setObject:@"" forKey:(id)kSecAttrAccount];
    [dictForAdd setObject:@"" forKey:(id)kSecAttrLabel];
    
    // The keychain access group attribute determines if this item can be shared
    // amongst multiple apps whose code signing entitlements contain the same keychain access group.
    NSString *accessGroup = [NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];
    if (accessGroup != nil)
    {
#if TARGET_IPHONE_SIMULATOR
        // Ignore the access group if running on the iPhone simulator.
        //
        // Apps that are built for the simulator aren't signed, so there's no keychain access group
        // for the simulator to check. This means that all apps can see all keychain items when run
        // on the simulator.
        //
        // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
        // simulator will return -25243 (errSecNoAccessForItem).
#else
        [dictForAdd setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
    }

    const char *udidStr = [udid UTF8String];
    NSData *keyChainItemValue = [NSData dataWithBytes:udidStr length:strlen(udidStr)];
    [dictForAdd setValue:keyChainItemValue forKey:(id)kSecValueData];
    
    OSStatus writeErr = noErr;
    if ([SvUDIDTools getUDIDFromKeyChain]) {        // there is item in keychain
        [SvUDIDTools updateUDIDInKeyChain:udid];
        [dictForAdd release];
        return YES;
    }
    else {          // add item to keychain
        writeErr = SecItemAdd((CFDictionaryRef)dictForAdd, NULL);
        if (writeErr != errSecSuccess) {
            NSLog(@"Add KeyChain Item Error!!! Error Code:%ld", writeErr);
            
            [dictForAdd release];
            return NO;
        }
        else {
            NSLog(@"Add KeyChain Item Success!!!");
            [dictForAdd release];
            return YES;
        }
    }
    
    [dictForAdd release];
    return NO;
}

ÉÏÃæ´úÂëÖУ¬Ê×Ïȹ¹½¨Ò»¸öÒªÌí¼Óµ½KeyChainÖÐÊý¾ÝµÄDictionary£¬°üº¬Ò»Ð©»ù±¾µÄKeyChain ItemµÄÊý¾ÝÀàÐÍ£¬ÃèÊö£¬·ÃÎÊ·Ö×éÒÔ¼°×îÖØÒªµÄÊý¾ÝµÈÐÅÏ¢£¬×îºóͨ¹ýµ÷ÓÃSecItemAdd·½·¨½«ÎÒÃÇÐèÒª±£´æµÄUUID±£´æµ½KeyChainÖС£

»ñÈ¡KeyChainÖÐÏàÓ¦Êý¾ÝµÄ´úÂëÈçÏÂ:

+ (NSString*)getUDIDFromKeyChain
{
    NSMutableDictionary *dictForQuery = [[NSMutableDictionary alloc] init];
    [dictForQuery setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    
    // set Attr Description for query
    [dictForQuery setValue:[NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]
                    forKey:kSecAttrDescription];
    
    // set Attr Identity for query
    NSData *keychainItemID = [NSData dataWithBytes:kKeychainUDIDItemIdentifier
                                            length:strlen(kKeychainUDIDItemIdentifier)];
    [dictForQuery setObject:keychainItemID forKey:(id)kSecAttrGeneric];
    
    // The keychain access group attribute determines if this item can be shared
    // amongst multiple apps whose code signing entitlements contain the same keychain access group.
    NSString *accessGroup = [NSString stringWithUTF8String:kKeyChainUDIDAccessGroup];
    if (accessGroup != nil)
    {
#if TARGET_IPHONE_SIMULATOR
        // Ignore the access group if running on the iPhone simulator.
        //
        // Apps that are built for the simulator aren't signed, so there's no keychain access group
        // for the simulator to check. This means that all apps can see all keychain items when run
        // on the simulator.
        //
        // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the
        // simulator will return -25243 (errSecNoAccessForItem).
#else
        [dictForQuery setObject:accessGroup forKey:(id)kSecAttrAccessGroup];
#endif
    }
    
    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecMatchCaseInsensitive];
    [dictForQuery setValue:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    
    OSStatus queryErr   = noErr;
    NSData   *udidValue = nil;
    NSString *udid      = nil;
    queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery, (CFTypeRef*)&udidValue);
    
    NSMutableDictionary *dict = nil;
    [dictForQuery setValue:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
    queryErr = SecItemCopyMatching((CFDictionaryRef)dictForQuery, (CFTypeRef*)&dict);
    
    if (queryErr == errSecItemNotFound) {
        NSLog(@"KeyChain Item: %@ not found!!!", [NSString stringWithUTF8String:kKeychainUDIDItemIdentifier]);
    }
    else if (queryErr != errSecSuccess) {
        NSLog(@"KeyChain Item query Error!!! Error code:%ld", queryErr);
    }
    if (queryErr == errSecSuccess) {
        NSLog(@"KeyChain Item: %@", udidValue);
        
        if (udidValue) {
            udid = [NSString stringWithUTF8String:udidValue.bytes];
        }
    }
    
    [dictForQuery release];
    return udid;
}

ÉÏÃæ´úÂëµÄÁ÷³ÌÒ²²î²»¶àÒ»Ñù£¬Ê×ÏÈ´´½¨Ò»¸öDictionary£¬ÆäÖÐÉèÖÃһϲéÕÒÌõ¼þ£¬È»ºóͨ¹ýSecItemCopyMatching·½·¨»ñÈ¡µ½ÎÒÃÇ֮ǰ±£´æµ½KeyChainÖеÄÊý¾Ý¡£

ËÄ¡¢×ܽá

±¾ÎĽéÉÜÁËʹÓÃKeyChainʵÏÖAPPɾ³ýºóÒÀÈ»¿ÉÒÔ»ñÈ¡µ½ÏàͬµÄUDIDÐÅÏ¢µÄ½â¾ö·½·¨¡£

Äã¿ÉÄÜÓÐÒÉÎÊ£¬Èç¹ûϵͳÉý¼¶ÒÔºó£¬ÊÇ·ñÈÔÈ»¿ÉÒÔ»ñÈ¡µ½Ö®Ç°¼Ç¼µÄUDIDÊý¾Ý£¿

´ð°¸Êǿ϶¨µÄ£¬ÕâÒ»µãÎÒרÃÅ×öÁ˲âÊÔ¡£¾ÍËãÎÒÃdzÌÐòɾ³ýµô£¬ÏµÍ³¾­¹ýÉý¼¶ÒÔºóÔÙ°²×°»ØÀ´£¬ÒÀ¾É¿ÉÒÔ»ñÈ¡µ½Óë֮ǰһÖµÄUDID¡£µ«Êǵ±ÎÒÃǰÑÕû¸öϵͳ»¹Ô­ÒÔºóÊÇ·ñ»¹ÄÜ»ñÈ¡µ½Ö®Ç°¼Ç¼µÄUDID£¬ÕâÒ»µãÎÒ¾õµÃÓ¦¸Ã²»ÐУ¬²»¹ýÊÖ»úÀïÃæÊý¾ÝÌ«¶à£¬Ã»ÓвâÊÔ£¬Èç¹û´ó¼ÒÓÐÐËȤ¿ÉÒÔ²âÊÔһϣ¬ÑéÖ¤Ò»ÏÂÎҵIJÂÏë¡£

   
3932 ´Îä¯ÀÀ       29
 
Ïà¹ØÎÄÕÂ

ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖÓë̽ÌÖ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
 
Ïà¹ØÎĵµ

Android_UI¹Ù·½Éè¼Æ½Ì³Ì
ÊÖ»ú¿ª·¢Æ½Ì¨½éÉÜ
androidÅÄÕÕ¼°ÉÏ´«¹¦ÄÜ
Android½²ÒåÖÇÄÜÊÖ»ú¿ª·¢
Ïà¹Ø¿Î³Ì

Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
Androidϵͳ¿ª·¢
AndroidÓ¦Óÿª·¢
ÊÖ»úÈí¼þ²âÊÔ
×îл¼Æ»®
DeepSeekÔÚÈí¼þ²âÊÔÓ¦ÓÃʵ¼ù 4-12[ÔÚÏß]
DeepSeek´óÄ£ÐÍÓ¦Óÿª·¢Êµ¼ù 4-19[ÔÚÏß]
UAF¼Ü¹¹ÌåϵÓëʵ¼ù 4-11[±±¾©]
AIÖÇÄÜ»¯Èí¼þ²âÊÔ·½·¨Óëʵ¼ù 5-23[ÉϺ£]
»ùÓÚ UML ºÍEA½øÐзÖÎöÉè¼Æ 4-26[±±¾©]
ÒµÎñ¼Ü¹¹Éè¼ÆÓ뽨ģ 4-18[±±¾©]

androidÈË»ú½çÃæÖ¸ÄÏ
AndroidÊÖ»ú¿ª·¢£¨Ò»£©
AndroidÊÖ»ú¿ª·¢£¨¶þ£©
AndroidÊÖ»ú¿ª·¢£¨Èý£©
AndroidÊÖ»ú¿ª·¢£¨ËÄ£©
iPhoneÏûÏ¢ÍÆËÍ»úÖÆÊµÏÖ̽ÌÖ
ÊÖ»úÈí¼þ²âÊÔÓÃÀýÉè¼ÆÊµ¼ù
ÊÖ»ú¿Í»§¶ËUI²âÊÔ·ÖÎö
ÊÖ»úÈí¼þ×Ô¶¯»¯²âÊÔÑо¿±¨¸æ

Android¸ß¼¶Òƶ¯Ó¦ÓóÌÐò
AndroidÓ¦Óÿª·¢
Androidϵͳ¿ª·¢
ÊÖ»úÈí¼þ²âÊÔ
ǶÈëʽÈí¼þ²âÊÔ
AndroidÈí¡¢Ó²¡¢ÔÆÕûºÏ

ÁìÏÈIT¹«Ë¾ android¿ª·¢Æ½Ì¨×î¼Ñʵ¼ù
±±¾© Android¿ª·¢¼¼Êõ½ø½×
ijÐÂÄÜÔ´ÁìÓòÆóÒµ Android¿ª·¢¼¼Êõ
ijº½Ì칫˾ Android¡¢IOSÓ¦ÓÃÈí¼þ¿ª·¢
°¢¶û¿¨ÌØ LinuxÄÚºËÇý¶¯
°¬Ä¬Éú ǶÈëʽÈí¼þ¼Ü¹¹Éè¼Æ
Î÷ÃÅ×Ó Ç¶Èëʽ¼Ü¹¹Éè¼Æ