[转载]与webview打交道中踩过的那些坑 - 吕大豹 - 博客园

mikel阅读(1270)

[转载]与webview打交道中踩过的那些坑 – 吕大豹 – 博客园.

   随着HTML5被越来越多的用到web APP的开发当中,webview这一个神器便日渐凸显出重要地位。简要的说,webview能够在移动应用中开辟出一个窗口,在里面显示html页 面,css以及js代码也可以被解析执行,它使用的是我们熟悉的webkit内核。Android和ios都有相应的API,所以写一份代码在多个平台运 行的能力就是以webview为基础的。

今天我们要聊的不是如何使用webview,而是笔者本人作为一名前端工程师,在与客户端开发人员通过webview打交道中遇到的种种神奇事件。

事情还得从去年说起,我还是一个小白实习生的时候。当经理知道有webview这个神器之后,遂下令让Android组和ios组削减工作内 容,所有共同的界面均由web组提供。而web组当时处于“传统软件公司无前端”的局面,页面相当臃肿,压根不适于移动设备。于是乎,不明局势的经理指挥 一个不明真相的小白实习生,带着还没使利索的JQuery,开始了所谓的Hybrid App开发。一个凄惨的故事拉开序幕,下面是在开发当中踩过的各种坑,记录下来以供备忘。

webview会调用系统自带的浏览器内核来解析页面。这是个真命题吗?市场上的大部分平板电脑自带浏览器为webkit内核,webview 使用的也是webkit内核,并且按一个应用的大小来看也不可能自己带一个内核进去。所以是调用系统自带的是没错的了。那我在一台设备上,使用浏览器打开 一个页面和使用webview打开同一页面,得到的结果会是一模一样吗?当然是废话了,都说了是调用关系。

假如真是废话,那我也没必要记下这一点了。因为从我的实际操作情况来看,有些时候确实是不一样的。浏览器里一个样,webview里又是一个样。ipad上情况好些。在Android品牌杂乱的设备上,此现象还真的出现不只一次。尤其是页面DOM结构比较复杂的时候。

有理由怀疑我的代码不符合W3C规范啥的,但业界良心,W3C规范还是不敢违反的。所以得出结论,webview与自带浏览器解析的结果并不是完全一致,不能以为页面在浏览器中正常了,在移动设备上也就正常了。

绝对要慎用的瀑布流

大概是两年前,瀑布流这个概念红遍大江南北,各网站纷纷效仿,相应的文章、JQuery插件层出不穷。后来真正有思想的人开始质疑,提出我们要学习的不是瀑布流的形式,而是思想,我们需要的是真正适合自己产品的东西。后来,我们经理也听说了瀑布流这个东西。。。

加!加瀑布流!我们不要分页列表那些东西!于是小白实习生网上各种搜索,找到了当时比较流行的叫做infinitescroll的JQuery插件。各种改源码配合实现产品业务、各移动设备兼容性bug处理暂且放一边。这里要提的是与移动应用密切相关的一个问题。

做移动开发的对闪退这种现象估计是咬牙切齿,移动应用的性能问题一直是不容小觑的。就webview来讲,当html页面的DOM元素很多,或 者说层级关系较复杂时,对其的压力是相当大的。再看看我们的瀑布流,随着页面的滚动,不断往上append节点,这对webview来说压力极大,当节点 数量到一定程度时,就发现页面滚动不是那么流畅,开始一卡一卡。别急,你在翻转一下屏幕试试,瞬间崩溃,界面这个花了,内容像是绘制不出来一样。因为在做 横竖屏翻转时,解析引擎会进行页面的重绘,这么多的节点工作量可不小。ipad因为其优越的图像处理性能表现还不错,android设备上简直一塌糊涂。

有什么解决办法呢?我在听一个大牛的经验分享会上曾听到,在页面滚动的时候可以通过计算,动态remove节点,保证用户能看到的地方是有内容 的,其他滚动卷去的部分就直接remove掉,等滚动回来的时候再加回来。这样保证页面上的节点不会太多,性能自然提升。我没有尝试这种方案,其中的注意 事项也不好说。不过大牛成功了,必然是可行的。

总之得出一个结论,在移动设备上,要用瀑布流,一定要慎用,必须先有性能的解决办法。

响应式布局与viewport

我们知道移动设备在渲染页面的时候,会先在一个虚拟画布上渲染,然后再缩放到设备的尺寸,比如IOS是在宽度为980px的虚拟画布上渲染。我们看一些响应式设计的文章,也会知道在页面<head>中要添加如下内容:

<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

来保证页面会按照设备的宽度进行渲染而不是使用虚拟画布。然后便可以使用响应式设计的相关技术,弹性盒子、媒体查询等,让页面适应设备宽度显示。

然而我遇到了一个问题,因为页面结构较复杂,在横竖屏翻转的时候出现了花屏,各种显示不全,各种抽风抖动。当然是在android设备上。。。原因就是设备的宽度发生变化webview要进行页面重绘,然而在重绘的过程中,由于页面太复杂而不堪重负,绘到一半不管了。

因为当时该页面的设计,会显示图片、音频、视频等媒体,并且是多个同时显示,进行页面精简不可行。说来惭愧,面对紧迫的时间,我只好悄悄把上面 的<meta>标签删掉,让页面还是在虚拟画布上渲染,这样渲染好的页面在进行横竖屏翻转的时候,貌似是不会进行重绘的,只会由系统缩放一 下,花屏的现象也不会发生了。只不过在竖屏下,页面元素明显小了。算是个下策。

像这样的情况,个人觉的在页面设计的时候就应该考虑到,若要进行横竖屏翻转,页面尽量设计的精简清爽。不过话说回来,移动应用上的页面,精简是一直需要且必须的。

尽量不要用别人的插件

不怕丢人的承认,我们做web App用的是jQuery,原谅我当时是个小白吧。。。如果早些知道我们的东西只需支持现代浏览器,无论如何也得试试zepto或是其他的小而轻的库。不过既然用了,还是来面对这个现实吧。

小白的特征之一就是从素材网站收藏了好多jQuery插件,然后在项目中不假思索就用。我们的页面是先在PC上用,然后才被告知要被 webview引用的。这下麻烦来了,原先使用的好好的插件,一但跑在移动设备上,各种羊癫疯发作。然后开始不遗余力的改源码,过程简直不堪回首。

比较典型的一个,我们的页面中有富文本编辑器,当时选择的是国内的一款开源编辑器KindEditor。我没有诋毁这个项目的意思,它在PC上 使用还是蛮好的。一上了平板,直接傻了,基本上废了。环视网上,没有一款为移动设备设计的编辑器。所以编辑器这东西,还是让本地代码来做比较合理。

另一个插件用的比较痛苦的是H5视频播放的,用了mediaelement,它在官网宣称支持各浏览器各平台,然而真正效果却并非宣称的那样。在android4.0以上的设备中都有各种兼容性问题。又是一顿改源码。。。

所以得出的结论就是,如果某个组件可以自己写出来,千万别从网上找别人的,到头来自己还得麻烦。倘若真的准备要使用,一定先做一个全方位的测评。包括能否与你的业务逻辑完美融合,能否支持你所需要的设备。

:hover伪类在移动设备上的特殊现象

我们在做鼠标悬停效果时,经常会用到:hover,无论用在<a>标签或是其他标签,现代浏览器都能正常兼容。比如我有一个图标,在鼠标移上去之后想要一个阴影效果,可能会这样写:

.icon:hover{box-shadow:2px 2px 2px;}

