CC2540自己的配置文件
首先要指出,字段属性有notify的不能同时有read,write属性,别问哥,哥也不知道,反正我做的就不能notify,只能read,write。
分享的程序段第一字段有notify属性,第二字段read,write属性。
费话少说,看代码,H文件:
- #ifndef LOCKER_H
- #define LOCKER_H
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- #define SERVAPP_NUM_ATTR_SUPPORTED (1+4+3)
- // Simple Profile Service UUID
- #define LOCKERPROFILE_SERV_UUID 0xFFF0
- #define LOCKERPROFILE_NOTIFY_UUID 0xFFF1
- #define LOCKERPROFILE_NOTIFY_MAX_LEN 5
- #define LOCKERPROFILE_STREAM_UUID 0xFFF2
- #define LOCKERPROFILE_STREAM_MAX_LEN 5
- #define SIMPLEPROFILE_SERVICE 0x00000001
- /*********************************************************************
- * Profile Callbacks
- */
- // Callback when a characteristic value has changed
- typedef void (*app_input_cb_t)( uint16 uuid ,uint8 *pdata, int len);
- /*********************************************************************
- * lockerProfile_AddService- Initializes the Simple GATT Profile service by registering
- * GATT attributes with the GATT server.
- * @param services - services to add. This is a bit map and can contain more than one service.
- * @param cb - the function will be called, while service receive a message .
- * return always return SUCCESS
- */
- bStatus_t lockerProfile_AddService( uint32 services ,app_input_cb_t cb);
- /*
- * lockerProfile_AddService - Set a Simple GATT Profile parameter.
- * uuid - which service's uuid as sender target
- * len - length of data to right
- * value - pointer to data to write. This is dependent on
- * the parameter uuid and WILL be cast to the appropriate
- * data type .
- */
- bStatus_t locker_send( uint16 uuid,void *pdata , uint8 len);
- /*
- * locker_Read - Get a Simple GATT Profile parameter by uuid.
- * param - Profile uuid
- * value - pointer to data to write. This is dependent on
- * the parameter ID and WILL be cast to the appropriate
- * data type .
- * return : return data length, if op' failse it'll return -1;
- */
- int locker_Read( uint16 uuid, void *pdata );
- #ifdef __cplusplus
- }
- #endif
- #endif /* SIMPLEGATTPROFILE_H */
C文件:
- /*********************************************************************
- * INCLUDES
- */
- #include "bcomdef.h"
- #include "OSAL.h"
- #include "linkdb.h"
- #include "att.h"
- #include "gatt.h"
- #include "gatt_uuid.h"
- #include "gattservapp.h"
- #include "gapbondmgr.h"
- #include "locker.h"
- #include "stdio.h"
- /*********************************************************************
- * GLOBAL VARIABLES
- */
- // Simple GATT Profile Service UUID: 0xFFF0
- CONST uint8 lockerSvrUUID[ATT_BT_UUID_SIZE] =
- {
- LO_UINT16(LOCKERPROFILE_SERV_UUID),
- HI_UINT16(LOCKERPROFILE_SERV_UUID)
- };
- // notify UUID: 0xFFF1
- CONST uint8 lockerNotifyUUID[ATT_BT_UUID_SIZE] =
- {
- LO_UINT16(LOCKERPROFILE_NOTIFY_UUID),
- HI_UINT16(LOCKERPROFILE_NOTIFY_UUID)
- };
- // stream UUID: 0xFFF2
- CONST uint8 lockerStreamUUID[ATT_BT_UUID_SIZE] =
- {
- LO_UINT16(LOCKERPROFILE_STREAM_UUID),
- HI_UINT16(LOCKERPROFILE_STREAM_UUID)
- };
- /*********************************************************************
- * LOCAL VARIABLES
- */
- static app_input_cb_t app_input_cb = NULL;
- /*********************************************************************
- * Profile Attributes - variables
- */
- // locker Profile Service attribute
- static CONST gattAttrType_t lockerProfileService = { ATT_BT_UUID_SIZE, lockerSvrUUID };
- // locker Profile Notify Properties
- static uint8 lockerNotifyProps = GATT_PROP_NOTIFY;
- static uint8 lockerNotifyStream[LOCKERPROFILE_NOTIFY_MAX_LEN];
- static uint8 lockerNotifyDesp[17] = "notify\0";
- static gattCharCfg_t lockerNotifyConfig[GATT_MAX_NUM_CONN];
- // locker Profile Stream Properties
- static uint8 lockerStreamProps = GATT_PROP_READ | GATT_PROP_WRITE;
- static uint8 lockerStream[LOCKERPROFILE_STREAM_MAX_LEN];
- static uint8 lockerStreamDesp[17] = "stream\0";
- /*********************************************************************
- * Profile Attributes - Table
- */
- static gattAttribute_t LockerProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
- {
- // Simple Profile Service
- {
- { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
- GATT_PERMIT_READ, /* permissions */
- 0, /* handle */
- (uint8 *)&lockerProfileService /* pValue */
- },
- /**************notify attribute**********************/
- // notify Declaration
- {
- { ATT_BT_UUID_SIZE, characterUUID },
- GATT_PERMIT_READ,
- 0,
- &lockerNotifyProps
- },
- // notify stream buffer
- {
- { ATT_BT_UUID_SIZE, lockerNotifyUUID },
- 0,
- 0,
- lockerNotifyStream
- },
- // notify stream configuration
- {
- { ATT_BT_UUID_SIZE, clientCharCfgUUID },
- GATT_PERMIT_READ | GATT_PERMIT_WRITE,
- 0,
- (uint8 *)lockerNotifyConfig
- },
- // notify stream Description
- {
- { ATT_BT_UUID_SIZE, charUserDescUUID },
- GATT_PERMIT_READ,
- 0,
- lockerNotifyDesp
- },
- /************************stream buffer attribute***********************/
- // stream Declaration
- {
- { ATT_BT_UUID_SIZE, characterUUID },
- GATT_PERMIT_READ,
- 0,
- &lockerStreamProps
- },
- // stream buffer
- {
- { ATT_BT_UUID_SIZE, lockerStreamUUID },
- GATT_PERMIT_READ | GATT_PERMIT_WRITE,
- 0,
- lockerStream
- },
- // stream Description
- {
- { ATT_BT_UUID_SIZE, charUserDescUUID },
- GATT_PERMIT_READ,
- 0,
- lockerStreamDesp
- },
- };
- /*********************************************************************
- * LOCAL FUNCTIONS
- */
- static uint8 lockerReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
- uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen );
- static bStatus_t lockerWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
- uint8 *pValue, uint8 len, uint16 offset );
- static void lockerHandleConnStatusCB( uint16 connHandle, uint8 changeType );
- /*********************************************************************
- * PROFILE CALLBACKS
- */
- // Simple Profile Service Callbacks
- CONST gattServiceCBs_t lockerProfileCBs =
- {
- lockerReadAttrCB, // Read callback function pointer
- lockerWriteAttrCB, // Write callback function pointer
- NULL // Authorization callback function pointer
- };
- bStatus_t lockerProfile_AddService( uint32 services ,app_input_cb_t cb)
- {
- uint8 status = SUCCESS;
- printf("lockerProfile_AddService: \n");
- // Initialize Client Characteristic Configuration attributes
- GATTServApp_InitCharCfg( INVALID_CONNHANDLE, lockerNotifyConfig );
- // Register with Link DB to receive link status change callback
- VOID linkDB_Register( lockerHandleConnStatusCB );
- if ( services & SIMPLEPROFILE_SERVICE )
- {
- // Register GATT attribute list and CBs with GATT Server App
- status = GATTServApp_RegisterService( LockerProfileAttrTbl,
- GATT_NUM_ATTRS( LockerProfileAttrTbl ),
- &lockerProfileCBs );
- }
- app_input_cb = cb;
- return ( status );
- }
- bStatus_t locker_send( uint16 uuid,void *pdata , uint8 len)
- {
- bStatus_t ret = SUCCESS;
- switch ( uuid )
- {
- case LOCKERPROFILE_NOTIFY_UUID:
- if ( len <= LOCKERPROFILE_NOTIFY_MAX_LEN)
- {
- printf("locker_send: uuid:%04x notify app \n",uuid);
- osal_memcpy(lockerNotifyStream,pdata,len);
- GATTServApp_ProcessCharCfg(lockerNotifyConfig,lockerNotifyStream, FALSE,
- LockerProfileAttrTbl, GATT_NUM_ATTRS( LockerProfileAttrTbl ),
- INVALID_TASK_ID );
- }
- else
- {
- ret = bleInvalidRange;
- }
- break;
- case LOCKERPROFILE_STREAM_UUID:
- if ( len <= LOCKERPROFILE_STREAM_MAX_LEN)
- {
- printf("locker_Send: uuid:%04x write to stream buffer and waite to read \n",uuid);
- osal_memcpy(lockerStream,pdata,len);
- }
- else
- {
- ret = bleInvalidRange;
- }
- default:
- ret = INVALIDPARAMETER;
- break;
- }
- return ( ret );
- }
- int locker_Read( uint16 uuid, void *pdata )
- {
- int ret;
- printf("locker_Read: uuid:%04x \n",uuid);
- switch ( uuid )
- {
- case LOCKERPROFILE_NOTIFY_UUID:
- osal_memcpy(pdata,lockerNotifyStream,LOCKERPROFILE_NOTIFY_MAX_LEN);
- ret = LOCKERPROFILE_NOTIFY_MAX_LEN;
- break;
- case LOCKERPROFILE_STREAM_UUID:
- osal_memcpy(pdata,lockerStream,LOCKERPROFILE_STREAM_MAX_LEN);
- ret = LOCKERPROFILE_NOTIFY_MAX_LEN;
- break;
- default:
- ret = -1;
- break;
- }
- return ( ret );
- }
- static uint8 lockerReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
- uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen )
- {
- bStatus_t status = SUCCESS;
- // If attribute permissions require authorization to read, return error
- if ( gattPermitAuthorRead( pAttr->permissions ) )
- {
- // Insufficient authorization
- return ( ATT_ERR_INSUFFICIENT_AUTHOR );
- }
- // Make sure it's not a blob operation (no attributes in the profile are long)
- if ( offset > 0 )
- {
- return ( ATT_ERR_ATTR_NOT_LONG );
- }
- if ( pAttr->type.len == ATT_BT_UUID_SIZE )
- {
- // 16-bit UUID
- uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
- printf("lockerProfile_ReadAttrCB: uuid:%04x \n",uuid);
- switch ( uuid )
- {
- // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
- // gattserverapp handles those reads
- // characteristics 1 and 2 have read permissions
- // can be sent as a notification, it is included here
- case LOCKERPROFILE_NOTIFY_UUID:
- *pLen = LOCKERPROFILE_NOTIFY_MAX_LEN;
- osal_memcpy(pValue,pAttr->pValue,LOCKERPROFILE_NOTIFY_MAX_LEN);
- break;
- case LOCKERPROFILE_STREAM_UUID:
- *pLen = LOCKERPROFILE_STREAM_MAX_LEN;
- osal_memcpy(pValue,pAttr->pValue,LOCKERPROFILE_STREAM_MAX_LEN);
- break;
- default:
- // Should never get here! (characteristics 3 and 4 do not have read permissions)
- *pLen = 0;
- status = ATT_ERR_ATTR_NOT_FOUND;
- break;
- }
- }
- else
- {
- // 128-bit UUID
- *pLen = 0;
- status = ATT_ERR_INVALID_HANDLE;
- }
- return ( status );
- }
- static bStatus_t lockerWriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
- uint8 *pValue, uint8 len, uint16 offset )
- {
- bStatus_t status = SUCCESS;
- // If attribute permissions require authorization to write, return error
- if ( gattPermitAuthorWrite( pAttr->permissions ) )
- {
- // Insufficient authorization
- return ( ATT_ERR_INSUFFICIENT_AUTHOR );
- }
- if ( pAttr->type.len == ATT_BT_UUID_SIZE )
- {
- // 16-bit UUID
- uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
- printf("lockerProfile_WriteAttrCB: uuid:%04x \n",uuid);
- switch ( uuid )
- {
- case LOCKERPROFILE_NOTIFY_UUID:
- status = ATT_ERR_INVALID_HANDLE;
- //Write the value
- break;
- case LOCKERPROFILE_STREAM_UUID:
- if((offset==0)&(app_input_cb!=NULL))
- {
- if(len<=LOCKERPROFILE_STREAM_MAX_LEN)
- osal_memcpy(lockerStream,pValue,len);
- app_input_cb(LOCKERPROFILE_STREAM_UUID,pValue,len);
- }
- break;
- case GATT_CLIENT_CHAR_CFG_UUID:
- status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
- offset, GATT_CLIENT_CFG_NOTIFY );
- break;
- default:
- // Should never get here! (characteristics 2 and 4 do not have write permissions)
- status = ATT_ERR_ATTR_NOT_FOUND;
- break;
- }
- }
- else
- {
- // 128-bit UUID
- status = ATT_ERR_INVALID_HANDLE;
- }
- return ( status );
- }
- static void lockerHandleConnStatusCB( uint16 connHandle, uint8 changeType )
- {
- // Make sure this is not loopback connection
- if ( connHandle != LOOPBACK_CONNHANDLE )
- {
- // Reset Client Char Config if connection has dropped
- if ( ( changeType == LINKDB_STATUS_UPDATE_REMOVED ) ||
- ( ( changeType == LINKDB_STATUS_UPDATE_STATEFLAGS ) &&
- ( !linkDB_Up( connHandle ) ) ) )
- {
- printf("lockerProfile_HandleConnStatusCB: Reset Client Char Config if connection has dropped \n");
- GATTServApp_InitCharCfg( connHandle, lockerNotifyConfig );
- }
- }
- }
- /*********************************************************************
- *********************************************************************/
在simpleBLEPeripheral.c下增加input函数用于接收数据:
- void input(uint16 uuid, uint8 *pdata , int len)
- {
- int i;
- printf("input from uuid: %04x len:%d data:",uuid,len);
- for(i=0;i<len;i++)
- printf("%02x ",pdata[i]);
- printf("\n");
- }
初始化时:
- void SimpleBLEPeripheral_Init( uint8 task_id )
- {
- simpleBLEPeripheral_TaskID = task_id;
- // Setup the GAP
- VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL );
- // Setup the GAP Peripheral Role Profile
- {
- uint8 initial_advertising_enable = TRUE;
- // By setting this to zero, the device will go into the waiting state after
- // being discoverable for 30.72 second, and will not being advertising again
- // until the enabler is set back to TRUE
- uint16 gapRole_AdvertOffTime = 0;
- uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST;
- uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
- uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
- uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY;
- uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT;
- // Set the GAP Role Parameters
- GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable );
- GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime );
- GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );
- GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData );
- GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request );
- GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval );
- GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval );
- GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency );
- GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout );
- }
- // Set the GAP Characteristics
- GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName );
- // Set advertising interval
- {
- uint16 advInt = DEFAULT_ADVERTISING_INTERVAL;
- GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt );
- GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt );
- GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt );
- GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt );
- }
- // Setup the GAP Bond Manager
- {
- uint32 passkey = 0; // passkey "000000"
- uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
- uint8 mitm = TRUE;
- uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
- uint8 bonding = TRUE;
- GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey );
- GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode );
- GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm );
- GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap );
- GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding );
- }
- // Initialize GATT attributes
- GGS_AddService( GATT_ALL_SERVICES ); // GAP
- GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes
- DevInfo_AddService(); // Device Information Service
- lockerProfile_AddService( GATT_ALL_SERVICES,input); // Simple GATT Profile
- // Register for all key events - This app will handle all key events
- RegisterForKeys( simpleBLEPeripheral_TaskID );
- // Enable clock divide on halt
- // This reduces active current while radio is active and CC254x MCU
- // is halted
- HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT );
- // Setup a delayed profile startup
- osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );
- }
good luck!!我的已经工作的,你的呢?
CC2540自己的配置文件的更多相关文章
- 蓝牙协议 基于TI cc2540 模块的理解(转)
源:蓝牙协议 基于TI cc2540 模块的理解 Bluetooth 4.0开发 Platform:TI IC:cc2540 Environment:windows 7 tools:IAR 8.20. ...
- Ti CC2540蓝牙模块学习笔记整理
接触CC2540几天,终于有了初步的理解,现将笔记整理如下,只是皮毛,如有错误,还请指正,还有好多没闹明白的地方,以后应该还会继续向里面更新~ 一.整体 1.TI的蓝牙平台支持2种协议栈/应用配置:单 ...
- .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整(续)-使用配置文件动态注入
上次实现了依赖注入,但是web项目必须要引用业务逻辑层和数据存储层的实现,项目解耦并不完全:另一方面,要同时注入业务逻辑层和数据访问层,注入的服务直接写在Startup中显得非常臃肿.理想的方式是,w ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(64)-补充WebApi与Unity注入-配置文件
系列目录 上一篇演示了WebApi利用Unity注入 很多人问我如何用配置文件来配置注入,本节演示如何利用配置文件来注入,道理是一样的,跳转到上一节下载源码一起来动手! 1.打开源码定位到文件Depe ...
- Spring配置文件标签报错:The prefix "XXX" for element "XXX:XXX" is not bound. .
例如:The prefix "context" for element "context:annotation-config" is not bound. 这种 ...
- nginx服务器安装及配置文件详解
nginx在工作中已经有好几个环境在使用了,每次都是重新去网上扒博客,各种编译配置,今天自己也整理一份安装文档和nginx.conf配置选项的说明,留作以后参考.像负载均衡配置(包括健康检查).缓存( ...
- C#开发中使用配置文件对象简化配置的本地保存
C#开发中使用配置文件对象简化配置的本地保存 0x00 起因 程序的核心是数据和逻辑,开发过程中免不了要对操作的数据进行设置,而有些数据在程序执行过程中被用户或程序做出的修改是应该保存下来的,这样程序 ...
- 使用T4模板生成不同部署环境下的配置文件
在开发企业级应用的时候,通常会有不同的开发环境,比如有开发环境,测试环境,正式环境,生产环境等.在一份代码部署到不同环境的时候,不同环境的配置文件可能需要根据目标环境不同而不同.比如在开发环境中,数据 ...
- 配置文件Java读写
今天把配置文件的Bug修复了,总结一下Java配置文件如何读写 配置文件的格式 以.properties后缀结尾,内容不出现空格和双引号 //config.properties Driver=com. ...
随机推荐
- c# Entity DbArithmeticExpression arguments must have a numeric common type
在Entity Lambda表达式中计算DateTime类型的时候 不能直接用DateTime类型进行相减计算差值 需要使用DbFunctions提供的一些方法. 例如: DbFunctions.Di ...
- Beta版本冲刺第七天
Aruba 408 409 410 428 429 431 完成任务: 新增:完成文字导出为图片并改善画布大小 改进:适应MIUI系统相册选图 改进:调整activity间的跳转逻辑 改进:调整编辑窗 ...
- 2016第七季极客大挑战Writeup
第一次接触CTF,只会做杂项和一点点Web题--因为时间比较仓促,写的比较简略.以后再写下工具使用什么的. 纯新手,啥都不会.处于瑟瑟发抖的状态. 一.MISC 1.签到题 直接填入题目所给的SYC{ ...
- ubuntu修改163软件源
cd /etc/apt cat sources.list sudo su root sudo echo '' > sources.list nano sources.list 复制163软件源 ...
- ionic ios iframe 白屏
之前碰到一个问题: 在ios下边使用iframe出现白屏问题 android下边正常 原因是ios对app打开外部网页有限制需要取消限制 解决方法 1.确认添加whitelist 插件 2.在conf ...
- Android studio 软件板块
- IntelliJ IDEA mac 快捷键
cmd+O 查找类alt+cmd+O 符号shift+cmd+O 查找文件^+space 补全alt + F7 查找符号的使用情况F1 查看文档cmd+b 跳转定义,或者 鼠标+ctrlcmd+F12 ...
- 仿淘宝分页按钮效果简单美观易使用的JS分页控件
分页按钮思想: 1.少于9页,全部显示 2.大于9页,1.2页显示,中间页码当前页为中心,前后各留两个页码 附件中有完整例子的压缩包下载.已更新到最新版本 先看效果图: 01输入框焦点效果 ...
- 1. web前端开发分享-css,js入门篇
关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...
- chrome谷歌浏览器插件制作简易教程
1.在磁盘上创建一个目录,用来放应用的代码和资源 2.在这个目录中,创建一个文本文件,命名为manifest.json,其内容为: { "manifest_version": 2, ...