Use GraceNote SDK in iOS(一)通过序列化GDO查询专辑封面
于Use MusicBrainz in iOS之后,因为MusicBrainz找出专辑封面,它只能转移到其他网站提供的音乐信息搜索服务,领导给出GraceNote。(有压力。。
。)
需求类似:通过一个音频文件的歌曲名,专辑名等信息查询到该文件专辑的封面。
本文介绍下怎样在iOS中使用GraceNote给出的GNSDK(一个用C写的SDK)。并通过序列化的GDO查询专辑封面。实际上,就是我对GNSDK文件里给出的samples的一些修正和调用而已。
首先前往GraceNote站点注冊一个帐号。然后创建一个app(看得懂英语的都知道怎么做吧,我就略过了),完毕后例如以下所看到的:
新建一个Demoproject。名字和上面的app名一致(不一致是否可行,我还没试过)。
下载GNSDK:点击打开链接
本文基于3.0.6版本号。
下载完毕后解压。前往lib_static/ios_armv7s-32。因为我的机子指令集是armv7s。所以使用该目录中的静态库文件。将全部.a文件拷贝到Demoproject中。
再将include文件夹下的全部.h文件和ios_armv7s_32文件夹拷贝到Demoproject中。
完毕后project文件夹例如以下:
打开Build Settings选项。设置Header Search Paths和Library Search Paths:
确保Build Phases所有静态库链接成功:
在project中新建一个文本文件,比如my_licence.txt,内容为你所创建的App Details中的License String中的内容(注意不要有不论什么修改,空缺的信息无需补上),示比例如以下:
-- BEGIN LICENSE v1.0 1CBA6766 --
licensee: Gracenote, Inc.
name:
notes: Lic Gen 2.1
start_date: 0000-00-00
client_id: 4541440
musicid_file: enabled
musicid_search: enabled
musicid_stream: enabled
musicid: enabled
playlist: enabled
-- SIGNATURE 1CBA6766 --
lAADAgAe5/qrtIoNKp6SWqcqU+a+R6l/SaJ3aW5YQ+93T7nPAB8Bm9BtwE5OsPgoKjHK14foIdX5dPugbz1mJnkfT6Kt
-- END LICENSE 1CBA6766 --
新建一个Test.C,代码例如以下:
#define USE_LOCAL 0 #define GNSDK_LINK 1
#define GNSDK_STORAGE_SQLITE 1
#include "gnsdk.h" gnsdk_byte_t* response_data;
gnsdk_size_t response_data_length; #include <stdio.h>
#include <string.h>
#include <stdlib.h> /**********************************************
* Local Function Declarations
**********************************************/ static int
_init_gnsdk(
const char* client_id,
const char* client_id_tag,
const char* client_app_version,
const char* license_path,
gnsdk_user_handle_t* p_user_handle
); static void
_shutdown_gnsdk (gnsdk_user_handle_t user_handle); static void
_query_for_album_images (gnsdk_user_handle_t user_handle); /******************************************************************
*
* MAIN
*
******************************************************************/
int
coverart_main(int argc, const char* argv[])
{
gnsdk_user_handle_t user_handle = GNSDK_NULL;
const char* client_id = NULL;
const char* client_id_tag = NULL;
const char* client_app_version = "1"; /* increment with each version of your app */
const char* license_path = NULL;
int rc = 0; /* Client ID, Client ID Tag and License file must be passed in */ if (argc == 4)
{
client_id = argv[1];
client_id_tag = argv[2];
license_path = argv[3]; /* Initialize GNSDK */
rc = _init_gnsdk(
client_id,
client_id_tag,
client_app_version,
license_path,
&user_handle
);
if (0 == rc)
{
/* Perform a sample cover art query */
_query_for_album_images(user_handle); /* Clean up and shutdown */
_shutdown_gnsdk(user_handle);
}
}
else
{
printf("\nUsage:\n%s clientid clientidtag license\n", argv[0]);
rc = -1;
} return rc; } /* main() */ /******************************************************************
*
* _DISPLAY_LAST_ERROR
*
* Echo the error and information.
*
*****************************************************************/
static void
_display_last_error(
int line_num
)
{
/* Get the last error information from the SDK */
const gnsdk_error_info_t* error_info = gnsdk_manager_error_info(); /* Error_info will never be GNSDK_NULL.
* The SDK will always return a pointer to a populated error info structure.
*/
printf(
"\nerror from: %s() [on line %d]\n\t0x%08x %s",
error_info->error_api,
line_num,
error_info->error_code,
error_info->error_description
); } /* display_last_error() */ /******************************************************************
*
* _GET_USER_HANDLE
*
* Load existing user handle, or register new one.
*
* GNSDK requires a user handle instance to perform queries.
* User handles encapsulate your Gracenote provided Client ID which is unique for your
* application. User handles are registered once with Gracenote then must be saved by
* your application and reused on future invocations.
*
*****************************************************************/
static int
_get_user_handle(
const char* client_id,
const char* client_id_tag,
const char* client_app_version,
gnsdk_user_handle_t* p_user_handle
)
{
gnsdk_user_handle_t user_handle = GNSDK_NULL;
gnsdk_str_t serialized_user = GNSDK_NULL;
gnsdk_error_t error = GNSDK_SUCCESS;
char* user_filename = NULL;
size_t user_filename_len = 0;
int rc = 0;
FILE* file = NULL; // user_filename_len = strlen(client_id)+strlen("_user.txt")+1;
// user_filename = malloc(user_filename_len); user_filename_len = strlen("/var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/tmp/4541440_user.txt") + 1;
user_filename = malloc(user_filename_len); if (NULL != user_filename)
{
// strcpy(user_filename, client_id);
// strcat(user_filename, "_user.txt"); strcpy(user_filename, "/var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/tmp/4541440_user.txt"); // /* Do we have a user saved locally? */
// file = fopen(user_filename, "r");
// if (NULL != file)
// {
// gnsdk_char_t serialized_user_string[1024] = {0};
//
// if (NULL != (fgets(serialized_user_string, 1024, file)))
// {
// /* Create the user handle from the saved user */
// error = gnsdk_manager_user_create(serialized_user_string, client_id, client_id_tag, client_app_version, &user_handle);
// if (GNSDK_SUCCESS != error)
// {
// _display_last_error(__LINE__);
// rc = -1;
// }
// }
// else
// {
// printf("Error reading user file into buffer.\n");
// rc = -1;
// }
// fclose(file);
// }
// else
// {
// printf("\nInfo: No stored user - this must be the app's first run.\n");
// } /* If not, create new one*/
if (GNSDK_NULL == user_handle)
{
error = gnsdk_manager_user_register(GNSDK_USER_REGISTER_MODE_ONLINE, client_id, client_id_tag, client_app_version, &serialized_user); if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
rc = -1;
}
else
{
/* save newly registered user for use next time */
file = fopen(user_filename, "w");
if (NULL != file)
{
if (0 > fputs(serialized_user, file))
{
printf("Error writing user registration file from buffer.\n");
rc = -1;
}
fclose(file);
}
else
{
printf("\nError: Failed to open the user filename for use in saving the updated serialized user. (%s)\n", user_filename);
} /* Create the user handle from the registered user */
error = gnsdk_manager_user_create(serialized_user, client_id, client_id_tag, client_app_version, &user_handle);
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
rc = -1;
} gnsdk_manager_string_free(serialized_user);
}
} free(user_filename);
}
else
{
printf("Error allocating memory.\n");
rc = -1;
} if (rc == 0)
{
*p_user_handle = user_handle;
} return rc;
} /* _get_user_handle() */ /******************************************************************
*
* _ENABLE_LOGGING
*
* Enable logging for the SDK. Not used by Sample App. This helps
* Gracenote debug your app, if necessary.
*
******************************************************************/
static int
_enable_logging(void)
{
gnsdk_error_t error = GNSDK_SUCCESS;
int rc = 0; error = gnsdk_manager_logging_enable(
"/var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/tmp/sample.log", /* Log file path */
GNSDK_LOG_PKG_ALL, /* Include entries for all packages and subsystems */
GNSDK_LOG_LEVEL_ERROR|GNSDK_LOG_LEVEL_WARNING, /* Include only error and warning entries */
GNSDK_LOG_OPTION_ALL, /* All logging options: timestamps, thread IDs, etc */
0, /* Max size of log: 0 means a new log file will be created each run */
GNSDK_FALSE /* GNSDK_TRUE = old logs will be renamed and saved */
);
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
rc = -1;
} return rc; } /* _enable_logging() */ /*
* Set the application Locale.
*/
static int
_set_locale (gnsdk_user_handle_t user_handle)
{
gnsdk_locale_handle_t locale_handle = GNSDK_NULL;
gnsdk_error_t error = GNSDK_SUCCESS;
int rc = 0; error = gnsdk_manager_locale_load(
GNSDK_LOCALE_GROUP_MUSIC, /* Locale group */
GNSDK_LANG_ENGLISH, /* Languae */
GNSDK_REGION_DEFAULT, /* Region */
GNSDK_DESCRIPTOR_SIMPLIFIED, /* Descriptor */
user_handle, /* User handle */
GNSDK_NULL, /* User callback function */
0, /* Optional data for user callback function */
&locale_handle /* Return handle */
); if (GNSDK_SUCCESS == error)
{
/* Setting the 'locale' as default
* If default not set, no locale-specific results would be available
*/
error = gnsdk_manager_locale_set_group_default(locale_handle);
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
rc = -1;
} /* The manager will hold onto the locale when set as default
* so it's ok to release our reference to it here
*/
gnsdk_manager_locale_release(locale_handle);
}
else
{
_display_last_error(__LINE__);
rc = -1;
} return rc; } /* _set_locale() */ /******************************************************************
*
* _INIT_GNSDK
*
* Initializing the GNSDK is required before any other APIs can be called.
* First step is to always initialize the Manager module, then use the returned
* handle to initialize any modules to be used by the application.
*
* For this sample, we also load a locale which is used by GNSDK to provide
* appropriate locale-sensitive metadata for certain metadata values. Loading of the
* locale is done here for sample convenience but can be done at anytime in your
* application.
******************************************************************/
static int
_init_gnsdk(
const char* client_id,
const char* client_id_tag,
const char* client_app_version,
const char* license_path,
gnsdk_user_handle_t* p_user_handle
)
{
gnsdk_manager_handle_t sdkmgr_handle = GNSDK_NULL;
gnsdk_error_t error = GNSDK_SUCCESS;
gnsdk_user_handle_t user_handle = GNSDK_NULL;
int rc = 0; /* Initialize the GNSDK Manager */
error = gnsdk_manager_initialize(
&sdkmgr_handle,
license_path,
GNSDK_MANAGER_LICENSEDATA_FILENAME
);
if (GNSDK_SUCCESS != error) { _display_last_error(__LINE__); return -1; } /* Enable logging */
if (0 == rc)
rc = _enable_logging(); /* Initialize the Storage SQLite Library */
if (0 == rc)
{
error = gnsdk_storage_sqlite_initialize(sdkmgr_handle);
if (GNSDK_SUCCESS != error) { _display_last_error(__LINE__); rc = -1; }
} /* For this library to successfully operate, you must first establish a valid storage folder path using the
* GNSDK_SQLITE_OPTION_STORAGE_FOLDER option. */
error = gnsdk_storage_sqlite_option_set(
GNSDK_STORAGE_SQLITE_OPTION_STORAGE_FOLDER, // option name : storage folder [required]
"/var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/Documents" // option value : "." set it to current directory for this sample
); if( GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
return -1;
} error = gnsdk_manager_storage_location_set(GNSDK_MANAGER_STORAGE_QUERYCACHE, "/var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/Documents/querycache");
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
} /* Initialize the Link Content Library */
if (0 == rc)
{
error = gnsdk_link_initialize(sdkmgr_handle);
if (GNSDK_SUCCESS != error) { _display_last_error(__LINE__); rc = -1; }
} /* Get a user handle for our client ID. This will be passed in for all queries */
if (0 == rc)
{
rc = _get_user_handle(
client_id,
client_id_tag,
client_app_version,
&user_handle
);
} /* Set the 'locale' to return locale-specifc results values. This examples loads an English locale. */
if (0 == rc)
rc = _set_locale(user_handle); if (0 != rc)
{
/* Clean up on failure. */
_shutdown_gnsdk(user_handle);
}
else
{
/* return the User handle for use at query time */
*p_user_handle = user_handle;
} return rc; } /* _init_gnsdk() */ /******************************************************************
*
* _SHUTDOWN_GNSDK
*
* Call shutdown all initialized GNSDK modules.
* Release all existing handles before shutting down any of the modules.
* Shutting down the Manager module should occur last, but the shutdown ordering of
* all other modules does not matter.
*
*****************************************************************/
static void
_shutdown_gnsdk (gnsdk_user_handle_t user_handle)
{
gnsdk_error_t error = GNSDK_SUCCESS; error = gnsdk_manager_user_release(user_handle);
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
} /* Shutdown the Manager to shutdown all libraries */
gnsdk_manager_shutdown();
} /*-----------------------------------------------------------------------------
* _fetch_image
*/
static int
_fetch_image(
gnsdk_link_query_handle_t query_handle,
gnsdk_link_content_type_t image_type,
gnsdk_char_t* image_type_str
)
{
gnsdk_link_data_type_t data_type = gnsdk_link_data_unknown;
gnsdk_byte_t* buffer = GNSDK_NULL;
gnsdk_size_t buffer_size = 0;
int rc = 0;
gnsdk_error_t error = GNSDK_SUCCESS; error = gnsdk_link_query_content_retrieve(
query_handle,
image_type,
1,
&data_type,
&buffer,
&buffer_size); if (GNSDK_SUCCESS == error)
{
/* data_type will always be == gnsdk_link_data_image_jpeg */ /* Do something with the image, e.g. display, save, etc. Here we just print the size. */
printf("\nRETRIEVED: %s image: %d byte JPEG\n", image_type_str, (gnsdk_uint32_t)buffer_size); response_data = buffer; response_data_length = buffer_size; // for (int i = 0; i < buffer_size; i++) {
// printf("%x", *(buffer + i));
// } /* free the data when you are done with it */
error = gnsdk_link_query_content_free(buffer);
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
rc = -1;
}
}
else
{
if (GNSDKERR_NotFound != GNSDKERR_ERROR_CODE(error))
{
_display_last_error(__LINE__);
rc = -1;
}
else
{
/* Do not return error code for not found. */
/* For image to be fetched, it must exist in the size specified and you must be entitled to fetch images. */
printf("\nNOT FOUND: %s image\n", image_type_str);
}
} return rc;
} /*-----------------------------------------------------------------------------
* _query_for_album_images
*/
static void
_query_for_album_images (gnsdk_user_handle_t user_handle)
{
gnsdk_gdo_handle_t input_gdo = GNSDK_NULL;
gnsdk_link_query_handle_t query_handle = GNSDK_NULL;
gnsdk_cstr_t image_size = GNSDK_NULL;
gnsdk_cstr_t preferred_image_size = GNSDK_NULL;
gnsdk_error_t error = GNSDK_SUCCESS; printf("\n*****Sample Link Album Query*****\n"); /* Create the query handle. Do not include a callback or callback data (2nd & 3rd args are GNSDK_NULL). */
error = gnsdk_link_query_create(user_handle, GNSDK_NULL, GNSDK_NULL, &query_handle);
if (GNSDK_SUCCESS != error) { _display_last_error(__LINE__); return; } /* Set the input GDO */
if (GNSDK_SUCCESS == error)
{
gnsdk_cstr_t serialized_gdo = "WEcxAbwX1+DYDXSI3nZZ/L9ntBr8EhRjYAYzNEwlFNYCWkbGGLvyitwgmBccgJtgIM/dkcbDgrOqBMIQJZMmvysjCkx10ppXc68ZcgU0SgLelyjfo1Tt7Ix/cn32BvcbeuPkAk0WwwReVdcSLuO8cYxAGcGQrEE+4s2H75HwxFG28r/yb2QX71pR"; /* Typically, the GDO passed in to a Link query will come from the output of a GNSDK query.
* For an example of how to perform a query and get a GDO please refer to the documentation
* or other sample applications.
* The below serialized GDO was an 1-track album result from another GNSDK query.
*/
error = gnsdk_manager_gdo_deserialize(serialized_gdo, &input_gdo);
if (GNSDK_SUCCESS == error)
{
error = gnsdk_link_query_set_gdo(query_handle, input_gdo);
if (GNSDK_SUCCESS != error) { _display_last_error(__LINE__); } gnsdk_manager_gdo_release(input_gdo);
}
else
{
_display_last_error(__LINE__);
}
} /* Set preferred image size */
preferred_image_size = GNSDK_LINK_OPTION_VALUE_IMAGE_SIZE_170; /* Obtain image size available */
image_size = preferred_image_size; /* Specify the desired image size */
if (GNSDK_SUCCESS == error)
{
if (GNSDK_NULL != image_size)
{
error = gnsdk_link_query_option_set(
query_handle,
GNSDK_LINK_OPTION_KEY_IMAGE_SIZE,
image_size
);
if (GNSDK_SUCCESS != error)
{
_display_last_error(__LINE__);
}
else
{
/* Perform the image fetches */
_fetch_image(query_handle, gnsdk_link_content_cover_art, "cover art");
// _fetch_image(query_handle, gnsdk_link_content_image_artist, "artist");
}
}
} /* release the Link query handle */
gnsdk_link_query_release(query_handle); } /* _query_for_album_images() */
注意。为了便利(个人也很的懒惰),代码中关于路径的代码直接使用了硬编码。比如:
"/var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/Documents/querycache"。
再写个Test.h开放接口出来:
#ifndef GNTest_iOS_Test_h
#define GNTest_iOS_Test_h int coverart_main(int argc, const char* argv[]); #endif
最后回到一个普通的ViewController文件里,代码例如以下:
#import "ViewController.h"
#import "Test.h"
#import "ShareData.h"
#include "gnsdk.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad
{
[super viewDidLoad]; NSString *licencePath = [[NSBundle mainBundle] pathForResource:@"my_licence" ofType:@"txt"]; const char* pathPtr = [licencePath UTF8String];
const char* argv[] = {NULL, "4541440", "79EFBF4E21724D084BA87FF9B242F0C9", pathPtr};
NSLog(@"%@", licencePath); coverart_main(4, argv); extern gnsdk_byte_t* response_data;
extern gnsdk_size_t response_data_length;
NSData *data = [NSData dataWithBytes:response_data length:response_data_length];
NSLog(@"%@", data);
UIImage *image = [UIImage imageWithData:data];
[self.album_imageView setImage:image];
} @end
简单说下其执行过程,在sample中有一个所谓的序列化GDO(GraceNote Data Objects,是该站点自定的一种数据模型),该GDO由一列字符串标识,它相应的音乐专辑就是我们的查询目标。
gnsdk_cstr_t serialized_gdo = "WEcxAbwX1+DYDXSI3nZZ/L9ntBr8EhRjYAYzNEwlFNYCWkbGGLvyitwgmBccgJtgIM/dkcbDgrOqBMIQJZMmvysjCkx10ppXc68ZcgU0SgLelyjfo1Tt7Ix/cn32BvcbeuPkAk0WwwReVdcSLuO8cYxAGcGQrEE+4s2H75HwxFG28r/yb2QX71pR";
然后调用查询接口(就是C文件里的“主函数”):
const char* pathPtr = [licencePath UTF8String];
const char* argv[] = {NULL, "4541440", "79EFBF4E21724D084BA87FF9B242F0C9", pathPtr};
NSLog(@"%@", licencePath); coverart_main(4, argv);
当中argv[]中的第二个參数是App Details中的client id,第三个參数是App Details中的client tag,第四个參数是上面的my_licence.txt文件的路径。
在查询完毕后,站点返回的二进制数据保存在一个缓冲区中,我将其起始位置和缓冲区长度保存在下面全局变量中:
gnsdk_byte_t* response_data;
gnsdk_size_t response_data_length;
最后解析缓冲区中的数据。并以UIImage形式展示出来:
extern gnsdk_byte_t* response_data;
extern gnsdk_size_t response_data_length;
NSData *data = [NSData dataWithBytes:response_data length:response_data_length];
NSLog(@"%@", data);
UIImage *image = [UIImage imageWithData:data];
[self.album_imageView setImage:image];
接着我又偷了懒。打开PP助手,在app的Documents文件夹下创建一个querycache文件夹(用于存储查询结果到本地缓存中。这一步不可缺少):
在armv7s 32位机子上的执行。
控制台部分输出例如以下:
2014-04-25 22:43:55.906 GNTest_iOS[784:60b] /var/mobile/Applications/1B3B6648-8D50-430F-B7D2-21D99AA78B6F/GNTest_iOS.app/my_licence.txt *****Sample Link Album Query***** RETRIEVED: cover art image: 11808 byte JPEG
2014-04-25 22:43:58.470 GNTest_iOS[784:60b] <ffd8ffe0 00104a46 49460001 01010060 00600000 ffdb0043 00080606 07060508 07070709 09080a0c 140d0c0b 0b0c1912 130f141d 1a1f1e1d 1a1c1c20 242e2720 222c231c 1c283729 2c303134 34341f27 393d3832 3c2e3334 32ffdb00 43010909 090c0b0c 180d0d18 32211c21 32323232 32323232 32323232 32323232 32323232 32323232 32323232 32323232 32323232 32323232 32323232 32323232 3232ffc0 00110800 aa00aa03 01220002 11010311 01ffc400 1f000001 05010101 01010100 00000000 00000001 02030405 06070809 0a0bffc4 00b51000 02010303 02040305 05040400 00017d01
执行结果例如以下,也就是上面的GDO相应的专辑封面图片:
本文比較乱,Demo中的代码还有非常多地方要改善。等后面将关键的技术问题解决后再写篇博客好好梳理下,到时候我会给出无需不论什么手工操作的Demo。
版权声明:本文博主原创文章。博客,未经同意不得转载。
Use GraceNote SDK in iOS(一)通过序列化GDO查询专辑封面的更多相关文章
- Use GraceNote SDK in iOS(二)获取音乐的完整信息
在需求彻底明朗化,外加从MusicFans转到GraceNote,再从GraceNote的GNSDK转到iOS SDK后,最终完毕了在iOS上通过音乐的部分信息获取完整信息的功能了.(好吧,我承认是相 ...
- 移动端影像解决方案Adobe Creative SDK for ios
移动端影像解决方案Adobe Creative SDK for ios 2015-12-20 分类:整理 阅读(390) 评论(0) 老牌影像界泰斗不甘落寞,正式推出了Adobe Creative ...
- ArcGIS Runtime SDK for iOS开发地图图层-图形图层
注:本文翻译自:https://developers.arcgis.com/ios/objective-c/guide/creating-a-graphics-layer.htm 创建图 ...
- ArcGIS Runtime SDK for iOS之符号和渲染
符号定义了图形外观的非地理方面.它包括了图形的颜色.线宽.透明度等等.ArcGIS Runtime SDK for iOS包含了许多符号类,其中的每个类可以让你以独特的方式指定符号.每个符号的类型也是 ...
- FFmpeg SDK for iOS
FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的跨平台开源计算机程序. 很多平台视频播放器都是使用FFmpeg来开发的,FFmpeg官方并没有为各个平台提供编译好的SDK,所以使 ...
- [BEROR]CodeSign error: code signing is required for product type 'Application' in SDK 'iOS 8.1'
解决方法: 选择project->Build Settings -> Code Signing -> Code Signing Identity -> Debug -> ...
- 视频直播SDK-ios版
IOS视频直播接入说明 一.名词解释 分辨率:用于计算机视频处理的图像,以水平和垂直方向上所能显示的像素数来表示分辨率.常见视频分辨率的有1080P即1920x1080,720P即1080x720,6 ...
- 探寻不同版本号的SDK对iOS程序的影响
PDF版本号:http://pan.baidu.com/s/1eQ8DVdo 结论: 同样的代码.使用不同版本号的SDK来编译.会影响MachO头中的值, 从而使程序表现出不同的外观. 代码: - ( ...
- ArcGIS Runtime SDK for iOS开发系列教程(5)——要素信息的绘制
在客户端绘制点.线.面要素是GIS应用的基本功能,这一讲我将向大家介绍在iOS中如何来实现这一功能.大家都知道在Flex.Silverlight.js中对于要素的绘制都有一个叫GraphicsLaye ...
随机推荐
- 你确定你是一个合格的.Net开发人员吗?
做.net开发已有近5年时间,自认掌握的知识比较全面.最近部门需要招人,今天抽空在网上看了一下,发现我了解的还是不够多啊.下面是我大致的罗列了一下作为一名.Net开发人员所需要掌握的只是.看看你是不是 ...
- 自制Javascript分页插件,支持AJAX加载和URL带参跳转两种初始化方式,可用于同一页面的多个分页和不同页面的调用
闲话部分 最近闲着实在无聊,就做了点小东西练练手,由于原来一直在用AspNetPager进行分页,而且也进行了深度的定制与原有系统整合的也不错,不过毕竟是用别人的,想着看自己能试着做出来不能,后台的分 ...
- linux free命令建检查内存状态
前端时间发现博客服务器物理内存使用过高问题,就是使用linux free命令检查的,这次详细介绍下这个命令. 命 令: free 功能说明:显示内存状态.语 法: free [-bkmotV][-s ...
- Android开发手记(12) Menu的使用
Android中的Menu分为三种,分别为:OptionsMenu(选项菜单).ContextMenu(上下文菜单).SubMenu(子菜单). 1.OptionsMenu 按Menu键就会显示,用于 ...
- 数据转换错误,java.lang.NumberFormatException: null
今天写项目时报了一个数组转换错误的异常,让我找了半天5555 -_- . 一般出现这种错误呢,情况都是parseInt转换所触发的,像下面这行代码 int factorOneInt = Integer ...
- MySQL的truncate table 和source 命令
1. truncate table XXX 在测试时,我很讨厌某表的主键一直自增长下去,总觉得从1开始最舒服,^_^,truncate table 就可以帮我,相比delete from 来说 ...
- Css Div半透明
用CSS控制外层DIV不透明,而内层DIV透明,这样实现的效果是意想不到的,还不错吧,其实代码也是很简单的,也很好理解,主要是用了CSS的滤镜. <html xmlns="http:/ ...
- 《Linux内核分析》 week5作业-system call中断处理过程
一.使用gdb跟踪分析一个系统调用内核函数 1.在test.c文件中添加time函数与采用c语言内嵌汇编的time函数.具体实现请看下图. 2.然后在main函数中添加MenuConfig函数,进行注 ...
- 三元运算和lambda表达式
19.三目运算,三元运算: if else 的简写: name = 'alex' if 1 == 1 else 'SB' ==> 等价于 if 1 == 1: ...
- 怎么把QQ我的收藏表情图片转移到另一台电脑上
把收藏的QQ表情从一台电脑转移到另一台电脑的操作步骤如下: 1.在有表情的电脑登陆QQ,随便打开一个聊天窗口,点击[表情],选择[表情设置],点击[导入导出表情包],选择[导出全部表情包]: ...