在移动设备上,是没有鼠标指针的。当用手指点击图标的时候,可以出现阴影效果,这种效果也是可以接受的。但是当点击完成后,手指离开了屏幕,图 标的hover效果却没有消失,依然是带着阴影,就好像是有一个隐形的鼠标指针停留在图标上一样,实在是让人不能理解。当再点击页面的其他部分时,图标的 hover效果就消失了,好像是隐形的鼠标指针移到了别的地方。

ipad和android设备上都有此现象。为了避免此问题,css中的:hover伪类就必须利用媒体查询,只在桌面浏览器中生效。

ipad关闭屏幕造成的问题

ipad出于节约电量的设计,关闭屏幕后浏览器中的一些线程也会暂时关闭,等到开启屏幕时再起。如果有需要持续执行的js代码,关闭屏幕后便无 法工作了。比如,要用setInterval函数实现一个计时功能,每隔一秒进行时间更新。当屏幕关闭后,计时函数就不能工作了,即关闭屏幕5秒种,你的 计时器也将停止5秒。

如果是实现一些网页动态效果,这倒没什么影响。但如果你的计时器涉及到了业务逻辑,比如计的是一次考试的时间,那影响就大了。一个考生关闭屏幕后将可以使时间静止。这是不希望发生的。所以,如果代码中有用js进行计时,或其他需持续执行的任务。需要考虑到此问题。

对于计时器,我们可以隔一段时间与服务器进行时钟同步,从而解决客户端因关闭屏幕造成的计时误差。

顺便再加一句,使用ipad上的safari浏览器,在切换到别的标签页时,原标签中的线程也会被停掉,跟关闭屏幕一样的效果。

定位属性与重绘的纠葛

在移动设备横竖屏翻转的时候,会进行页面的重绘,ipad图像处理性能较强,问题不大,但是形形色色的android设备性能不一,一些较差的 在转屏时经常会显示不出来界面,或是出现花屏。比较明显而且严重的情况是,当页面上的元素使用了position:fixed或是 position:absolute时,转屏后该元素的定位将会错乱,可能是转屏时页面所处的环境变动太大,渲染引擎计算的时候性能消耗太多,总是无法将 这类元素正确显示出来。

我的处理办法是自己让webview把这个元素再重绘一下,操作元素的属性、className,或者是设置visibility均可触发重绘 行为。但这种方式也不是屡屡见效,有时候也无济于事。没办法,android就是这么奇葩,太不稳定。所以实在不行我也会这么写:

$(‘html’).css(‘visibility’,’hidden’);
setTimeout(function(){
         $(‘html’).css(‘visibility’,’visible);
},100);

我怀疑webview的重绘是否真的进行了,所以直接让页面闪烁一下,这样效果会好很多,一般情况都能重绘正确。

再糟的情况,实在用HTML解决不了了,可以去找客户端的同学,让他们操作webview,webview也可以进行重绘或者是直接reload。

不得不说的touch事件

在桌面浏览器上,基本的功能都是靠监听click事件来完成的,移动设备上没有鼠标指针压根就没有click这事件,不过对于这么重要的东西,引擎当然是做了相应处理。click事件在pad上可以很好的被响应。

但正如上面提到的,小白总是会使用一些现成的插件。。我用了一个弹出窗口插件,在桌面上可以用鼠标拖动,但是在pad上却无法拖动了。移动设备 上的引擎虽然对click做了很好的处理,但是对mousedown、mousemove、mouseup却没有理会,所以需要在代码中对应的加上 touchstart、touchmove、touchend事件。

有些现象是可以想出原因来的,但有些现象是那种根本就不讲道理的,我这里也不知道如何描述。大概就是当touch事件和click事件同时被监听,再加上页面结构复杂等其他因素,就会出现各种抽风行为。

首先精简页面结构是最最重要的,没有之一。其次对于不同设备的奇异现象,我也只能想办法进行各种hack了。

明确要支持哪些设备

这一点跟技术无关了,是一个决策问题。ipad无论是2、3、4还是mini都比较稳定,兼容问题基本没有。主要是android,系统版本从 2.x到4.x不等,各种牌子:三星、华硕、联想算比较主流的,其他是像昂达、酷派、粤教云。而且各品牌还有多种型号。再加上各厂家对android系统 的无节操修改,浏览器内核都改。整个现在那叫一个乱啊。

所以在项目初期,明确要支持哪些设备是非常重要的。这样就可以针对这些设备进行兼容性的测试。而不是今天客户说要用哪个设备,我们就想办法兼容哪个设备,真是会累死。还真有这样的客户,说我们就只使用千元以下的平板,性能那真是一个蛋疼。

 

经历了一番痛苦的挣扎,秉着能解决就解决,解决不了就hack的原则,项目还真按期完成了。hack写多了真是有种犯罪感啊!现在看着项目,真 的有种假如上天给我再来一次机会的呐喊,不过一切都过去了。经验教训一大把,在此挑些典型的与大家共享。可能在专做移动开发的前端眼里,这些都是小儿科, 但作为一个从小白走过来的程序员,这些经验还是相当重要。

[转载]window中安装iphone开发环境 - 残星 - 博客园

mikel阅读(1100)

[转载]window中安装iphone开发环境 – 残星 – 博客园.

很多朋友希望在体验或学习iPhone开发,但是iphone开发环境一般需要安装在mac计算机下Mac OS中。
这给许多朋友带来了额外成本投入。 
网上已经有各种破解方法,在非苹果电脑上安装iphone开发环境,给我们带来了佳音。但是各种版本比较杂乱,可能会费时费力而无果。 
最近,苹果推出了新的开发环境版本。我将新版开发环境在Windows XP下VMWare虚拟机中安装开发环境过程贴出来,让大家分享。 
本文在Windows Xp + VMware Workstation 7.0 + MAC OS X Snow Leopard 10.6 环境下安装iPhone SDK3.1.2成功!

两种安装MAC OS的方法

在PC机上安装MAC OS X系统有两种方法: 
方法一:在硬盘上分区,专门安装MAC OS X; 
方法二:在现有Windows系统中,使用VMWare等虚拟机软件安装Mac OS。 
注意:一般都需要将苹果系统的DMG光盘镜像文件刻录到D9光盘上,这个步骤比较麻烦。 
本文介绍一下在Windows XP中使用VMWare虚拟机,安装MAC OS X时,无需刻录D9光盘,无需转换成ISO格式, 
直接使用MAC OS X和iPhone SDK的DMG镜像文件进行安装的方法。

安装条件:

硬件:一台拥有支持虚拟技术的64位双核处理器和2GB以上内存的PC。 
本人采用笔记本:DELL D630  4G内存 
注意:运行MAC OS,需要电脑支持虚拟技术(VT),安装时,需要将VT启动,在BIOS中开启。 
软件: 
 Windows XP: 
 VMware :VMware-workstation-7.0.0-203739  EXE安装文件 
 Mac OS:Mac_OS_10.6_Snow_Leopard_10.6  DMG光盘镜像文件 
 iPhone SDK:iphone_sdk_3.1.2_with_xcode_3.2.1  DMG光盘镜像文件 
 Darwin.iso或Rebel EFI.iso  引导光盘ISO镜像文件

下载

1.下载安装包 
1.1.下载VMWare 7.0: 
这里是VMware-workstation-7.0.0-203739标准版.exe的链接,可以用迅雷下载: 
https://download2.vmware.com/software/wkst/VMware-workstation-7.0.0-203739.exe?HashKey=1338595dbfed5502d44e5506520145fe&ext=.exe&AuthKey=1258895780_40bddf08d507e11e4cb51f2f729cced0&ext=.exe

