在Use MusicBrainz in iOS之后,由于MusicBrainz查不到专辑封面,只能转移到其它提供音乐信息搜索服务的网站,领导给出的就是GraceNote。(有压力。。。)

需求类似:通过一个音频文件的歌曲名,专辑名等信息查询到该文件专辑的封面。

本文介绍下如何在iOS中使用GraceNote给出的GNSDK(一个用C写的SDK),并通过序列化的GDO查询专辑封面。实际上,就是我对GNSDK文件中给出的samples的一些修正和调用而已。

首先前往GraceNote网站注册一个帐号,然后创建一个app(看得懂英语的都知道怎么做吧,我就略过了),完成后如下所示:

新建一个Demo工程,名字和上面的app名一致(不一致是否可行,我还没试过)。

下载GNSDK:点击打开链接

本文基于3.0.6版本。

下载完成后解压,前往lib_static/ios_armv7s-32,由于我的机子指令集是armv7s,所以使用该文件夹中的静态库文件。将所有.a文件复制到Demo工程中。

再将include目录下的所有.h文件和ios_armv7s_32文件夹复制到Demo工程中。

完成后工程目录如下:

打开Build Settings选项,设置Header Search Paths和Library Search Paths:

确保Build Phases全部静态库链接成功:

在工程中新建一个文本文件,例如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_hint 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查询专辑封面相关推荐

  1. Use GraceNote SDK in iOS(一)通过序列化GDO查询专辑封面

    于Use MusicBrainz in iOS之后,因为MusicBrainz找出专辑封面,它只能转移到其他网站提供的音乐信息搜索服务,领导给出GraceNote.(有压力.. .) 需求类似:通过一 ...

  2. Use GraceNote SDK in iOS(二)获取音乐的完整信息

    在需求彻底明朗化,外加从MusicFans转到GraceNote,再从GraceNote的GNSDK转到iOS SDK后,最终完毕了在iOS上通过音乐的部分信息获取完整信息的功能了.(好吧,我承认是相 ...

  3. IOS 归档 即序列化与反序列化

    IOS 归档 即序列化与反序列化 小弟很久没有更新了 最近在往IOS上靠 IOS中的归档  即是我们所知道的序列化和反序列化 我们可以用plist来存储比较简单的数据类型 但是如果我想把自己定义的类型 ...

  4. 中国移动灵犀云语音识别及合成SDK(iOS)使用指南

    随着智能家居概念的火热,语音交互这一新时代的人机交互方式再度掀起了热潮.移动互联网应用在设计开发时也纷纷考虑加入语音识别功能,带给用户除传统键盘或触控交互方式外的更便捷交互体验.中国移动近日推出的&q ...

  5. untiy接入微信SDK实现iOS分享

    untiy接入微信SDK实现iOS分享功能 说明: 使用平台:mac电脑 Unity处理 进入微信开发者官网申请应用 2.下载微信的开发工具包sdk导入untiy的 Assest/Plugins/iO ...

  6. Cognex Mobile Barcode SDK for iOS

    概述 Cognex Mobile Barcode SDK (cmbSDK) 是用于开发移动条码扫描应用程序的SDK. SDK是付费的,但功能很强大. Cognex Mobile Barcode SDK ...

  7. 基于声网 SDK 实现 iOS 端的一对一视频通话

    在很多产品,加入实时视频通话已经不是新鲜事情了,尤其是近几年的疫情影响,个人公司国家对于实时音视频的需求一直在快速的增长.例如视频会议.社交应用.实时游戏,甚至也可能出现在一些元宇宙的场景中. 本文将 ...

  8. ArcGIS Runtime SDK for iOS之符号和渲染

    本篇文章翻译自与点击打开链接,有不妥之处还请大家多多指正! 符号定义了图形外观的非地理方面.它包括了图形的颜色.线宽.透明度等等.ArcGIS Runtime SDK for iOS包含了许多符号类, ...

  9. uniapp离线打包升级SDK(iOS端)

    uniapp离线打包升级SDK(iOS端) 使用的工具 苹果账号 生成CertificateSigningRequest.certSigningRequest文件 创建Certificates 创建p ...

最新文章

  1. 算法--------------整数反转
  2. NetworkManager 冲突
  3. 手机版本高于xcode,xcode的快速升级
  4. DNS resolving 占用大量日志
  5. 『AA』AutoAnchor自动猫
  6. CentOS7 安装或迁移 wordpress(完整迁移)
  7. [python 学习] requests 库的使用
  8. 大数据是应对安全形势的进攻武器
  9. ros openwrt 分流_常平:推进“截污大会战”补贴助力企业雨污分流
  10. JAVA→HashMap、常用方法、遍历方式、底层原理、初始化性能分析
  11. 怎么更改网络选项为家庭计算机,我的现在是公用网络我想更改为家庭网络应该如何更改...
  12. ps3 自制系统的C 语言,老树发新芽:PS3自制系统的使用与研究
  13. 再学 GDI+[57]: 路径 - Widen
  14. 超五类屏蔽双绞线和计算机电缆区别,超五类单屏网线和六类单屏蔽网线的区别是什么?...
  15. 微信小程序之身份证照片正反上传
  16. linux gfortran编译,gfortran编译学习
  17. 提高工作效率的15个技巧
  18. 网页版文件服务器搭建,Windows 下部署 Seafile 服务器
  19. nodejs uuid 生成
  20. C语言易错点汇总(二)

热门文章

  1. 如何查看文章所投期刊属于科睿唯安(Clarivate Analytics)分区的几区?
  2. 护网行动安全防守工作指南应看
  3. 什么是回流焊?回流焊原理及工艺介绍
  4. JS 数组转字符串的4种方法
  5. Unity-场景-Sky
  6. 爬虫日记(40):Flask的模板介绍
  7. Mac 查看端口占用情况及杀死进程
  8. 小米用USB上网成功
  9. 【git认证错误】fatal: Authentication failed for ‘http://gitlab.gwm.cn/les-zt/middleware/erp_upload.git/‘
  10. npm install报错C:\Program Files\Git\cmd\git.EXE ls-remote -h -t ssh://git@github.com/sohee-lee7/Squire