`
jiapumin
  • 浏览: 341481 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
收藏列表
标题 标签 来源
iOS Objective c 16进制字符串转为二进制数组 iphone iOS Objective c 16进制字符串转为二进制数组
@implementation NSString (StringToHexData)

//
// Decodes an NSString containing hex encoded bytes into an NSData object
//
- (NSData *) stringToHexData
{
    int len = [self length] / 2;    // Target length
    unsigned char *buf = malloc(len)
    unsigned char *whole_byte = buf;
    char byte_chars[3] = {'\0','\0','\0'};

    int i;
    for (i=0; i < [self length] / 2; i++) {
        byte_chars[0] = [self characterAtIndex:i*2];
        byte_chars[1] = [self characterAtIndex:i*2+1];
        *whole_byte = strtol(byte_chars, NULL, 16);
        whole_byte++;
    }

    NSData *data = [NSData dataWithBytes:buf length:len];
    free( buf );
    return data;
}
@end
@implementation NSData (DataToHexString)

- (NSString *) dataToHexString
{
    NSUInteger          len = [self length];
    char *              chars = (char *)[self bytes];
    NSMutableString *   hexString = [[NSMutableString alloc] init];

    for(NSUInteger i = 0; i < len; i++ )
        [hexString appendString:[NSString stringWithFormat:@"%0.2hhx", chars[i]]];

    return hexString;
}
@end
Cocos2d-x 3.0 动作,动画 iphone, cocos2d-x3.0
//执行一个action动作对象
    runAction("action对象");  
     
    //暂停一个对象的动作
    Director::sharedDirector()->getActionManger()->pauseTarget("对象");
     
    //暂停所有对象的动作
    Director::sharedDirector()->getActionManager()->pauseAllRunningActions();
     
    //暂停所有对象的动作及其更新函数
    pauseSchedulerAndActions();
     
    //继续一个对象的动作
    Director::sharedDirector()->getActionManager()->resumeTarget("对象");
     
    //继续所有对象的动作
    Director::sharedDirector()->getActionManager()->resumeTargets("CCSet对象");
     
    //继续所有对象的动作及其更新函数
    resumeSchedulerAndActions();
     
    //停止对象的动作
    stopAction("action对象");
     
    //停止目标对象的动作
    stopActionByTag("tag值");
     
    //停止所有对象的动作
    stopAllActions();
     
    //删除动作对象
    Director::sharedDirector()->getActionManager()->removeAction("action对象");
     
    //删除动作对象
    Director::sharedDirector()->getActionManager()->removeActionByTag("tag值");
     
    //删除所有动作对象
    Director::sharedDirector()->getActionManager()->removeAllActions();
     
    //删除所有相同tag值得动作对象
    Director::sharedDirector()->getActionManager()->removeAllActionsFromTarget("tag值");
     
    //几秒后移动到坐标点
    MoveTo::create("时间","坐标");
     
    //几秒后移动到坐标点
    MoveBy::create("时间","坐标");
     
    //几秒后缩放到指定大小(1:原大小;大于1:放大;小于1:缩小)
    ScaleTo::create("时间","缩放比例");
     
    //几秒后缩放到指定大小(1:原大小;大于1:放大;小于1:缩小)
    ScaleBy::create("时间","缩放比例");
     
    //几秒后旋转多少度[0,360]
    RotateTo::create("时间","角度");
     
    //几秒后旋转多少度[0,360]
    RotateBy::create("时间","角度");
     
    //几秒后倾斜指定角度
    SkewTo::create("时间","x轴角度","y轴角度");
     
    //几秒后倾斜指定角度
    SkewBy::create("时间","x轴角度","y轴角度");
 
    //几秒后经过几次跳到指定位置
    JumpTo::create("时间","目标位置","高度","到目标所需次数");
     
    //几秒后经过几次跳到指定位置
    JumpBy::create("时间","目标位置","高度","到目标所需次数");
     
    //几秒内按指定贝塞尔曲线运动
    BezierTo::create("时间","ccBezierConfig构造体");
     
    //几秒内按指定贝塞尔曲线运动
    BezierBy::create("时间","ccBezierConfig构造体");
     
    //几秒后变为指定颜色
    TintTo::create("时间","红","绿","蓝");
     
    //几秒后变为指定颜色
    TintBy::create("时间","红","绿","蓝");
     
    //几秒内按曲线运动(拟合度0最柔和)
    CardinalSplineTo::create("时间","控制点坐标数组","拟合度");
 
    //几秒内按曲线运动(拟合度0最柔和)
    CardinalSplineBy::create("时间","控制点坐标数组","拟合度");
     
    //几秒内完成一个样条插值轨迹(直线)
    CatmullRomTo::create("时间","控制点坐标数组");
     
    //几秒内完成一个样条插值轨迹(直线)
    CatmullRomBy::create("时间","控制点坐标数组");
     
    //渐显
    FadeIn::create("时间");
 
    //渐消
    FadeOut::create("时间");
     
    //让目标动作具有反弹效果,从起点反弹
    EaseBounceIn::create("action对象");
     
    //让目标动作具有反弹效果,从终点反弹
    EaseBounceOut::create("action对象");
     
    //让目标动作具有反弹效果,起点终点都反弹
    EaseBounceInOut::create("action对象");
 
    //让目标动作具有回力效果,起点作为回力点
    EaseBackIn::create("action对象");
 
    //让目标动作具有回力效果,终点作为回力点
    EaseBackOut::create("action对象");
     
    //让目标动作具有回力效果,起点终点都作为回力点
    EaseBackInOut::create("action对象");
     
    //让目标动作具有弹力效果,起点具有弹性
    EaseElasticIn::create("action对象");
     
    //让目标动作具有弹力效果,终点具有弹性
    EaseElasticOut::create("action对象");
 
 
    //让目标动作具有弹力效果,起点终点都具有弹性
    EaseElasticInOut::create("action对象");
     
    //让目标动作缓慢开始
    EaseExponentialIn::create("action对象");
     
    //让目标动作缓慢结束
    EaseExponentialOut::create("action对象");
     
    //让目标动作缓慢开始并缓慢结束
    EaseExponentialInOut::create("action对象");
     
    //让目标动作由慢到快
    EaseSineIn::create("action对象");
     
    //让目标动作由快到慢
    EaseSineOut::create("action对象");
     
    //让目标动作由慢到快再到慢
    EaseSineInOut::create("action对象");
     
    //为目标动作设置速度
    EaseRateAction::create("action对象","速度");
     
    //为目标动作速度翻倍
    Speed::create("action对象","倍数");
     
    //多个不同类动作同时执行(NUll结尾)
    Spawn::create("action对象1","action对象2".....);
 
    //多个目标动作顺序执行(NUll结尾)
    Sequence::create("action对象1","action对象2"......);
     
    //几秒内闪烁几次
    Blink::create("时间","次数");
     
    //重复目标动作
    Repeat::create("action对象","次数");
 
    //永久重复目标动作
    RepeatForever::create("action对象");
     
    //延迟几秒执行(在顺序执行Sequence中延迟哦)
    DelayTime::create("时间");
 
    //镜头跟着目标走,超过范围就结束。
    Follow::create("跟随对象","跟随范围");
     
    //几秒内球面运动
    OrbitCamera::create("时间","起始半径","半径差","起始z角","旋转z角","起始x角","旋转x角");
     
    //创建一个回调动作(不带参数)
    CallFunc::create("对象","回调函数");
     
    //创建一个回调动作(传调用者为参数)
    CallFuncN::create("对象","回调函数");
     
    //创建一个回调动作(带2个参数)
    CallFuncN::create("对象","回调函数","任意参数");
iOS - 3种方法获取设备硬件类型 iphone
1.这种是在较高层次获取设备类型,返回的是 iPhone , iPod , iPad 。适合要求不高的。

NSString *deviceType = [[UIDevice currentDevice] model];

2.这是Linux中获取设备类型的方法,主要是C语言的方法,注意引入头文件 #include 。输入底层获取设备类型的方法。

#include <sys sysctl.h="">
 
- (NSString *)getDeviceVersionInfo
{
    size_t size;
    // get the length of machine name
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    // get machine name
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithFormat:@"%s", machine];
    free(machine);
     
    return platform;
}
 
-(NSString *)correspondVersion
{
    NSString *correspondVersion = [self getDeviceVersionInfo];
     
    if ([correspondVersion isEqualToString:@"i386"])        return@"Simulator";
    if ([correspondVersion isEqualToString:@"x86_64"])       return @"Simulator";
     
    if ([correspondVersion isEqualToString:@"iPhone1,1"])   return@"iPhone 1";
    if ([correspondVersion isEqualToString:@"iPhone1,2"])   return@"iPhone 3";
    if ([correspondVersion isEqualToString:@"iPhone2,1"])   return@"iPhone 3S";
    if ([correspondVersion isEqualToString:@"iPhone3,1"] || [correspondVersion isEqualToString:@"iPhone3,2"])   return@"iPhone 4";
    if ([correspondVersion isEqualToString:@"iPhone4,1"])   return@"iPhone 4S";
    if ([correspondVersion isEqualToString:@"iPhone5,1"] || [correspondVersion isEqualToString:@"iPhone5,2"])   return @"iPhone 5";
    if ([correspondVersion isEqualToString:@"iPhone5,3"] || [correspondVersion isEqualToString:@"iPhone5,4"])   return @"iPhone 5C";
    if ([correspondVersion isEqualToString:@"iPhone6,1"] || [correspondVersion isEqualToString:@"iPhone6,2"])   return @"iPhone 5S";
     
    if ([correspondVersion isEqualToString:@"iPod1,1"])     return@"iPod Touch 1";
    if ([correspondVersion isEqualToString:@"iPod2,1"])     return@"iPod Touch 2";
    if ([correspondVersion isEqualToString:@"iPod3,1"])     return@"iPod Touch 3";
    if ([correspondVersion isEqualToString:@"iPod4,1"])     return@"iPod Touch 4";
    if ([correspondVersion isEqualToString:@"iPod5,1"])     return@"iPod Touch 5";
     
    if ([correspondVersion isEqualToString:@"iPad1,1"])     return@"iPad 1";
    if ([correspondVersion isEqualToString:@"iPad2,1"] || [correspondVersion isEqualToString:@"iPad2,2"] || [correspondVersion isEqualToString:@"iPad2,3"] || [correspondVersion isEqualToString:@"iPad2,4"])     return@"iPad 2";
    if ([correspondVersion isEqualToString:@"iPad2,5"] || [correspondVersion isEqualToString:@"iPad2,6"] || [correspondVersion isEqualToString:@"iPad2,7"] )      return @"iPad Mini";
    if ([correspondVersion isEqualToString:@"iPad3,1"] || [correspondVersion isEqualToString:@"iPad3,2"] || [correspondVersion isEqualToString:@"iPad3,3"] || [correspondVersion isEqualToString:@"iPad3,4"] || [correspondVersion isEqualToString:@"iPad3,5"] || [correspondVersion isEqualToString:@"iPad3,6"])      return @"iPad 3";
     
    return correspondVersion;
}

3.这是2一样,是Linux中获取设备类型的方法,主要是C语言的方法,注意引入头文件 #import "sys/utsname.h" 。输入底层获取设备类型的方法。

#import "sys/utsname.h"
 
- (NSString *)getDeviceVersionInfo
{
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *platform = [NSString stringWithFormat:@"%s", systemInfo.machine];
     
    return platform;
}
 
-(NSString *)correspondVersion
{
    NSString *correspondVersion = [self getDeviceVersionInfo];
     
    if ([correspondVersion isEqualToString:@"i386"])        return@"Simulator";
    if ([correspondVersion isEqualToString:@"x86_64"])       return @"Simulator";
     
    if ([correspondVersion isEqualToString:@"iPhone1,1"])   return@"iPhone 1";
    if ([correspondVersion isEqualToString:@"iPhone1,2"])   return@"iPhone 3";
    if ([correspondVersion isEqualToString:@"iPhone2,1"])   return@"iPhone 3S";
    if ([correspondVersion isEqualToString:@"iPhone3,1"] || [correspondVersion isEqualToString:@"iPhone3,2"])   return@"iPhone 4";
    if ([correspondVersion isEqualToString:@"iPhone4,1"])   return@"iPhone 4S";
    if ([correspondVersion isEqualToString:@"iPhone5,1"] || [correspondVersion isEqualToString:@"iPhone5,2"])   return @"iPhone 5";
    if ([correspondVersion isEqualToString:@"iPhone5,3"] || [correspondVersion isEqualToString:@"iPhone5,4"])   return @"iPhone 5C";
    if ([correspondVersion isEqualToString:@"iPhone6,1"] || [correspondVersion isEqualToString:@"iPhone6,2"])   return @"iPhone 5S";
     
    if ([correspondVersion isEqualToString:@"iPod1,1"])     return@"iPod Touch 1";
    if ([correspondVersion isEqualToString:@"iPod2,1"])     return@"iPod Touch 2";
    if ([correspondVersion isEqualToString:@"iPod3,1"])     return@"iPod Touch 3";
    if ([correspondVersion isEqualToString:@"iPod4,1"])     return@"iPod Touch 4";
    if ([correspondVersion isEqualToString:@"iPod5,1"])     return@"iPod Touch 5";
     
    if ([correspondVersion isEqualToString:@"iPad1,1"])     return@"iPad 1";
    if ([correspondVersion isEqualToString:@"iPad2,1"] || [correspondVersion isEqualToString:@"iPad2,2"] || [correspondVersion isEqualToString:@"iPad2,3"] || [correspondVersion isEqualToString:@"iPad2,4"])     return@"iPad 2";
    if ([correspondVersion isEqualToString:@"iPad2,5"] || [correspondVersion isEqualToString:@"iPad2,6"] || [correspondVersion isEqualToString:@"iPad2,7"] )      return @"iPad Mini";
    if ([correspondVersion isEqualToString:@"iPad3,1"] || [correspondVersion isEqualToString:@"iPad3,2"] || [correspondVersion isEqualToString:@"iPad3,3"] || [correspondVersion isEqualToString:@"iPad3,4"] || [correspondVersion isEqualToString:@"iPad3,5"] || [correspondVersion isEqualToString:@"iPad3,6"])      return @"iPad 3";
     
    return correspondVersion;
}
iOS 获取手机的型号,系统版本,软件名称,软件版本 iphone http://www.2cto.com/kf/201210/162333.html
//手机序列号  
    NSString* identifierNumber = [[UIDevice currentDevice] uniqueIdentifier]; 
    NSLog(@"手机序列号: %@",identifierNumber); 
    //手机别名: 用户定义的名称  
    NSString* userPhoneName = [[UIDevice currentDevice] name]; 
    NSLog(@"手机别名: %@", userPhoneName); 
    //设备名称  
    NSString* deviceName = [[UIDevice currentDevice] systemName]; 
    NSLog(@"设备名称: %@",deviceName ); 
    //手机系统版本  
    NSString* phoneVersion = [[UIDevice currentDevice] systemVersion]; 
    NSLog(@"手机系统版本: %@", phoneVersion); 
    //手机型号  
    NSString* phoneModel = [[UIDevice currentDevice] model]; 
    NSLog(@"手机型号: %@",phoneModel ); 
    //地方型号  (国际化区域名称)  
    NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel]; 
    NSLog(@"国际化区域名称: %@",localPhoneModel ); 
     
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; 
    // 当前应用名称  
    NSString *appCurName = [infoDictionary objectForKey:@"CFBundleDisplayName"]; 
    NSLog(@"当前应用名称:%@",appCurName); 
    // 当前应用软件版本  比如:1.0.1  
    NSString *appCurVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"]; 
    NSLog(@"当前应用软件版本:%@",appCurVersion); 
    // 当前应用版本号码   int类型  
    NSString *appCurVersionNum = [infoDictionary objectForKey:@"CFBundleVersion"]; 
    NSLog(@"当前应用版本号码:%@",appCurVersionNum); 

//手机序列号
    NSString* identifierNumber = [[UIDevice currentDevice] uniqueIdentifier];
    NSLog(@"手机序列号: %@",identifierNumber);
    //手机别名: 用户定义的名称
    NSString* userPhoneName = [[UIDevice currentDevice] name];
    NSLog(@"手机别名: %@", userPhoneName);
    //设备名称
    NSString* deviceName = [[UIDevice currentDevice] systemName];
    NSLog(@"设备名称: %@",deviceName );
    //手机系统版本
    NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];
    NSLog(@"手机系统版本: %@", phoneVersion);
    //手机型号
    NSString* phoneModel = [[UIDevice currentDevice] model];
    NSLog(@"手机型号: %@",phoneModel );
    //地方型号  (国际化区域名称)
    NSString* localPhoneModel = [[UIDevice currentDevice] localizedModel];
    NSLog(@"国际化区域名称: %@",localPhoneModel );
   
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
    // 当前应用名称
    NSString *appCurName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
    NSLog(@"当前应用名称:%@",appCurName);
    // 当前应用软件版本  比如:1.0.1
    NSString *appCurVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
    NSLog(@"当前应用软件版本:%@",appCurVersion);
    // 当前应用版本号码   int类型
    NSString *appCurVersionNum = [infoDictionary objectForKey:@"CFBundleVersion"];
    NSLog(@"当前应用版本号码:%@",appCurVersionNum);

 


结果:


[plain]
2012-10-19 14:07:47.622 myDemo[5779:707] 手机序列号: 6685c75e34104be0b04c6ceb72985dc381f0f746 
2012-10-19 14:07:47.624 myDemo[5779:707] 手机别名: “spring sky”的 iPod 
2012-10-19 14:07:47.627 myDemo[5779:707] 设备名称: iPhone OS 
2012-10-19 14:07:47.629 myDemo[5779:707] 手机系统版本: 5.1.1 
2012-10-19 14:07:47.641 myDemo[5779:707] 手机型号: iPod touch 
2012-10-19 14:07:47.642 myDemo[5779:707] 国际化区域名称: iPod touch 
2012-10-19 14:07:47.643 myDemo[5779:707] 当前应用名称:myDemo 
2012-10-19 14:07:47.645 myDemo[5779:707] 当前应用软件版本:1.0.1 
2012-10-19 14:07:47.646 myDemo[5779:707] 当前应用版本号码:101 

2012-10-19 14:07:47.622 myDemo[5779:707] 手机序列号: 6685c75e34104be0b04c6ceb72985dc381f0f746
2012-10-19 14:07:47.624 myDemo[5779:707] 手机别名: “spring sky”的 iPod
2012-10-19 14:07:47.627 myDemo[5779:707] 设备名称: iPhone OS
2012-10-19 14:07:47.629 myDemo[5779:707] 手机系统版本: 5.1.1
2012-10-19 14:07:47.641 myDemo[5779:707] 手机型号: iPod touch
2012-10-19 14:07:47.642 myDemo[5779:707] 国际化区域名称: iPod touch
2012-10-19 14:07:47.643 myDemo[5779:707] 当前应用名称:myDemo
2012-10-19 14:07:47.645 myDemo[5779:707] 当前应用软件版本:1.0.1
2012-10-19 14:07:47.646 myDemo[5779:707] 当前应用版本号码:101
IOS开发之格式化日期时间 iphone
在开发iOS程序时,有时候需要将时间格式调整成自己希望的格式,这个时候我们可以用NSDateFormatter类来处理。
例如:
//实例化一个NSDateFormatter对象
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//设定时间格式,这里可以设置成自己需要的格式
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
//用[NSDate date]可以获取系统当前时间
NSString *currentDateStr = [dateFormatter stringFromDate:[NSDate date]];
//输出格式为:2010-10-27 10:22:13
NSLog(@"%@",currentDateStr);
//alloc后对不使用的对象别忘了release
[dateFormatter release];
字符说明
(:)
时间分隔符。在某些区域设置中,可以使用其他字符表示时间分隔符。时间分隔符在格式化时间值时分隔小时、分钟和秒。格式化输出中用作时间分隔符的实际字符由您的应用程序的当前区域性值确定。
(/)
日期分隔符。在某些区域设置中,可以使用其他字符表示日期分隔符。日期分隔符在格式化日期值时分隔日、月和年。格式化输出中用作日期分隔符的实际字符由您的应用程序的当前区域性确定。
(%)
用于表明不论尾随什么字母,随后字符都应该以单字母格式读取。也用于表明单字母格式应以用户定义格式读取。有关更多详细信息,请参见下面的内容。
d
将日显示为不带前导零的数字(如 1)。如果这是用户定义的数字格式中的唯一字符,请使用 %d。
dd
将日显示为带前导零的数字(如 01)。
EEE
将日显示为缩写形式(例如 Sun)。
EEEE
将日显示为全名(例如 Sunday)。
M
将月份显示为不带前导零的数字(如一月表示为 1)。如果这是用户定义的数字格式中的唯一字符,请使用 %M。
MM
将月份显示为带前导零的数字(例如 01/12/01)。
MMM
将月份显示为缩写形式(例如 Jan)。
MMMM
将月份显示为完整月份名(例如 January)。
gg
显示时代/纪元字符串(例如 A.D.)
h
使用 12 小时制将小时显示为不带前导零的数字(例如 1:15:15 PM)。如果这是用户定义的数字格式中的唯一字符,请使用 %h。
hh
使用 12 小时制将小时显示为带前导零的数字(例如 01:15:15 PM)。
H
使用 24 小时制将小时显示为不带前导零的数字(例如 1:15:15)。如果这是用户定义的数字格式中的唯一字符,请使用 %H。
HH
使用 24 小时制将小时显示为带前导零的数字(例如 01:15:15)。
m
将分钟显示为不带前导零的数字(例如 12:1:15)。如果这是用户定义的数字格式中的唯一字符,请使用 %m。
mm
将分钟显示为带前导零的数字(例如 12:01:15)。
s
将秒显示为不带前导零的数字(例如 12:15:5)。如果这是用户定义的数字格式中的唯一字符,请使用 %s。
ss
将秒显示为带前导零的数字(例如 12:15:05)。
f
显示秒的小数部分。例如,ff 将精确显示到百分之一秒,而 ffff 将精确显示到万分之一秒。用户定义格式中最多可使用七个 f 符号。如果这是用户定义的数字格式中的唯一字符,请使用 %f。
t
使用 12 小时制,并对中午之前的任一小时显示大写的 A,对中午到 11:59 P.M 之间的任一小时显示大写的 P。如果这是用户定义的数字格式中的唯一字符,请使用 %t。
tt
对于使用 12 小时制的区域设置,对中午之前任一小时显示大写的 AM,对中午到 11:59 P.M 之间的任一小时显示大写的 PM。
对于使用 24 小时制的区域设置,不显示任何字符。
y
将年份 (0-9) 显示为不带前导零的数字。如果这是用户定义的数字格式中的唯一字符,请使用 %y。
yy
以带前导零的两位数字格式显示年份(如果适用)。
yyy
以四位数字格式显示年份。
yyyy
以四位数字格式显示年份。
z
显示不带前导零的时区偏移量(如 -8)。如果这是用户定义的数字格式中的唯一字符,请使用 %z。
zz
显示带前导零的时区偏移量(例如 -08)
zzz
显示完整的时区偏移量(例如 -08:00)
格式显示
M/d/yy
12/7/58
d-MMM
7-Dec
d-MMMM-yy
7-December-58
d MMMM
7 December
MMMM yy
December 58
hh:mm tt
08:50 PM
h:mm:ss t
8:50:35 P
H:mm
20:50
H:mm:ss
20:50:35
M/d/yyyy H:mm
12/7/1958 20:50
IOS--CALayer实现,界限、透明度、位置、旋转、缩放组合动画(转) iphone http://www.cocoachina.com/bbs/read.php?tid=124506
首先引入框架:QuartzCore.framework
在头文件声明:CALayer *logoLayer
{
//界限

CABasicAnimation *boundsAnimation = [CABasicAnimationanimationWithKeyPath:@"bounds"];
boundsAnimation.fromValue = [NSValue valueWithCGRect: logoLayer.bounds];
boundsAnimation.toValue = [NSValue valueWithCGRect:CGRectZero];


//透明度变化
CABasicAnimation *opacityAnimation = [CABasicAnimationanimationWithKeyPath:@"opacity"];
opacityAnimation.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnimation.toValue = [NSNumber numberWithFloat:0.5];
//位置移动

CABasicAnimation *animation  = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue =  [NSValue valueWithCGPoint: logoLayer.position];
CGPoint toPoint = logoLayer.position;
toPoint.x += 180;
animation.toValue = [NSValue valueWithCGPoint:toPoint];
//旋转动画
CABasicAnimation* rotationAnimation =
       [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];//"z"还可以是“x”“y”,表示沿z轴旋转
rotationAnimation.toValue = [NSNumber numberWithFloat:(2 * M_PI) * 3]; 
    // 3 is the number of 360 degree rotations
// Make the rotation animation duration slightly less than the other animations to give it the feel
// that it pauses at its largest scale value
rotationAnimation.duration = 2.0f;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; //缓入缓出


//缩放动画

CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.fromValue = [NSNumber numberWithFloat:0.0];
scaleAnimation.toValue = [NSNumber numberWithFloat:1.0];
scaleAnimation.duration = 2.0f;
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.duration = 2.0f;
animationGroup.autoreverses = YES;   //是否重播,原动画的倒播
animationGroup.repeatCount = NSNotFound;//HUGE_VALF;     //HUGE_VALF,源自math.h
[animationGroup setAnimations:[NSArray arrayWithObjects:rotationAnimation, scaleAnimation, nil]];


//将上述两个动画编组
[logoLayer addAnimation:animationGroup forKey:@"animationGroup"];
}
//去掉所有动画
[logoLayer removeAllAnimations];
//去掉key动画

[logoLayer removeAnimationForKey:@"animationGroup"];
日期格式化元素含义 android, iphone, java
字母  日期或时间元素  表示  示例  
G  Era 标志符  Text  AD  
y  年  Year  1996; 96  
M  年中的月份  Month  July; Jul; 07  
w  年中的周数  Number  27  
W  月份中的周数  Number  2  
D  年中的天数  Number  189  
d  月份中的天数  Number  10  
F  月份中的星期  Number  2  
E  星期中的天数  Text  Tuesday; Tue  
a  Am/pm 标记  Text  PM  
H  一天中的小时数(0-23)  Number  0  
k  一天中的小时数(1-24)  Number  24  
K  am/pm 中的小时数(0-11)  Number  0  
h  am/pm 中的小时数(1-12)  Number  12  
m  小时中的分钟数  Number  30  
s  分钟中的秒数  Number  55  
S  毫秒数  Number  978  
z  时区  General time zone  Pacific Standard Time; PST; GMT-08:00  
Z  时区  RFC 822 time zone  -0800
NSArray的排序方法 iphone NSArray的排序方法
1.sortedArrayUsingSelector
(按Key值大小对NSDictionary排序)
[plain] view plaincopy
NSMutableArray *array = [NSMutableArray arrayWithObjects:  
                             [NSDictionary dictionaryWithObjectsAndKeys:@"Obj0", [NSNumber numberWithInt:0], nil],  
                             [NSDictionary dictionaryWithObjectsAndKeys:@"Obj5", [NSNumber numberWithInt:5], nil],  
                             [NSDictionary dictionaryWithObjectsAndKeys:@"Obj2", [NSNumber numberWithInt:2], nil],  
                             [NSDictionary dictionaryWithObjectsAndKeys:@"Obj3", [NSNumber numberWithInt:3], nil],  
                             [NSDictionary dictionaryWithObjectsAndKeys:@"Obj1", [NSNumber numberWithInt:1], nil],  
                             [NSDictionary dictionaryWithObjectsAndKeys:@"Obj4", [NSNumber numberWithInt:4], nil], nil];  
      
NSArray *resultArray = [array sortedArrayUsingSelector:@selector(compare:)];  

因为NSDictionary没有compare的排序比较方法,所以需要我们自己写
[plain] view plaincopy
.h  
@interface NSDictionary (compare)  
{}  
  
-(NSComparisonResult)compare:(NSDictionary *)otherDictionary;  
  
@end  
  
.m  
@implementation NSDictionary (compare)  
  
- (NSComparisonResult)compare: (NSDictionary *)otherDictionary  
{  
    NSDictionary *tempDictionary = (NSDictionary *)self;  
      
    NSNumber *number1 = [[tempDictionary allKeys] objectAtIndex:0];  
    NSNumber *number2 = [[otherDictionary allKeys] objectAtIndex:0];  
      
    NSComparisonResult result = [number1 compare:number2];  
      
    return result == NSOrderedDescending; // 升序  
//    return result == NSOrderedAscending;  // 降序  
}  
  
@end  

2.sortedArrayUsingComparator
[plain] view plaincopy
NSMutableArray *array = [NSMutableArray arrayWithObjects:  
                         [NSDictionary dictionaryWithObjectsAndKeys:@"Obj0", [NSNumber numberWithInt:0], nil],  
                         [NSDictionary dictionaryWithObjectsAndKeys:@"Obj5", [NSNumber numberWithInt:5], nil],  
                         [NSDictionary dictionaryWithObjectsAndKeys:@"Obj2", [NSNumber numberWithInt:2], nil],  
                         [NSDictionary dictionaryWithObjectsAndKeys:@"Obj3", [NSNumber numberWithInt:3], nil],  
                         [NSDictionary dictionaryWithObjectsAndKeys:@"Obj1", [NSNumber numberWithInt:1], nil],  
                         [NSDictionary dictionaryWithObjectsAndKeys:@"Obj4", [NSNumber numberWithInt:4], nil], nil];  
  
  NSArray *resultArray = [array sortedArrayUsingSelector:@selector(compare:)];  
  
NSArray *resultArray = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {  
      
    NSNumber *number1 = [[obj1 allKeys] objectAtIndex:0];  
    NSNumber *number2 = [[obj2 allKeys] objectAtIndex:0];  
      
    NSComparisonResult result = [number1 compare:number2];  
      
    return result == NSOrderedDescending; // 升序  
      return result == NSOrderedAscending;  // 降序  
}];  
3.sortedArrayUsingDescriptors & sortUsingDescriptors
前者带返回值,是NSArray的方法,排好序的数组是返回值中的数组;
后者不带返回值,是NSMutableArray的方法,是对当前数组自己排序
[plain] view plaincopy
.h  
@interface Person : NSObject  
{  
    NSString  *_name;  
      
    NSInteger  _age;  
}  
@property (nonatomic, retain) NSString  *name;  
@property (nonatomic, assign) NSInteger  age;  
@end  
  
.m  
@implementation Person  
@synthesize name = _name;  
@synthesize age  = _age;  
  
  
- (void)dealloc  
{  
    [_name release];  
      
    [super dealloc];  
}  
  
@end  
[plain] view plaincopy
    Person *person1 = [[Person alloc] init];  
    [person1 setName:@"ABC"];  
    [person1 setAge:24];  
      
    Person *person2 = [[Person alloc] init];  
    [person2 setName:@"ACB"];  
    [person2 setAge:22];  
      
    Person *person3 = [[Person alloc] init];  
    [person3 setName:@"ABD"];  
    [person3 setAge:33];  
      
    NSMutableArray *array = [NSMutableArray arrayWithObjects:person1, person2, person3, nil];  
    [person1 release];  
    [person2 release];  
    [person3 release];  
      
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"_age" ascending:YES];  
      
    NSArray *tempArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];  
      
    for(NSInteger i = 0; i < [tempArray count]; i++)  
    {  
        NSLog(@"%@--------%d\n", [[tempArray objectAtIndex:i] name], [[tempArray objectAtIndex:i] age]);  
    }  
      
//    [array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];  
//      
//    for(NSInteger i = 0; i < [array count]; i++)  
//    {  
//        NSLog(@"%@--------%d\n", [[array objectAtIndex:i] name], [[array objectAtIndex:i] age]);  
//    }  
sortDescriptorWithKey:@"_age",以age作为标准来做比较。
[plain] view plaincopy
    Person *person1 = [[Person alloc] init];  
    [person1 setName:@"ABCD"];  
    [person1 setAge:24];  
      
    Person *person2 = [[Person alloc] init];  
    [person2 setName:@"ACBD"];  
    [person2 setAge:22];  
      
    Person *person3 = [[Person alloc] init];  
    [person3 setName:@"ABDC"];  
    [person3 setAge:33];  
      
    Person *person4 = [[Person alloc] init];  
    [person4 setName:@"ACDB"];  
    [person4 setAge:22];  
      
    NSMutableArray *array = [NSMutableArray arrayWithObjects:person1, person3, person4, person2, nil];  
    [person1 release];  
    [person2 release];  
    [person3 release];  
    [person4 release];  
      
    NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"_age" ascending:YES];  
    NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"_name" ascending:YES];  
      
    NSArray *tempArray = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor1, sortDescriptor2, nil]];  
      
    for(NSInteger i = 0; i < [tempArray count]; i++)  
    {  
        NSLog(@"%@--------%d\n", [[tempArray objectAtIndex:i] name], [[tempArray objectAtIndex:i] age]);  
    }  
      
//    [array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];  
//      
//    for(NSInteger i = 0; i < [array count]; i++)  
//    {  
//        NSLog(@"%@--------%d\n", [[array objectAtIndex:i] name], [[array objectAtIndex:i] age]);  
//    }  

    NSSortDescriptor *sortDescriptor1 = [NSSortDescriptorsortDescriptorWithKey:@"_age"ascending:YES];
   NSSortDescriptor *sortDescriptor2 = [NSSortDescriptorsortDescriptorWithKey:@"_name"ascending:YES];
    NSArray *tempArray = [array sortedArrayUsingDescriptors:[NSArrayarrayWithObjects:sortDescriptor1, sortDescriptor2, nil]];

这里的NSArray中的第一元素表示首先按照这个元素的升序或者降序进行排序,对于有重复项的,再按照第二元素进行排序,依次进行类推
IOS 开发,调用打电话,发短信,打开网址 iphone IOS 开发,调用打电话,发短信,打开网址
1、调用 自带mail
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://admin@hzlzh.com"]];
 
2、调用 电话phone
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://8008808888"]];
 
3、调用 SMS
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms://800888"]];
 
4、调用自带 浏览器 safari
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.hzlzh.com"]];
 
调用phone可以传递号码,调用SMS 只能设定号码,不能初始化SMS内容。
 
若需要传递内容可以做如下操作:
加入:MessageUI.framework
 
#import <MessageUI/MFMessageComposeViewController.h>
 
实现代理:MFMessageComposeViewControllerDelegate
 
 
 
调用sendSMS函数
//内容,收件人列表
- (void)sendSMS:(NSString *)bodyOfMessage recipientList:(NSArray *)recipients
{
 
    MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
 
    if([MFMessageComposeViewController canSendText])
 
    {
 
        controller.body = bodyOfMessage;   
 
        controller.recipients = recipients;
 
        controller.messageComposeDelegate = self;
 
        [self presentModalViewController:controller animated:YES];
 
    }   
 
}
 
// 处理发送完的响应结果
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
  [self dismissModalViewControllerAnimated:YES];
 
  if (result == MessageComposeResultCancelled)
    NSLog(@"Message cancelled")
  else if (result == MessageComposeResultSent)
    NSLog(@"Message sent")  
  else 
    NSLog(@"Message failed")  
}
 
 
发送邮件的为:
导入#import <MessageUI/MFMailComposeViewController.h>
实现代理:MFMailComposeViewControllerDelegate
 
//发送邮件
-(void)sendMail:(NSString *)subject content:(NSString *)content{
 
    MFMailComposeViewController *controller = [[[MFMailComposeViewController alloc] init] autorelease];
 
    if([MFMailComposeViewController canSendMail])
 
    {
 
        [controller setSubject:subject];
 
        [controller setMessageBody:content isHTML:NO];
 
        controller.mailComposeDelegate = self;
 
        [self presentModalViewController:controller animated:YES];
 
    }    
}
 
//邮件完成处理
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error{
 
    [self dismissModalViewControllerAnimated:YES];
 
    if (result == MessageComposeResultCancelled)
        NSLog(@"Message cancelled");
    else if (result == MessageComposeResultSent)
        NSLog(@"Message sent"); 
    else 
        NSLog(@"Message failed");  
 
}
 
 
 
 
默认发送短信的界面为英文的,解决办法为:
在.xib 中的Localization添加一組chinese就ok了
objective-c 字符串、日期、Int转换 iphone objective-c 字符串、日期、Int转换
1、字符串转换为日期
  NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];//实例化一个NSDateFormatter对象
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//设定时间格式,这里可以设置成自己需要的格式
NSDate *date =[dateFormat dateFromString:@"1980-01-01 00:00:01"];
2、日期转换为字符串
NSDateFormatter* dateFormat = [[NSDateFormatter alloc] init];//实例化一个NSDateFormatter对象
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];//设定时间格式,这里可以设置成自己需要的格式
NSString *currentDateStr = [dateFormat stringFromDate:[NSDate date]];
3、字符串转int
Convert NSString to int
NSString *aNumberString = @"123";
int i = [aNumberString intValue];
4、int转字符串
Convert int to NSString
int aNumber = 123;
NSString *aString = [NSString stringWithFormat:@"%d", aNumber];
Objective-C运算符 iphone Objective-C运算符
算术运算符:
用于各类数值运算。包括加(+)、减(.)、乘(*)、除(/)、求余(或称模运算,%)、自增(++)、自减(..)共七种。

关系运算符:
用于比较运算。包括大于(>)、小于(<)、等于(==)、 大于等于(>=)、小于等于(<=)和不等于(!=)六种。


逻辑运算符:
用于逻辑运算。包括与(&&)、或(||)、非(!)三种。


位操作运算符:
参与运算的数值按二进制位进行运算。包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)六种。


赋值运算符:
用于赋值运算,分为简单赋值(=)、复合算术赋值(+=、.=、*=、/=、%=)和复合位运算赋值(&=、|=、^=、>>=、<<=)三类共十一种。


条件运算符:
这是一个三目运算符,用于条件求值(?:)。


逗号运算符:
使用“,”把若干表达式组合成一个表达式。


指针运算符:
用于取内容(*)和取地址(&)二种运算。


求字节数运算符:
用于计算数据类型所占的字节数(sizeof)。


特殊运算符:
有括号(( ))、下标([ ])、成员(.)等几种。
objective-c字符串处理 iphone IOS基础:Objective-C 字符串处理
/一、NSString
/*----------------创建字符串的方法----------------*/
 
//1、创建常量字符串。
NSString *astring = @"This is a String!";

//2、创建空字符串,给予赋值。
NSString *astring = [[NSString alloc] init];
astring = @"This is a String!";
[astring release];
NSLog(@"astring:%@",astring);
 
//3、在以上方法中,提升速度:initWithString方法
NSString *astring = [[NSString alloc] initWithString:@"This is a String!"];
NSLog(@"astring:%@",astring);
[astring release];

//4、用标准c创建字符串:initWithCString方法
char *Cstring = "This is a String!";
NSString *astring = [[NSString alloc] initWithCString:Cstring];
NSLog(@"astring:%@",astring);
[astring release];

//5、创建格式化字符串:占位符(由一个%加一个字符组成)
int i = 1;
int j = 2;
NSString *astring = [[NSString alloc] initWithString:[NSString stringWithFormat:@"%d.This is %i string!",i,j]];
NSLog(@"astring:%@",astring);
[astring release];

//6、创建临时字符串
NSString *astring;
astring = [NSString stringWithCString:"This is a temporary string"];
NSLog(@"astring:%@",astring);


/*----------------从文件读取字符串:initWithContentsOfFile方法----------------*/
NSString *path = @"astring.text";
NSString *astring = [[NSString alloc] initWithContentsOfFile:path];
NSLog(@"astring:%@",astring);
[astring release];

/*----------------写字符串到文件:writeToFile方法----------------*/

NSString *astring = [[NSString alloc] initWithString:@"This is a String!"];
NSLog(@"astring:%@",astring);
NSString *path = @"astring.text";
[astring writeToFile: path atomically: YES];
[astring release];

/*----------------比较两个字符串----------------*/

//用C比较:strcmp函数
char string1[] = "string!";
char string2[] = "string!";
if(strcmp(string1, string2) = = 0)
{
NSLog(@"1");
}

//isEqualToString方法
NSString *astring01 = @"This is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 isEqualToString:astring02];
NSLog(@"result:%d",result);

//compare方法(comparer返回的三种值)
NSString *astring01 = @"This is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 compare:astring02] = = NSOrderedSame;
NSLog(@"result:%d",result);
//NSOrderedSame判断两者内容是否相同

NSString *astring01 = @"This is a String!";
NSString *astring02 = @"this is a String!";
BOOL result = [astring01 compare:astring02] = = NSOrderedAscending;
NSLog(@"result:%d",result);
//NSOrderedAscending判断两对象值的大小(按字母顺序进行比较,astring02大于astring01为真)

NSString *astring01 = @"this is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 compare:astring02] = = NSOrderedDescending;
NSLog(@"result:%d",result);
//NSOrderedDescending判断两对象值的大小(按字母顺序进行比较,astring02小于astring01为真)

//不考虑大小写比较字符串1
NSString *astring01 = @"this is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 caseInsensitiveCompare:astring02] = = NSOrderedSame;
NSLog(@"result:%d",result);
//NSOrderedDescending判断两对象值的大小(按字母顺序进行比较,astring02小于astring01为真)

//不考虑大小写比较字符串2
NSString *astring01 = @"this is a String!";
NSString *astring02 = @"This is a String!";
BOOL result = [astring01 compare:astring02
options:NSCaseInsensitiveSearch | NSNumericSearch] = = NSOrderedSame;
NSLog(@"result:%d",result);

//NSCaseInsensitiveSearch:不区分大小写比较 NSLiteralSearch:进行完全比较,区分大小写 NSNumericSearch:比较字符串的字符个数,而不是字符值。

/*----------------改变字符串的大小写----------------*/
NSString *string1 = @"A String";
NSString *string2 = @"String";
NSLog(@"string1:%@",[string1 uppercaseString]);//大写
NSLog(@"string2:%@",[string2 lowercaseString]);//小写
NSLog(@"string2:%@",[string2 capitalizedString]);//首字母大小

/*---------------在串中搜索子串----------------*/
NSString *string1 = @"This is a string";
NSString *string2 = @"string";
NSRange range = [string1 rangeOfString:string2];
int location = range.location;
int leight = range.length;
NSString *astring = [[NSString alloc] initWithString:[NSString stringWithFormat:@"Location:%i,Leight:%i",location,leight]];
NSLog(@"astring:%@",astring);
[astring release];

/*----------------抽取子串 ----------------*/

//-substringToIndex: 从字符串的开头一直截取到指定的位置,但不包括该位置的字符
NSString *string1 = @"This is a string";
NSString *string2 = [string1 substringToIndex:3];
NSLog(@"string2:%@",string2);

//-substringFromIndex: 以指定位置开始(包括指定位置的字符),并包括之后的全部字符
NSString *string1 = @"This is a string";
NSString *string2 = [string1 substringFromIndex:3];
NSLog(@"string2:%@",string2);

//-substringWithRange: //按照所给出的位置,长度,任意地从字符串中截取子串
NSString *string1 = @"This is a string";
NSString *string2 = [string1 substringWithRange:NSMakeRange(0, 4)];
NSLog(@"string2:%@",string2);

//扩展路径
NSString *Path = @"~/NSData.txt";
NSString *absolutePath = [Path stringByExpandingTildeInPath];
NSLog(@"absolutePath:%@",absolutePath);
NSLog(@"Path:%@",[absolutePath stringByAbbreviatingWithTildeInPath]);

//文件扩展名
NSString *Path = @"~/NSData.txt";
NSLog(@"Extension:%@",[Path pathExtension]);

/*******************************************************************************************
NSMutableString
*******************************************************************************************/

/*---------------给字符串分配容量----------------*/
//stringWithCapacity:
NSMutableString *String;
String = [NSMutableString stringWithCapacity:40];

/*---------------在已有字符串后面添加字符----------------*/

//appendString: and appendFormat:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
//[String1 appendString:@", I will be adding some character"];
[String1 appendFormat:[NSString stringWithFormat:@", I will be adding some character"]];
NSLog(@"String1:%@",String1);
*/

/*--------在已有字符串中按照所给出范围和长度删除字符------*/
/*
//deleteCharactersInRange:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 deleteCharactersInRange:NSMakeRange(0, 5)];
NSLog(@"String1:%@",String1);

/*--------在已有字符串后面在所指定的位置中插入给出的字符串------*/

//-insertString: atIndex:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 insertString:@"Hi! " atIndex:0];
NSLog(@"String1:%@",String1);

/*--------将已有的空符串换成其它的字符串------*/

//-setString:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 setString:@"Hello Word!"];
NSLog(@"String1:%@",String1);

/*--------按照所给出的范围,和字符串替换的原有的字符------*/

//-setString:
NSMutableString *String1 = [[NSMutableString alloc] initWithString:@"This is a NSMutableString"];
[String1 replaceCharactersInRange:NSMakeRange(0, 4) withString:@"That"];
NSLog(@"String1:%@",String1);

/*-------------判断字符串内是否还包含别的字符串(前缀,后缀)-------------*/
//01:检查字符串是否以另一个字符串开头- (BOOL) hasPrefix: (NSString *) aString;
NSString *String1 = @"NSStringInformation.txt";
[String1 hasPrefix:@"NSString"] = = 1 ?NSLog(@"YES") : NSLog(@"NO");
[String1 hasSuffix:@".txt"] = = 1 ?NSLog(@"YES") : NSLog(@"NO");

//02:查找字符串某处是否包含其它字符串 - (NSRange) rangeOfString: (NSString *) aString,这一点前面在串中搜索子串用到过;


/*-------------以参数为分隔符,把切分字符串,并返回切分后的数组。-------------*/
-(NSArray) componentsSeparatedByString:(NSString *) aString;
实例:
NSString *string = @"opp:ack:bork:greeble:ponoes";
NSArray *chunks = [string componentsSeparatedByString:@":"];
Android主流机型分辨率总结 android
==== 320x480 ====
1. 三星 S5830 Galaxy Ace
2. 索尼爱立信 X8 (E15i)
3. 华为 U8500 
4. Motorola XT502 
5. LG P503
6. 酷派 D530
7. LG GT540
8. 夏普 SH8118U
9. 天语 W606 (估计运行困难)
10. 中兴 R750
11. 华为 U8500-HiQQ (估计运行困难)
12. 酷派 W711(估计运行困难)
13. 首派 A60
14. 三星I7500
15. HTC G6 Legend
16. Motorola ME600
17. Motorola CLIQ
18. 三星 I5700
19. HTC Aria (G9)
20. LG GW620
21. 华为 C8600
22. Motorola ME501
23. LG P500


==== 480x800 ====
1. HTC Desire (G7)
2. HTC A9191 
3. 三星 I9003 
4. 联想W101 乐phone (1.6系统非原生)
5. 夏普 SH8128 
6. 三星 I9088
7. 中兴 V880
8. 三星 I909
9. Motorola A1680
10. 联想W100 乐phone(1.6)
11. 联想C101  
12. 酷派 N930
13. 三星 I9088
14. HTC 双擎T9199
15. HTC A9191
16. 中兴 V9E
17. 三星I909 (SPhone)
18. 酷派 N930
19. 华为 U8800
20. HTC Desire HD (G10)
21. 三星 I9010
22. 夏普 SH7218U(新机)
23. Google Nexus One (G5)
24. Google Nexus S
25. 三星I9000
26. 三星T959
27. 三星W899
28. HTC Incredible S (S710e)
29. HTC Desire Z
30. HTC EVO 4G
31. 戴尔Mini5 (Streak)
32. 三星I9020
33. 戴尔Venue 

==== 640x960 ====
1. 魅族 M9

==== 480x854 ====
1. Motorola XT702
2. Motorola XT711
3. Motorola ME722 (里程碑2)
4. Motorola XT800
5. Motorola ME811 (Droid X)
6. Motorola ME525
7. Motorola XT800+ 
8. 索尼爱立信 X10i
9. Motorola XT806Ix


==== 320x240 ====
1. SAMSUNG S5570
2. HTC A3366 Wildfire
3. Motorola ME511 
4. Motorola XT301 
5. 华为 C8500
6. HTC A3380 
7. 三星 I5508
8. HTC A3360
9. 中兴 X850
10. Motoroal XT300
11. 索尼爱立信 U201

==== 600x1024 ====
1. 三星 Galaxy P1000
Android屏幕密度(Density)和分辨率的解释 android http://www.cnblogs.com/scotthenry/archive/2010/11/14/1877166.html
HVGA屏density=160;QVGA屏density=120;WVGA屏density=240;WQVGA屏density=120
density值表示每英寸有多少个显示点,与分辨率是两个概念。

不同density下屏幕 分辨率信息,以480dip*800dip的WVGA(density=240)为例

density=120时 屏幕实际分辨率为240px*400px (两个点对应一个分辨率)
状态栏和标题栏高各19px或者25dip 
横屏是屏幕宽度400px 或者800dip,工作区域高度211px或者480dip
竖屏时屏幕宽度240px或者480dip,工作区域高度381px或者775dip

density=160时 屏幕实际分辨率为320px*533px (3个点对应两个分辨率)
状态栏和标题栏高个25px或者25dip 
横屏是屏幕宽度533px 或者800dip,工作区域高度295px或者480dip
竖屏时屏幕宽度320px或者480dip,工作区域高度508px或者775dip


density=240时 屏幕实际分辨率为480px*800px (一个点对于一个分辨率)
状态栏和标题栏高个38px或者25dip 
横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip
竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip


apk的资源包中,当屏幕density=240时使用hdpi标签的资源
当屏幕density=160时,使用mdpi标签的资源
当屏幕density=120时,使用ldpi标签的资源。
不加任何标签的资源是各种分辨率情况下共用的。
布局时尽量使用单位dip,少使用px
java 整除(/) 求余(%) 运算 java
java 整除(/)  求余(%)  运算

1.求余
    System.out.println(11%2);     //顾名思义就是11除2的余数-->1
    System.out.println(11%-2);    //结果-->1
    System.out.println(-11%2);    //结果-->-1
    System.out.println(-11%-2);   //结果-->-1

    求余的正负号说明:
    主要是取决于前面一个数是正数还是负数,不管后面数。

    例子1:System.out.println(115%5);     //结果为-->0
    例子2:System.out.println(115%2);     //结果为-->1


2.整除
    System.out.println(11/2);     //就是11除2的商-->5
    System.out.println(11/-2);    //结果-->-5
    System.out.println(-11/2);    //结果-->-5
    System.out.println(-11/-2);   //结果-->5

    例子1:System.out.println(10/2);   //结果-->5
    例子2:System.out.println(10.0/2);   //结果-->5.0
    例子3:System.out.println(35/2);   //结果-->17
    例子4:System.out.println(0.35/2);   //结果-->0.175
关于uses-permission权限列表 android
android.permission.ACCESS_CHECKIN_PROPERTIES
允许读写访问”properties”表在checkin数据库中,改值可以修改上传

android.permission.ACCESS_COARSE_LOCATION
允许一个程序访问CellID或WiFi来获取粗略的位置

android.permission.ACCESS_FINE_LOCATION
允许一个程序访问精良位置(如GPS)

android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
允许应用程序访问额外的位置提供命令

android.permission.ACCESS_MOCK_LOCATION
允许程序创建模拟位置用于测试

android.permission.ACCESS_NETWORK_STATE
允许程序访问有关的网络信息

android.permission.ACCESS_SURFACE_FLINGER
允许程序使用SurfaceFlinger底层特性

android.permission.ACCESS_WIFI_STATE
允许程序访问Wi-Fi网络状态信息

android.permission.ACCOUNT_MANAGER
允许一个应用程序启动账户认证,该权限只能系统去设置

android.permission.AUTHENTICATE_ACCOUNTS
允许应用程序的验证账户扮演一个账户管理者

android.permission.BATTERY_STATS
允许程序更新手机电池统计信

android.permission.BIND_APPWIDGET
许应用告诉AppWidget哪个应用能够访问该AppWidget的数据

android.permission.BIND_DEVICE_ADMIN
必须通过关机接收者的请求,来确保只有系统能够与之交互

android.permission.BIND_INPUT_METHOD
必须通过InputMethodService的请求,来确保只有系统能够与之绑定

android.permission.BIND_WALLPAPER
必须通过WallpaperService的请求,来确保只有系统能够与之绑定

android.permission.BLUETOOTH
允许程序连接到已配对的蓝牙设备

android.permission.BLUETOOTH_ADMIN
允许程序发现和配对蓝牙设备

android.permission.BRICK
请求能够禁用设备(非常危险)

android.permission.BROADCAST_PACKAGE_REMOVED
允许应用发出一个程序包被移除的广播消息

android.permission.BROADCAST_SMS
允许应用发出一个收到短信的消息

android.permission.BROADCAST_STICKY
允许应用发出一个与intent相连的消息

android.permission.BROADCAST_WAP_PUSH
允许应用发出一个收到WAP PUSH的广播消息

android.permission.CALL_PHONE
允许一个程序初始化一个电话拨号,不需通过拨号用户界面需要用户确认

android.permission.CALL_PRIVILEGED
允许一个程序拨打任何号码,包含紧急号码无需通过拨号用户界面需要用户确认

android.permission.CAMERA
请求访问使用照相设备

android.permission.CHANGE_COMPONENT_ENABLED_STATE
允许一个程序是否改变一个组件或其他的启用或禁用

android.permission.CHANGE_CONFIGURATION
允许一个程序修改当前设置,如本地化

android.permission.CHANGE_NETWORK_STATE
允许程序改变网络连接状态

android.permission.CHANGE_WIFI_STATE
允许程序改变Wi-Fi连接状态

android.permission.CLEAR_APP_CACHE
允许一个程序在设备中清除所有安装的程序的缓存

android.permission.CLEAR_APP_USER_DATA
允许一个程序清除用户数据

android.permission.CONTROL_LOCATION_UPDATES
允许启用禁止位置更新提示从无线模块

android.permission.DELETE_CACHE_FILES
允许程序删除缓存文件

android.permission.DELETE_PACKAGES
允许一个程序删除包

android.permission.DEVICE_POWER
允许访问底层电源管理

android.permission.DIAGNOSTIC
允许程序RW诊断资源

android.permission.DISABLE_KEYGUARD
允许程序禁用键盘锁

android.permission.DUMP
允许程序返回状态抓取信息从系统服务

android.permission.EXPAND_STATUS_BAR
允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序

android.permission.FACTORY_TEST
作为一个工厂测试程序,运行在root用户

android.permission.FLASHLIGHT
允许访问闪光灯,其中HTC Dream不包含闪光灯

android.permission.FORCE_BACK

允许应用强制执行返回操作而不论是不是最终的activity

android.permission.GET_ACCOUNTS
允许访问在Accounts Service中的一个帐户列表

android.permission.GET_PACKAGE_SIZE
允许一个程序获取任何package占用空间容量

android.permission.GET_TASKS
允许一个程序获取信息有关当前或最近运行的任务,一个缩略的任务状态,是否活动等等

android.permission.GLOBAL_SEARCH

可以被内容提供者用来允许使用全程搜索他们的数据

android.permission.HARDWARE_TEST
允许访问硬件

android.permission.INJECT_EVENTS
允许一个程序截获用户事件如按键、触摸、轨迹球等等到一个时间流

android.permission.INSTALL_PACKAGES
允许一个程序安装packages

android.permission.INTERNAL_SYSTEM_WINDOW
允许打开窗口使用系统用户界面

android.permission.INTERNET
允许程序打开网络sockets

android.permission.KILL_BACKGROUND_PROCESSES

允许应用去呼叫killBackgroundProcesses方法

android.permission.MANAGE_ACCOUNTS
允许程序去管理账户列表(在账户管理者中)

android.permission.MANAGE_APP_TOKENS
允许程序管理(创建、催后、 z- order默认向z轴推移)程序引用在窗口管理器中

android.permission.MASTER_CLEAR

目前还没有明确的解释

android.permission.MODIFY_AUDIO_SETTINGS
允许程序修改全局音频设置

android.permission.MODIFY_PHONE_STATE
允许修改话机状态,如电源,人机接口等

android.permission.MODIFY_FORMAT_FILESYSTEMS

允许格式化可移除的存储仓库的文件系统

android.permission.MOUNT_UNMOUNT_FILESYSTEMS
允许挂载和反挂载文件系统可移动存储

android.permission.PERSISTENT_ACTIVITY
允许一个程序设置他的activities显示

android.permission.PROCESS_OUTGOING_CALLS
允许程序监视、修改有关播出电话

android.permission.READ_CALENDAR
允许程序读取用户日历数据

android.permission.READ_CONTACTS
允许程序读取用户联系人数据

android.permission.READ_FRAME_BUFFER
允许程序屏幕波或和更多常规的访问帧缓冲数据

android.permission.READ_HISTORY_BOOKMARKS
允许应用去读取(非写)用户浏览历史和书签

android.permission.READ_INPUT_STATE
允许程序返回当前按键状态

android.permission.READ_LOGS
允许程序读取底层系统日志文件

android.permission.READ_OWNER_DATA
允许程序读取所有者数据

android.permission.READ_PHONE_STATE
允许读取电话的状态

android.permission.READ_SMS
允许程序读取短信息(Allows an application to read SMS messages.)

android.permission.READ_SYNC_SETTINGS
允许程序读取同步设置

android.permission.READ_SYNC_STATS
允许程序读取同步状态

android.permission.REBOOT
请求能够重新启动设备

android.permission.RECEIVE_BOOT_COMPLETED
允许一个程序接收到 ACTION_BOOT_COMPLETED广播在系统完成启动

android.permission.RECEIVE_MMS
允许一个程序监控将收到MMS彩信,记录或处理

android.permission.RECEIVE_SMS
允许程序监控一个将收到短信息,记录或处理

android.permission.RECEIVE_WAP_PUSH
允许程序监控将收到WAP PUSH信息

android.permission.RECORD_AUDIO
允许程序录制音频

android.permission.REORDER_TASKS
允许程序改变Z轴排列任务

android.permission.RESTART_PACKAGES
允许程序重新启动其他程序(此值已废弃使用)

android.permission.SEND_SMS
允许程序发送SMS短信

android.permission.SET_ACTIVITY_WATCHER
允许程序监控或控制activities已经启动全局系统中

android.permission.SET_ALWAYS_FINISH
允许程序控制是否活动间接完成在处于后台时

android.permission.SET_ANIMATION_SCALE
修改全局信息比例

android.permission.SET_DEBUG_APP
配置一个程序用于调试

android.permission.SET_ORIENTATION
允许底层访问设置屏幕方向和实际旋转

android.permission.SET_PREFERRED_APPLICATIONS
允许一个程序修改列表参数PackageManager.addPackageToPreferred()和PackageManager.removePackageFromPreferred()方法

android.permission.SET_PROCESS_LIMIT
允许设置最大的运行进程数量

android.permission.SET_TIME
允许应用设置系统时间

android.permission.SET_TIME_ZONE
允许程序设置系统时区时间

android.permission.SET_WALLPAPER
允许程序设置壁纸

android.permission.SET_WALLPAPER_HINTS
允许程序设置壁纸hits

android.permission.SIGNAL_PERSISTENT_PROCESSES
允许程序请求发送信号到所有显示的进程中

android.permission.STATUS_BAR
允许程序打开、关闭或禁用状态栏及图标

android.permission.SUBSCRIBED_FEEDS_READ
允许一个程序访问订阅RSS Feed内容提供

android.permission.SUBSCRIBED_FEEDS_WRITE
系统暂时保留改设置,

android.permission.SYSTEM_ALERT_WINDOW
允许一个程序打开窗口使用 TYPE_SYSTEM_ALERT,显示在其他所有程序的顶层

android.permission.UPDATE_DEVICE_STATS
允许应用更新设备资料信息

android.permission.USE_CREDENTIALS
允许应用从管理器得到授权请求

android.permission.VIBRATE
允许访问振动设备

android.permission.WAKE_LOCK
允许使用PowerManager的 WakeLocks保持进程在休眠时从屏幕消失

android.permission.WRITE_APN_SETTINGS
允许程序写入API设置

android.permission.WRITE_CALENDAR
允许一个程序写入但不读取用户日历数据

android.permission.WRITE_CONTACTS
允许程序写入但不读取用户联系人数据

android.permission.WRITE_EXTERNAL_STORAGE
允许应用写(非读)用户的外部存储器

android.permission.WRITE_GSERVICES
允许程序修改Google服务地图

android.permission.WRITE_HISTORY_BOOKMARKS
允许应用写(非读)用户的浏览器历史和书签

android.permission.WRITE_OWNER_DATA
允许一个程序写入但不读取所有者数据

android.permission.WRITE_SECURE_SETTINGS
允许应用写或读当前系统设置

android.permission.WRITE_SETTINGS
允许程序读取或写入系统设置

android.permission.WRITE_SMS
允许程序写短信

android.permission.WRITE_SYNC_SETTINGS
允许程序写入同步设置
java 运算符 java
Java运算符

Java提供了丰富的运算符环境。Java有4大类运算符:算术运算、位运算、关系运算和逻辑运算。Java还定义了一些附加的运算符用于处理特殊情况。本章将描述Java所有的运算符,而比较运算符instanceof将在第12章讨论。 

注意:如果你对C/C++熟悉,你将会高兴,因为Java的绝大多数运算符和C/C++中的用法一样。但有一些微妙的差别,所以提醒你要仔细阅读。 

4.1 算术运算符 

算术运算符用在数学表达式中,其用法和功能与代数学(或其他计算机语言)中一样,Java定义了下列算术运算符(见表4-1): 

表4.1 算术运算符及其含义 

运算符 含义 

+ 加法 

– 减法(一元减号) 

* 乘法 

/ 除法 

% 模运算 

++ 递增运算 

+= 加法赋值 

–= 减法赋值 

*= 乘法赋值 

/= 除法赋值 

%= 模运算赋值 

-- 递减运算 

算术运算符的运算数必须是数字类型。算术运算符不能用在布尔类型上,但是可以用在char类型上,因为实质上在Java中,char类型是int类型的一个子集。 

4.1.1 基本算术运算符 

基本算术运算符——加、减、乘、除可以对所有的数字类型操作。减运算也用作表示单个操作数的负号。记住对整数进行“/”除法运算时,所有的余数都要被舍去。下面这个简单例子示范了算术运算符,也说明了浮点型除法和整型除法之间的差别。 

// Demonstrate the basic arithmetic operators. 

class BasicMath { 

public static void main(String args[]) { 

// arithmetic using integers 

System.out.println("Integer Arithmetic"); 

int a = 1 + 1; 

int b = a * 3; 

int c = b / 4; 

int d = c - a; 

int e = -d; 

System.out.println("a = " + a); 

System.out.println("b = " + b); 

System.out.println("c = " + c); 

System.out.println("d = " + d); 

System.out.println("e = " + e); 

// arithmetic using doubles 

System.out.println("\nFloating Point Arithmetic"); 

double da = 1 + 1; 

double db = da * 3; 

double dc = db / 4; 

double dd = dc - a; 

double de = -dd; 

System.out.println("da = " + da); 

System.out.println("db = " + db); 

System.out.println("dc = " + dc); 

System.out.println("dd = " + dd); 

System.out.println("de = " + de); 

} 

} 

当你运行这个程序,你会看到输出如下: 

Integer Arithmetic 

a = 2 

b = 6 

c = 1 

d = -1 

e = 1 

Floating Point Arithmetic 

da = 2.0 

db = 6.0 

dc = 1.5 

dd = -0.5 

de = 0.5 

4.1.2 模运算符 

模运算符%,其运算结果是整数除法的余数。它能像整数类型一样被用于浮点类型(这不同于C/C++,在C/C++中模运算符%仅仅能用于整数类型)。下面的示例程序说明了模运算符%的用法: 

// Demonstrate the % operator. 

class Modulus { 

public static void main(String args[]) { 

int x = 42; 

double y = 42.25; 

System.out.println("x mod 10 = " + x % 10); 

System.out.println("y mod 10 = " + y % 10); 

} 

} 

当你运行这个程序,你会看到输出如下: 

x mod 10 = 2 

y mod 10 = 2.25 

4.1.3 算术赋值运算符 

Java提供特殊的算术赋值运算符,该运算符可用来将算术运算符与赋值结合起来。你可能知道,像下列这样的语句在编程中是很常见的: 

a = a +4; 

在Java中,你可将该语句重写如下: 

a += 4; 

该语句使用“+=”进行赋值操作。上面两行语句完成的功能是一样的:使变量a的值增加4 。下面是另一个例子: 

a = a % 2; 

该语句可简写为: 

a %= 2; 

在本例中,%=算术运算符的结果是a/2的余数,并把结果重新赋给变量a。这种简写形式对于Java的二元(即需要两个操作数的)运算符都适用。其语句格式为: 

var= var op expression; 

可以被重写为: 

var op= expression; 

这种赋值运算符有两个好处。第一,它们比标准的等式要紧凑。第二,它们有助于提高Java的运行效率。由于这些原因,在Java的专业程序中,你经常会看见这些简写的赋值运算符。 

下面的例子显示了几个赋值运算符的作用: 

// Demonstrate several assignment operators. 

class OpEquals { 

public static void main(String args[]) { 

int a = 1; 

int b = 2; 

int c = 3; 

54 第1 部分 Java 语言 

a += 5; 

b *= 4; 

c += a * b; 

c %= 6; 

System.out.println("a = " + a); 

System.out.println("b = " + b); 

System.out.println("c = " + c); 

} 

} 

该程序的输出如下: 

a = 6 

b = 8 

c = 3 



4.1.4 递增和递减运算 

在第2章中曾经介绍过,“++”和“--”是Java的递增和递减运算符。下面将对它们做详细讨论。它们具有一些特殊的性能,这使它们变得非常有趣。我们先来复习一下递增和递减运算符的操作。 

递增运算符对其运算数加1,递减运算符对其运算数减1。因此: 

x = x + 1; 

运用递增运算符可以重写为: 

x++; 

同样,语句: 

x = x - 1; 

与下面一句相同: 

x--; 

在前面的例子中,递增或递减运算符采用前缀(prefix)或后缀(postfix)格式都是相同的。但是,当递增或递减运算符作为一个较大的表达式的一部分,就会有重要的不同。如果递增或递减运算符放在其运算数前面,Java就会在获得该运算数的值之前执行相应的操作,并将其用于表达式的其他部分。如果运算符放在其运算数后面,Java就会先获得该操作数的值再执行递增或递减运算。例如: 

x = 42 ; 

y =++x ; 

在这个例子中,y将被赋值为43,因为在将x的值赋给y以前,要先执行递增运算。这样,语句行y =++x ;和下面两句是等价的: 

x = x + 1; 

y = x; 

但是,当写成这样时: 

x = 42; 

y = x++; 

在执行递增运算以前,已将x的值赋给了y,因此y的值还是42 。当然,在这两个例子中,x都被赋值为43。在本例中,程序行y =x++;与下面两个语句等价: 

y = x; 

x = x + 1; 

下面的程序说明了递增运算符的使用: 

// Demonstrate ++. 

class IncDec { 

public static void main(String args[]) { 

int a = 1; 

int b = 2; 

int c; 

int d; 

c = ++b; 

d = a++; 

c++; 

System.out.println("a = " + a); 

System.out.println("b = " + b); 

System.out.println("c = " + c); 

System.out.println("d = " + d); 

} 

} 

该程序的输出如下: 

a = 2 

b = 3 

c = 4 

d = 1 

4.2 位 运 算 符 

Java定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long,int,short,char,and byte。表4-2列出了位运算: 

表4.2 位运算符及其结果 

运算符 结果 

~ 按位非(NOT)(一元运算) 

& 按位与(AND) 

| 按位或(OR) 

^ 按位异或(XOR) 

>> 右移 

>>> 右移,左边空出的位以0填充 


续表 

运算符 结果 

<< 左移 

&= 按位与赋值 

|= 按位或赋值 

^= 按位异或赋值 

>>= 右移赋值 

>>>= 右移赋值,左边空出的位以0填充 

<<= 左移赋值 

既然位运算符在整数范围内对位操作,因此理解这样的操作会对一个值产生什么效果是重要的。具体地说,知道Java是如何存储整数值并且如何表示负数的是有用的。因此,在继续讨论之前,让我们简短概述一下这两个话题。 

所有的整数类型以二进制数字位的变化及其宽度来表示。例如,byte型值42的二进制代码是00101010,其中每个位置在此代表2的次方,在最右边的位以20开始。向左下一个位置将是21,或2,依次向左是22,或4,然后是8,16,32等等,依此类推。因此42在其位置1,3,5的值为1(从右边以0开始数);这样42是21+23+25的和,也即是2+8+32 。 

所有的整数类型(除了char类型之外)都是有符号的整数。这意味着他们既能表示正数,又能表示负数。Java使用大家知道的2的补码(two's complement)这种编码来表示负数,也就是通过将与其对应的正数的二进制代码取反(即将1变成0,将0变成1),然后对其结果加1。例如,-42就是通过将42的二进制代码的各个位取反,即对00101010取反得到11010101,然后再加1,得到11010110,即-42 。要对一个负数解码,首先对其所有的位取反,然后加1。例如-42,或11010110取反后为00101001,或41,然后加1,这样就得到了42。 



如果考虑到零的交叉(zero crossing)问题,你就容易理解Java(以及其他绝大多数语言)这样用2的补码的原因。假定byte类型的值零用00000000代表。它的补码是仅仅将它的每一位取反,即生成11111111,它代表负零。但问题是负零在整数数学中是无效的。为了解决负零的问题,在使用2的补码代表负数的值时,对其值加1。即负零11111111加1后为100000000。但这样使1位太靠左而不适合返回到byte类型的值,因此人们规定,-0和0的表示方法一样,-1的解码为11111111。尽管我们在这个例子使用了byte类型的值,但同样的基本的原则也适用于所有Java 的整数类型。 

因为Java使用2的补码来存储负数,并且因为Java中的所有整数都是有符号的,这样应用位运算符可以容易地达到意想不到的结果。例如,不管你如何打算,Java用高位来代表负数。为避免这个讨厌的意外,请记住不管高位的顺序如何,它决定一个整数的符号。 

4.2.1 位逻辑运算符 

位逻辑运算符有“与”(AND)、“或”(OR)、“异或(XOR)”、“非(NOT)”,分别用“&”、“|”、“^”、“~”表示,4-3表显示了每个位逻辑运算的结果。在继续讨论之前,请记住位运算符应用于每个运算数内的每个单独的位。 

表4-3 位逻辑运算符的结果 

A B A | B A & B A ^ B ~A 

0 0 0 0 0 1 

1 0 1 0 1 0 

0 1 1 0 1 1 

1 1 1 1 0 0 

按位非(NOT) 

按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。例如,数字42,它的二进制代码为:00101010 

经过按位非运算成为 

11010101 

按位与(AND) 

按位与运算符“&”,如果两个运算数都是1,则结果为1。其他情况下,结果均为零。 

看下面的例子: 

00101010 42 

&00001111 15 

-------------- 

00001010 10 

按位或(OR) 

按位或运算符“|”,任何一个运算数为1,则结果为1。如下面的例子所示: 

00101010 42 

| 00001111 15 

-------------- 

00101111 47 

按位异或(XOR) 

按位异或运算符“^”,只有在两个比较的位不同时其结果是 1。否则,结果是零。下面的例子显示了“^”运算符的效果。这个例子也表明了XOR运算符的一个有用的属性。注意第二个运算数有数字1的位,42对应二进制代码的对应位是如何被转换的。第二个运算数有数字0的位,第一个运算数对应位的数字不变。当对某些类型进行位运算时,你将会看到这个属性的用处。 

00101010 42 

^ 00001111 15 

------------- 

00100101 37 

位逻辑运算符的应用 

下面的例子说明了位逻辑运算符: 

// Demonstrate the bitwise logical operators. 

class BitLogic { 

public static void main(String args[]) { 

String binary[] = { 

"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", 

"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" 

}; 

int a = 3; // 0 + 2 + 1 or 0011 in binary 

int b = 6; // 4 + 2 + 0 or 0110 in binary 

int c = a | b; 

int d = a & b; 

int e = a ^ b; 

int f = (~a & b) | (a & ~b); 

int g = ~a & 0x0f; 

System.out.println(" a = " + binary[a]); 

System.out.println(" b = " + binary[b]); 

System.out.println(" a|b = " + binary[c]); 

System.out.println(" a&b = " + binary[d]); 

System.out.println(" a^b = " + binary[e]); 

System.out.println("~a&b|a&~b = " + binary[f]); 

System.out.println(" ~a = " + binary[g]); 

} 

} 

在本例中,变量a与b对应位的组合代表了二进制数所有的 4 种组合模式:0-0,0-1,1-0,和1-1。“|”运算符和“&”运算符分别对变量a与b各个对应位的运算得到了变量c和变量d的值。对变量e和f的赋值说明了“^”运算符的功能。字符串数组binary代表了0到15对应的二进制的值。在本例中,数组各元素的排列顺序显示了变量对应值的二进制代码。数组之所以这样构造是因为变量的值n对应的二进制代码可以被正确的存储在数组对应元素binary[n]中。例如变量a的值为3,则它的二进制代码对应地存储在数组元素binary[3]中。~a的值与数字0x0f (对应二进制为0000 1111)进行按位与运算的目的是减小~a的值,保证变量g的结果小于16。因此该程序的运行结果可以用数组binary对应的元素来表示。该程序的输出如下: 

a = 0011 

b = 0110 

a|b = 0111 

a&b = 0010 

a^b = 0101 

~a&b|a&~b = 0101 

~a = 1100 



4.2.2 左移运算符 

左移运算符<<使指定值的所有位都左移规定的次数。它的通用格式如下所示: 

value << num 

这里,num指定要移位值value移动的位数。也就是,左移运算符<<使指定值的所有位都左移num位。每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。这意味着当左移的运算数是int类型时,每移动1位它的第31位就要被移出并且丢弃;当左移的运算数是long类型时,每移动1位它的第63位就要被移出并且丢弃。 

在对byte和short类型的值进行移位运算时,你必须小心。因为你知道Java在对表达式求值时,将自动把这些类型扩大为 int型,而且,表达式的值也是int型 。对byte和short类型的值进行移位运算的结果是int型,而且如果左移不超过31位,原来对应各位的值也不会丢弃。但是,如果你对一个负的byte或者short类型的值进行移位运算,它被扩大为int型后,它的符号也被扩展。这样,整数值结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单办法是将结果转换为byte型。下面的程序说明了这一点: 

// Left shifting a byte value. 

class ByteShift { 

public static void main(String args[]) { 

byte a = 64, b; 

int i; 

i = a << 2; 

b = (byte) (a << 2); 

System.out.println("Original value of a: " + a); 

System.out.println("i and b: " + i + " " + b); 

} 

} 

该程序产生的输出下所示: 

Original value of a: 64 

i and b: 256 0 

因变量a在赋值表达式中,故被扩大为int型,64(0100 0000)被左移两次生成值256(10000 0000)被赋给变量i。然而,经过左移后,变量b中惟一的1被移出,低位全部成了0,因此b的值也变成了0。 

既然每次左移都可以使原来的操作数翻倍,程序员们经常使用这个办法来进行快速的2的乘法。但是你要小心,如果你将1移进高阶位(31或63位),那么该值将变为负值。下面的程序说明了这一点: 

// Left shifting as a quick way to multiply by 2. 

class MultByTwo { 

public static void main(String args[]) { 

int i; 

int num = 0xFFFFFFE; 

for(i=0; i<4; i++) { 

num = num << 1; 

System.out.println(num); 

} 

} 

} 

该程序的输出如下所示: 

536870908 

1073741816 

2147483632 

-32 

初值经过仔细选择,以便在左移 4 位后,它会产生-32。正如你看到的,当1被移进31位时,数字被解释为负值。 

4.2.3 右移运算符 

右移运算符>>使指定值的所有位都右移规定的次数。它的通用格式如下所示: 

value >> num 

这里,num指定要移位值value移动的位数。也就是,右移运算符>>使指定值的所有位都右移num位。 

下面的程序片段将值32右移2次,将结果8赋给变量a: 

int a = 32; 

a = a >> 2; // a now contains 8 

当值中的某些位被“移出”时,这些位的值将丢弃。例如,下面的程序片段将35右移2次,它的2个低位被移出丢弃,也将结果8赋给变量a: 

int a = 35; 

a = a >> 2; // a still contains 8 

用二进制表示该过程可以更清楚地看到程序的运行过程: 

00100011 35 

>> 2 

00001000 8 

将值每右移一次,就相当于将该值除以2并且舍弃了余数。你可以利用这个特点将一个整数进行快速的2的除法。当然,你一定要确保你不会将该数原有的任何一位移出。 

右移时,被移走的最高位(最左边的位)由原来最高位的数字补充。例如,如果要移走的值为负数,每一次右移都在左边补1,如果要移走的值为正数,每一次右移都在左边补0,这叫做符号位扩展(保留符号位)(sign extension),在进行右移操作时用来保持负数的符号。例如,–8 >> 1 是–4,用二进制表示如下: 

11111000 –8 

>>1 

11111100 –4 

一个要注意的有趣问题是,由于符号位扩展(保留符号位)每次都会在高位补1,因此-1右移的结果总是–1。有时你不希望在右移时保留符号。例如,下面的例子将一个byte型的值转换为用十六进制表示。注意右移后的值与0x0f进行按位与运算,这样可以舍弃任何的符号位扩展,以便得到的值可以作为定义数组的下标,从而得到对应数组元素代表的十六进制字符。 

// Masking sign extension. 

class HexByte { 

static public void main(String args[]) { 

char hex[] = { 

'0', '1', '2', '3', '4', '5', '6', '7', 

'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'' 

}; 

byte b = (byte) 0xf1; 

System.out.println("b = 0x" + hex[(b >> 4) & 0x0f] + hex[b & 0x0f]); 

} 

} 

该程序的输出如下: 

b = 0xf1 



4.2.4 无符号右移 

正如上面刚刚看到的,每一次右移,>>运算符总是自动地用它的先前最高位的内容补它的最高位。这样做保留了原值的符号。但有时这并不是我们想要的。例如,如果你进行移位操作的运算数不是数字值,你就不希望进行符号位扩展(保留符号位)。当你处理像素值或图形时,这种情况是相当普遍的。在这种情况下,不管运算数的初值是什么,你希望移位后总是在高位(最左边)补0。这就是人们所说的无符号移动(unsigned shift)。这时你可以使用Java的无符号右移运算符>>>,它总是在左边补0。下面的程序段说明了无符号右移运算符>>>。在本例中,变量a被赋值为-1,用二进制表示就是32位全是1。这个值然后被无符号右移24位,当然它忽略了符号位扩展,在它的左边总是补0。这样得到的值255被赋给变量a。 

int a = -1; 

a = a >>> 24; 

下面用二进制形式进一步说明该操作: 

11111111 11111111 11111111 11111111 int型- 1的二进制代码 

>>> 24 无符号右移24位 

00000000 00000000 00000000 11111111 int型255的二进制代码由于无符号右移运算符>>>只是对32位和64位的值有意义,所以它并不像你想象的那样有用。因为你要记住,在表达式中过小的值总是被自动扩大为int型。这意味着符号位扩展和移动总是发生在32位而不是8位或16位。这样,对第7位以0开始的byte型的值进行无符号移动是不可能的,因为在实际移动运算时,是对扩大后的32位值进行操作。下面的例子说明了这一点: 

// Unsigned shifting a byte value. 

class ByteUShift { 

static public void main(String args[]) { 

char hex[] = { 

'0', '1', '2', '3', '4', '5', '6', '7', 

'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 

}; 

byte b = (byte) 0xf1; 

byte c = (byte) (b >> 4); 

byte d = (byte) (b >>> 4); 

byte e = (byte) ((b & 0xff) >> 4); 

System.out.println(" b = 0x" 

+ hex[(b >> 4) & 0x0f] + hex[b & 0x0f]); 

System.out.println(" b >> 4 = 0x" 

+ hex[(c >> 4) & 0x0f] + hex[c & 0x0f]); 

System.out.println(" b >>> 4 = 0x" 

+ hex[(d >> 4) & 0x0f] + hex[d & 0x0f]); 

System.out.println("( b & 0xff) >> 4 = 0x" 

+ hex[(e >> 4) & 0x0f] + hex[e & 0x0f]); 

} 

} 

该程序的输出显示了无符号右移运算符>>>对byte型值处理时,实际上不是对byte型值直接操作,而是将其扩大到int型后再处理。在本例中变量b被赋为任意的负byte型值。对变量b右移4位后转换为byte型,将得到的值赋给变量c,因为有符号位扩展,所以该值为0xff。对变量b进行无符号右移4位操作后转换为byte型,将得到的值赋给变量d,你可能期望该值是0x0f,但实际上它是0xff,因为在移动之前变量b就被扩展为int型,已经有符号扩展位。最后一个表达式将变量b的值通过按位与运算将其变为8位,然后右移4位,然后将得到的值赋给变量e,这次得到了预想的结果0x0f。由于对变量d(它的值已经是0xff)进行按位与运算后的符号位的状态已经明了,所以注意,对变量d再没有进行无符号右移运算。 

B = 0xf1 

b >> 4 = 0xff 

b >>> 4 = 0xff 

(b & 0xff) >> 4 = 0x0f 



4.2.5 位运算符赋值 

所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式。例如,下面两个语句都是将变量a右移4位后赋给a: 

a = a >> 4; 

a >>= 4; 

同样,下面两个语句都是将表达式a OR b运算后的结果赋给a: 

a = a | b; 

a |= b; 

下面的程序定义了几个int型变量,然后运用位赋值简写的形式将运算后的值赋给相应的变量: 

class OpBitEquals { 

public static void main(String args[]) { 

int a = 1; 

int b = 2; 

int c = 3; 

a |= 4; 

b >>= 1; 

c <<= 1; 

a ^= c; 

System.out.println("a = " + a); 

System.out.println("b = " + b); 

System.out.println("c = " + c); 

} 

} 

该程序的输出如下所示: 

a = 3 

b = 1 

c = 6 

4.3 关系运算符 

关系运算符(relational operators)决定值和值之间的关系。例如决定相等不相等以及排列次序。关系运算符如表4-4所示: 

表4-4 关系运算符及其意义 

运算符 意义 

== 等于 

!= 不等于 

> 大于 

< 小于 

>= 大于等于 

<= 小于等于 

这些关系运算符产生的结果是布尔值。关系运算符常常用在if控制语句和各种循环语句的表达式中。 

Java中的任何类型,包括整数,浮点数,字符,以及布尔型都可用“==”来比较是否相等,用“!=”来测试是否不等。注意Java(就像C和C++一样)比较是否相等的运算符是2个等号,而不是一个(注意:单等号是赋值运算符)。只有数字类型可以使用排序运算符进行比较。也就是,只有整数、浮点数和字符运算数可以用来比较哪个大哪个小。前面已经说过,关系运算符的结果是布尔(boolean)类型。例如,下面的程序段对变量c的赋值是有效的: 

int a = 4; 

int b = 1; 

boolean c = a < b; 

在本例中,a如果你有C/C++语言知识的背景,请注意下面的几条语句。在C/C++中,这些类型的语 

句是很常见的: 

int done; 

// ... 

if(!done) ... // Valid in C/C++ 

if(done) ... // but not in Java. 

在Java中,这些语句必须写成下面这样: 

if(done == 0)) ... // This is Java-style. 

if(done != 0) ... 

这样做的原因是Java定义真和假的方法和C/C++中的不一样。在C/C++中,真是任何非0的值而假是值0。在Java中,真值假值是非数字的,它和0或非0联系不到一起。因此,为了测试0值或非0值,你必须明确地用一个或多个关系运算符。 


4.4 布尔逻辑运算符 

布尔逻辑运算符的运算数只能是布尔型。而且逻辑运算的结果也是布尔类型(见表4-5)。 

表4-5 布尔逻辑运算符及其意义 

运算符 含义 

& 逻辑与 

| 逻辑或 

^ 异或 

|| 短路或 

&& 短路与 

! 逻辑反 

&= 逻辑与赋值(赋值的简写形式) 

|= 逻辑或赋值(赋值的简写形式) 

^= 异或赋值(赋值的简写形式) 

== 相等 

!= 不相等 

?: 三元运算符(IF-THEN-ELSE) 

布尔逻辑运算符“&”、“ |”、“ ^”,对布尔值的运算和它们对整数位的运算一样。 

逻辑运算符“!”的结果表示布尔值的相反状态:!true == false 和 !false == true。各个逻辑运算符的运算结果如表4-6所示: 

表4-6 布尔逻辑运算符的运算 

A B A|B A&B A^B !A 

False False False False False True 

True False True False True False 

False True True False True True 

True True True True False False 

下面的例子和前面讲的位逻辑运算的几乎一样,只不过本例中的运算数是布尔逻辑值而不是二进制的位值: 

// Demonstrate the boolean logical operators. 

class BoolLogic { 

public static void main(String args[]) { 

boolean a = true; 

boolean b = false; 

boolean c = a | b; 

boolean d = a & b; 

boolean e = a ^ b; 

boolean f = (!a & b) | (a & !b); 

boolean g = !a; 

System.out.println(" a = " + a); 

System.out.println(" b = " + b); 

System.out.println(" a|b = " + c); 

System.out.println(" a&b = " + d); 

System.out.println(" a^b = " + e); 

System.out.println("!a&b|a&!b = " + f); 

System.out.println(" !a = " + g); 

} 

} 

在你运行该程序后,你会发现逻辑运算符对布尔值和位运算值的逻辑规则一样。而且 

从下面的输出你也可以看出Java中的布尔值是字符串常量“true”或“false”: 

a = true 

b = false 

a|b = true 

a&b = false 

a^b = true 

a&b|a&!b = true 

!a = false 

4.4.1 短路(short-circuit)逻辑运算符 

Java 提供了两个在大多数其他计算机语言中没有的有趣的布尔运算符。这就是逻辑AND和逻辑OR的特殊的短路版本。从上表可以看出,在逻辑OR的运算中,如果第一个运算数A为真,则不管第二个运算数B是真是假,其运算结果为真。同样,在逻辑AND的运算中,如果第一个运算数A为假,则不管第二个运算数是真是假,其运算结果为假。如果运用||和&&形式,而不是|和&,那么一个运算数就能决定表达式的值,Java的短路版本就不会对第二个运算数求值,只有在需要时才对第二个运算数求值。为完成正确的功能,当右边的运算数取决于左边的运算数是真或是假时,短路版本是很有用的。例如,下面的程序语句说明了短路逻辑运算符的优点,用它来防止被0除的错误: 

if (denom != 0 && num / denom > 10) 

既然用了短路AND运算符,就不会有当denom为0时产生的意外运行时错误。如果该行代码使用标准AND运算符(&),它将对两个运算数都求值,当出现被0除的情况时,就会产生运行时错误。既然短路运算符在布尔逻辑运算中有效,那么就在布尔逻辑运算中全用它,而标准的AND和OR运算符(只有一个字符)仅在位运算中使用。然而,这条规则也有例外。例如,考虑下面的语句: 

if(c==1 & e++ < 100) d = 100; 

这里,使用标准AND运算符(单个的&)来保证不论c是否等于1,e都被自增量。 

4.5 赋值运算符 

在第2章中你已经使用过赋值运算符。下面我们正式讨论它。赋值运算符是一个等号“=”。它在Java中的运算与在其他计算机语言中的运算一样,其通用格式为: 

var = expression; 

这里,变量var的类型必须与表达式expression的类型一致。 

赋值运算符有一个有趣的属性,你或许并不熟悉:它允许你对一连串变量赋值。例如,请看下面的例子: 

int x,y,z; 

x = y = z = 100; // set x,y,and z to 100 

该例子使用一个赋值语句对变量 x、y、z 都赋值为100。这是因为“=”运算符产生右边表达式的值,因此 z = 100 的值是 100,然后该值被赋给 y ,并依次被赋给 x 。使用“串赋值”是给一组变量赋同一个值的简单办法。 



4.6 ?运算符 

Java提供一个特别的三元运算符(ternary)经常用于取代某个类型的if-then-else 语句。这个运算符就是?,并且它在Java中的用法和在C/C++中的几乎一样。该符号初看起来有些迷惑,但是一旦掌握了它,用?运算符是很方便高效的。?运算符的通用格式如下: 

expression1 ? expression2 : expression3 

其中,expression1是一个布尔表达式。如果expression1为真,那么expression2被求值;否则,expression3被求值。整个?表达式的值就是被求值表达式(expression2或expression3)的值。expression2和expression3是除了void以外的任何类型的表达式,且它们的类型必须相同。 

下面是一个利用?运算符的例子: 

ratio = denom == 0 ? 0 : num / denom; 

当Java计算这个表达式时,它首先看问号左边的表达式。如果 denom 等于0,那么在问号和冒号之间的表达式被求值,并且该值被作为整个?表达式的值。如果 denom 不等于零,那么在冒号之后的表达式被求值,并且该值被作为整个?表达式的值。然后将整个?表达式的值赋给变量ratio。下面的程序说明了?运算符,该程序得到一个变量的绝对值。 

// Demonstrate ?. 

class Ternary { 

public static void main(String args[]) { 

int i, k; 

i = 10; 

k = i < 0 ? -i : i; // get absolute value of i 

System.out.print("Absolute value of "); 

System.out.println(i + " is " + k); 

i = -10; 

k = i < 0 ? -i : i; // get absolute value of i 

System.out.print("Absolute value of "); 

System.out.println(i + " is " + k); 

} 

} 

该程序的输出如下所示: 

Absolute value of 10 is 10 

Absolute value of -10 is 10 

4.7 运算符优先级 

表4-7显示了Java 运算符从最高到最低的优先级。注意第一行显示的项你通常不能把它们作为运算符:圆括号,方括号,点运算符。圆括号被用来改变运算的优先级。从前面章节我们知道,方括号用来表示数组的下标。点运算符用来将对象名和成员名连接起来,这将在本书的后面讨论。 

表4-7 Java 运算符优先级 

最高 

( ) [ ] . 

++ – – ~ ! 

* / % 

+ – 

>> >>> << 

> >= < <= 

续表 

== != 

& 

^ 

| 

&& 

|| 

?: 

= op= 

最低 

4.8 使用圆括号 

圆括号(Parentheses)提高了括在其中的运算的优先级。这常常对于获得你需要的结果是必要的。例如,考虑下列表达式: 

a >> b + 3 

该表达式首先把 3 加到变量 b,得到一个中间结果,然后将变量a右移该中间结果位。该表达式可用添加圆括号的办法重写如下: 

a >> (b + 3) 

然而,如果你想先将a右移b位,得到一个中间结果,然后对该中间结果加3,你需要对表达式加如下的圆括号: 

(a >> b) + 3 

除了改变一个运算的正常优先级外,括号有时被用来帮助澄清表达式的含义。对于阅读你程序代码的人来说,理解一个复杂的表达式是困难的。对复杂表达式增加圆括号能帮助防止以后的混乱。例如,下面哪一个表达式更容易读呢? 

a | 4 + c >> b & 7 

(a | (((4 + c) >> b) & 7)) 

另外一点:圆括号(不管是不是多余的)不会降低你程序的运行速度。因此,添加圆括号可以减少含糊不清,不会对你的程序产生消极影响。 

让Notification点击时进入到当前正在运行的应用界面 android
/**
	 * 将应用增加到通知栏中
	 */
	private void notification()
	{
		notificationManager = (NotificationManager) activity.getSystemService(activity.NOTIFICATION_SERVICE);
		Notification notification = new Notification(R.drawable.icon, "该您出牌了!", System.currentTimeMillis());
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_LAUNCHER);
		intent.setClass(activity.getApplicationContext(), GameActivity.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
		PendingIntent contentIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
		notification.setLatestEventInfo(activity.getApplicationContext(), "唐人斗地主", "该您出牌了!", contentIntent);
		notificationManager.notify(R.drawable.icon, notification);
	}

	/**
	 * 清除通知栏图标
	 */
	public void cancelNotification()
	{
		if (notificationManager != null)
		{
			notificationManager.cancel(R.drawable.icon);
		}
	}
Notification_应用 android
NotificationManager和Notification的使用总结 
这几天一直在修改twigee的源代码,其中一个要加入的功能是常驻Notification栏,以前写的时候只能出现在“通知”这一组中,想把它放在“正在运行”组中却不知道怎么放,查了下官方文档,找到了方法,在notification的flags字段中加一下“FLAG_ONGOING_EVENT”就可以了。同时我也把Notification的使用方法给总结了一下。详见下文:
(1)、使用系统定义的Notification
以下是使用示例代码: 
//创建一个NotificationManager的引用 
String ns = Context.NOTIFICATION_SERVICE; 
NotificationManager mNotificationManager = (NotificationManager)getSystemService(ns); 
//定义Notification的各种属性 
int icon = R.drawable.icon; //通知图标 
CharSequence tickerText = "Hello"; //状态栏显示的通知文本提示 
long when = System.currentTimeMillis(); //通知产生的时间,会在通知信息里显示 
//用上面的属性初始化Nofification 
Notification notification = new Notification(icon,tickerText,when); 
/* 
* 添加声音 
* notification.defaults |=Notification.DEFAULT_SOUND; 
* 或者使用以下几种方式 
* notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3"); 
* notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); 
* 如果想要让声音持续重复直到用户对通知做出反应,则可以在notification的flags字段增加"FLAG_INSISTENT" 
* 如果notification的defaults字段包括了"DEFAULT_SOUND"属性,则这个属性将覆盖sound字段中定义的声音 
*/ 
/* 
* 添加振动 
* notification.defaults |= Notification.DEFAULT_VIBRATE; 
* 或者可以定义自己的振动模式: 
* long[] vibrate = {0,100,200,300}; //0毫秒后开始振动,振动100毫秒后停止,再过200毫秒后再次振动300毫秒 
* notification.vibrate = vibrate; 
* long数组可以定义成想要的任何长度 
* 如果notification的defaults字段包括了"DEFAULT_VIBRATE",则这个属性将覆盖vibrate字段中定义的振动 
*/ 
/* 
* 添加LED灯提醒 
* notification.defaults |= Notification.DEFAULT_LIGHTS; 
* 或者可以自己的LED提醒模式: 
* notification.ledARGB = 0xff00ff00; 
* notification.ledOnMS = 300; //亮的时间 
* notification.ledOffMS = 1000; //灭的时间 
* notification.flags |= Notification.FLAG_SHOW_LIGHTS; 
*/ 
/* 
* 更多的特征属性 
* notification.flags |= FLAG_AUTO_CANCEL; //在通知栏上点击此通知后自动清除此通知 
* notification.flags |= FLAG_INSISTENT; //重复发出声音,直到用户响应此通知 
* notification.flags |= FLAG_ONGOING_EVENT; //将此通知放到通知栏的"Ongoing"即"正在运行"组中 
* notification.flags |= FLAG_NO_CLEAR; //表明在点击了通知栏中的"清除通知"后,此通知不清除, 
* //经常与FLAG_ONGOING_EVENT一起使用 
* notification.number = 1; //number字段表示此通知代表的当前事件数量,它将覆盖在状态栏图标的顶部 
* //如果要使用此字段,必须从1开始 
* notification.iconLevel = ; // 
*/ 
//设置通知的事件消息 
Context context = getApplicationContext(); //上下文 
CharSequence contentTitle = "My Notification"; //通知栏标题 
CharSequence contentText = "Hello World!"; //通知栏内容 
Intent notificationIntent = new Intent(this,Main.class); //点击该通知后要跳转的Activity 
PendingIntent contentIntent = PendingIntent.getActivity(this,0,notificationIntent,0); 
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent); 
//把Notification传递给NotificationManager 
mNotificationManager.notify(0,notification);
如果想要更新一个通知,只需要在设置好notification之后,再次调用 setLatestEventInfo(),然后重新发送一次通知即可,即再次调用notify()。 
(2)、使用自定义的Notification
要创建一个自定义的Notification,可以使用RemoteViews。要定义自己的扩展消息,首先要初始化一个RemoteViews对象,然后将它传递给Notification的contentView字段,再把PendingIntent传递给contentIntent字段。以下示例代码是完整步骤: 
//1、创建一个自定义的消息布局 view.xml 
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" android:layout_height="fill_parent"> 
<ImageView android:id="@+id/image" android:layout_width="wrap_content" 
android:layout_height="fill_parent" android:layout_marginRight="10dp" /> 
<TextView android:id="@+id/text" android:layout_width="wrap_content" 
android:layout_height="fill_parent" android:textColor="#000" /> 
</LinearLayout> 
//2、在程序代码中使用RemoteViews的方法来定义image和text。然后把RemoteViews对象传到contentView字段 
RemoteViews contentView = new RemoteViews(getPackageName(),R.layout.view); 
contentView.setImageViewResource(R.id.image,R.drawable.icon); 
contentView.setTextViewText(R.id.text,”Hello,this message is in a custom expanded view”); 
notification.contentView = contentView; 
//3、为Notification的contentIntent字段定义一个Intent(注意,使用自定义View不需要setLatestEventInfo()方法) 
Intent notificationIntent = new Intent(this,Main.class); 
PendingIntent contentIntent = PendingIntent.getActivity(this,0,notificationIntent,0); 
notification.contentIntent = contentIntent; 
//4、发送通知 
mNotificationManager.notify(2,notification); 
//以下是全部示例代码 
//创建一个NotificationManager的引用 
String ns = Context.NOTIFICATION_SERVICE; 
NotificationManager mNotificationManager = (NotificationManager)getSystemService(ns); 
//定义Notification的各种属性 
int icon = R.drawable.icon; //通知图标 
CharSequence tickerText = "Hello"; //状态栏显示的通知文本提示 
long when = System.currentTimeMillis(); //通知产生的时间,会在通知信息里显示 
//用上面的属性初始化Nofification 
Notification notification = new Notification(icon,tickerText,when); 
RemoteViews contentView = new RemoteViews(getPackageName(),R.layout.view); 
contentView.setImageViewResource(R.id.image, R.drawable.iconempty); 
contentView.setTextViewText(R.id.text, "Hello,this is JC"); 
notification.contentView = contentView; 
Intent notificationIntent = new Intent(this,Main.class); 
PendingIntent contentIntent = PendingIntent.getActivity(this,0,notificationIntent,0); 
notification.contentIntent = contentIntent; 
//把Notification传递给NotificationManager 
mNotificationManager.notify(0,notification);

Android开发 获取手机总内存和可用内存 android
private String getAvailMemory()
	{// 获取android当前可用内存大小
		ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
		MemoryInfo mi = new MemoryInfo();
		am.getMemoryInfo(mi);
		// mi.availMem; 当前系统的可用内存
		return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化
	}
JAVA截取符串长度(包括汉字) java http://hi.baidu.com/zhangnan4913/blog/item/1cf52a7be1a153f60bd18768.html
	/**
	 * 功能:根据限制长度截取字符串(字符串中包括汉字,一个汉字等于两个字符)
	 * 
	 * @param strParameter
	 *            要截取的字符串
	 * @param limitLength
	 *            截取的长度
	 * @return 截取后的字符串
	 */
	public static String getStrByLength(String strParameter, int limitLength)
	{
		String return_str = strParameter;// 返回的字符串
		int temp_int = 0;// 将汉字转换成两个字符后的字符串长度
		int cut_int = 0;// 对原始字符串截取的长度
		byte[] b = null;
		try
		{
                         //不同的编码转换的汉字得到的字节书不一样,gbk汉字=2字节,utf8汉字转换=3字节
			b = strParameter.getBytes("GBK");
		} catch (UnsupportedEncodingException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}// 将字符串转换成字符数组

		for (int i = 0; i < b.length; i++)
		{
			if (b[i] >= 0)
			{
				temp_int = temp_int + 1;
			} else
			{
				temp_int = temp_int + 2;// 一个汉字等于两个字符
				i++;
			}
			cut_int++;

			if (temp_int >= limitLength)
			{
				if (temp_int % 2 != 0 && b[temp_int - 1] < 0)
				{
					cut_int--;
				}
				return_str = return_str.substring(0, cut_int);
				break;
			}
		}
		return return_str;
	}
一个理解wait()与notify()的例子 java
file://分析这段程序,并解释一下,着重讲讲synchronized、wait(),notify 谢谢!
class ThreadA 
{
  public static void main(String[] args) 
  {
    ThreadB b=new ThreadB();
    b.start();
    System.out.println("b is start....");
    synchronized(b)//括号里的b是什么意思,起什么作用?
    {
      try
      {
 System.out.println("Waiting for b to complete...");
 b.wait();//这一句是什么意思,究竟让谁wait?
        System.out.println("Completed.Now back to main thread");
      }catch (InterruptedException e){}
    }
    System.out.println("Total is :"+b.total);
   }
}

class ThreadB extends Thread
{
  int total;
  public void run()
  {
    synchronized(this)
    {
      System.out.println("ThreadB is running..");
      for (int i=0;i<100;i++ )
      {
        total +=i;
        System.out.println("total is "+total);
      }
      notify();
    }
  }
}
要分析这个程序,首先要理解notify()和wait(),为什么在前几天纪录线程的时候没有纪录这两个方法呢,因为这两个方法本来就不属于Thread类,而是属于最底层的object基础类的,也就是说不光是Thread,每个对象都有notify和wait的功能,为什么?因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了.
 再往下看之前呢,首先最好复习一下Think in Java的14.3.1中第3部分内容:等待和通知,也就是wait()和notify了.
按照Think in Java中的解释:"wait()允许我们将线程置入“睡眠”状态,同时又“积极”地等待条件发生改变.而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."
  我们来解释一下这句话.
  "wait()允许我们将线程置入“睡眠”状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend是相同的.那和sleep,suspend有什么区别呢?
   区别在于"(wait)同时又“积极”地等待条件发生改变",这一点很关键,sleep和suspend无法做到.因为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放.
   而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁,而将它暂时让给其它需要对象锁的人(这里应该是程序块,或线程)用,这意味着可在执行wait()期间调用线程对象中的其他同步方法!在其它情况下(sleep啊,suspend啊),这是不可能的.
   但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,我wait所在的线程还是要把这个对象锁收回来的呀.wait什么?就是wait别人用完了还给我啊!
   好,那怎么把对象锁收回来呢?
   第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借出去1秒中,一秒钟之后,我自动收回.
   第二种方法,让借出去的人通知我,他用完了,要还给我了.这时,我马上就收回来.哎,假如我设了1小时之后收回,别人只用了半小时就完了,那怎么办呢?靠!当然用完了就收回了,还管我设的是多长时间啊.
   那么别人怎么通知我呢?相信大家都可以想到了,notify(),这就是最后一句话"而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒"的意思了.
   因此,我们可将一个wait()和notify()置入任何同步方法或同步块内部,无论在那个类里是否准备进行涉及线程的处理。而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify().
   这个时候我们来解释上面的程序,简直是易如反掌了.
   synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放锁,并阻塞当前线程,好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完,待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行.
java线程同步原理及wait,notify的用法及与sleep的区别 java http://hi.baidu.com/100world/blog/item/49b53cb3d86e52a9d8335a59.html
一。 java线程同步原理
java会为每个object对象分配一个monitor,当某个对象的同步方法(synchronized methods )被多个线程调用时,该对象的monitor将负责处理这些访问的并发独占要求。
当一个线程调用一个对象的同步方法时,JVM会检查该对象的monitor。如果monitor没有被占用,那么这个线程就得到了monitor的占有权,可以继续执行该对象的同步方法;如果monitor被其他线程所占用,那么该线程将被挂起,直到monitor被释放。
当线程退出同步方法调用时,该线程会释放monitor,这将允许其他等待的线程获得monitor以使对同步方法的调用执行下去。
注意:Java对象的monitor机制和传统的临界检查代码区技术不一样。java的一个同步方法并不意味着同时只有一个线程独占执行,但临界检查代码区技术确实会保证同步方法在一个时刻只被一个线程独占执行。Java的monitor机制的准确含义是:任何时刻,对一个指定object对象的某同步方法只能由一个线程来调用。
java对象的monitor是跟随object实例来使用的,而不是跟随程序代码。两个线程可以同时执行相同的同步方法,比如:一个类的同步方法是xMethod(),有a,b两个对象实例,一个线程执行a.xMethod(),另一个线程执行b.xMethod(). 互不冲突。

二。 wait()、notify(),notifyAll()的使用
obj.wait()方法将使本线程挂起,并释放obj对象的monitor。只有其他线程调用obj对象的notify()或notifyAll()时,才可以被唤醒。
obj.notifyAll()方法唤醒所有该obj对象相关的沉睡线程,然后被唤醒的众多线程开始竞争obj对象的monitor占有权,最终得到的那个线程会继续执行下去,但其他线程还将继续等待。
obj.notify()方法是随机唤醒一个沉睡线程。
wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,
如:
synchronized(x){
x.notify()
//或者wait()
}
以上内容说明了为什么调用wait(),notify(),notifyAll()的线程必须要拥有obj实例对象的monitor占有权。
每个对象实例都有一个等待线程队列。这些线程都是等待对该对象的同步方法的调用许可。对一个线程来说,有两种方法可以进入这个等待线程队列。一个是当其他线程执行同步方法时,自身同时也要执行该同步方法;另一个是调用obj.wait()方法。
当同步方法执行完毕或者执行wait()时,其他某个线程将获得对象的访问权。当一个线程被放入等待队列时,必须要确保可以通过notify()的调用来解冻该线程,以使其能够继续执行下去。

三。 wait()与sleep()的区别:
sleep()函数是Thread类的静态函数,不涉及到线程间同步概念,仅仅为了让一个线程自身获得一段沉睡时间。sleep可以在任何地方使用。
wait函数是object类的函数,要解决的问题是线程间的同步,该过程包含了同步锁的获取和释放,调用wait方法将会将调用者的线程挂起,直到其他线程调用同一个对象的notify方法才会重新激活调用者。
注意,线程调用notify()之后,只有该线程完全从 synchronized代码里面执行完毕后,monitor才会被释放,被唤醒线程才可以真正得到执行权。
android api 源码全集 android
下载网址1:
http://www.devfrustrated.com/devBlog/browsing-android-source-code-in-eclipse/
下载网址2:
http://www.eoeandroid.com/thread-57709-1-2.html
Android API学习 SoundPool 和 MediaPlayer android http://dev.10086.cn/cmdn/wiki/index.php?doc-view-5522.html
Android平台中关于音频播放有以下两种方式:
  1. SoundPool —— 适合短促且对反应速度比较高的情况(游戏音效或按键声等)
  2. MediaPlayer —— 适合比较长且对时间要求不高的情况
  -------------------------------------------------------------------------------------------
  SoundPool
  1. 创建一个SoundPool
  public SoundPool(int maxStream, int streamType, int srcQuality)
  maxStream —— 同时播放的流的最大数量
  streamType —— 流的类型,一般为STREAM_MUSIC(具体在AudioManager类中列出)
  srcQuality —— 采样率转化质量,当前无效果,使用0作为默认值
  eg.
  SoundPool soundPool = new SoundPool(3, AudioManager.STREAM_MUSIC, 0);
  创建了一个最多支持3个流同时播放的,类型标记为音乐的SoundPool。
  2. 加载音频资源
  可以通过四种途径来记载一个音频资源:
  int load(AssetFileDescriptor afd, int priority)
  通过一个AssetFileDescriptor对象
  int load(Context context, int resId, int priority)
  通过一个资源ID
  int load(String path, int priority)
  通过指定的路径加载
  int load(FileDescriptor fd, long offset, long length, int priority)
  通过FileDescriptor加载
  *API中指出,其中的priority参数目前没有效果,建议设置为1。
  一个SoundPool能同时管理多个音频,所以可以通过多次调用load函数来记载,如果记载成功将返回一个非0的soundID ,用于播放时指定特定的音频。
  eg.
  int soundID1 = soundPool.load(this, R.raw.sound1, 1);
  if(soundID1 ==0){
  // 记载失败
  }else{
  // 加载成功
  }
  int soundID2 = soundPool.load(this, R.raw.sound2, 1);
  ...
  这里加载了两个流,并分别记录了返回的soundID 。
  需要注意的是,
  流的加载过程是一个将音频解压为原始16位PCM数据的过程,由一个后台线程来进行处理异步,所以初始化后不能立即播放,需要等待一点时间。
  3. 播放控制
有以下几个函数可用于控制播放:
  final int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)
  播放指定音频的音效,并返回一个streamID 。
  priority —— 流的优先级,值越大优先级高,影响当同时播放数量超出了最大支持数时SoundPool对该流的处理;
  loop —— 循环播放的次数,0为值播放一次,-1为无限循环,其他值为播放loop+1次(例如,3为一共播放4次).
  rate —— 播放的速率,范围0.5-2.0(0.5为一半速率,1.0为正常速率,2.0为两倍速率)
  final void pause(int streamID)
  暂停指定播放流的音效(streamID 应通过play()返回)。
  final void resume(int streamID)
  继续播放指定播放流的音效(streamID 应通过play()返回)。
  final void stop(int streamID)
  终止指定播放流的音效(streamID 应通过play()返回)。
  这里需要注意的是,
  1.play()函数传递的是一个load()返回的soundID——指向一个被记载的音频资源 ,如果播放成功则返回一个非0的streamID——指向一个成功播放的流 ;同一个soundID 可以通过多次调用play()而获得多个不同的streamID (只要不超出同时播放的最大数量);
  2.pause()、resume()和stop()是针对播放流操作的,传递的是play()返回的streamID ;
  3.play()中的priority参数,只在同时播放的流的数量超过了预先设定的最大数量是起作用,管理器将自动终止优先级低的播放流。如果存在多个同样优先级的流,再进一步根据其创建事件来处理,新创建的流的年龄是最小的,将被终止;
  4.无论如何,程序退出时,手动终止播放并释放资源是必要的。
  eg.
  //这里对soundID1的音效进行播放——优先级为0(最低),无限循环,正常速率。
  int streamID = soundPool.play(soundID1 , 1.0, 1.0, 0, -1, 1.0);
  if(streamID ==0){
  // 播放失败
  }else{
  // 播放成功
  }
  ...
  // 暂停soundID1的播放
  soundPool.pause(streamID );
  ...
  // 恢复soundID1的播放
  soundPool.resume(streamID );
  ...
  // 终止播放,记住循环为-1时必须手动停止
soundPool.stop(streamID );
  *API中指出,即使使用无效的soundID /streamID (操作失败或指向无效的资源)来调用相关函数也不会导致错误,这样能减轻逻辑的处理。
  4. 更多属性设置
  其实就是paly()中的一些参数的独立设置:
  final void setLoop(int streamID, int loop)
  设置指定播放流的循环.
  final void setVolume(int streamID, float leftVolume, float rightVolume)
  设置指定播放流的音量.
  final void setPriority(int streamID, int priority)
  设置指定播放流的优先级,上面已说明priority的作用.
  final void setRate(int streamID, float rate)
  设置指定播放流的速率,0.5-2.0.
  5. 释放资源
  可操作的函数有:
  final boolean unload(int soundID)
  卸载一个指定的音频资源.
  final void release()
  释放SoundPool中的所有音频资源.
  -汇总-
  一个SoundPool可以:
  1.管理多个音频资源,通过load()函数,成功则返回非0的soundID;
  2.同时播放多个音频,通过play()函数,成功则返回非0的streamID;
  3.pause()、resume()和stop()等操作是针对streamID(播放流)的;
  4.当设置为无限循环时,需要手动调用stop()来终止播放;
  5.播放流的优先级(play()中的priority参数),只在同时播放数超过设定的最大数时起作用;
  6.程序中不用考虑(play触发的)播放流的生命周期,无效的soundID/streamID不会导致程序错误。
  -------------------------------------------------------------------------------------------
  MediaPlayer
  你可以通过new或便捷的静态create函数组来创建一个MediaPlayer对象。
  两种方式的比较:
  new MediaPlayer()
  1.成功调用后,MediaPlayer将处于Idle状态;
  2.setDataSource提供了对String(path)、Uri和FileDescriptor格式的资源路径的支持;
  3.后续需要手动调用prepare()才能进行播放。
  MediaPlayer.create(...)
  1.成功调用后,MediaPlayer将处于Prepared状态;
  2.create提供了对int(resID)和Uri格式的资源路径的支持;
 3.无需(也不能)再次调用prepare()就能直接播放。
 要点:
  1.如果由于错误的操作mp.setDataSource("/sdcard/test.mp3"); // 直接传URL也是可以的,将自动处理缓冲
  } catch (IllegalArgumentException e) {
  e.printStackTrace();
  } catch (IllegalStateException e) {
  // 如果在非Idle状态下调用setDataSource就会导致该异常
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  }
  // 设置必要的监听器
  mp.setOnPreparedListener(new OnPreparedListener(){
  @Override
  public void onPrepared(MediaPlayer mp) {
  // 这时能确保player处于Prepared状态,触发start是最合适的
  mp.start();
  }
  });
  mp.setOnCompletionListener(new OnCompletionListener() {
  @Override
  public void onCompletion(MediaPlayer mp) {
  // 正常播放结束,可以触发播放下一首
  }
  });
  mp.setOnErrorListener(new OnErrorListener() {
  @Override
  public boolean onError(MediaPlayer mp, int what, intextra) {
  // 操作错误或其他原因导致的错误会在这里被通知
  return true;
  }
  });
  // 连接并加载资源
  try {
  mp.prepare();
  // mp.prepareAsync() 这也是可以的,这是异步处理,上面的是同步处理,实际加载完毕以OnPreparedListener.onPrepared()为准。
  } catch (IllegalStateException e) {
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  }
  // mp.start(); // 建议在OnPreparedListener.onPrepared()回调中触发该函数,特别是使用异步加载时
  /**
  * ... 你的其他操作 ...
  */
  // 终止播放并释放资源
  try{
  mp.stop(); // 这是必要的,如果你设置了循环播放,否则程序退出了音乐仍在后台继续播...
  mp.release();
  }catch(IllegalStateException e){
  e.printStackTrace();
  }
  // 通过new创建后的player处于Idle状态
导致MediaPlayer处于Error状态,可通过reset()函数来使其恢复到Idle状态,再重新执行setDataSource等初始化操作(ps:如果是通过create函数绑定资源ID创建的就郁闷了...);
  2.API中指出虽然reset后的MediaPlayer就像相当于新new的一样,但存在微妙的差异的:
  在这两种情况下播放器处于Idle状态,此时调用getCurrentPosition(), getDuration(),getVideoHeight(),getVideoWidth(), setAudioStreamType(int),setLooping(boolean), setVolume(float, float), pause(), start(), stop(),seekTo(int), prepare() 或 prepareAsync() 等函数都属与编程错误。当在MediaPlayer刚创建后调用这些函数,用户指定的OnErrorListener.onError() 回调函数不会被internal player engine(内部播放引擎)调用,并且播放器的状态依然未变;但如果是在调用reset() 函数之后,用户指定的OnErrorListener.onError() 回调函数将会被internal player engine(内部播放引擎)调用,并且播放器的状态将转变为Error(错误)状态。
  3.使用完毕后应该立即调用release()函数来释放资源,如果操作成功,MediaPlayer对象将处于End状态,此时无法再进行任何操作,除非重新创建MediaPlayer对象。
  更多的细节通过一个用new方式来创建的示例说明:
  Java代码
  // 通过new创建后的player处于Idle状态
  MediaPlayer mp = new MediaPlayer();
  if(mp==null){
  // new创建有可能会返回null值,检测是好的习惯
  return;
  }
  // 设置资源路径,成功执行的话player将处于Initialized状态
  try {
MediaPlayer mp = new MediaPlayer();
  if(mp==null){
  // new创建有可能会返回null值,检测是好的习惯
  return;
  }
  // 设置资源路径,成功执行的话player将处于Initialized状态
  try {
  mp.setDataSource("/sdcard/test.mp3"); // 直接传URL也是可以的,将自动处理缓冲
  } catch (IllegalArgumentException e) {
  e.printStackTrace();
  } catch (IllegalStateException e) {
  // 如果在非Idle状态下调用setDataSource就会导致该异常
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  }
  // 设置必要的监听器
  mp.setOnPreparedListener(new OnPreparedListener(){
  @Override
  public void onPrepared(MediaPlayer mp) {
  // 这时能确保player处于Prepared状态,触发start是最合适的
  mp.start();
  }
  });
  mp.setOnCompletionListener(new OnCompletionListener() {
  @Override
  public void onCompletion(MediaPlayer mp) {
  // 正常播放结束,可以触发播放下一首
  }
  });
  mp.setOnErrorListener(new OnErrorListener() {
  @Override
  public boolean onError(MediaPlayer mp, int what, intextra) {
  // 操作错误或其他原因导致的错误会在这里被通知
  return true;
  }
  });
  // 连接并加载资源
  try {
  mp.prepare();
  // mp.prepareAsync() 这也是可以的,这是异步处理,上面的是同步处理,实际加载完毕以OnPreparedListener.onPrepared()为准。
  } catch (IllegalStateException e) {
  e.printStackTrace();
  } catch (IOException e) {
  e.printStackTrace();
  }
  // mp.start(); // 建议在OnPreparedListener.onPrepared()回调中触发该函数,特别是使用异步加载时
  /**
  * ... 你的其他操作 ...
  */
  // 终止播放并释放资源
 try{
  mp.stop(); // 这是必要的,如果你设置了循环播放,否则程序退出了音乐仍在后台继续播...
  mp.release();
  }catch(IllegalStateException e){
  e.printStackTrace();
  }
  播放控制上基本与SoundPool相同有:
  start()、pause()、stop()、seekTo()、setLooping()...
  需要注意的是, 循环播放设置上与SoundPool不同,不能指定确定的循环次数,而是一个布尔值,指定是否循环播放...
  更多的函数使用请查阅API文档。
不同Activity之间的切换和数据传输 android
在Android的开发过程中我们很多时候需要在不同的Activity之间切换,同时进行一些参数的传输。这时候我们就需要会这方面的编程。
在Android开发中的四大组件{活动(Activity),服务(Services),广播接收者(BroadcastReceiver),内容提供者(ContentProvider)}中,活动(Activity)是一个很重要的部分,活动
(Activity)表示一个可视化的用户界面,关注用户从事的事件,几乎所有的活动都是要和用户进行交互的,一个Activity可以通过setContentView(View)设置一个可视化的界面,通过这个界面和用
户进行交互。每一个Activity都需要注册,注册的方式就是在AndroidManifest.xml配置文件中进行下列的配置设置:
<activity android:name=".ActivityName"
android:label="@string/app_name">
</activity>
以上的配置代码很简单,但是很重要,每一个Activity都需要进行这样的配置,没有这样的配置你的Activity就不用使用,当然在实际的开发过程中有时候不仅是上面的那些配置就足够了,还需要进行
意图过滤器的配置;配置玩这些之后然后就可以通过意图(Intent)实现不同Activity之间的切换和数据传输了,在实现这些之前,先让我们认识一下Intent(意图),意图说白了就是你要做一件什么
样的事情,意图负责对应用中的一次操作的动作,动作涉及数据,附加数据进行描述,意图过滤器定义了一些行为,对每一个意图在请求的时候进行过滤,意图还有很多知识,这里不多言了,以后抽个
时间专门写一个帖子来介绍下,现在我们写一下通过意图来实现不同Activity之间的切换和附加数据传输,首先实例化一个Intent对象,当然实例化Intent对象的方法有很多,
①Intent intent = new Intent(Context context,Class<?> cls);
②Intent intent = new Intent();
intent.setClass(Context context ,Class<?> cls);
③Intent intent = new Intent();
intent.setComponent(new ComponentName(Context context,Class<?> cls));
大家可以明显看出最简单的方式就是第一种,通过这种方式就得到了一个intent对象,通过这个intent对象我们可以夹带一些数据进行数据传输:
intent.putExtra(“name”,类型);根据实际需要选择合适的重载函数;
放入数据之后通过Activity和Intent对象完成最后一步:
ActivityName.startActivity(intent);
整个过程代码就是:
intent = new Intent(currentActivity, nextActivity.getClass());
intent.putExtra("String", “abc”);
intent.putExtra("INT", 123);
currentActivity.startActivity(intent);
currentActivity.finish();//可以通过这个函数来结束Activity的生命周期;
新打开的Activity可以通过:
String name = this.getIntent().getStringExtra("String");
Int age = this.getIntent().getIntExtra("INT");
来获取上一个Activity传过来的数据;
JAVA取整 java
舍掉小数取整:Math.floor(2.0)=2
舍掉小数取整:Math.floor(2.1)=2
舍掉小数取整:Math.floor(2.5)=2
舍掉小数取整:Math.floor(2.9)=2

舍掉小数取整:Math.floor(-2.0)=-2
舍掉小数取整:Math.floor(-2.1)=-3
舍掉小数取整:Math.floor(-2.5)=-3
舍掉小数取整:Math.floor(-2.9)=-3

四舍五入取整:Math.rint(2.0)=2
四舍五入取整:Math.rint(2.1)=2
四舍五入取整:Math.rint(2.5)=2
四舍五入取整:Math.rint(2.9)=3

四舍五入取整:Math.rint(-2.0)=-2
四舍五入取整:Math.rint(-2.1)=-2
四舍五入取整:Math.rint(-2.5)=-2
四舍五入取整:Math.rint(-2.9)=-3

凑整:Math.ceil(2.0)=2
凑整:Math.ceil(2.1)=3
凑整:Math.ceil(2.5)=3
凑整:Math.ceil(2.9)=3

凑整:Math.ceil(-2.0)=-2
凑整:Math.ceil(-2.1)=-2
凑整:Math.ceil(-2.5)=-2
凑整:Math.ceil(-2.9)=-2

四舍五入取整:Math.round(2.0)=2
四舍五入取整:Math.round(2.1)=2
四舍五入取整:Math.round(2.5)=3
四舍五入取整:Math.round(2.9)=3

四舍五入取整:Math.round(-2.0)=-2
四舍五入取整:Math.round(-2.1)=-2
四舍五入取整:Math.round(-2.5)=-2
四舍五入取整:Math.round(-2.9)=-3
android内存泄露的问题 android http://www.cnblogs.com/lbeing/archive/2010/09/29/1838858.html
Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身经历与各位网友分享解决这些问题的办法。
作为Internet最流行的编程语言之一,Java现正非常流行。我们的网络应用程序就主要采用Java语言开发,大体上分为客户端、服务器和数据库三个层次。在进入测试过程中,我们发现有一个程序模块系统内存和CPU资源消耗急剧增加,持续增长到出现java.lang.OutOfMemoryError为止。经过分析Java内存泄漏是破坏系统的主要因素。这里与大家分享我们在开发过程中遇到的Java内存泄漏的检测和处理解决过程. 

本文先介绍Java的内存管理,以及导致Java内存泄露的原因。

一. Java是如何管理内存 

为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,内存的分配是由程序完成的,而内存的释放是由垃圾收集器(Garbage Collection,GC)完成的,程序员不需要通过调用函数来释放内存,但它只能回收无用并且不再被其它对象引用的那些对象所占用的空间。 

Java的内存垃圾回收机制是从程序的主要运行对象开始检查引用链,当遍历一遍后发现没有被引用的孤立对象就作为垃圾回收。GC为了能够正确释放对象,必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。 

在Java中,这些无用的对象都由GC负责回收,因此程序员不需要考虑这部分的内存泄露。虽然,我们有几个函数可以访问GC,例如运行GC的函数System.gc(),但是根据Java语言规范定义,该函数不保证JVM的垃圾收集器一定会执行。因为不同的JVM实现者可能使用不同的算法管理GC。通常GC的线程的优先级别较低。JVM调用GC的策略也有很多种,有的是内存使用到达一定程度时,GC才开始工作,也有定时执行的,有的是平缓执行GC,有的是中断式执行GC。但通常来说,我们不需要关心这些。 

二. 什么是Java中的内存泄露 

导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。 

在Java中,内存泄漏就是存在一些被分配的对象,这些对象有下面两个特点,首先,这些对象是有被引用的,即在有向树形图中,存在树枝通路可以与其相连;其次,这些对象是无用的,即程序以后不会再使用这些对象。如果对象满足这两个条件,这些对象就可以判定为Java中的内存泄漏,这些对象不会被GC所回收,然而它却占用内存。 

这里引用一个常看到的例子,在下面的代码中,循环申请Object对象,并将所申请的对象放入一个Vector中,如果仅仅释放对象本身,但因为Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,还必须从Vector中删除,最简单的方法就是将Vector对象设置为null。 

Vector v = new Vector(10);      for (int i = 1; i < 100; i++)      {       Object o = new Object();       v.add(o);       o = null;      }//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。     实际上这些对象已经是无用的,但还被引用,GC就无能为力了(事实上GC认为它还有用),这一点是导致内存泄漏最重要的原因。 再引用另一个例子来说明Java的内存泄漏。假设有一个日志类Logger,其提供一个静态的log(String msg),任何其它类都可以调用Logger.Log(message)来将message的内容记录到系统的日志文件中。

Logger类有一个类型为HashMap的静态变量temp,每次在执行log(message)的时候,都首先将message的值写入temp中(以当前线程+当前时间为键),在退出之前再从temp中将以当前线程和当前时间为键的条目删除。注意,这里当前时间是不断变化的,所以log在退出之前执行删除条目的操作并不能删除执行之初写入的条目。这样,任何一个作为参数传给log的字符串最终由于被Logger的静态变量temp引用,而无法得到回收,这种对象保持就是我们所说的Java内存泄漏。 总的来说,内存管理中的内存泄漏产生的主要原因:保留下来却永远不再使用的对象引用。


 
1:查找内存泄露的方法。


与C++的内存不同,C++的内存泄露是由于分配了内存给某程序但是又没有回收造成的。Java的内存泄露则是引用了一些垃圾对象,意思就是说程序引用了某些对象,但是又从来没有使用过。

Jave中的引用分为3种:

强引用:引用为空的时候,Java的垃圾回收器会处理。一般来说自己写的程序大部分都是强引用。

软引用:堆内存不够的时候,Java的垃圾回收器会处理这类引用。

弱引用:Jave的垃圾回收器每次都会回收这类引用。

如何用MAT来分析,前提是Android开发和测试的工具安装完整,SDK,Eclipse:

1.打开Eclipse

2.选择 Help->Install New Software;

3.在Work with中添加站点:http://download.eclipse.org/mat/1.0/update-site/(这个地址可能会变化,但是新的地址可以在官方网站上找到:http://www.eclipse.org/mat/downloads.php )

4.生成.hprof文件:插入SD卡(Android机器很多程序都需要插入SD卡),并将设备连接到PC,在Eclipse中的DDMS中选择要测试的进程,然后点击Update Heap 和Dump HPROF file两个Button。

.hprof 文件会自动保存在SD卡上,把 .hprof 文件拷贝到PC上的\ android-sdk-windows\tools目录下。这个由DDMS生成的文件不能直接在MAT打开,需要转换。

运行cmd打开命令行,cd到\ android-sdk-windows\tools所在目录,并输入命令hprof-conv xxxxx.hprof yyyyy.hprof,其中xxxxx.hprof为原始文件,yyyyy.hprof为转换过后的文件。转换过后的文件自动放在android-sdk-windows\tools 目录下。

OK,到此为止,.hprof文件处理完毕,可以用来分析内存泄露情况了。

5.打开MAT:

在Eclipse中点击Windows->Open Perspective->Other->Memory Analysis

6.导入.hprof文件

在MAT中点击 File->Open File,浏览到刚刚转换而得到的.hprof文件,并Cancel掉自动生成报告,点击Dominator Tree,并按Package分组,选择自己所定义的Package 类点右键,在弹出菜单中选择List objects->With incoming references。

这时会列出所有可疑类,右键点击某一项,并选择Path to GC Roots->exclude weak/soft references,会进一步筛选出跟程序相关的所有有内存泄露的类。据此,可以追踪到代码中的某一个产生泄露的类。
2:相关知识

Android将进程分为六大类:

前台进程(foreground):目前正在屏幕上显示的进程和一些系统进程。举例来说,Dialer Storage,Google Search等系统进程就是前台进程;再举例来说,当你运行一个程序,如浏览器,当浏览器界面在前台显示时,浏览器属于前台进程(foreground),但一旦你按home回到主界面,浏览器就变成了后台程序(background)。我们最不希望终止的进程就是前台进程。
  可见进程(visible):可见进程是一些不再前台,但用户依然可见的进程,举个例来说:widget、输入法等,都属于visible。这部分进程虽然不在前台,但与我们的使用也密切相关,我们也不希望它们被终止(你肯定不希望时钟、天气,新闻等widget被终止,那它们将无法同步,你也不希望输入法被终止,否则你每次输入时都需要重新启动输入法)
  次要服务(secondary server):目前正在运行的一些服务(主要服务,如拨号等,是不可能被进程管理终止的,故这里只谈次要服务),举例来说:谷歌企业套件,Gmail内部存储,联系人内部存储等。这部分服务虽然属于次要服务,但很一些系统功能依然息息相关,我们时常需要用到它们,所以也太希望他们被终止。
  后台进程(hidden):虽然作者用了hidden这个词,但实际即是后台进程(background),就是我们通常意义上理解的启动后被切换到后台的进程,如浏览器,阅读器等。当程序显示在屏幕上时,他所运行的进程即为前台进程(foreground),一旦我们按home返回主界面(注意是按home,不是按back),程序就驻留在后台,成为后台进程(background)。后台进程的管理策略有多种:有较为积极的方式,一旦程序到达后台立即终止,这种方式会提高程序的运行速度,但无法加速程序的再次启动;也有较消极的方式,尽可能多的保留后台程序,虽然可能会影响到单个程序的运行速度,但在再次启动已启动的程序时,速度会有所提升。这里就需要用户根据自己的使用习惯找到一个平衡点
  内容供应节点(content provider):没有程序实体,进提供内容供别的程序去用的,比如日历供应节点,邮件供应节点等。在终止进程时,这类程序应该有较高的优先权
  空进程(empty):没有任何东西在内运行的进程,有些程序,比如BTE,在程序退出后,依然会在进程中驻留一个空进程,这个进程里没有任何数据在运行,作用往往是提高该程序下次的启动速度或者记录程序的一些历史信息。这部分进程无疑是应该最先终止的。系统会对进程的重要性进行评估,并将重要性以“oom_adj”这个数值表示出来,赋予各个进程;(系统会根据“oom_adj”来判断需要结束哪些进程,一般来说,“oom_adj”的值越大,该进程被系统选中终止的可能就越高)
  前台程序的“oom_adj”值为0,这意味着它不会被系统终止,一旦它不可访问后,会获得个更高的“oom_adj”,作者推测“oom_adj”的值是根据软件在LRU列表中的位置所决定的; 
Android不同于Linux,有一套自己独特的进程管理模块,这个模块有更强的可定制性,可根据“oom_adj”值的范围来决定进程管理策略,比如可以设定“当内存小于X时,结束“oom_adj”大于Y的进程”。这给了进程管理脚本的编写以更多的选择。
android Drawable、Bitmap、byte[]之间的转换 android
1、Drawable → Bitmap
public static Bitmap drawableToBitmap(Drawable drawable) {
        
        Bitmap bitmap = Bitmap
                        .createBitmap(
                                        drawable.getIntrinsicWidth(),
                                        drawable.getIntrinsicHeight(),
                                        drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                                                        : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        //canvas.setBitmap(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
}
2、从资源中获取Bitmap
Resources res=getResources();

Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.pic);
3、Bitmap → byte[]
private byte[] Bitmap2Bytes(Bitmap bm){
  ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
  bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
  return baos.toByteArray();
}
4、 byte[] → Bitmap
private Bitmap Bytes2Bimap(byte[] b){
	if(b.length!=0){
		return BitmapFactory.decodeByteArray(b, 0, b.length);
	  }
	 else {
		return null;
	 }
  }
android 内存泄露问题 android http://hi.baidu.com/gaogaf/blog/item/f3064936c0daa3c9a3cc2bfd.html
尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。

因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
无需再使用java层的createBitmap,从而节省了java层的空间。
如果在读取时加上图片的Config参数,可以跟有效减少加载的内存,从而跟有效阻止抛out of Memory异常
另外,decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应, 
使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源, 
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

另外,以下方式也大有帮助:
1. InputStream is = this.getResources().openRawResource(R.drawable.pic1);
     BitmapFactory.Options options=new BitmapFactory.Options();
     options.inJustDecodeBounds = false;
     options.inSampleSize = 10;   //width,hight设为原来的十分一
     Bitmap btp =BitmapFactory.decodeStream(is,null,options);
2. if(!bmp.isRecycle() ){
         bmp.recycle()   //回收图片所占的内存
         system.gc()  //提醒系统及时回收
}

以下奉上一个方法:

Java代码

 /**
  * 以最省内存的方式读取本地资源的图片
  * @param context
  * @param resId
  * @return
  */  
 public static Bitmap readBitMap(Context context, int resId){  
     BitmapFactory.Options opt = new BitmapFactory.Options();  
     opt.inPreferredConfig = Bitmap.Config.RGB_565;   
     opt.inPurgeable = true;  
     opt.inInputShareable = true;  
    //获取资源图片  
    InputStream is = context.getResources().openRawResource(resId);  
       return BitmapFactory.decodeStream(is,null,opt);  
}
Global site tag (gtag.js) - Google Analytics