1.2.下载Mac OS: 
这就是苹果的操作系统。本文下载的是LeoSnow即Mac OS 10.6。 
这个链接可以用迅雷下载: 
ftp://snowleoparddown.maiyadi.com/Mac_OS_10.6_Snow_Leopard_10.6_Retail_maiyadi.dmg

1.3.下载iphone SDK: 
“iphone_sdk_3.1.2_with_xcode_3.2.1__snow_leopard__10m2003.dmg”, 
这个链接可以用迅雷下载: 
http://ipsw.info/iphone_sdk_3.1.2_with_xcode_3.2.1__snow_leopard__10m2003.dmg

1.4.下载iphone SDK: 
Darwin.iso或Rebel EFI.iso  用于引导光盘ISO镜像文件。

启动XCODE开始开发

启动Xcode开发环境: 
打开Finder,在磁盘上的“Developer”目录中“Applications”目录中,有Xcode程序, 
双击Xcode图标,即启动Xcode: 
点击“Create a new Xcode project”图标,则打开工程模板窗口: 
选择iPhone OS项目模板中的“View-based Application”图标,并点击“Choose”按钮: 
提示输入新项目名字和新项目保存的目录, 
按提示输入后,点击“Save”按钮,则出现新窗口,显示向导生成的项目及该项目目录和文件: 
点击图标“Build and Run”,则开始编译; 
编译完成,则自动启动iphone模拟器。 
iphone mac xcode 苹果 goodmao


(图)在Windows中安装iPhone开发环境

[转载]jQuery插件编写学习+实例——无限滚动 - Null Pointer - 博客园

mikel阅读(1103)

[转载]jQuery插件编写学习+实例——无限滚动 – Null Pointer – 博客园.

最近自己在搞一个网站,需要用到无限滚动分页,想想工作两年有余了,竟然都没有写过插件,实在惭愧,于是简单学习了下JQuery的插件编写,然后分享出来。

 

先说下基础知识,基本上分为两种,一种是对象级别的插件,另一种是全局级别的插件。对象级别的插件就像是实例方法,它是属于实例对象的,而全局级别 的相当于静态方法,是属于类的,调用起来自然也就不一样,对于全局级别的插件我们自然是使用JQuery来调用,比 如$.NPScrollLoad(….),对象级别的插件自然是应用与JQuery对象上了,比 如:$(“selector”).NPScrollLoad(…)。这个不难理解吧。

对于$.NPScrollLoad()这种形式,我们要对jQuery进行扩展,怎么扩展呢,很简单,就像给对象赋值一样

方法1:

方法2:

这就是在博客园,发布博客界面测试的,F12打开开发者工具,切换到Console,先输入运行”$”,确认页面引入了jQuery,然后扩展 jQuery,一种方法是直接给属性名赋值$.youname = function(){…},另一种方法是使用$.extend({yourname:function(){…}}),使用哪种看个人喜好。

 

对于$(“selector”).NPScrollLoad()这种方式,扩展就不是jQuery本身了,而是jQuery.fn:

方法1:

方法2:

和全局级别的插件方法区别就是扩展的时$.fn而不是$。

 

因为各式各样的插件很多,属性重名的概率很高,为了避免这样那样的问题,我们使用闭包来写插件,从而使插件的变量和function和其他的不互相影响,这个我尽量简化:

复制代码
 1 ;(function($) {
 2     // jQuery扩展
 3     $.youname = function([args]) {
 4         // TODO
 5     };
 6     // 或者
 7     $.extend({
 8         youname : function() {
 9             // TODO
10         }
11     });
12     
13     // jQuery对象扩展
14     $.fn.youname = function([args]) {
15         // TODO
16     };
17     // 或者
18     $.fn.extend({
19         youname : function() {
20             // TODO
21         }
22     });
23 }) (jQuery);
复制代码

 

为什么要这样写?看下面的例子你就明白了:

这个其实就相当于我们直接执行一个匿名函数,并且传递给他一个参数,比如上面的例子就是,我们定义了一个匿名函数用来alert传进去的参数,然后 我们给它传递”hello!”,它就会马上执行,把插件的相关方法写到这里面并且引入这个js文件的话也就会在第一时间把我们的插件扩展到jQuery 上,从而可以直接使用,并且可以保护我们的代码不受外面代码影响,也不会污染其他的代码。为了防止以后压缩代码的时候出错,所以最好在前后都加上一个分 号”;”。

 

为了让我们的插件足够通用,我们需要把一些配置留给用户自己定义,通用的做法是使用一个对象来承载所有的设置项,并给他们默认值。

1 var defaults = {
2     msg1: "hello1",
3     msg2: "hello2"
4 }

然后我们给我们的插件函数加上参数:

复制代码
 1 ;(function($) {
 2     var defaults = {
 3     msg1: "hello1",
 4     msg2: "hello2"
 5     };
 6 
 7     $.NPScrollLoad = function(options) {
 8         var opts = $.extend(defaults, options);
 9         alert(opts.msg1 + opts.msg2);
10     };
11 
12 }) (jQuery);
复制代码

 

然后就可以调用了

$.NPScrollLoad({msg1 : "你好"});
$.NPScrollLoad({msg1 : "你好", msg2 : "呵呵"});
$.NPScrollLoad({msg2 : "......"});
$.NPScrollLoad();

没有赋值的属性会使用defaults里面定义的默认值,赋值的属性则会覆盖defaults中相应的属性。

 

下面是我写的插件代码,代码有些地方比较拙劣,懒得设计和修改了。。。

复制代码
 1 /**
 2  * 无限滚动
 3  * 作者:Null Pointer
 4  */
 5  ;(function($) {
 6     $.NPScrollLoad = function(options) {
 7         // var opts = $.extend($.NPScrollLoad.defaults, options);
 8         $.NPScrollLoad.defaults = $.extend($.NPScrollLoad.defaults, options);
 9         return $(window).scroll(function() {
10             processor.process();
11         });
12     };
13 
14     var processor = {
15         timeoutId: null,
16         process: function () {
17             clearTimeout(this.timeoutId);
18             this.timeoutId = setTimeout(function () {
19                 loadData();
20             }, 400);
21         }
22     };
23 
24     /**
25      * 加载数据
26      */
27     function loadData() {
28         if (($(document).height() - ($(document).scrollTop() + $(document.documentElement).scrollTop() + $(window).height())) <= $.NPScrollLoad.defaults.offsetPixelToLoad) {
29             $(window).unbind("scroll");
30             $.NPScrollLoad.preLoad();
31             $.post(
32                 $.NPScrollLoad.defaults.url,
33                 { pageIndex : $.NPScrollLoad.defaults.pageIndex },
34                 function (data) {
35                     $.each(data, function (i, item) {
36                         $.NPScrollLoad.handleResult(item);
37                     });
38                     $.NPScrollLoad.afterLoad();
39                     $.NPScrollLoad.defaults.pageIndex++;
40                     if (data.length < $.NPScrollLoad.defaults.pageSize) {
41                         $.NPScrollLoad.noMoreData();
42                     } else if ($.NPScrollLoad.defaults.pageIndex == $.NPScrollLoad.defaults.maxPage) {
43                          $.NPScrollLoad.reachMaxPage();
44                     } else {
45                         $(window).bind("scroll", processor.process)
46                     }
47                 }
48             );
49         }
50     };
51 
52 
53     /**
54      * 处理
55      */
56     $.NPScrollLoad.handleResult = function(jsonItem) {
57 
58     };
59 
60     /**
61      * 加载之前
62      */
63     $.NPScrollLoad.preLoad = function() {
64         $("#loading").fadeIn();
65     };
66 
67     /**
68      * 加载之后
69      */
70     $.NPScrollLoad.afterLoad = function() {
71         $("#loading").fadeOut();
72     };
73 
74     /**
75      *  无更多数据
76      */
77     $.NPScrollLoad.noMoreData = function() {
78         $("#nomoreresult").fadeIn();
79     };
80 
81     /**
82      * 到达最大页数
83      */
84     $.NPScrollLoad.reachMaxPage = function() {
85         $("#loadmore").show();
86     };
87 
88     $.NPScrollLoad.defaults = {
89         /* 距离底部距离(开始加载数据) */
90         offsetPixelToLoad : 100,
91         url : "",
92         pageSize : 10,
93         maxPage : 5,
94         pageIndex : 1
95     };
96 
97 })(jQuery);
复制代码

 

 

