当前位置: 编程技术>移动开发
本页文章导读:
▪取得百度音乐盒音乐的下载地址 获得百度音乐盒音乐的下载地址
//
// BaiduMusicBoxParser.h
//
// Created by scott.8an@gmail.com on 12-3-11.
// Copyright (c) 2012年. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASIHTTPRequest.h"
#import ".........
▪ ClassLoader学习记要2 ClassLoader学习记录2
写程序的时候,时常会思考,我们的类是哪来的?为何我们想用sdk中的类,就有这个类呢?答案肯定是classloader读进虚拟机来的。那他究竟是怎么被加载到虚拟机中.........
▪ 初始化有EditText或AutoCompleteEditText的界面时系统自动打开软键盘的有关问题 初始化有EditText或AutoCompleteEditText的界面时系统自动打开软键盘的问题
相信刚做android开发的朋友都会遇到这个问题:如果一个界面有EditText或者AutoComplete控件的时候,EditText得到焦点了会自.........
[1]取得百度音乐盒音乐的下载地址
来源: 互联网 发布时间: 2014-02-18
获得百度音乐盒音乐的下载地址
// // BaiduMusicBoxParser.h // // Created by scott.8an@gmail.com on 12-3-11. // Copyright (c) 2012年. All rights reserved. // #import <Foundation/Foundation.h> #import "ASIHTTPRequest.h" #import "ASINetworkQueue.h" #import "TFHpple.h" #import "XPathQuery.h" #import "TFHppleElement.h" @interface BaiduMusicBoxParser : NSObject + (BaiduMusicBoxParser*)shareInstance; /** 返回的数组结构: [ { album = "\U672a\U6765\U5c5e\U4e8e\U5b69\U5b50 \U4e2d\U5916\U540d\U66f2\U7cbe\U9009"; artist = "\U6768\U9e3f\U5e74"; "download_url" = "http://mp3.baidu.com/j?j=2&url=http%3A%2F%2Fzhangmenshiting.baidu.com%2Fdata2%2Fmusic%2F9405342%2F9405342.mp3%3Fxcode%3Dfdaccf3ade1f2d967110c329ab53b046"; quality = "MP3(3.9M)"; "song_name" = "we are the world"; },... ] **/ - (NSArray*)baiduSongsInfoBySearchingSongName:(NSString *)name pageNumber:(int)pgNO; //获取歌词 - (NSString*)lyricsWithSong:(NSString*)sName; //获取百度歌手列表,从大写字母A~Z,其他为0 /** [ "A"=[ AOK, Alizee,... ], "B"={ BOBO, 白雪,... },... ] **/ - (NSArray*)allArtistsListOfBaiduMp3; - (NSArray*)artistsListOfBaiduMp3ByFilterCharacter:(NSString*)character; @end
// // BaiduMusicBoxParser.m // // Created by scott.8an@gmail.com on 12-3-11. // Copyright (c) 2012年. All rights reserved. // #import "BaiduMusicBoxParser.h" #import "GDataXMLNode.h" static BaiduMusicBoxParser *parser_ = nil; @interface BaiduMusicBoxParser (Private) /** 返回的数组结构: [ "http://box.zhangmen.baidu.com/m?word=mp3,,,[love+of+my+life]&gate=1&ct=134217728&tn=baidumt,love+of+my+life&si=love+of+my+life;;keith%20martin;;0;;0&lm=-1&attr=0,0&rf=zb&size=1992294", ... ] sName:歌曲名称 pgNo:页数。默认为0. **/ - (NSArray*)jumpToURLBySongName:(NSString*)sName pageNumber:(int)pgNo; @end @implementation BaiduMusicBoxParser - (void)dealloc{ [super dealloc]; } + (BaiduMusicBoxParser*)shareInstance{ if (!parser_) { parser_ = [[self alloc] init]; } return parser_; } - (id)init{ if ([super init]) { } return self; } - (NSArray*)jumpToURLBySongName:(NSString*)sName pageNumber:(int)pgNo{ if(sName==nil || [sName length]==0)return nil; if (pgNo<0) { return nil; } //去除两端的空格 [sName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; //把歌曲拼凑成格式如:love+of+my+life 的形式 NSArray *nameArr = [sName componentsSeparatedByString:@" "]; NSMutableString *newName = [NSMutableString stringWithCapacity:0]; if (nameArr && [nameArr count]) { for (NSString *s in nameArr) { [newName appendFormat:@"%@+",s]; } //去掉最后一个 '+'号 if ([newName length]) { [newName deleteCharactersInRange:NSMakeRange([newName length]-1, 1)]; } } //用户输入的是整个字符串,没有空格 if (nameArr && [nameArr count]==1) { [newName appendString:[nameArr objectAtIndex:0]]; } //组合地址并编码 NSString *requestURL = [NSString stringWithFormat:@"http://mp3.baidu.com/m?word=%@&lm=-1&f=ms&tn=baidump3&ct=134217728&lf=&rn=&pn=%i",newName,pgNo*30]; NSString *requestURLWithEnc = [requestURL stringByAddingPercentEscapesUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)]; //NSLog(@"===%@",requestURLWithEnc); //发送请求,获得返回数据 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:requestURLWithEnc]]; [request startSynchronous]; if ([request error]) { return nil; } //接收返回数据 //获取id = "songResults"的节点 TFHpple *helper = [TFHpple hppleWithHTMLData:[request responseData]]; NSString *xPathDescription = @"//*[@id=\"songResults\"]"; TFHppleElement *divElement = [helper peekAtSearchWithXPathQuery:xPathDescription]; NSArray *children = divElement.children; //return NSMutableArray *jumpToPageURLArray = [NSMutableArray arrayWithCapacity:0]; //获得table TFHppleElement *tb = [children objectAtIndex:0]; NSArray *tbodyChildren = tb.children; if (tbodyChildren && [tbodyChildren count]) { for (TFHppleElement *trElement in tbodyChildren) { NSArray *tdArr = trElement.children; if (tdArr && [tdArr count]) { for (TFHppleElement *tdNode in tdArr) { //<td > if (tdNode && [[tdNode objectForKey:@"class"] isEqualToString:@"down"]) { NSArray *tdNodeArr = tdNode.children; if (tdNodeArr && [tdNodeArr count]) { TFHppleElement *aNode = tdNode.firstChild; if (aNode) { //获得要跳转的地址 NSString *jumpToURL = [aNode objectForKey:@"href"]; if ([jumpToURL length]) { [jumpToPageURLArray addObject:jumpToURL]; } } } } } } } } //跳转界面地址数组 //NSLog(@"共有跳转地址:%i个,它们是:%@",[jumpToPageURLArray count],jumpToPageURLArray); if ([jumpToPageURLArray count]) { return jumpToPageURLArray; } return nil; } - (NSArray*)baiduSongsInfoBySearchingSongName:(NSString *)name pageNumber:(int)pgNO{ if(name==nil || [name length]==0)return nil; if (pgNO<0) return nil; NSArray *jumpToURLArr = [self jumpToURLBySongName:name pageNumber:pgNO]; //获得跳转地址的数组 NSMutableArray *musicInfoArr = [NSMutableArray arrayWithCapacity:0]; if (jumpToURLArr && [jumpToURLArr count]) { for (NSString *urlStr in jumpToURLArr) { ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlStr]]; [request startSynchronous]; //获得返回数据 NSData *responseData = [request responseData]; if (responseData) { TFHpple *helper = [TFHpple hppleWithHTMLData:responseData]; if (helper) { //获得歌曲的下载地址 NSString *xPath = @"//*[@id='downlink']"; TFHppleElement *downloadLinkNode = [helper peekAtSearchWithXPathQuery:xPath]; NSString *musicDownloadURI = [downloadLinkNode objectForKey:@"href"]; NSString *musicDownloadURL = [NSString stringWithFormat:@"http://mp3.baidu.com%@",musicDownloadURI]; //NSLog(@"======下载地址是:%@",musicDownloadURL); if (musicDownloadURI && [musicDownloadURI length]) { //获得歌手名字 /**<div > <span >歌手: <a href="http://mp3.baidu.com/singerlist/back ii back.html" target="_blank">back ii back</a> </span> <span >所属专辑: 《<a href="http://mp3.baidu.com/albumlist/back ii back;;;;;;back ii back.html" target="_blank">back ii back</a> 》</span> </div> **/ NSString *aritistNameXpath = @"//*[@]"; TFHppleElement *aritistNameNode = [helper peekAtSearchWithXPathQuery:aritistNameXpath]; TFHppleElement *spanNode = aritistNameNode.firstChild; TFHppleElement *aNode = spanNode.firstChild; NSString *artistName = aNode.content; //NSLog(@"*************歌手:%@",artistName); //获得专辑名字 TFHppleElement *albumNode = [aritistNameNode.children objectAtIndex:1]; TFHppleElement *AaNode = albumNode.firstChild; NSString *albumName = AaNode.content; //NSLog(@"*************专辑:%@",albumName); //获得歌曲的品质 /** <div >品质:<b>MP3(4.0M)</b></div> **/ NSString *qulityXpath = @"//*[@]"; TFHppleElement *qulityNode = [helper peekAtSearchWithXPathQuery:qulityXpath]; TFHppleElement *bNode = qulityNode.firstChild; NSString *qulityDescription = bNode.content; //NSLog(@"*************品质:%@",qulityDescription); if (musicDownloadURI && [musicDownloadURI length]) { NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:0]; [dic setObject:musicDownloadURL forKey:@"download_url"]; [dic setObject:name forKey:@"song_name"]; [dic setObject:artistName?artistName:[NSNull null] forKey:@"artist"]; [dic setObject:albumName?albumName:[NSNull null] forKey:@"album"]; [dic setObject:qulityDescription?qulityDescription:[NSNull null] forKey:@"quality"]; if ([dic count]) { [musicInfoArr addObject:dic]; } } } } } } } //NSLog(@"歌曲信息数组-------------%@",musicInfoArr); if ([musicInfoArr count]) { return musicInfoArr; } return nil; } - (NSString*)lyricsWithSong:(NSString*)sName { return nil; } - (NSArray*)allArtistsListOfBaiduMp3{ return nil; } - (NSArray*)artistsListOfBaiduMp3ByFilterCharacter:(NSString*)character{ return nil; } @end
[2] ClassLoader学习记要2
来源: 互联网 发布时间: 2014-02-18
ClassLoader学习记录2
写程序的时候,时常会思考,我们的类是哪来的?为何我们想用sdk中的类,就有这个类呢?答案肯定是classloader读进虚拟机来的。那他究竟是怎么被加载到虚拟机中的呢?看看如何定制classloader的代码,就相当一目了然了。
此段代码看完发现(defineClass方法),虚拟机加载新类的方式就是:使用父类的defineClass方法将某Class类的字节码传递给虚拟机,(其实就是以字节形式把字节码传递给虚拟机),并且创建相应的类。
下来解释一下上面的程序:key这个int。这个例子使用了一个小的加密方法,就是类文件中所有的字节都向后移动了key个位置,比如3,那么,在加载此类时,就应该向前移动3,来保证文件被解密。这里我们就引申出了自定义classloader的用法之一,即加密。你想使用这个类?请知道密钥先!就好像游戏的注册码一样,没有key和我们的classloader,你拿到类文件也是没有任何意义的。(好吧我承认程序里的加密方法不怎么先进)
怎么样,很棒吧。其实一直以来,还有个疑问,如果包名和类名一样的情况,classloader应该如何处理?首先,像上面的情况,一个路径下是不能放相同名字的类文件的,先排除此情况。那如果在多jar包的环境下,真的有两个一样的类名呢?我想、估计是直接使用第一个被load进的类吧,因为classloader会判断此类已经被加载进来了,毕竟classloader也不会读心数,知道你想使用哪个jar包的类。
其实,如果类名和包名都重复,我们可以看见,如果classloader不一样,你那么也不会有任何问题,它们之间是不会相互干扰的,比如Web中的每个applet,就是由不同的classloader加载的,所以,命名冲突在applet之间是允许的。就好像不同的命名空间。
还有个比喻,我想到的,可能会比较烂。比如,android上的两个不同的apk,如果两个程序中,使用相同的包名和类名的话,应该也不会相互干扰,因为不同的classloader导致。(因为每个进程都有自己的虚拟机,那么classloader也理应不同,恩,应该是这样,本身classloader就是给虚拟机服务的嘛。)
写程序的时候,时常会思考,我们的类是哪来的?为何我们想用sdk中的类,就有这个类呢?答案肯定是classloader读进虚拟机来的。那他究竟是怎么被加载到虚拟机中的呢?看看如何定制classloader的代码,就相当一目了然了。
main() { runClass(name, key); } public void runClass(String name, int key){ ClassLoader classLoader = new CryptoClassLoader(key); Class<?> c = classLoader.loadClass(); Method m = c.getMethod("main", String[].class); m.invoke(null, (Object)new String[]{}); } class CryptoClassLoader extends ClassLoader{ int key; CryptoClassLoader(int key){ this.key = key } protected Class<?> findClass(String name) throws ClassNotFoundException{ byte[] classBytes = null; try{ classBytes = loadClassBytes(name); } catch(IOException e) { throw new ClassNotFoundException(); } Class<?> cl = defineClass(name, classBytes, 0, classBytes.length); if (cl == null) throw new ClassNotFoundException(name); return cl; } private byte[] loadClassBytes(String name) throws IOException{ String cname = name.replace(".","/") + ".caesar"; //(我怎么觉得应该是.class? 不太懂这里...不会印刷错误吧?) FileInputStream in = null; in = new FileInputStream(cname); try{ ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int ch; while((ch = in.read()) != -1){ byte b = (byte)(ch - key); buffer.write(b); } return b.toByteArray(); } finally { in.close(); } } }
此段代码看完发现(defineClass方法),虚拟机加载新类的方式就是:使用父类的defineClass方法将某Class类的字节码传递给虚拟机,(其实就是以字节形式把字节码传递给虚拟机),并且创建相应的类。
下来解释一下上面的程序:key这个int。这个例子使用了一个小的加密方法,就是类文件中所有的字节都向后移动了key个位置,比如3,那么,在加载此类时,就应该向前移动3,来保证文件被解密。这里我们就引申出了自定义classloader的用法之一,即加密。你想使用这个类?请知道密钥先!就好像游戏的注册码一样,没有key和我们的classloader,你拿到类文件也是没有任何意义的。(好吧我承认程序里的加密方法不怎么先进)
怎么样,很棒吧。其实一直以来,还有个疑问,如果包名和类名一样的情况,classloader应该如何处理?首先,像上面的情况,一个路径下是不能放相同名字的类文件的,先排除此情况。那如果在多jar包的环境下,真的有两个一样的类名呢?我想、估计是直接使用第一个被load进的类吧,因为classloader会判断此类已经被加载进来了,毕竟classloader也不会读心数,知道你想使用哪个jar包的类。
其实,如果类名和包名都重复,我们可以看见,如果classloader不一样,你那么也不会有任何问题,它们之间是不会相互干扰的,比如Web中的每个applet,就是由不同的classloader加载的,所以,命名冲突在applet之间是允许的。就好像不同的命名空间。
还有个比喻,我想到的,可能会比较烂。比如,android上的两个不同的apk,如果两个程序中,使用相同的包名和类名的话,应该也不会相互干扰,因为不同的classloader导致。(因为每个进程都有自己的虚拟机,那么classloader也理应不同,恩,应该是这样,本身classloader就是给虚拟机服务的嘛。)
[3] 初始化有EditText或AutoCompleteEditText的界面时系统自动打开软键盘的有关问题
来源: 互联网 发布时间: 2014-02-18
初始化有EditText或AutoCompleteEditText的界面时系统自动打开软键盘的问题
相信刚做android开发的朋友都会遇到这个问题:如果一个界面有EditText或者AutoComplete控件的时候,EditText得到焦点了会自动的打开系统的软键盘,那么怎么才能让软键盘在第一次看到界面的时候隐藏起来喃?有两种办法:
1:
在第一个EditText或AutoComplete控件之前加上以上代码,因为宽和高都为0,所以不占用布局空间。
2:在AndroidManifest.xml对应的Activity声明处:
相信刚做android开发的朋友都会遇到这个问题:如果一个界面有EditText或者AutoComplete控件的时候,EditText得到焦点了会自动的打开系统的软键盘,那么怎么才能让软键盘在第一次看到界面的时候隐藏起来喃?有两种办法:
1:
<Linearlayout android:focusable="true" android:focusableintouchmode="true" android:layout_height="0px" android:layout_width="0px"/>
在第一个EditText或AutoComplete控件之前加上以上代码,因为宽和高都为0,所以不占用布局空间。
2:在AndroidManifest.xml对应的Activity声明处:
<activity android:windowSoftInputMode="adjustUnspecified|stateHidden" android:configChanges="orientation|keyboardHidden"]> </activity>
最新技术文章: