首页 文章 精选 留言 我的

精选列表

搜索[笔记工具],共10000篇文章
优秀的个人博客,低调大师

【NGN学习笔记】5 IMS技术

1.移动网络的发展--引子 20世纪80年代,商业性移动通信网络得到发展 第一代移动通信系统:TACS、NMT等模拟系统 第二代移动通信系统:GSM、IS-95、DECT、IS-136等数字系统,目前建设的2G移动网络使用两种主要技术,GSM网络使用TDMA技术,大约占70%,IS-95网络基于CDMA技术,大约占25%。 1992年开始对3G移动通信系统进行研究:R99、R4、R5、R6、R7、R8、R9…… 2G (GSM), 基于电路交换 2.5G (GPRS), 引入分组交换 3G时代的到来 1992年ETSI发起对即将到来的3G移动通信系统进行研究。采用2GHz附近的频率,支持多种空中接口: WCDMA——使用2GHz频谱的宽带码分多址接入 EDGE——用于GSM演进的增强数据传输速率 CDMA2000(1xRTT)——多载波SCDMA系统,用于在与IS-95相同的频带上建设CDMA网络 TD-SCDMA——由中国提出 支持分组数据业务,采用通用体系结构——UMTS(由3GPP负责制定),已有6个版本: 3GPP R99、R4、R5、R6、R7和R8 具体的: 3G (R99), 引入全新的UTRAN 3G (R4),电路域采用移动软交换 3G (R5), 引入IMS域 3G (R6),引入WLAN接入 3G (R7), 功能增强: CSI (Combination of CS and IMS services):研究如何将CS承载和IMS结合起来为用户提供统一的业务,CS传递实时业务,IMS分组域传递非实时业务 VCC (Voice Call Continuity):解决CS域和IMS之间语音业务切换的连续性问题 SMSIP: 研究如何通过IPCAN来提供短消息/多媒体消息业务 FBI: IMS如何支持固定接入,借鉴TISPAN的研究成果 LCS3: 如何在WLAN接入IMS的系统中提供定位业务 E2EQos: 研究端到端的Qos机制,研究IMS中计费和策略控制框架的合并 EC: 研究通过IMS如何提供紧急呼叫业务 2.IMS与现有通信系统之间的关系 标准化组织在IMS上的协作 3.IMS与软交换 IMS在3GPPRelease 5版本中提出,是对IP多媒体业务进行控制的网络核心层逻辑功能实体的总称。3GPP R5主要定义IMS的核心结构,网元功能、接口和流程等内容:R6版本增加了部分IMS业务特性、IMS与其他网络的互通规范和无线局域网(WLAN)接入特性等;R7版本加强了对固定、移动融合的标准化制订,要求IMS支持数字用户线(xDSL)、电缆调制解调器等固定接入方式。 软交换技术从1998年就开始出现并且已经历了实验、商用等多个发展阶段,目前已比较成熟。全球范围早已有多家电信运营商开展了软交换试验,发展至今,软交换技术已经具备了替代电路交换机的能力,并具备一定的宽带多媒体业务能力。在软交换技术已发展如此成熟的今天,IMS的出路在何方?又该如何发展和定位呢?首先需要对IMS和软交换进行较为全面的比较和分析。 如果从采用的基础技术上看,IMS和软交换有很大的相似性:都是基于IP分组网;都实现了控制与承载的分离;大部分的协议都是相似或者完全相同的;许多网关设备和终端设备甚至是可以通用的。 IMS和软交换最大的区别在于以下几个方面。 (1)在软交换控制与承载分离的基础上,IMS更进一步的实现了呼叫控制层和业务控制层的分离; (2)IMS起源于移动通信网络的应用,因此充分考虑了对移动性的支持,并增加了外置数据库——归属用户服务器(HSS),用于用户鉴权和保护用户业务触发规则; (3)IMS全部采用会话初始协议(SIP)作为呼叫控制和业务控制的信令,而在软交换中,SIP只是可用于呼叫控制的多种协议的一种,更多的使用媒体网关协议(MGCP)和H.248协议。 总体来讲,IMS和软交换的区别主要是在网络构架上。软交换网络体系基于主从控制的特点,使得其与具体的接入手段关系密切,而IMS体系由于终端与核心侧采用基于IP承载的SIP协议,IP技术与承载媒体无关的特性使得IMS体系可以支持各类接入方式,从而使得IMS的应用范围从最初始的移动网逐步扩大到固定领域。此外,由于IMS体系架构可以支持移动性管理并且具有一定的服务质量(QoS)保障机制,因此IMS技术相比于软交换的优势还体现在宽带用户的漫游管理和QoS保障方面。 3.IMS的特点和体系结构 1)特点: 采用分层的架构,便于网络演进和业务部署:接入层、承载层、会话控制层、业务应用层 接入无关性,提供优越的融合特性:核心功能与接入技术无关 基于SIP的会话控制,具备良好的多媒体业务支持能力 采用分布式开放性的体系结构,提供良好的可扩展性:开放的业务控制接口,拥有SIP的灵活和可扩展性 统一的用户数据管理(HSS) 归属网络服务控制,提供一致的用户通信体验 基于iFC(初始过滤规则)的业务触发机制,实现呼叫控制和业务逻辑的分离 2)分层体系结构: 3)功能实体简要归类 a)会话管理和路由类 服务呼叫会话控制功能S-CSCF 询问呼叫会话控制功能I-CSCF 代理呼叫会话控制功能S-CSCF b)数据库 归属用户服务器HSS 用户定位功能SLF c)网间配合实体 出口网关控制功能BGCF 媒体网关控制功能MGCF IP多媒体媒体网关功能IM-MGW 信令网关SGW d)服务 应用服务器AS 媒体资源控制功能 媒体资源处理功能 e)支撑实体 拓扑隐藏功能 THIG 安全网关SEG 策略决策功能 f)计费 4.功能实体详解 1)应用服务器 AS位于用户的归属网络或第三方网络 负责提供应用逻辑和应用的运行环境 处理和影响从IMS发来的SIP会话 发起SIP请求 发送计费信息给CCF和OCS 根据提供业务的方式不同,AS分三类 SIP AS:提供基于SIP的多媒体业务,如Presence OSA AS:由第三方提供基于OSA API开发的应用 CSE:提供传统的智能网业务 2)CSCF——Call Session Control Function IMS系统中完成呼叫控制功能的核心组件,主要功能:信令路由,会话管理,资源分配,安全认证,业务触发,计费控制。 a)P-CSCF:代理呼叫会话控制功能 IMS系统中用户的第一个接触点,主要功能: 作为SIP Proxy,在UE和S/I-CSCF间转发SIP请求和响应信令消息 异常会话释放/注册时,充当SIP UA发起SIP事务 检测紧急会话 向CCF(计费采集功能)提供计费信息 SIP信令完整性和机密性保护 SIP消息的压缩和解压 向S-CSCF订阅注册事件包 执行媒体监管 维护会话计时器 b)I-CSCF:问询呼叫会话控制功能 运营商归属网络中为所有连接到该运营商网络的用户的连接提供的一个联系点,主要功能: 注册阶段指定S-CSCF 获取S-CSCF的名字 前转SIP消息和响应给S-CSCF 向CCF提供计费信息 拓扑隐藏功能 c)S-CSCF:服务呼叫会话控制功能 IMS的核心所在,位于归属网络,提供注册和呼叫控制服务,主要功能: 注册服务功能 基于AKA的认证 从HSS下载用户信息和业务数据 消息路由和转发 会话控制功能 与业务平台交互 E.164号码与SIP URI之间的转换 维护会话计时器、执行媒体监管、支持紧急呼叫 向CCF或OCS提供计费信息 d)HSS:归属用户服务器 IMS中所有与用户和业务相关数据的主要存储器,主要数据包括:用户身份、注册信息、接入参数、业务触发信息。 HSS功能包括三部分: IMS功能 CS域HLR/AUC功能 PS域HLR/AUC功能 e)MRF:媒体资源功能,多用于多方会话 MRFC:媒体资源功能控制器--对IMS域内部的媒体资源进行控制,通过H.248协议维护、控制MRFP中的媒体资源,与S-CSCF交互,间接接受AS的控制,向CCF或OCS提供计费信息。 MRFP:媒体资源功能处理器--对IMS域内部的媒体资源进行处理,接受MRFC的控制:H.248,完成对媒体流的编解码、转换、混合和播放等功能。 f)网关功能 BGCF:外出网关控制功能--负责在IMS与PSTN/CS域互通时候选择到CS域的出口的位置,即选择MGCF或BGCF MGCF:媒体网关控制功能--IMS用户与CS用户互通的控制网关,控制IMS-MGW中媒体信道的连接,选择CSCF,进行协议转换:SIP与ISUP,并与SGW交互 IMS-MGW:IMS媒体网关功能--在IMS与CS间提供用户平面链路,在MGCF的控制下,完成媒体协议转换、回声消除、转码等功能 SGW:信令网关--SIP与SS7之间的转换,支持SIGTRAN 5.参考点 ISC:S-CSCF与AS平台之间,提供IMS业务控制机制的重要接口,基于SIP协议,传送AS提供的业务相关的SIP消息。 Cx:CSCF与HSS之间,提供S-CSCF分配、路由查询、认证授权、业务过滤控制等功能,基于Diameter协议。 Gm:UE与P-CSCF之间,基于SIP协议,完成注册、呼叫控制、事务处理等功能。 Mw:CSCF与CSCF之间,基于SIP协议,完成注册、呼叫控制、事务处理等功能。 Mg:MGCF与CSCF之间,基于SIP协议,负责将边缘功能MGCF连接到IMS上。 Mr:CSCF与MRFC之间,基于SIP协议,支持S-CSCF与MRFC之间的交互,是IMS域内实现多方会议的通道。 Mp:MRFC与MRFP之间,MRF内部通道,兼容H.248/Megaco,支持MRFC对MRFP提供的资源的控制。 Mn:MGCF与IMS-MGW之间,采用H.248,用于控制用户平面资源。 Mi:CSCF与BGCF之间,基于SIP协议,是IMS域内部与CS域互通的通道。 Mj:BGCF与MGCF之间,基于SIP协议,是IMS内部与CS域互通的通道。 Sh:HSS与AS(SIP AS及OSA AS)之间,基于Diameter协议,完成数据处理、订购通知。 Si:HSS与CAMEL SE之间,采用MAP协议,传输CAMEL订购关系信息。 6.IMS的主要协议 主要是SIP,SDP,H.248/Megaco,Diameter。 1)IMS对SIP的扩展 SIP压缩:SigComp 安全 CSCF路由 网络发起的呼叫释放 RFC3455定义了专用于3GPP IMS的SIP头 P-Charging-Vector P-Charging-Function-Address P-Visited-Network-ID P-Access-Network-Info P-Associated-URI 2)Diameter协议 Diameter是IETF开发的用于认证、授权和计费(AAA)的协议,基于远程拨入用户认证服务(RADIUS)协议构建而成。 Diameter基本协议基于RFC3588,客户/服务器协议,传递Diameter数据单元、协商能力集、处理错误并提供可扩展性,基于TCP或SCTP进行传输。 Diameter应用:定义了特定应用的功能和数据单元,有Diameter移动IP应用和Diameter SIP应用,应用于IMS系统。 3)Diameter SIP应用 定义了一个被SIP服务器用来实现对不同SIP资源进行授权的应用。 应用的接口: Cx:I/S-CSCF与HSS之间 Dx:SLF与I-CSCF之间 Sh:HSS与SIP AS及OSA AS之间 Dh:SLF与AS之间 命令: 7.IMS标识 1)IMS用户标识:私有用户身份和公共用户身份 a)私有用户身份: 由归属网络运营商定义的具有唯一性的全球身份,可用于在归属网络中从网络的角度唯一地标识用户。私有用户身份并不是标识用户本身,而是标识了用户与运营商的订购/签约关系,主要用于注册过程中对用户进行认证,也可以用于计费和管理目的。存储在ISIM (身份模块) 应用中,采用NAI (网络接入标识符) 的形式:form_user@realm。 b)公共用户身份: IMS网络中的用户身份,用于请求与其他用户进行通信时使用的身份,可以被公布到号码簿、主页等上,ISIM中至少要存储一个公共用户身份。通过注册过程在网络中注册,网络不对公共用户身份进行认证,公共用户身份的两种形式:SIP URI sip:joe.doer@rims.example.com 、 tel URL tel:+358 50 1234567。 公共用户身份与私有用户身份之间的关系: c)公共业务身份: 公共业务身份,对AS提供的业务进行标识,由用户根据需要在AS中创建,使用之前不需要进行注册。采用SIP URI形式,如标识消息列表业务的公共业务身份:sip:messagelist_joe@ims.example.com d)网络实体标识: 处理SIP路由的网络节点通过SIP URI标识,例子: sip:finland.scscf@ims.example.com。 2)IMS身份模块——ISIM ISIM是位于UICC上的应用,用于存储由运营商提供的IMS专用数据。 8.IMS的业务控制机制 1)IMS 用户配置 用户与运营商确定订购关系时,由运营商给用户分配IMS用户配置,永久存储在HSS中。 2)初始过滤规则 初始过滤规则用来表示业务触发信息,描述了S-CSCF何时将到来的SIP消息进一步路由到一个特定的应用服务器。 初始过滤规则的创建: 初始过滤规则在用户获得IMS订购关系时创建 创建初始过滤规则需要考虑的问题:触发点是什么?当触发点被匹配时,正确的AS是什么?各初始过滤规则的优先级是什么?如果应用服务器没有应答,应该怎么做? 初始过滤规则的结构: 3)IMS业务提供 IMS本身不是业务,而是基于SIP的控制体系,IMS业务触发由S-CSCF完成。IMS为业务的提供提供了必要的方法,包含3个步骤: 定义可能的业务或业务集 在用户注册时,以初始过滤规则的形式创建用户特定的业务配置数据 根据业务配置数据中的初始过滤规则将到达S-CSCF的SIP请求转发给AS 4)AS的选择与AS的行为 AS的选择(业务控制):S-CSCF下载初始过滤规则,注册阶段完成;S-CSCF进行业务控制,选择AS;存在多个过滤规则时,需要进行多次业务控制。 AS的可能行为:UAC、UAS、Proxy Server、Redirect Server、B2BUA。 9.IMS的典型流程 1)P-CSCF的发现 a)使用DHCP和DNS发现P-CSCF:IP-CAN作为DHCP中继代理,通过DHCP机制给出P-CSCF的域名或IP地址 b)使用PDP上下文激活信令发现P-CSCF 2)用户注册/注销 注册:特点是归属域注册,注册前后及注册期间的信息存储: a)用户初始注册: b)用户刷新注册/注销: c)隐性注册 通过一次注册过程注册多个公共用户身份的机制。需先在HSS中定义隐性注册集,通过订阅/通知机制,UE可以获得隐性注册的公共用户身份。 d)多个UE共享单个公共用户身份进行通信 前提:IMS支持多个UE注册相同的公共用户身份 多个UE共享单个公共用户身份的方法: 基于用户定义的优先级 基于SIP的Forking机制(顺序、并行) 3)会话建立 漫游移动发起端MO: 归属移动发起端MO: 漫游移动终止端MT: 归属移动终止端MT: 4)会话建立(S-CSCF到S-CSCF) a)会话的发起和终止由不同的网络运营商来服务 b)会话的发起和终止由相同网络运营商来服务 c)IMS会话建立 d)PSTN->IMS e)IMS-> PSTN 附:IMS典型网络互通架构 网络类型1:演进ISP 提供电话、VoD和标准ISP业务,通过热点也完成对无线的接入,所有的业务最终都由IMS进行控制。 网络类型2:传统电信运行商 其中一部分是软交换与PSTN互通,其中的应用服务器可以被其他网络结构使用。 网络类型3:3GPP移动网络 主要是接入方式的不同,GERAN或UTRAN。 网络类型4:WIMAX 这里没有IMS域,它是由一些SIP服务器等完成相应功能的。 以下是摘自http://blog.ixpub.net/html/96/12690296-146875.html的一篇关于IMS和软交换的对比,写的不错: 一、业务提供方式对比 1.软交换业务架构 由于软交换并未完全实现业务与控制的分离,因此传统的基本业务和一些补充业务仍然是通过软交换来实现(方式一)。但对于更多的增值业务,软交换还提供了多种方式进行业务提供,如图1所示。 图1软义换多方式业务提供示意图 方式二:智能网业务方式。业务逻辑在SCP中驻留和运行,软交换设备实现业务交换功能(SSP)触发智能业务到智能网SCP,与SCP配合实现智能网提供的业务。 方式三:SIP应用服务器方式。由运营商提供SIP应用服务器,其中的业务逻辑可直接访问和控制软交换设备提供的网络能力,通常实现运营商的自营业务。 方式四:第三方应用服务器方式。由运营商或者第三方服务提供商提供Parlay应用服务器,而运营商提供业务能力网关,Parlay应用服务器中的业务逻辑通过业务能力网关间接访问和控制软交换设备提供的网络能力,多用于运营商与第三方合作的业务,也可用于运营商自营业务。 2.IMS业务架构 在IMS系统中,实现了业务与控制的完全分离,所有的业务都是通过应用服务器来提供的,业务逻辑驻留于应用服务器中,用户数据统一存储在HSS,如图2所示。图中的应用服务器包括三类:SIP应用服务器,OSA应用服务器及IM-SSF。SIP应用服务器(SIP AS)用于实现基于SIP的增值应用;SIP/OSA应用服务器(SIP/OSA AS)通过OSA业务能力服务器(OSA SCS)与IMS核心网进行交互;而IM-SSF用于支持IMS用户使用现有智能网的能力。目前IM-SSF支持使用CAMEL的业务能力,为考虑固定网络的智能网业务,IM-SSF的功能可以扩展到对INAP的支持。 图2IMS业务架构 在这一架构中,IMS的核心网元S-CSCF只通过ISC接口与应用平台交互,从而使得业务接口和触发方式得以标准化,进而获得更好的开放性。对三种应用服务器的具体应用如下: (1)基于SIP的应用服务器(SIP AS) SIP应用服务器和S-CSCF之间直接利用SIP及其扩展的呼叫信令协议,因此不需要进行呼叫信令协议之间的转换工作。另外由于基于SIP可以非常方便的实现语音、数据以及视频等多媒体类的会话,因此基于SIP的应用服务器可以高效率的提供各种新型的融合业务。 (2)基于OSA的应用服务器(OSA SCS) 在对第三方应用方面,IMS采用Parlay/OSA API。在Parlay/OSA API中,提供给应用的网络功能实体被定义为若干业务能力特征(SCF)的集合,由业务能力服务器(SCS)支持,这些SCF为应用开发提供了必要的网络接入功能。第三方应用服务器通过Parlay/OSA API和SCS相连接,而OSA SCS则在第三方应用服务器和S-CSCF之间负责API和ISC之间的映射。 (3)基于智能网的业务服务器(IM-SSF) 现有的移动智能网以及固定智能网都已经提供了丰富的智能网业务,并且有着庞大的用户群,为了兼容已有的网络资源,实现技术和服务提供的平滑过渡,IMS需要接入现有的智能网,并且还可以实现将现有智能网的业务延伸到IMS用户。目前通过IM-SSF接入现有移动智能网CAMEL已经完备。从CAMEL角度来看,IM SSF是智能网的服务交换节点SSP,相当于CAMEL中业务交换功能SSF和呼叫控制功能CCF。IM SSF在S-CSCF和CAMEL之间实现SIP消息和CAP信令的映射。为支持固定智能网,IM-SSF需要支持INAP协议,相关的研究还正在进行中。 从上面的分析可以看出,软交换和IMS都可以实现智能网提供业务和应用服务器提供业务,并且都可以开放接口给第三方使用,供第三方开发业务。但是由于软交换与不同的业务平台之间采用的接口不同,而IMS则统一采用ISC接口,另外对于IMS,由于3GPP,OMA等组织形成了大量的基于应用服务器的业务规范,并可以作为业务引擎,供其他的业务调用。因此IMS在业务提供的方便性、灵活性以及扩展性等方面都显示出了优势。 二、业务触发机制对比 1.软交换触发机制 软交换触发机制有两类: (1)基于智能网的触发机制 软交换可作为SSP,根据用户的主叫属性以及被叫属性(DP点触发)完成业务触发,在SCP或者应用服务器的智能业务逻辑控制下实现智能业务。 (2)基于应用服务器的触发机制 根据用户的profile或呼叫相关信息触发到应用服务器。应用服务器提供标准接口与前端服务器连接,接受来自前端服务器的业务触发信息和交互业务处理过程的信息。业务触发信息可能包括鉴权信息(如主叫号码、账号、密码)、发起方主机IP地址、被叫号码、业务标识、业务配置信息。 2.IMS触发机制 IMS的业务触发机制是基于iFC(Initial Filter Criteria)实现的。业务的触发在S-CSCF中完成,业务数据在注册阶段从HSS中下载到S-CSCF中,包括Initial Filter Criteria。在收到用户会话请求后,S-CSCF首先检查Initial Filter Criteria中的触发标准是否满足,然后再进行到用户的路由和呼叫控制。如果满足则通过ISC接口的SIP消息,将业务触发到对应的业务平台。业务平台然后根据业务的既定逻辑流程,通过SIP消息对S-CSCF中的业务进行后续控制。 从上述分析可以看出,软交换的业务触发机制表现为多样性,既有基于传统智能网模式的又有基于用户业务数据的。而对于基于应用服务器的业务,软交换与IMS的业务触发机制有很多的相似之处,但由于软交换在标准化方面的局限性,造成了业务触发方面无法规范化,也就决定了其在实际应用中只能由设备供应商自行提供解决方案。相比较,IMS就提供了比较完善的标准化,从而使得业务实现和互通更加规范统一。 三、业务实现流程对比 尽管基于软交换和基于IMS都可以提供宽带多媒体类的业务,但由于软交换在提供宽带多媒体业务方面缺乏相关的规范,因此现有的各种业务多是厂家基于自己的平台进行开发的,并对协议进行了私有扩展,业务之间的互通性较差。而在IMS网络架构下,由于IMS的业务规范好,各种部件的标准化程度高,因此业务之间的互通性好。下面以目前最常用的即时消息(IM)和状态呈现(Presence)两种业务的流程说明其区别: 1.基于软交换的业务流程示例 以国内某主流软交换提供厂商为例,在其基于软交换实现宽带多媒体业务时,用户与业务应用服务器采用HTTP和SIP两种消息的进行交互。对于数据业务采用HTTP协议,用户可使用Web客户端,最大程度实现业务的可达性,另外可通过HTTPS,实现安全的传输机制。对于媒体业务采用SIP,完成与呼叫相关的业务处理。为完成用户与应用服务器之间消息的实时传送,该厂商对HTTP协议进行了修改,实现用户Web浏览器与应用服务器之间建立一条持续的HTTP连接(Persistent HTTP connection)。采用这种方式实现即时消息和状态通知的流程如图3、4所示: 图3基于软交换的业务流程示意:即时消息 图4基于软交换的业务流程示意:状态通知 2.基于IMS的业务流程示例 对于基于IMS提供的业务,由于目前业务的标准化程度高,特别是IMSinOMA Enabler规范的实施,更好的协调了OMA与3GPP/3GPP2的IMS之间的合作关系,目前已经发布了Presence,PoC,XDMS等一系列符合IMSinOMA框架的规范,成为业界遵循的标准。例如对于即时消息,在SIP消息中定义了Message消息可以直接用于即时消息的传递,具体流程如图5所示: 图5基于IMS的业务流程示意:即时消息(Page-Mode) 对于Presence业务,则规定了状态订阅使用SIP的SUBSCRIBE消息,状态更新使用SIP的PUBLISH消息,状态更新通知使用SIP的NOTIFY消息。如果用户的状态有更新,则通过PUBLISH消息更新自己的状态信息到Presence服务器;用户希望知道好友的状态,需要首先到Presence服务器订阅好友的状态,Presence服务器对用户进行权限检查,如果好友允许该用户知道自己的状态信息,好友的状态变化后,Presence服务器再把状态变化信息通知给用户。业务流程如下面的图6、7所示: 图6基于IMS的业务流程示意:发布状态(Publish) 图7基于IMS的业务流程示意:订阅/通知状态变化(Subscriber/Notify) 因此从业务流程上可以看出,尽管基于软交换与基于IMS都使用了SIP协议,但在使用的信令消息上有一定的区别。另外在具体的信令消息参数上也有所不同 本文转自gnuhpc博客园博客,原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/12/11/2813494.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发学习笔记:浅谈ListView