代码中有一部分是我之前没有说到的细节:

1.我把defaults定义成$.NPScrollLoad.defaults这样用户可以在外部直接设置默认值,比如$.NPScrollLoad.defaults.url = “text.aspx”;这样就行了。

2.在(function($){})(jQuery)内部定义的function是私有的,只有此function内可以访问,比如loadData就只可以在此匿名函数内部访问。

3.我把部分function写成jQuery的扩展,用户就可以在外部访问,或者自定义,比如$.NPScrollLoad.handleResult这样就可以间接实现类似于函数重写的功能,让用户自定义部分操作。

4.第九行我加了一个return,这里是为了延续jQuery的链式调用,比 如$(“selector”).val(“abc”).attr(“id”, “aaa”)。。。。因为jQuery的函数本身都是返回自身的,所以$(window).scroll()也会返回$(window),所以最后的 return可以延续其链式调用特性,不过,因为我写的是全局扩展,所以也就谈不上链式调用了。。。这个对于对象扩展还是有一定重要性的。

5.定义processor对象是因为实时监听scroll事件灰常消耗资源,没滑过1px都会触发事件,所以加个延迟时间,让其一定时间内如果触发的话就取消前一次事件。代码应该不难理解。

下面是调用代码:

复制代码
1 <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.2.min.js"></script>
2 <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.NPScrollLoad.1.0.js"></script>
3 <script type="text/javascript">
4 $(function() {
5     var contextPath = "${pageContext.request.contextPath}";
6     $.NPScrollLoad({url:contextPath + "/ajaxPage/home"});
7 });
8 </script>
复制代码

 

 

本来还想排版,这么晚了,算了,睡觉了。

[转载]WinForm 天猫2013双11自动抢红包 - polk6 - 博客园

mikel阅读(999)

转载WinForm 天猫2013双11自动抢红包 – polk6 – 博客园.

1. 正确获取红包流程

 

2. 软件介绍

2.1 效果图:

 

2.2 功能介绍

2.2.1 账号登录

页面开始时,会载入这个网站:https://login.taobao.com/member/login.jhtml?redirect_url=http%3A%2F%2F1111.tmall.com%2F

登录成功后,会自动跳转到1111.tmall.com活动页面。

 

2.2.2 【去抽奖】按钮

这按钮是手动跳转到1111.tmall.com页面

 

2.2.3 【开始狂欢】按钮

隐藏活动界面的载入Div

 

2.2.4 【亲品牌】按钮

调用Js,触发点击”亲品牌,赢红包”

 

2.2.5 【开始游戏】按钮

①在这之前,会显示”游戏攻略”界面,需要手动点击”不再提示”和”开始游戏”

②然后点击【开始游戏】按钮,会模拟鼠标点击和”再来一次”。

 

3. 主要代码

备注:wbTmall 为System.Windows.Forms.WebBrowser 控件。

3.1 操作js代码

1
2
string GameStart_js = "JavaScript:document.getElementById('" + this._ac_playagain + "').click()";
WbTmall.Navigate(GameStart_js);

3.2 关闭Js错误提示

1
WbTmall.ScriptErrorsSuppressed = true;

3.3 模拟鼠标点击(google搜索到的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int x = 100; // X coordinate of the click
int y = 100; // Y coordinate of the click
IntPtr handle = WbTmall.Handle;
StringBuilder className = new StringBuilder(100);
while (className.ToString() != "Internet Explorer_Server") // The class control for the browser
{
    handle = GetWindow(handle, 5); // Get a handle to the child window
    GetClassName(handle, className, className.Capacity);
}
IntPtr lParam = (IntPtr)((y << 16) | x); // The coordinates
IntPtr wParam = IntPtr.Zero; // Additional parameters for the click (e.g. Ctrl)
const uint downCode = 0x201; // Left click down code
const uint upCode = 0x202; // Left click up code
SendMessage(handle, downCode, wParam, lParam); // Mouse button down
SendMessage(handle, upCode, wParam, lParam); // Mouse button up

4. 备注

4.1 开发环境

系统:Win8.1

VS版本:VS2010

.Net版本:4.0

4.2 未解决地方

①进行操作时,内存占用会达到100M左右。

②并且在运行2小时后,有明显的卡顿现象。

③CPU占用达到8%左右。

不知是代码的原因,还是抽奖页面是HTML5的canvas原因。

④抽中红包的话,会卡在”抽中红包”界面,点下”查看金额”就好了(抱歉,因为没做抽中红包的判断),然后再点下【亲品牌】按钮就又可以玩了。。

 

5. 下载地址

1.百度云盘:http://pan.baidu.com/s/1xfLmW

2.360云盘:http://awwymzejsn.l19.yunpan.cn/lk/Q9vnEddhadStW

 

[转载]IOS开发环境搭建教程 - tonykan - 博客园

mikel阅读(1003)

[转载]IOS开发环境搭建教程 – tonykan – 博客园.

安装条件:

硬件:一台拥有支持虚拟技术的64位双核处理器和2GB以上内存的PC。

注意:运行MAC OS,需要电脑支持虚拟技术(VT),安装时,需要将VT启动,在BIOS中开启。

关于如何检测你的电脑支持VT,可以去下面这个网站下载这个工具,测试:

http://www.grc.com/securable.htm

 

或者直接点击下面连接下载:

http://www.grc.com/files/securable.exe

 

软件:

Windows XP:

VMware :VMware-workstation-7.0.0-203739  EXE安装文件

Mac OS:Mac_OS_10.6_Snow_Leopard_10.6  DMG光盘镜像文件

iPhone SDK:iphone_sdk_3.1.2_with_xcode_3.2.1  DMG光盘镜像文件

Darwin.iso或Rebel EFI.iso  引导光盘ISO镜像文件

1.下载安装包

1.1.下载VMWare 7.0:

这里是VMware-workstation标准版.exe的链接,可以用迅雷下载:

http://download.pchome.net/system/sysenhance/detail-4673.html

1.2.下载Mac OS:

这就是苹果的操作系统。本文下载的是LeoSnow即Mac OS 10.6.2。 Ipad以及Iphone的SDK需要1.6的Mac.

这个链接可以用迅雷下载:

http://www.verycd.com/topics/2778507

找到一个安装好Mac的种子,需要的这里下载(里面带有所有的引导文件,非常方便),我已经下下来了,并且搭建了iphone的开发环境,发现真实可用。如果使用的是这个就跳过VM安装MAC的部分吧,直接看下面搭建环境的部分。

http://www.rayfile.com/zh-cn/files/6b56760a-1eb5-11e0-81b6-0015c55db73d/

1.3.下载iphone SDK:

xcode_3.2.3_and_iphone_sdk_4__final.dmg  2.06GB

iPad和iPhone的软件开发工具包,包含Xcode 3.2.3集成开发环境,iPhone SDKs (最高支持4.0), iPhone OS 模拟器,性能分析工具

系统要求:基于Intel的Mac电脑,运行Mac OS X Snow Leopard 10.6.2 或以上版本的操作系统种子我放到rayfile上面了,大家可以去下载:

http://www.rayfile.com/zh-cn/files/21e1da05-0e45-11e0-9cd4-0015c55db73d/

此BT种子经下载测试,巨慢,有时下到一半就停止了,再无速度。下面给出官方下载地址,不过这个需要用apple ID 登陆,没有的先注册。

http://developer.apple.com/ios/download.action?path=/iphone/iphone_sdk_4__final/xcode_3.2.3_and_iphone_sdk_4__final.dmg

1.4.下载引导盘:

Darwin.iso或Rebel EFI.iso  用于引导光盘ISO镜像文件。

Darwin.iso    http://www.verycd.com/topics2818537

Rebel EFI.iso http://www.rayfile.com/zh-cn/files/689c7f1c-0f05-11e0-a0c9-0015c55db73d/

1.5 注册Mac账号

http://developer.apple.com/programs/register/  我注册不了。。。汗。。。

2.安装虚拟机VMWare7.0

2.1安装虚拟机

在Windows XP上安装虚拟机:VMWare Workstation 7。

本文安装的是VMware-workstation-full-7.1.3-324285.exe。

这里有我搜集的14组可用注册码,当然本人并没有一一尝试。我就选了其中之一,是正确的,其他的请大家自己尝试吧。

  1. CC542-2QF41-M847P-EZPQT-Q3AU6  
  2. UA7MH-0NW80-08EVZ-7XMZT-MGAZA  
  3. YY1E0-A6E51-M892Y-FGPZZ-XC0TF  
  4. ZY7N8-F7Y44-M88RP-VGWXZ-QAAR2  
  5. FC78A-6ZXDN-M88DP-DPN7V-YZHX4  
  6. FA18H-4ZZ15-M805P-6MN5G-ZY0G0  
  7. AF1T0-4PW1M-H84LP-FDQ5C-ZQ0T4  
  8. VV3M0-42Z4M-M80XY-T5PNT-MAUZF  
  9. CG308-08Y10-0892Q-XNMEZ-PKKD0  
  10. GY51K-2MED5-M84MQ-5EPG9-NLUUD  
  11. CC542-2QF41-M847P-EZPQT-Q3AU6  
  12.  
  13. VA34H-DWWD6-08ELZ-3XQ7X-PAK90  
  14. AF1R8-21X17-M8EHQ-QYZXX-WKKW8  
  15. VU59U-D0E0L-48ENQ-G6WGG-PQUZF 

对应的汉化补丁,需要的请到这里下载:

http://www.rayfile.com/zh-cn/files/83d4fbf5-0f00-11e0-b6ba-0015c55db73d/

2.2 创建虚拟机

使用File->New->Virtual Machine创建一个虚拟机。

标准(推荐)-》

以后再安装操作系统-》

在选择操作系统时,选择Other->FreeBSD 64-bit。

2.3虚拟机设置

1.CPU设置为1核即可,2核也可以。

2.内存建议设置为:1024MB。

3.硬盘最少分配15GB。

4.删除软驱。

可以在Customize Hardware选项中,将软驱删除,因为我们不会再用软驱。

我设置的硬件如下:

2.4虚拟机修改

建立完虚拟机不要急于打开,关闭VMware。进入刚建立的虚拟机目录,找到一个扩展名为.vmx的文件,

用记事本或者UE打开,找到guestOS = “freebsd-64″一行,

将引号中的freebsd-64改为darwin10,

修改完后是:guestOS = “darwin10″,保存修改后的文件。

现在,在打开VMware,在虚拟机的Options->General选项,

就可看到操作系统版本显示为:MAC OS X Server 10.6。

若后面无法启动MAC OS X安装程序,很可能是忽略了这步或者修改错了。

3.在虚拟机VMWare7.0上安装Mac OS

3.1用Darwin.iso镜像进行引导。

先装载镜像文件:在刚才建立的虚拟机Settings->Hardware中,

选择CD/DVD(IDE)设备,

选择右侧的Use ISO image file,

点Browse加载Darwin.iso。

装载完镜像文件后,现在启动虚拟机。

先演示使用Rebel EFI镜像启动,引导完成后按照提示进行。

按照屏幕提示等待10秒或者按’1’键,选择当前光盘驱动器。

这里提示请插入MAC OS X的DVD光盘。

此时我们再次打开这个虚拟机的Settings->Hardware,

找到CD/DVD(IDE)设备(你可以双击VMWare窗口右下角的光盘图标来快速打开,如图: ),

将刚才的Rebel EFI镜像替换为苹果系统的DMG镜像;

点Browse,将文件类型CD-ROM images(*.iso)改为All files (*.*)就能浏览到DMG文件了。

这里有一个关键地方:选择DMG镜像文件后,

将Device status里的Connected前打上勾(否则不能进入安装界面),然后确定。

此时,我们便进入了MAC OS X的安装程序准备阶段。

有的朋友使用Rebel EFI引导可能会出现禁止符号,无法安装。

遇到这个问题可以使用Darwin镜像替换Rebel EFI,并重新启动虚拟机。

在出现提示界面后,在CD/DVD(IDE)设备里将Darwin镜像改为苹果的DMG镜像即可,同样记得给“Connected”选项打勾。

经过一阵准备阶段就进入了苹果系统的安装过程;

在这里特别提一下,有的同学在进行到选择安装盘的步骤时看不到硬盘选项,

在屏幕上方的菜单中找到“实用工具”->“磁盘工具”;

对你的虚拟硬盘执行“抹掉”操作;

操作完成后关闭“磁盘工具”窗口就OK了;

根据你的电脑配置不同,大概进行几十分钟的安装,你就可以用上苹果操作系统了。

看到下图的界面,表示你的系统已经安装完成,需要重新启动。

重新启动前你要特别注意,先要去掉安装时在CD/DVD(IDE)设备上加载的苹果DMG镜像,

换上Darwin或者Rebel EFI引导镜像,否则你将不能成功引导安装好的MAC OS X系统。

如果使用一种引导失败,可以试着使用其他的引导镜像。

还有需要在VMWare里的MAC系统上安装声卡、显卡等驱动的朋友,可以在网上寻找相关文章和驱动,

或参考《号外!折腾无限!VMware Workstation 7.0 虚拟机安装雪豹snow leopard 10.6》文章,本文就不赘述了。

4.XP和MAC共享目录

因为我是在Windows XP中下载的Mac OS和iPhone SDK等安装必备文件,所以,要安装iphone开发环境,则需要将下载的安装包文件刻录成光盘;若不想刻录光盘,可以直接将这些文件传到虚拟机VMWare 7,就可以进行安装。

我在这里采用windows XP和VMWare共享目录的方法实现。

在xp中需要将iphoneSDK目录,共享给VMWare7.0中的Mac(leosnow)的方法:

4.1在Windows XP中需要将目录iphoneSDK设置为共享

步骤:在Windows XP中将iphoneSDK目录设置为共享:

点击鼠标右键,

选择属性->共享,选中“在网络上共享这个文件夹”,点击确定按钮。

4.2.记下Windows XP的IP地址

4.3在VMWare7.0中安装的Mac中访问XP的共享目录

在VMWare7.0中安装的Mac中访问XP中的共享目录iphoneSDK目录。

步骤:在mac中,点击主菜单Finder菜单项,

按住命令按钮和k键组合键,

注意:在普通PC或笔记本上(非mac电脑)的cmd+K ,连接服务器,smb://ip地址:

在smb://后输入Windows XP的IP地址:192.168.6.222点击“连接”按钮即可看到如下提示:

选择我们需要共享的目录iphoneSDK,并点击“好”按钮确认,即可打开该共享目录:

或者进入network 看有没有局域网共享,有的话最好了,直接打开就行。如图

5.安装iphoneSDK(IpadSDK):

1.在Mac中找到iphoneSDK的安装文件:

“iphone_sdk_3.1.2_with_xcode_3.2.1__snow_leopard__10m2003.dmg”,用鼠标双击该文件图标,则会看到一个弹出窗口:

点击“继续”按钮,出现安装器欢迎界面:

点击“继续”按钮,是软件“许可”协议信息:

点击“继续”按钮,出现“确认”窗口:

点击“同意”按钮,出现协议信息:

点击“继续”按钮,出现“确认”窗口:

点击“Agree”按钮,出现安装路径选择窗口:

选中安装目标路径后,点击“继续”按钮,出现“安装类型”选择窗口:

点击“继续”按钮,出现“确认”窗口:

点击“安装”按钮:

注意:在安装过程之前,需要推出先退出itunes。

在itunes图标上,点击鼠标右键,在弹出菜单中选择“退出”即可关闭:

之后,点击“continue”按钮,则安装继续进行:

注意:如果安装过程中失败,把系统时间改成“2012-01-01”,再重新安装。自己试了,管用。

安装结束的提示:

安装完成后,点击“完成”按钮即可。

6.启动XCODE开始开发

启动Xcode开发环境:

打开Finder,在磁盘上的“Developer”目录中“Applications”目录中,有Xcode程序,

双击Xcode图标,即启动Xcode:

点击“Create a new Xcode project”图标,则打开工程模板窗口:

选择iPhone OS项目模板中的“View-based Application”图标,并点击“Choose”按钮:

提示输入新项目名字和新项目保存的目录,

按提示输入后,点击“Save”按钮,则出现新窗口,显示向导生成的项目及该项目目录和文件:

点击图标“Build and Run”,则开始编译;

编译完成,则自动启动iphone模拟器。

小结:IOS开发学习 IDE环境搭建教程的内容介绍完了,希望本文对你有所帮助。

 

另外,安装过程中如果遇到用vmware装雪豹的一个问题,”虚拟 CPU 已进入关闭状态“。

我滴个神,折腾了一个下午 ,就为了这一个问题,检查了CPU 虚拟化,检查了主板虚拟是否开启,检查了cpu 指令集,上百度查了N久,终于把这个问题解决了,咱知道啃苹果不容易,分享给那些遇到这个问题的童鞋们,希望对你们有帮助!
咱的解决方法:在CPU的确支持 VT 虚拟化的情况下 曾经试过 darwin.ios 引导文件后 依然出现这问题, 也试过 Rebel EFI.ios 答案也是肯定的不行, 最后查到了一个darwin_snow_legacy.iso 的引导文件, 终于让我成功了,我当时只差没喷泪了,所以我得到了个结果,在出现类似的情况下不如各位童鞋们 换下 引导文件,如上三个轮着来,所以需要些耐心了.

资源:apple 开发者联盟 中文网址 http://www.apple.com.cn/developer/support/

iphone开发者联盟 http://iphone.tgbus.com/dev/

斯坦福大学公开课:iphone开发入门 http://v.163.com/special/opencourse/iphonekaifa.html 还提供MP4格式视频文件下载,方便地铁一族用Iphone学习

 

另外我在安装xcode出现一个错误,

the installation failed

xcode the installation failed an unknown error occurred, the installer encountered an an error that caused installation to failed

解决办法真的很奇怪,竟然是mac os的系统改成2012-01-01就可以了。

[转载]分组求和,将一列的数据求和 - jayxhj - 博客园

mikel阅读(974)

[转载]分组求和,将一列的数据求和 – jayxhj – 博客园.

在数据库操作中常常会将某一列的具有相似性质的数据进行求和,昨天在做的项目中遇到了。
后来请教了一下自己又摸索了一下,得出了解决方案,那就是<strong>分组求和</strong>。
需求:将某列数据求和
例子:

数据库内容为:

 

根据record_type进行分组再求和,也就是将1、2、3三种类型进行分组,所以结果预期为三行

 

再一种是根据record_date来分组,由于日期有两组,故预期分组也为两组,结果为同一日期的c、d列数据相加

 

总结:当需要进行对某一列的具有相似条件(对应于where中的条件)的数据进行合并时,使用group by将记录分组,再使用聚合函数对数据进行需要的操作。这样就可以使用一条语句将所有的数据进行分组求和。

 

创建例子中的数据的SQL语句为

复制代码
 1 CREATE DATABASE /*!32312 IF NOT EXISTS*/`group` /*!40100 DEFAULT CHARACTER SET utf8 */;
 2 
 3 USE `group`;
 4 
 5 /*Table structure for table `test` */
 6 
 7 DROP TABLE IF EXISTS `test`;
 8 
 9 CREATE TABLE `test` (
10   `id` int(10) NOT NULL AUTO_INCREMENT,
11   `record_date` date DEFAULT NULL,
12   `record_type` int(10) DEFAULT NULL,
13   `c` int(10) DEFAULT NULL,
14   `d` int(10) DEFAULT NULL,
15   PRIMARY KEY (`id`)
16 ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
17 
18 /*Data for the table `test` */
19 
20 insert  into `test`(`id`,`record_date`,`record_type`,`c`,`d`) values (1,'2013-10-14',1,1000,10000),(2,'2013-10-15',1,2000,20000),(3,'2013-10-14',2,3000,30000),(4,'2013-10-15',2,4000,40000),(5,'2013-10-14',3,5000,50000);
复制代码

查询语句为

SELECT SUM(c) 'c列数据的和',SUM(d)'d列数据的和'
FROM test
WHERE record_date BETWEEN '2013-10-13' AND '2013-10-16'    
GROUP BY record_type
ORDER BY record_type ASC

 

 

[转载]Android ListView的item背景色设置以及item点击无响应等相关问题 - 海 子 - 博客园

mikel阅读(725)

[转载]Android ListView的item背景色设置以及item点击无响应等相关问题 – 海 子 – 博客园.

            Android ListView的item背景色设置以及item点击无响应等相关问题

Android开发中,listview控件是非常常用的控件,在大多数情况下,大家都会改掉listview的item默认的外观,下面讲解以下在使用listview时最常见的几个问题。

1.如何改变item的背景色和按下颜色

listview默认情况下,item的背景色是黑色,在用户点击时是黄色的。如果需要修改为自定义的背景颜色,一般情况下有三种方法:

1)设置listSelector

2)在布局文件中设置item的background

3)在adapter的getview中设置

这三种方法都能达到改变item默认的背景色和按下颜色,下面来分别讲解,但是在这之前需要先写好selector.xml文件;

<?xml version="1.0" encoding="utf-8"?>
<selector
  xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/light_blue"></item>
    <item android:state_pressed="false" android:drawable="@color/sgray"></item>
</selector>

在改变button或者listview的item默认背景色,就可以用到selector。drawable可以设置为色彩资源,也可以设置为图片资源。

1)设置listview的listSelector

复制代码
<ListView
   android:id="@+id/history_list"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:divider="#565C5D"
   android:dividerHeight="3dp"
   android:listSelector="@drawable/selector"
   android:cacheColorHint="@android:color/transparent">
</ListView>
复制代码

2)在listitem的布局文件中设置background属性,下面是listitem的布局文件

复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:background="@drawable/selector">
    <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="历史记录"
          android:textColor="#ffffff"
          android:textSize="20sp"
          android:layout_centerInParent="true">
     </TextView>
</RelativeLayout>
复制代码

3)在adapter的getView方法中设置

 if(convertView ==null)
 {
     convertView = LayoutInflater.from(context).inflate(R.layout.listitem, null);
 }
 convertView.setBackgroundResource(R.drawable.selector);

上述方法都能达到同样的效果,就是改变item默认的背景色和点击时的背景颜色,第三种方法最灵活,如果listview的奇数行和偶数行需要设置为不同的selector,只能用第三种方法。