LisView列表视图是Android开发中非常常用的一种视图组件,它是以垂直列表的方式列出需要显示的列表项。 创建ListView可以用ListView组件,也可以继承ListActivity。在使用过程中最重要的是如何设置ListView显示的内容,也就是怎样设置Adapter。Adapter类型可以分为三种:ArrayAdapter,SimpleCursorAdapter和SimpleAdapter。下面介绍这三种Adapter是如何添加列表视图内容的: 一.ArrayAdapter ArrayAdapter是这三种Adapter最简单的,只能展示一行文字,使用它来添加ListView显示的内容的步骤如下: 1.创建ArrayAdapter 2.调用ListActivity的setListAdapter( )方法来设置显示的内容 下面是具体的例子: MainActivity.java packagecom.android.listview1.avtivity; importandroid.app.ListActivity; importandroid.os.Bundle; importandroid.widget.ArrayAdapter; publicclassMainActivityextendsListActivity{ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //列表项的数据 String[]strs={"Android","IOS","Mango","MeeGo","Symbian"}; //this,布局文件 //android.R.layout.simple_list_item_1,系统定义的布局文件 //strs,数据来源 ArrayAdapter<String>adapter=newArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strs); //为ListView设置适配器 setListAdapter(adapter); } } 效果图: 二.SimpleCursorAdapter SimpleCursorAdapter从游标得到的数据进行列表显示,并可以把指定的列映射到对应的TextView中。下面是使用它来显示Android中的联系人姓名的步骤: 1.调用getContentResolver( )方法返回ContentResolver( )对象,通过该对象查询得到Cursor对象 2.创建SimpleCursorAdapter对象 3.调用ListActivity的setListAdapter( )方法显示列表项 下面是具体的例子: MainActivity.java packagecom.android.listview2.activity; importandroid.app.ListActivity; importandroid.database.Cursor; importandroid.os.Bundle; importandroid.provider.Contacts.People; importandroid.widget.ListAdapter; importandroid.widget.SimpleCursorAdapter; publicclassMainActivityextendsListActivity{ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //获得一个指向系统通讯录数据库的Cursor对象获得数据来源 Cursorcur=getContentResolver().query(People.CONTENT_URI,null,null,null,null); startManagingCursor(cur); //实例化列表适配器 ListAdapteradapter=newSimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cur, newString[]{People.NAME},//含数据库的列的String型数组 newint[]{android.R.id.text1});//包含布局文件中对应组件id的int型数组 //为ListView设置适配器 setListAdapter(adapter); } } 在AndroidManifest.xml文件中添加17行的声明 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.listview2.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> <uses-permissionandroid:name="android.permission.READ_CONTACTS"></uses-permission> </manifest> 效果图: 三.SimpleAdapter SimpleAdapter可以定义各种不同的布局,可以添加ImageView(图片),Button(按钮),CheckBox(复选框)等。 下面是添加图片的例子: MainActivity.java packagecom.android.listview3.activity; importjava.util.ArrayList; importjava.util.HashMap; importjava.util.List; importjava.util.Map; importandroid.app.ListActivity; importandroid.os.Bundle; importandroid.widget.SimpleAdapter; publicclassMainActivityextendsListActivity{ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); SimpleAdapteradapter=newSimpleAdapter(this,getData(), R.layout.main,//设置界面布局 newString[]{"title","img"},//列表上的文字信息,图片信息 newint[]{R.id.title,R.id.img});//引用文字资源,图片资源 //布局文件的各组件分别映射到HashMap的各元素上,完成适配 //为ListView设置适配器 setListAdapter(adapter); } privateList<Map<String,Object>>getData(){ //map.put(参数名字,参数值) List<Map<String,Object>>list=newArrayList<Map<String,Object>>(); Map<String,Object>map=newHashMap<String,Object>(); map.put("title","摩托罗拉"); map.put("img",R.drawable.pic1); list.add(map); map=newHashMap<String,Object>(); map.put("title","诺基亚"); map.put("img",R.drawable.pic2); list.add(map); map=newHashMap<String,Object>(); map.put("title","三星"); map.put("img",R.drawable.pic3); list.add(map); returnlist; } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5px" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="20px" /> </LinearLayout> 效果图: 注:上面的程序很多地方用到泛型编程,有关Java泛型编程的资料请看: http://liangruijun.blog.51cto.com/3061169/636850 http://www.cnblogs.com/panjun-Donet/archive/2008/09/27/1300609.html 本文转自 lingdududu 51CTO博客,原文链接: http://blog.51cto.com/liangruijun/646049

优秀的个人博客,低调大师

Android开发学习笔记:浅谈WebView

WebView(网络视图)能加载显示网页,可以将其视为一个浏览器。它使用了WebKit渲染引擎加载显示网页,实现WebView有以下两种不同的方法: 第一种方法的步骤: 1.在要Activity中实例化WebView组件:WebView webView = new WebView(this); 2.调用WebView的loadUrl()方法,设置WevView要显示的网页: 互联网用:webView.loadUrl("http://www.google.com"); 本地文件用:webView.loadUrl("file:///android_asset/XX.html");本地文件存放在:assets文件中 3.调用Activity的setContentView()方法来显示网页视图 4.用WebView点链接看了很多页以后为了让WebView支持回退功能,需要覆盖覆盖Activity类的onKeyDown()方法,如果不做任何处理,点击系统回退剪键,整个浏览器会调用finish()而结束自身,而不是回退到上一页面 5.需要在AndroidManifest.xml文件中添加权限,否则会出现Web page not available错误。<uses-permissionandroid:name="android.permission.INTERNET"/> 下面是具体例子: MainActivity.java packagecom.android.webview.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.KeyEvent; importandroid.webkit.WebView; publicclassMainActivityextendsActivity{ privateWebViewwebview; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); //实例化WebView对象 webview=newWebView(this); //设置WebView属性,能够执行Javascript脚本 webview.getSettings().setJavaScriptEnabled(true); //加载需要显示的网页 webview.loadUrl("http://www.51cto.com/"); //设置Web视图 setContentView(webview); } @Override //设置回退 //覆盖Activity类的onKeyDown(intkeyCoder,KeyEventevent)方法 publicbooleanonKeyDown(intkeyCode,KeyEventevent){ if((keyCode==KeyEvent.KEYCODE_BACK)&&webview.canGoBack()){ webview.goBack();//goBack()表示返回WebView的上一页面 returntrue; } returnfalse; } 在AndroidManifest.xml文件中的17行添加权限 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.webview.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest> 效果图: 第二种方法的步骤: 1、在布局文件中声明WebView 2、在Activity中实例化WebView 3、调用WebView的loadUrl( )方法,设置WevView要显示的网页 4、为了让WebView能够响应超链接功能,调用setWebViewClient( )方法,设置 WebView视图 5、用WebView点链接看了很多页以后为了让WebView支持回退功能,需要覆盖覆盖Activity类的onKeyDown()方法,如果不做任何处理,点击系统回退剪键,整个浏览器会调用finish()而结束自身,而不是回退到上一页面 6、需要在AndroidManifest.xml文件中添加权限,否则出现Web page not available错误。 <uses-permission android:name="android.permission.INTERNET"/> 下面是具体的例子: MainActivity.java packagecom.android.webview.activity; importandroid.app.Activity; importandroid.os.Bundle; importandroid.view.KeyEvent; importandroid.webkit.WebView; importandroid.webkit.WebViewClient; publicclassMainActivityextendsActivity{ privateWebViewwebview; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); webview=(WebView)findViewById(R.id.webview); //设置WebView属性,能够执行Javascript脚本 webview.getSettings().setJavaScriptEnabled(true); //加载需要显示的网页 webview.loadUrl("http://www.51cto.com/"); //设置Web视图 webview.setWebViewClient(newHelloWebViewClient()); } @Override //设置回退 //覆盖Activity类的onKeyDown(intkeyCoder,KeyEventevent)方法 publicbooleanonKeyDown(intkeyCode,KeyEventevent){ if((keyCode==KeyEvent.KEYCODE_BACK)&&webview.canGoBack()){ webview.goBack();//goBack()表示返回WebView的上一页面 returntrue; } returnfalse; } //Web视图 privateclassHelloWebViewClientextendsWebViewClient{ @Override publicbooleanshouldOverrideUrlLoading(WebViewview,Stringurl){ view.loadUrl(url); returntrue; } } } main.xml <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <WebView android:id="@+id/webview" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> 在AndroidManifest.xml文件中的17行添加权限 <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="com.android.webview.activity" android:versionCode="1" android:versionName="1.0"> <uses-sdkandroid:minSdkVersion="10"/> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".MainActivity" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> <uses-permissionandroid:name="android.permission.INTERNET"/> </manifest> 效果图: 本文转自 lingdududu 51CTO博客,原文链接:http://blog.51cto.com/liangruijun/647456

优秀的个人博客,低调大师

python学习笔记文件操作(六)

1、文件操作流程: 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 如下文件: 1 2 3 4 5 6 2017 - 03 - 24 11 : 25 : 06 : 349 - info:[debug][AndroidBootstrap]Sendingcommandtoandroid:{ "cmd" : "shutdown" } 2017 - 03 - 24 11 : 25 : 06 : 355 - info:[debug][AndroidBootstrap]Receivedcommandresult from bootstrap 2017 - 03 - 24 11 : 25 : 06 : 356 - info:[debug][UiAutomator]ShuttingdownUiAutomator 2017 - 03 - 24 11 : 25 : 06 : 357 - info:[debug][UiAutomator]Movingtostate 'stopping' 2017 - 03 - 24 11 : 25 : 06 : 360 - info:[AndroidBootstrap][BOOTSTRAPLOG][debug]Gotdata from client:{ "cmd" : "shutdown" } 2017 - 03 - 24 11 : 25 : 06 : 361 - info:[AndroidBootstrap][BOOTSTRAPLOG][debug]Gotcommandof type SHUTDOWN 操作流程: 1 2 3 f = open ( 'log.txt' , 'r' ) print (f.read()) f.close() 注意: 在win系统中log文件是utf8保存的,打开文件时open函数是通过操作系统打开的文件,而win操作系统默认的是gbk编码,所以直接打开会乱码,需要f=open('hello',encoding='utf8'),hello文件如果是gbk保存的,则直接打开即可。 2、文件打开模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #======================================================================== # #CharacterMeaning # #------------------------------------------------------------------------ # #'r'openforreading(default) # #'w'openforwriting,truncatingthefilefirst # #'x'createanewfileandopenitforwriting # #'a'openforwriting,appendingtotheendofthefileifitexists # #'b'binarymode # #'t'textmode(default) # #'+'openadiskfileforupdating(readingandwriting) # #'U'universalnewlinemode(deprecated) # #======================================================================== 3、文件操作方法 获取文件内容 1 2 3 4 f = open ( 'log.txt' , 'r' ) data = f.read() print (data) f.close() 输出: 2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdown"} 2017-03-24 11:25:06:355 - info: [debug] [AndroidBootstrap] Received command result from bootstrap 2017-03-24 11:25:06:356 - info: [debug] [UiAutomator] Shutting down UiAutomator 2017-03-24 11:25:06:357 - info: [debug] [UiAutomator] Moving to state 'stopping' 2017-03-24 11:25:06:360 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"shutdown"} 2017-03-24 11:25:06:361 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type SHUTDOWN =========================================================================================== 1 2 3 4 f= open ( 'log.txt' , 'r' ) data1=f. read (10) #读取10个字符。(在这里汉字也只占一个单位) print(data1) f.close() 输出: 2017-03-24 readline和readlines =========================================================================================== 1 2 3 f = open ( 'log.txt' , 'r' ) print (f.readlines()) #返回的是一个列表,注意换行符 f.close() 输出: ['2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdown"}\n', '2017-03-24 11:25:06:355 - info: [debug] [AndroidBootstrap] Received command result from bootstrap\n', '2017-03-24 11:25:06:356 - info: [debug] [UiAutomator] Shutting down UiAutomator\n', "2017-03-24 11:25:06:357 - info: [debug] [UiAutomator] Moving to state 'stopping'\n", '2017-03-24 11:25:06:360 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"shutdown"}\n', '2017-03-24 11:25:06:361 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type SHUTDOWN'] =========================================================================================== 1 2 3 4 5 f = open ( 'log.txt' , 'r' ) print (f.readline()) #逐行读取 print (f.readline()) print (f.readline(),f.readline(),f.readline()) #逐行读取,每行末尾换行符 f.close() 输出:(注意每行末尾的换行符) 2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdown"} 2017-03-24 11:25:06:355 - info: [debug] [AndroidBootstrap] Received command result from bootstrap 2017-03-24 11:25:06:356 - info: [debug] [UiAutomator] Shutting down UiAutomator 2017-03-24 11:25:06:357 - info: [debug] [UiAutomator] Moving to state 'stopping' 2017-03-24 11:25:06:360 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"shutdown"} =========================================================================================== 1 2 3 4 f = open ( 'log.txt' , 'r' ) for line in f.readlines(): print (line.strip()) f.close() 输出: 2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdown"} 2017-03-24 11:25:06:355 - info: [debug] [AndroidBootstrap] Received command result from bootstrap 2017-03-24 11:25:06:356 - info: [debug] [UiAutomator] Shutting down UiAutomator 2017-03-24 11:25:06:357 - info: [debug] [UiAutomator] Moving to state 'stopping' 2017-03-24 11:25:06:360 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"shutdown"} 2017-03-24 11:25:06:361 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type SHUTDOWN =========================================================================================== 1 2 3 4 5 f = open ( 'log.txt' , 'r' ) print (f) for i in f: print (i.strip()) f.close() 输出: <_io.TextIOWrapper name='log.txt' mode='r' encoding='cp936'> 2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdown"} 2017-03-24 11:25:06:355 - info: [debug] [AndroidBootstrap] Received command result from bootstrap 2017-03-24 11:25:06:356 - info: [debug] [UiAutomator] Shutting down UiAutomator 2017-03-24 11:25:06:357 - info: [debug] [UiAutomator] Moving to state 'stopping' 2017-03-24 11:25:06:360 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"shutdown"} 2017-03-24 11:25:06:361 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type SHUTDOWN =========================================================================================== 1 2 3 4 5 6 7 8 n = 0 f = open ( 'log.txt' , 'r' ) for i in f: if n = = 3 : i = ' '.join([i.strip(),' this is line 4 ']) print (i.strip()) n + = 1 f.close() 输出: 2017-03-24 11:25:06:349 - info: [debug] [AndroidBootstrap] Sending command to android: {"cmd":"shutdown"} 2017-03-24 11:25:06:355 - info: [debug] [AndroidBootstrap] Received command result from bootstrap 2017-03-24 11:25:06:356 - info: [debug] [UiAutomator] Shutting down UiAutomator 2017-03-24 11:25:06:357 - info: [debug] [UiAutomator] Moving to state 'stopping' this is line 4 2017-03-24 11:25:06:360 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"shutdown"} 2017-03-24 11:25:06:361 - info: [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type SHUTDOWN =========================================================================================== tell和seek 1 2 3 4 5 6 f = open ( 'log.txt' , 'r' ) print (f.read( 25 )) print (f.tell()) #取出光标所在位置 print (f.seek( 0 )) #移动光标到指定的位置 print (f.read( 50 )) f.close() 输出: 2017-03-24 11:25:06:349 - 25 0 2017-03-24 11:25:06:349 - info: [debug] [AndroidBo 注意:read后不管是中文字符还是英文字符,都统一算一个单位,read(6),此刻就读了6个中文字符;而seek和tell对于英文字符就是占一个,中文字符占三个,区分与read()的不同. =========================================================================================== flush:同步把数据从缓存移动到磁盘上去 1 2 3 4 5 6 7 8 9 10 11 12 #进度条实例 import sys,time for i in range ( 30 ): sys.stdout.write( "*" ) sys.stdout.flush() time.sleep( 0.1 ) #print的flush import sys,time for i in range ( 30 ): print ( '*' ,end = '',flush = True ) time.sleep( 0.1 ) =========================================================================================== 其他扩展: #truncate():截断数据(不能在r模式下)#在w模式下:先清空,再写,再截断#在a模式下:直接将指定位置后的内容截断 # r+:光标默认在0位置开始写,从0开始覆盖数据# w+:先清空,再写读# a+:光标默认在最后位置 =========================================================================================== with: 为了避免打开文件后忘记关闭,可以通过管理上下文,即: 1 2 with open ( 'log.txt' , 'r' )asf: print (f.readline()) 在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。 1 2 3 4 #with同时管理多个文件对象 with open ( 'log1' , 'r' )asf_read, open ( 'log2' , 'w' )asf_write: for line in f_read: f_write.write(line) 本文转自cqtesting51CTO博客,原文链接:http://blog.51cto.com/cqtesting/1959698 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

ELK日志分析集群部署笔记

ELK是什么?E=ElasticSearch ,一款基于的Lucene的分布式搜索引擎,我们熟悉的github,就是由ElastiSearch提供的搜索,据传已经有10TB+的数据量。L=LogStash , 一款分布式日志收集系统,支持多输入源,并内置一些过滤操作,支持多输入元K=Kibana , 一款配合ElasticSearch的web可视化界面,内置非常各种查询,聚合操作,并拥有漂亮的图形化展示功能为什么要用ELK?在实际应用中,我们的日志是非常重要的,它通常会记录一些比较重要的信息,如应用程序的log记录的error,warn级别的log,通常在量小的情况下,我们可以直接vi+awk+sed+grep定位原因,在量大的时候,这种方式就捉襟见肘了,而且我们还要各种聚合,或者基于异常多个关键词的搜索,并有且,或,交,并,差,补,排序等一些操作,而且相应速度必须给力,如果线上环境出了故障,能够立刻准确定位,ELK就是高手,在百万大军中取上将首级,犹如探囊取物,所以这时候ELK就非常适合了,当然除此之外,ELK也经常在运维工作中大放光彩,在应用级别的实时监控,非常适合一些重要核心服务的预警。ELK如何安装搭建?环境要求:Linux系统:Centos6.5 [root@ELK-Server ~]# cat /etc/redhat-release CentOS release 6.5 (Final) Java版本:JDK1.8 [root@ELK-Server ~]# java -version openjdk version "1.8.0_51" OpenJDK Runtime Environment (build 1.8.0_51-b16) OpenJDK 64-Bit Server VM (build 25.51-b03, mixed mode) ELK均为最新版本:(1)ElasticSearch1.7.2 基于Lucene4.10.4的版本(2)Logstash1.5.4(3)Kibana4.1.2集群拓扑:ElasticSearch 3台机器:集群名:search机器名+es节点名 => ip地址h1 => 192.168.1.120h2 => 192.168.1.121h3 => 192.168.1.122Logstash 192.168.1.120Kibana 192.168.1.120下载:elasticsearch: wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.3.tar.gzlogstash : wget https://download.elastic.co/logstash/logstash/logstash-1.5.4.tar.gzkibana : wget https://download.elastic.co/kibana/kibana/kibana-4.1.2-linux-x64.tar.gz 一: 安装elasticsearch集群:(1)解压到指定目录(2)配置elasticsearch.yml里面,集群名字和节点名字,如果不配置默认集群名为elasticsearch,节点名随机生成一个(3) 在线安装head和bigdisk插件直接在elasticsearch的根目录下,分别输入:bin/plugin --install mobz/elasticsearch-head 安装headbin/plugin --install lukas-vlcek/bigdesk 安装bigdesk(4)scp分发安装完毕后的elasticsearch(5)依次启动各个机器上的elasticsearch #/usr/local/elasticsearch/bin/elasticsearch 如果启动时遇到以下报错信息: [root@localhost elasticsearch]# ./bin/elasticsearch {1.7.3}: Initialization Failed ... - RuntimeException[Java version: 1.7.0_45 suffers from critical bug https://bugs.openjdk.java.net/browse/JDK-8024830 which can cause data corruption. Please upgrade the JVM, see http://www.elastic.co/guide/en/elasticsearch/reference/current/_installation.html for current recommendations. If you absolutely cannot upgrade, please add -XX:-UseSuperWord to the JVM_OPTS environment variable. Upgrading is preferred, this workaround will result in degraded performance.] 解决方法: # yum -y install java-1.8.0* # yum remove java 查看下java版本号:是否是1.8.0(因为最新版elasticsearch需要最新的java支持) [root@localhost elasticsearch]# java -version openjdk version "1.8.0_71" OpenJDK Runtime Environment (build 1.8.0_71-b15) OpenJDK 64-Bit Server VM (build 25.71-b15, mixed mode) 问题2: [root@localhost elasticsearch]# ./bin/elasticsearch Can't start up: not enough memory 解决方法也是重启安装下java 就行了 (6)head显示如下: (7)bigdisk显示如下:二:安装logstash(1)解压到指定目录(2)在根木下新建一个conf目录,在里面新建一个配置文件first.conf (3)启动logstash执行命令: bin/logstash -f conf/first.conf三:安装kibana(1)解压到指定目录(2)在根目录执行bin/kibana直接启动(3)访问http://192.168.1.120:5601/ 配置一个ElasticSearch索引(4)在logstach里面添加数据(5)查看图表:刚新加的数据四: 至此,ELK组件已经安装完毕,带图形化界面的简单日志查询分析系统就搞定了本篇只是一个简单的入门例子,如需深入可以研究elastic的官网文档:https://www.elastic.co/guide/index.html 本文转自yangxuncai110 51CTO博客,原文链接:http://blog.51cto.com/zlyang/1737622,如需转载请自行联系原作者

优秀的个人博客,低调大师

学习笔记-4.1用户管理命令

复习: /etc/passwd: 用户名:密码:UID:GID:注释:家目录:默认shell /etc/group: 组名:密码:GID:以此组为其附加组的用户列表 /etc/shadow: 用户名:密码:最近一次修改密码的时间:最短使用期限,最长使用期限: 警告时间:非活动时间:过期时间 useradd [options] USERNAME useradd -u 1000 user1 -u 指定其UID -g GID(基本组) 指定组一定要存在 -G GID,... (附加组) -c "COMMENT"指定注释信息 -d /path/to/directory指定家目录,默认是home下 -s SHELL useradd -s /sbin/nologin user5 su - user5 -m -k 强制复制bash配置文件到家目录 -M 创建用户,不创建家目录 -r 添加一个系统用户 /etc/login.defs /etc/shells:指定了当前系统可用的安全shell 环境变量:PATH HISTSIZE SHELL userdel: userdel [option] USERNAME 不指定选项,不会删除家目录 -r 删除用户的同时,同时删除用户的家目录 id :查看用户的账号属性信息 -u -g -G -n 上面都可用和-n合用 finger USERNAME(user1)查看用户账号相关信息 修改用户账号属性: usermod -u usermod -u 2002 user2 -g (基本组,事先存在的组) -G 附加组,已有附件组,修改了后原有附件组就没有了 -a -G:追加附件组(-a与-G联合使用) -c 注释 -d -m 为用户指定新的家目录,并移动此前新建的文件到新的家目录 -s shell -l 修改用户名 -L:锁定账号 -U:解锁 chsh:修改用户的默认shell chfn:修改用户的注释信息(fn是finger的缩写) 密码管理: passwd [USERNAME] --stdin -l 锁定账号 -u 解锁 -d 删除用户密码(禁止登录) echo "redhat" | passwd --stdin user3 pwch(passwdcheck)检查用户账号完整性 组管理: 创建组:groupadd groupadd -g GID -r 添加为系统组 groupmod -g GID -n GRPNAME groupdel gpasswd:为组设定密码 newgrp 临时切换基本组 exit退出 练习: 1 创建一个用户mandriva ,其ID号2002,基本组为distro(组ID3003),附加组 为linux: # groupadd -g 3003 distro # groupadd linux # useradd -u 2002 -g distro -G linux mandriva 2 创建一个用户fedora,其全名为Fedora Community,默认shell为tcsh # useradd -c "Fedora Community" -s /bin/tcsh/ fedora 3 修改mandriva的ID号为4004,基本组为linux,附加组为distro和Fedora # usermod -u 4004 -g linux -G distro,fedora mandriva 4 给Fedora加密码,并设定其密码最短使用期限为2天,最长为50天 # passwd -n 2 -x 50 fedora 5 将madriva的默认shell改为/bin/bash # usermod -s /bin/bash mandrira 6 添加系统用户hbase,且不允许其登陆系统 #useradd -r -s /sbin/noglogin hbase change(改变密码过期信息的) -d 最近一次的修改时间 -E 过期时间 -r: 非活动时间 -m 最短使用时间 -M 最长使用时间 -w:警告时间 本文转自飞行萌51CTO博客,原文链接: http://blog.51cto.com/8527508/1939822,如需转载请自行联系原作者

优秀的个人博客,低调大师

openstack学习笔记七 swift安装

项目--对象存储--容器 在容器里你创建的即使是一个文件夹,那么体现在硬盘里,也是一个文件,也就是对象object 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@h1~(keystone_admin)] #openstackservicelist +----------------------------------+------------+--------------+ |ID|Name|Type| +----------------------------------+------------+--------------+ |30c62c3c0797462a8bd4ff059a71296e|swift|object-store| [root@h1~(keystone_admin)] #keystoneendpoint-list|grep30c62c3c0797462a8bd4ff059a71296e |2408bc6cb5164053b86c0983fd39961a|RegionOne|http: //192 .168.1.201:8080 /v1/AUTH_ %(tenant_id)s|http: //192 .168.1.201:8080 /v1/AUTH_ %(tenant_id)s|http: //192 .168.1.201:8080|30c62c3c0797462a8bd4ff059a71296e| [root@h1~(keystone_admin)] #swiftlist h1 [root@h1~(keystone_admin)] #swiftlisth1 test1/ test1 /k1 .pem [root@h1~(keystone_admin)] #find/srv/node/swiftloopback/-typef-name"*.data" /srv/node/swiftloopback/objects/188901/27f/b87961659e1149b7094bb52b5d60f27f/1467698512 .58656.data ##删除k1后就没有了 /srv/node/swiftloopback/objects/59261/c81/39df7c7803321e4878fdcec1ac469c81/1467698493 .15690.data 映射 :ring(环) 映射到硬盘 容器 在容器里面创建对象 对象 文件就是对象 账户 权限 ring文件 保存到硬盘 account.ring.gz 账户 container.ring.gz 容器 object.ring.gz 对象 保存到硬盘里的目录,这个目录为zone /srv/node/swiftloopback/ 挂载点 必须放在/srv/node/目录下 zone1 zone2 两个相同,备份 packstack方式安装完成后,上传一个文件,只在硬盘里保留一份 对象先映射到 虚拟节点/分区partition 2^n 再映射到zone 目的:减少数据的迁移量 swift服务 1 一致性服务 consisteny server auditor 定期扫描,如果出现问题,就把有问题的文件放隔离区 replicate 从另外的zone复制相同的文件过来,实现数据同步 update 如果replicate失效了,那么等段时间再试 2 代维服务proxy server 接受用户发送过来的请求,比如上传、删除等请求 3 存储服务 容器服务器 container server 对象服务器 object server 账户服务器 acount server 安装软件 1 2 [root@h4~] #yumlistopenstack-swift* [root@h4~] #yum-yinstallopenstack-swift.noarchopenstack-swift-account.noarchopenstack-swift-container.noarchopenstack-swift-object.noarchopenstack-swift-proxy.noarchmemcache*python-swiftclient 任何服务都要向keystone进行注册 1 2 3 [root@h4~(keystone_admin)] #keystoneuser-create--nameswift--passhequan [root@h4~(keystone_admin)] #keystonetenant-create--nameservices [root@h4~(keystone_admin)] #keystoneuser-role-add--userswift--tenantservices--roleadmin 创建服务,指定endpoint 1 2 [root@h4~(keystone_admin)] #keystoneservice-create--nameswift--typeobject-store--description"swift" keystoneendpoint-create--service- id 0995c9a9ed4847da86435bca9a7be8fc--publicurl 'http://192.168.1.204:8080/v1/AUTH_%(tenant_id)s' --internalurl 'http://192.168.1.204:8080/v1/AUTH_%(tenant_id)s' --adminurl 'http://192.168.1.204:8080' 配置swift 准备了2个分区 1 2 3 zone1zone2在 /srv/node 12 /dev/sdb1 /srv/node/zone1 xfsdefaults00 ##挂载 13 /dev/sdb2 /srv/node/zone2 xfsdefaults00 1 [root@h4~(keystone_admin)] #chown-Rswift.swift/srv/node/ 1 2 3 4 5 6 7 8 9 10 [root@h4swift(keystone_admin)] #catswift.conf [swift- hash ] swift_hash_path_suffix=%SWIFT_HASH_PATH_SUFFIX% [root@h1~(keystone_admin)] #find/srv/node/swiftloopback/-typef-name"*.data" /srv/node/swiftloopback/objects/102340/afe/63f12ea37cca17f0227381adcf93eafe/1467982747 .16551.data zone对象类型/分区的编号 /sufix/ 文件名字的 hash /上传文件的时间戳 [root@h1~(keystone_admin)] #date--date=@1467982747.16551 2016年07月08日星期五20:59:07CST 创建ring文件的准备工作 创建模板,设定有几个备份,有多少分区。 1 2 3 [root@h4swift(keystone_admin)] #swift-ring-builderaccount.buildercreate1221 [root@h4swift(keystone_admin)] #swift-ring-builderobject.buildercreate1221 [root@h4swift(keystone_admin)] #swift-ring-buildercontainer.buildercreate1221 指定映射位置 1 2 3 4 5 6 7 8 [root@h4swift] #vimaccount-server.conf#3个都要改ip 6bind_ip=192.168.1.204 [root@h4swift(keystone_admin)] #swift-ring-builderaccount.builderaddz1-192.168.1.204:6202/zone1100 [root@h4swift(keystone_admin)] #swift-ring-builderaccount.builderaddz2-192.168.1.204:6202/zone2100 [root@h4swift(keystone_admin)] #swift-ring-builderobject.builderaddz1-192.168.1.204:6200/zone1100 [root@h4swift(keystone_admin)] #swift-ring-builderobject.builderaddz2-192.168.1.204:6200/zone2100 [root@h4swift(keystone_admin)] #swift-ring-buildercontainer.builderaddz1-192.168.1.204:6201/zone1100 [root@h4swift(keystone_admin)] #swift-ring-buildercontainer.builderaddz2-192.168.1.204:6201/zone2100 创建ring文件 1 2 3 4 5 [root@h4swift(keystone_admin)] #swift-ring-builderaccount.builderrebalance [root@h4swift(keystone_admin)] #swift-ring-builderobject.builderrebalance [root@h4swift(keystone_admin)] #swift-ring-buildercontainer.builderrebalance [root@h4swift(keystone_admin)] #ls*.gz account.ring.gzcontainer.ring.gzobject.ring.gz 启动服务 1 2 3 4 5 6 [root@h4srv(keystone_admin)] #systemctlstartopenstack-swift-accountopenstack-swift-objectopenstack-swift-container [root@h4srv(keystone_admin)] #systemctlis-activeopenstack-swift-accountopenstack-swift-objectopenstack-swift-container active active active [root@h4srv(keystone_admin)] #systemctlenableopenstack-swift-accountopenstack-swift-objectopenstack-swift-container 代维服务proxy server 1 2 3 4 5 6 7 8 9 10 11 [root@h4swift(keystone_admin)] #vimproxy-server.conf 53[filter:authtoken] 54 paste .filter_factory=keystonemiddleware.auth_token:filter_factory 55admin_tenant_name=services 56admin_user=swift 57admin_password=hequan 58 # 59identity_uri=http: //192 .168.1.204:35357/ 60auth_port=35357 61auth_protocol=http 62 #auth_uri=http://192.168.1.204:5000/ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@h4swift(keystone_admin)] #systemctlstartopenstack-swift-proxy.service [root@h4swift(keystone_admin)] #systemctlenableopenstack-swift-proxy.service [root@h4swift(keystone_admin)] #systemctlstartmemcached.service [root@h4swift(keystone_admin)] #systemctlenablememcached.service [root@h4swift(keystone_admin)] #swiftposth1 [root@h4swift(keystone_admin)] #swiftlist h1 [root@h4swift(keystone_admin)] #swiftuploadh1/etc/hosts 任意一个分区挂了,还是可以正常查看 两个都挂了,就看不到了 本文转自 295631788 51CTO博客,原文链接:http://blog.51cto.com/hequan/1812861,如需转载请自行联系原作者