2.包含button,checkbox等控件时点击无响应问题。

如果listitem里面包括button或者checkbox等控件,默认情况下listitem会失去焦点,导致无法响应item的事件,最常用的解决办法是在listitem的布局文件中设置descendantFocusability属性。

复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:paddingTop="10dp"
  android:paddingBottom="10dp"
  android:paddingLeft="5dp"
  android:paddingRight="5dp"
  android:descendantFocusability="blocksDescendants">

  <CheckBox
   android:id="@+id/history_item_checkbt"
   android:layout_height="30dp"
   android:layout_width="wrap_content"
   android:layout_centerVertical="true"
   android:layout_alignParentLeft="true"
   android:checked="false"
   >
  </CheckBox>

  <ImageView
   android:id="@+id/history_item_image"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerVertical="true"
   android:layout_toRightOf="@id/history_item_checkbt"
   android:background="@drawable/item_icon">
  </ImageView>

  <Button
   android:id="@+id/history_item_edit_bt"
   android:layout_alignParentRight="true"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerVertical="true"
   android:text="编辑"
   android:textColor="#ffffff"
   android:textSize="14sp"
   android:background="@drawable/button_bg">
  </Button>

  <TextView
   android:id="@+id/history_item_time_tv"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_centerVertical="true"
   android:textColor="#565C5D"
   android:textSize="14sp"
   android:text="10-01 10:20"
   android:layout_marginRight="5dp"
   android:layout_toLeftOf="@id/history_item_edit_bt">
  </TextView>

  <TextView
   android:id="@+id/history_item_title_tv"
   android:layout_height="wrap_content"
   android:layout_width="fill_parent"
   android:layout_centerVertical="true"
   android:textColor="#565C5D"
   android:textSize="14sp"
   android:text="xxxxxxxxXXXXXXXXXXXXXXXX"
   android:ellipsize="end"
   android:maxLines="1"
   android:layout_toRightOf="@id/history_item_image"
   android:layout_toLeftOf="@id/history_item_time_tv"
   android:layout_marginLeft="3dp">
  </TextView>

</RelativeLayout>
复制代码

 

作者:海子
本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]在Android中调用C#写的WebService(附源代码) - 小吉吉 - 博客园

mikel阅读(906)

[转载]在Android中调用C#写的WebService(附源代码) – 小吉吉 – 博客园.

由于项目中要使用Android调用C#写的WebService,于是便有了这篇文 章。在学习的过程中,发现在C#中直接调用WebService方便得多,直接添加一个引用,便可以直接使用将WebService当做一个对象使用,利 用Vs2010中的代码提示功能就能爽歪歪地把想要的东西全部点出来。在Android调用,麻烦了一点,但是也还好。主要是我们需要自己在代码中确定要 调用WebService的方法名是什么,要传给WebService什么参数以及对应的参数名,另外,一些额外的信息比如soap的版本号,也需要了解 了。

1.准备工作:写一个测试用的WebService

首先,让我们先准备一下WebService,WebService的代码很简单,一个是返回HelloWorld字段,另一个是原样返回用户发给WebService的字符串。

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace testAndroidCall
{
    /// <summary>
    /// WebService1 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
    // [System.Web.Script.Services.ScriptService]
    public class WebService1 : System.Web.Services.WebService
    {

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello World";
        }
         [WebMethod]
        public string EchoMessage(string msg)
        {
            return msg;
        }
    }
}
复制代码

接着,我们需要下载一个Android中调用WebService的类库

比较常用的有Ksoap2,可以从https://code.google.com/p/wsdl2ksoap/downloads/list进行下载。也可以直接点这里下载

将下载的ksoap2-android-assembly-2.4-jar-with-dependencies.jar包复制到Eclipse工程的lib目录中,当然也可以放在其他的目录里。同时在Eclipse工程中引用这个jar包。

image

2、完成简单的Android布局代码的编写

(1) 在AdroidManifest.xml中加入权限,<manifest>节点里面加入下面这句话

<!-- 访问网络的权限 -->

 <uses-permission android:name="android.permission.INTERNET" />

(2)、我们在Android中建立两个按钮,分别对应WebService中的两个方法

image

复制代码
private void initBtn() {
        View btnHelloWorld = this.findViewById(R.id.btnHelloWorld);
        btnHelloWorld.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                Map<String, String> values = new HashMap<String, String>();
                values.put("msg", "这是Android手机发出的信息");
                Request(METHOD_HELLO_WORLD);
            }
        });

        View btnEchoMessage = this.findViewById(R.id.btnEchoMessage);
        btnEchoMessage.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Map<String, String> values = new HashMap<String, String>();
                values.put("msg", "这是Android手机发出的信息");
                Request(METHOD_ECHO_MESSAGE,values);
            }
        });
    }
复制代码

在Request(…)方法中,我们主要是想实现将WebService中方法名和调用的参数传入WebService。在这个方法中,主要应用了 AsyncTask来处理WebService的调用,因为调用WebService是网络操作,可能会比较耗时,在Android3.0以上,已经不允 许在UI线程直接进行网络操作,另外,AsyncTask还可以直接更新UI上的控件。

复制代码
/**
     * 执行异步任务
     * 
     * @param params
     *            方法名+参数列表(哈希表形式)
     */
    public void Request(Object... params) {
        new AsyncTask<Object, Object, String>() {

            @Override
            protected String doInBackground(Object... params) {
                if (params != null && params.length == 2) {
                    return CallWebService((String) params[0],
                            (Map<String, String>) params[1]);
                } else if (params != null && params.length == 1) {
                    return CallWebService((String) params[0], null);
                } else {
                    return null;
                }
            }

            protected void onPostExecute(String result) {
                if (result != null) {
                    tvMessage.setText("服务器回复的信息 : " + result);
                }
            };

        }.execute(params);
    }
复制代码

3、分析Android调用WebService的代码

我们的重点将放在CallWebService()这个方法中。这个方法里面封装了ksoap2类库里面调用WebService的一些对象。

(1) 指定webservice的命名空间和调用的方法名,如:

SoapObject request =new SoapObject(Namespace,MethodName);

SoapObject类的第一个参数表示WebService的命名空间,可以从WSDL文档中找到WebService的命名空间。第二个参数表示要调用的WebService方法名。

(2) 设置调用方法的参数值,如果没有参数,可以省略,设置方法的参数值的代码如下:

Request.addProperty(“param1”,”value”);
Request.addProperty(“param2”,”value”);

要注意的是,addProperty方法的第1个参数表示调用方法的参数名,该参数值要与服务端的WebService类中的方法参数名一致,并且参数的顺序一致。

(3) 生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述,代码为:

SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER12);
Envelope.bodyOut = request;

创建SoapSerializationEnvelope对象时需要通过SoapSerializationEnvelope类的构造方法设置 SOAP协议的版本号。该版本号需要根据服务端WebService的版本号设置。在创建SoapSerializationEnvelope对象后,不 要忘了设置SOAPSoapSerializationEnvelope类的bodyOut属性,该属性的值就是在第一步创建的SoapObject对 象。

注:

SOAP协议的版本号可以从WebService的WSDL文档(在本例中是“http://192.168.0.121/testAndroidCall/WebService1.asmx?WSDL”)
image

(4) 创建HttpTransportsSE对象。通过HttpTransportsSE类的构造方法可以指定WebService的WSDL文档的URL:

HttpTransportSE ht=new HttpTransportSE(WEB_SERVICE_URL);

WEB_SERVICE_URL是指WebService的地址,如”http://192.168.0.121:80/testAndroidCall/WebService1.asmx?wsdl”这样的

(5)使用call方法调用WebService方法,代码:

ht.call(null,envelope);

Call方法的第一个参数一般为null,第2个参数就是在第3步创建的SoapSerializationEnvelope对象。

(6)使用getResponse方法获得WebService方法的返回结果,代码:

SoapPrimitive result = (SoapPrimitive) envelope.getResponse();

(7)最后,附上完整的CallWebService()方法

复制代码
/**
     * 调用WebService
     * 
     * @return WebService的返回值
     * 
     */
    public String CallWebService(String MethodName, Map<String, String> Params) {
        // 1、指定webservice的命名空间和调用的方法名
        
        SoapObject request = new SoapObject(Namespace, MethodName);
        // 2、设置调用方法的参数值,如果没有参数,可以省略,
        if (Params != null) {
            Iterator iter = Params.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry entry = (Map.Entry) iter.next();
                request.addProperty((String) entry.getKey(),
                        (String) entry.getValue());
            }
        }
        // 3、生成调用Webservice方法的SOAP请求信息。该信息由SoapSerializationEnvelope对象描述
        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                SoapEnvelope.VER12);
        envelope.bodyOut = request;
        // c#写的应用程序必须加上这句
        envelope.dotNet = true;
        HttpTransportSE ht = new HttpTransportSE(WEB_SERVICE_URL);
        // 使用call方法调用WebService方法
        try {
            ht.call(null, envelope);
        } catch (HttpResponseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
        try {
            final SoapPrimitive result = (SoapPrimitive) envelope.getResponse();
            if (result != null) {
                Log.d("----收到的回复----", result.toString());
                return result.toString();
            }

        } catch (SoapFault e) {
            Log.e("----发生错误---", e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
复制代码

4、运行代码

要运行文章中的代码,请先将WebService部署在IIS上,要保证Android手机的测试程序和WebService处在同一个局域网中。

 

示例代码

Android端源代码

WebService源代码

[转载]VMware 8安装苹果操作系统Mac OS X 10.7 Lion正式版 - 虚拟机教程文章_推动虚拟化发展 - 红黑联盟

mikel阅读(795)

[转载]VMware 8安装苹果操作系统Mac OS X 10.7 Lion正式版 – 虚拟机教程文章_推动虚拟化发展 – 红黑联盟.

今天介绍下VM8下安装Mac OS X 10.7

1、工具篇

下载Vmware Workstation 8.0正式版http://115.com/file/bhyk1l2u#

Vmware8.0 汉化包http://115.com/file/dn38a7eu#

(因为我的电脑要经常上网银什么的所以为了安全直起签我没有装汉化包,用的是原版英文版!但我测试过此汉化包)

下载Mac OS X  10.7 安装包http://115.com/file/clj1iu8m#

下载HJMac http://115.com/file/cljyu1rh#  (使用说明在后面)

下载Mac OS X  10.7 .2 离线升级包    http://115.com/file/cly2xggh#

(可能这个离线升级包不一定要用我这个有时间的朋友可以自己去网上找来测试下,升级方法在后面!)

2、虚拟机安装

这个安装很简单的,直接一路Next 到最后就可以了!这个应该可以略过啦…

3、虚拟机设置

安装完以后点桌面的VMware Workstation图标打开,开始创建虚拟机。

创建虚拟机,基本都下一步就可以很简单的。虚拟机型号要选FreeBSD X 64,

CPU最好要设双核,内存2G以上, 硬盘不小于30G这  样基本上搞定了。
























到这里虚拟机 设置好一切准备就绪

接下来就开始安装系统
























至此整个安装过程基本算是完成了

[转载]Eclipse无法连接真机 并非ADB被占用 原因 很2 已解决 记录之 - Jacky_Chen-Fight - 博客园

mikel阅读(735)

[转载]Eclipse无法连接真机 并非ADB被占用 原因 很2 已解决 记录之 – Jacky_Chen-Fight – 博客园.

最近一直忙着考试的事情,然后找工作,找实习,找钱啊。对于Android我抱有很大的梦想,现实是残酷的。

 

OK,上面纯粹扯蛋了。今天手机连接电脑,打开USB调试,理论上就应该连接eclipse成功,可以在手机上直接测试开发中的项目。但是问题来了,怎么弄都没有反应。

 

什么叫怎么弄都没反应,我尝试了百度中的所有方法:

  1. 重启adb,无论是工具中的Reset adb,亦或是cmd中的adb kill-server然后adb start-server,eclipse的Devices中始终没有手机的身影。
  2. 豌豆荚占用端口、腾讯tadb占用端口等问题亦不存在,通过cmd命令 netstat -aon|findstr “5037”,查询所有占用5037的端口,adb好端端的占用着,并不存在占用的问题,所以并不是我这里的解决办法。

OK,实在不能忍了,我就去了stackoverflow,已search发现有人的情况和我是一样的。引用一下原文,我才发现自己并没有深入的去理解自己的问题所在:


 

I don’t want to Debug my Android apps on emulator (Android Virtual Device) anymore. Instead, I want to Debug it on my phone. My phone is LG Optimus L7 P700.
I already have downloaded USB Driver for my phone from official LG support web site. On my AVD Manager: Google USB Driver is also installed. Also, I ticked my Settings > Developer options-> USB debugging on my phone to be enabled. I connected my phone via USB cable, but I have problem now. When I run adb devices command on my command prompt as mentioned on tutorials I found on Google, my list of attached devices is empty, as u can see below in screenshoot. Here is screenshoot of my command prompt: http://i.imgur.com/J43CDqs.jpg

Also when I go to My Computer->Manage, my phone have yellow exclamation point, I dont know why ? Here is screenshoot: http://i.imgur.com/cfna7ds.jpg


 

 

最终我发现,原来是我的Nexus 4驱动未装好,这里我就要纳闷了,我驱动没有装好,我也可以传各种文件么。。。额,求科普。而且我的驱动无法自动搜索,迫使我从网上下载安装,然后终于在Eclipse中看到了我的手机。OH MY GOD. HOLLY SHIT!

另外这里还有一个解决办法,放在这里,算是大杀器吧,理论上可以通杀非1,2方法的问题。

这里也是引用的别人的话,凑活看吧,比较好理解,就是删了重装。

 


this is tricky sometimes. uninstall adb drivers through device manager and re-install them. uninstall all other adb drivers probably installed on your machine first before re-install. after installation connect your phone and choose driver-path manually. this is always the biggest pain for me with android development, I wasn`t able to connect one of my devices at all.

 


 

 

原因找到了,觉得自己很2.唉,有木有,专业开发20年,也会犯这种错误么。。。