优秀的个人博客,低调大师

Nginx学习笔记(一) Nginx架构

Nginx全程是什么?Nginx ("engine x") 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP代理服务器。 daemon守护线程 nginx在启动后,在unix系统中会以daemon的方式在后台运行,后台进程包含一个master进程和多个worker进程。 当然nginx也是支持多线程的方式的,只是我们主流的方式还是多进程的方式,也是nginx的默认方式。 master进程主要用来管理worker进程,包含:接收来自外界的信号,向各worker进程发送信号,监控worker进程的运行状态,当worker进程退出后(异常情况下),会自动重新启动新的worker进程。 worker进程则是处理基本的网络事件。多个worker进程之间是对等的,他们同等竞争来自客户端的请求,各进程互相之间是独立的。一个请求,只可能在一个worker进程中处理,一个worker进程,不可能处理其它进程的请求。 worker进程的个数是可以设置的,一般我们会设置与机器cpu核数一致。更多的worker数,只会导致进程来竞争cpu资源了,从而带来不必要的上下文切换。而且,nginx为了更好的利用多核特性,具有cpu绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换带来cache的失效。 惊群现象 每个worker进程都是从master进程fork过来。在master进程里面,先建立好需要listen的socket之后,然后再fork出多个worker进程,这样每个worker进程都可以去accept这个socket(当然不是同一个socket,只是每个进程的这个socket会监控在同一个ip地址与端口,这个在网络协议里面是允许的)。一般来说,当一个连接进来后,所有在accept在这个socket上面的进程,都会收到通知,而只有一个进程可以accept这个连接,其它的则accept失败。 相对于线程,采用进程的优点 进程之间不共享资源,不需要加锁,所以省掉了锁带来的开销。 采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,master进程则很快重新启动新的worker进程。 编程上更加容易。 多线程的问题 而多线程在多并发情况下,线程的内存占用大,线程上下文切换造成CPU大量的开销。想想apache的常用工作方式(apache也有异步非阻塞版本,但因其与自带某些模块冲突,所以不常用),每个请求会独占一个工作线程,当并发数上到几千时,就同时有几千的线程在处理请求了。这对操作系统来说,是个不小的挑战,线程带来的内存占用非常大,线程的上下文切换带来的cpu开销很大,自然性能就上不去了,而这些开销完全是没有意义的。 异步非阻塞 异步的概念和同步相对的,也就是不是事件之间不是同时发生的。 非阻塞的概念是和阻塞对应的,阻塞是事件按顺序执行,每一事件都要等待上一事件的完成,而非阻塞是如果事件没有准备好,这个事件可以直接返回,过一段时间再进行处理询问,这期间可以做其他事情。但是,多次询问也会带来额外的开销。 总的来说,Nginx采用异步非阻塞的好处在于: 不需要创建线程,每个请求只占用少量的内存 没有上下文切换,事件处理非常轻量 淘宝tengine团队说测试结果是“24G内存机器上,处理并发请求可达200万”。 本文转自cococo点点博客园博客,原文链接:http://www.cnblogs.com/coder2012/p/3141469.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

CCNP-CIT中文笔记

故障处理方法 一、网络的复杂性 一般网络包括路由、拨号、交换、视频、WAN(ISDN、帧中继、ATM、…)、LAN、VLAN、… 二、故障处理模型 1、 界定问题(Define the Problem) 详细而精确地描述故障的症状和潜在的原因 2、 收集详细信息(Gather Facts) 信息来源:关键用户、网络管理系统、路由器/交换机 1) 识别症状: 2) 重现故障:校验故障依然存在 3) 调查故障频率: 4) 确定故障的范围:有三种方法建立故障范围 Ø由外到内故障处理(Outside-In Troubleshooting):通常适用于有多个主机不能连接到一台服务器或服务器集 Ø由内到外故障处理(Inside-Out Troubleshooting): Ø半分故障处理(Divide-by-Half Troubleshooting) 3、 考虑可能情形(Consider Possibilities) 考虑引起故障的可能原因 4、 建立一份行动计划(Create the Action Plan) 5、 部署行动计划(Implement the Action Plan) 用于纠正网络故障原因。从最象故障源处,想出处理方法 每完成一个步骤,检查故障是否解决 6、 观察行动计划执行结果(Observe Results) 7、 如有行动计划不能解决问题,重复上述过程(Iterate as Needed) 三、记录所做修改 在通过行动计划解决问题后,建议把记录作为故障处理的一部分,记录所有的配置修改。 第2章 网络文档 一、网络基线 解决网络问题的最简单途径是把当前配置和以前的配置相比较。 基线文档由不同的网络和系统文档组成,它包括: Ø网络配置表 Ø网络拓扑图 ØES网络配置表 ØES网络拓扑图 创建网络的注意事项: 1) 确定文档覆盖的范围; 2) 保持一致:收集网络中所有设备的相同信息; 3) 明确目标:了解文档的用途; 4) 文档易于使用和访问; 5) 及时维护更新文档。 二、网络配置表 网络配置表的通常目标是提供网络中使用的硬件和软件组成的列表,其组成有: 分级 项目 杂项信息 设备名、设备型号、CPU类型、FLASH、DRAM、接口描述、用户名口令 第1层 介质类型、速率、双工模式、接口号、连接插座或端口 第2层 MAC地址、STP状态、STP根桥、速端口信息、VLAN、Etherchannel配置、封装、中继状态、接口类型、端口安全、VTP状态、VTP模式 第3层 IP地址、IPX地址、HSRP地址、子网掩码、路由协议、ACL、隧道信息、环路接口 在多数情形下,存储这些信息的最佳方式是电子表格或数据库,电子表格用于较小的网络,数据库用于较大的网络。 三、网络拓扑图 网络拓扑图是图示网络的各组成部分之间如何在逻辑上和物理上相互连接。 1、网络拓扑图的组成 分级 项目 杂项信息 设备名、设备型号、设置间连接、接口描述 第1层 介质类型、接口号 第2层 MAC地址、VLAN、封装、中继状态、接口类型、DLCI 第3层 IP地址、子网掩码、路由协议 对于大型的网络,可以制作多个网络拓扑图,每个网络拓扑图反映一个分离的部分。 2、建立网络拓扑图 四、发现网络配置信息 1、收集路由器和第3层交换机网络配置信息 show version ;显示设备型号、Flash、DRAM、IOS版本 show ip interface brief ;显示接口简要信息(类型、状态、协议状态、IP地址) show interface e0/0 ;显示某接口详细信息(MAC、IP、MASK、…) show ip protocols ;显示IP路由协议信息 show ip interface e0/0 ;显示接口的IP协议信息(状态、IP地址、ACL、…) 2、收集交换机配置信息 交换机网络配置表包含的信息:设备名、型号、位置、Flash、DRAM、CATOS版本、管理地址、VTP域、VTP模式、端口号、端口速率、端口双工、VLAN、STP状态、速端口状态、中继状态、… show version ;显示IOS或CATOS版本、DRAM、Flash show vtp domain ;(CatOS)显示VTP域和VTP模式 show vtp status ;(IOS) show interface ;(CatOS)显示管理接口信息 show port ;(CatOS)显示每个端口的简要信息(号、VLAN、双工、…) show interface ;(IOS) show trunk ;(CatOS)显示中继信息(模式、封装、允许端口、剪裁、…) show interface trunk ;(IOS) show spantree 45 ;(CatOS)显示端口的STP模式、类型、状态、速端口、…) show spanning-tree 45 ;(IOS) 3、发现相邻CISCO设备的信息 CDP(Cisco Discovery Protocol)是CISCO的专用协议,用于识别直接相邻的CISCO设备信息,CDP工作在第2层。 Show cdp neighbor ;显示相邻CISCO设备的简要信息(ID、相邻接口、平台、…) Show cdp neighbor detail;显示相邻CISCO设备的详细信息(包含第3层信息) 五、创建网络文档的过程 1、 LOGIN ;登录到设备进入特权模式。 2、 接口发现 ;发现关于设备的所需信息 3、 Document ;在网络配置表中记录发现的信息。 4、 Diagram ;从网络配置表传输所需信息到网络拓扑图 5、 设备发现 ;判断是否有相邻设备没有记录文档。 本文转自gauyanm 51CTO博客,原文链接:http://blog.51cto.com/gauyanm/229048,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android笔记:定时提醒、闹钟实现

android要实现定时的功能那肯定就要用到闹铃相关的技术, 那么android闹铃实现是基于 AlarmManager 这个类的,首先我们来看一下它的几个主要的方法。 两个核心的方法 : 1 private final IAlarmManagermService; 1 2 3 4 5 6 public void set( int type, long triggerAtMillis,PendingIntentoperation){ try { mService.set(type,triggerAtMillis,operation); } catch (RemoteExceptionex){ } } 和 1 2 3 4 5 6 7 public void setRepeating( int type, long triggerAtMillis, long intervalMillis,PendingIntentoperation){ try { mService.setRepeating(type,triggerAtMillis,intervalMillis,operation); } catch (RemoteExceptionex){ } } 第一个方法主要功能是注册一个比较简单的闹铃,第二个方法是注册一个重复的闹铃,这里重复的意思是指:设置5s, 那么每隔5s会执行一次 。 我们看到这里具体的实现都是基于IAlarmManager的,而IAlarmManager是一个aidl(Android Interface definition language),具体的就不详细介绍了,大家有兴趣的可以自己研究一下。 下面我来看下set(int type, long triggerAtMillis, PendingIntent operation)方法是如何调用的: 1 2 3 4 5 6 7 8 9 10 11 //进行闹铃注册 Intentintent= new Intent(MainActivity. this ,AlarmReceiver. class ); PendingIntentsender=PendingIntent.getBroadcast(MainActivity. this , 0 ,intent, 0 ); //过10s执行这个闹铃 Calendarcalendar=Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.SECOND, 10 ); AlarmManagermanager=(AlarmManager)getSystemService(ALARM_SERVICE); manager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),sender); 看一下AlarmReceiver 的源码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /** * *@ClassName:AlarmReceiver *@Description:闹铃时间到了会进入这个广播,这个时候可以做一些该做的业务。 *@authorHuHood *@date2013-11-25下午4:44:30 * */ public class AlarmReceiver extends BroadcastReceiver{ @Override public void onReceive(Contextcontext,Intentintent){ Toast.makeText(context, "闹铃响了,可以做点事情了~~" ,Toast.LENGTH_LONG).show(); } } 还有别忘了,AndroidManifest.xml中需要加入: 1 <receiverandroid:name= "com.example.alarmmanagerdemo.AlarmReceiver" android:process= ":remote" > 运行之后,过10s 弹出 "闹铃响了,可以做点事情了~~", 说明成功了。 ok,这个结果肯定不是我们想要的,我们想要的功能是每天定时提醒的功能,那么需要基于 setRepeating(int type, long triggerAtMillis,long intervalMillis, PendingIntent operation) 这个方法来实现,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Intentintent= new Intent(MainActivity. this ,AlarmReceiver. class ); PendingIntentsender=PendingIntent.getBroadcast(MainActivity. this , 0 ,intent, 0 ); long firstTime=SystemClock.elapsedRealtime(); //开机之后到现在的运行时间(包括睡眠时间) long systemTime=System.currentTimeMillis(); Calendarcalendar=Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); //这里时区需要设置一下,不然会有8个小时的时间差 calendar.setTimeZone(TimeZone.getTimeZone( "GMT+8" )); calendar.set(Calendar.MINUTE,mMinute); calendar.set(Calendar.HOUR_OF_DAY,mHour); calendar.set(Calendar.SECOND, 0 ); calendar.set(Calendar.MILLISECOND, 0 ); //选择的定时时间 long selectTime=calendar.getTimeInMillis(); //如果当前时间大于设置的时间,那么就从第二天的设定时间开始 if (systemTime>selectTime){ Toast.makeText(MainActivity. this , "设置的时间小于当前时间" ,Toast.LENGTH_SHORT).show(); calendar.add(Calendar.DAY_OF_MONTH, 1 ); selectTime=calendar.getTimeInMillis(); } //计算现在时间到设定时间的时间差 long time=selectTime-systemTime; firstTime+=time; //进行闹铃注册 AlarmManagermanager=(AlarmManager)getSystemService(ALARM_SERVICE); manager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,DAY,sender); Log.i(TAG, "time====" +time+ ",selectTime=====" +selectTime+ ",systemTime====" +systemTime+ ",firstTime===" +firstTime); Toast.makeText(MainActivity. this , "设置重复闹铃成功!" ,Toast.LENGTH_LONG).show(); 以上的思路大致是这样的,首先根据设置的时间,算出当前时间离设置时间的时间差,加上这个时间差,我们就知道第一次提醒的时间,然后再设定重复的时间间隔,我们这里设置1天就可以了。现在解释一下setRepeating中第一个参数:AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠;当手机休眠时不发射闹钟。AlarmManager.RTC_WAKEUP,硬件闹钟,当闹钟发躰时唤醒手机休眠;AlarmManager.ELAPSED_REALTIME,真实时间流逝闹钟,不唤醒手机休眠;当手机休眠时不发射闹钟。AlarmManager.ELAPSED_REALTIME_WAKEUP,真实时间流逝闹钟,当闹钟发躰时唤醒手机休眠;RTC闹钟和ELAPSED_REALTIME最大的差别就是前者可以通过修改手机时间触发闹钟事件,后者要通过真实时间的流逝,即使在休眠状态,时间也会被计算。以上摘自:http://hualang.iteye.com/blog/1304054还有,我们这里是调用广播的形式来实现的,也可以用service的方式来进行实现,只要把PendingIntent改动一下即可,相关代码:PendingIntent.getService(MainActivity.this, 0,new Intent(MainActivity.this,AlarmService.class), 0);其他的均相同。完整Demo下载:http://download.csdn.net/detail/jakend/6612033 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1679698,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android笔记:Intent的Component使用

使用components有两种方式: 1 2 3 ComponentNamecom= new ComponentName(MainActivity. this ,MyActivity. class ); //first ComponentNamecom= new ComponentName( "com.example.testcomponent" , "com.example.testcomponent.MyActivity" ); //second 第二种方式的第二个参数必须写全包名,不然会报错的。 一样的,主Activity中: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 button.setOnClickListener( new Button.OnClickListener() { @Override public void onClick(Viewarg0) { //TODOAuto-generatedmethodstub Intentintent= new Intent(); ComponentNamecom= new ComponentName( "com.example.testcomponent" , "com.example.testcomponent.MyActivity" ); intent.setComponent(com); Strings= "ThisisaTest." ; intent.putExtra( "id" ,s); startActivity(intent); } }); 在目标Ativity中获取数据和上面是一样的,但是,在目标Activity中就可以获取到源目标,知道是从哪儿传递过来的: 1 2 3 4 5 6 7 8 text=(TextView)findViewById(R.id.text); Intentintent=getIntent(); Stringstr=intent.getStringExtra( "id" ); ComponentNamecom=intent.getComponent(); StringpkgName=com.getPackageName(); StringclassName=com.getClassName(); text.setText(str+ "\n" +pkgName+ "\n" +className); 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1611832,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册