分类存档: 程序人生

JW Player 编译及修改

修改方法去掉右键官方连接及官方logo水印:

  1. 去掉Logo水印;
    在文件“/com/longtailvideo/jwplayer/view/View.as ”中找到“_logo = new Logo(_player);及setupComponent(_logo, n++);”将其注释掉即可。【如果想保留logo,只是更改掉官方logo,查相关使用文档或者修改logo.as, 修改到logo.png的地址即可】
  2. 去掉右键about官网地址链接。
    在文件“/com/longtailvideo/jwplayer/view/RightclickMenu.as ”中找到“setAboutText();及addItem(about, aboutHandler);”将其注释掉即可。

我在flash builder 下面编译【Flex下面编译,同理】,建立文件pl.as:

package
{
	import com.longtailvideo.jwplayer.player.Player;

	public class pl extends Player
	{
		public function pl()
		{

		}
	}
}

最新jw player 5.7下载:点击下载 jw player 5.7 –采用GPU加速

附加问题:

  1. jw player源码问题,首先jw player是开源的,不需要破解反编译获得源码的,jw player源码现在地址为: http://developer.longtailvideo.com/svn/trunk/fl5
  2. 如果去编译jw player, 这个是基本Flash程序员需要学的基本知识,我是在src目录下建立fla文件的,需要将../lib目录中的as3corelib.swc设置好, 否则会提示json函数问题,虽然不影响基本使用。

HTML5游戏开发之一:动画制作

虽然目前几乎所有的webgame动画都使用Flash来实现,但是使用用JS来实现一场RPG的战斗动画,一直以来都不是什么难题。

去年我通过JS方式实现战斗引擎播放,效果也可以做的很绚丽,所有浏览器下,都测试通过,尚未发现卡的问题,但是,由于IE6下面,需要使用了VML()方式来处理PNG透明问题,并且要注意IE6缓存图片BUG的问题,解决这两个问题之后,JS耗CPU较少,但占用内存明显增大。基于兼顾IE6用户的考虑等等,我仍然会选择Flash来完成战斗动画。

由于将完成的一个游戏,是关卡玩法的游戏,PVE部分,比较适合放到手机平台上当做手机单机游戏来玩,所以我考虑,是否使用HTML5来完成战斗引擎,针对Webkit内核的等等支持HTML5的浏览器,我们可以使用HTML5来完成战斗动画播放,则可以直接使用在Andriod、iOS、WP7等手机平台上。

由于我从05年开始,我使用JavaScript越来越多,其中大部分是使用Prototype,所以下面这个例子,是基于了Prototype JS的。

注:如Internet Explorer的一些浏览器,不支持canvas标签或本演示。的Chrome、Firefox、Safari、Opera浏览器的最新版本正常工作。

不使用HTML5来完成动画的时候,通过css改变背景图片的偏移量可以做出战斗动画。使用HTML5来完成,只需要在Canvas上面循环画出图片上面不同帧即可。

如下例子中,使用了如下图片,一个攻击动画:
战斗动画图片

最好的说明是实例:

配置动画参数:

var attack = {
    name: 'attack',
    totalFrames: 10,
    loop: true,
    step: 4,
    width: 150,
    height: 150,
    sY: 0,
    sX: 0
}; //set initial animation set

角色动画:

/**
 * Sprite 系统,雏形
 *
 * @file_name   Sprite.js
 * @version     1.0
 * @author      黄新泽
 * @date        2011/1/14
 */

var	Sprite = Class.create({
	initialize : function(x, y, width, height, img, animation)//initialize sprite
    {
        this.canvas = document.createElement('canvas'); //动画canvas

        this.canvas.setAttribute('width', width);
        this.canvas.setAttribute('height', height);
        this.ctx = this.canvas.getContext('2d'); //get canvas drawing context

		this.x = x; // X position of this sprite
		this.y = y; //Y position of this sprite
		this.animation = 0; //current animation for this sprite
		this.currentFrame = 0; //current animation frame for this sprite
        this.width = width;
        this.height = height;

		this.image = img; //image that is being drawn to the canvas
		this.currentStep = 0; //number of frames since this sprite's animation was updated
		this.isReady = true; //sprite has finished loading and can be used

        this.animation = animation;
    },

    drawImage: function()
    {
        //draw image into sprite canvas
        this.ctx.clearRect(0, 0, this.width, this.height); //clear previous frame

        if(this.isReady)
        {
            //do not draw if sprite is not ready
            //calculate values for sprite based on animation
            var srcX = this.animation.sX + (this.currentFrame * this.animation.width);
            var srcY = this.animation.sY ;
            var srcWidth = this.animation.width;
            var srcHeight = this.animation.height;
            this.ctx.drawImage(this.image, srcX, srcY, srcWidth, srcHeight, 0, 0, srcWidth, srcHeight); //draw image
            this.stepSprite(); //advance animation
        }
    },

    stepSprite: function()
    {
        //advance animation based on animation speed (step value)
        if(this.currentStep >= this.animation.step)
        {
            this.currentStep = 0;
            this.currentFrame++;

            if(this.currentFrame >= this.animation.totalFrames)
            {
                if(this.animation.loop)
                {
                    this.currentFrame = 0; //loop animation back to start
                }
                else
                {
                    this.currentFrame = this.animation.totalFrames -1;	//if loop not set, hold on final frame
                }
            }
        }
        else
        {
            this.currentStep++; //advance step counter if step limit not reached
        }
    }
});

播放战斗动画:

var	FightAnimation = Class.create({

	canvas: 0, //main canvas object
	ctx: 0, //main canvas drawing context
	sprite: 0, //sprite object

	width: 900,
	height: 450,
	timer: 0,  //hold reference to game loop timer
	background: 0, //background image - for now is drawn right onto main canvas which is not ideal
	foreground: 0, //foreground object

	initialize: function(img)
    {
        //initialize FightAnimation
		this.canvas = document.getElementById('main');  //get canvas element from html
		this.ctx = this.canvas.getContext('2d'); //create main drawing canvas

		this.canvas.setAttribute('width', FightAnimation.width); //set attributes of canvas
		this.canvas.setAttribute('height', FightAnimation.height);

		this.sprite = new Sprite(0, 0, 150, 150, img, attack); //init sprite //create new Sprite object

        //document.body.insert(FightAnimation.sprite.canvas);
        this.timer = setInterval(this.drawFrame.bind(this), 40);
	},

	drawFrame: function()
    {
        //main drawing function
		this.ctx.clearRect(0, 0, this.width, this.height);  //clear main canvas

		//FightAnimation.ctx.drawImage(FightAnimation.background, 0, 0); // draw canvas background
		if(this.sprite)
        {
			this.sprite.drawImage(); //cause sprite to draw itself on its internal canvas
			this.ctx.drawImage(this.sprite.canvas, this.sprite.x, this.sprite.y);//draw sprite canvas onto main canvas
		}
	}
});

初始化战斗:

function startCanvas(e)
{
    new FightAnimation(img_res.successList['129_1_1'].img);  //initialize main Expermient object
}

document.on('img:oneloaded', startCanvas);  //处理进度条,........

var  img_res = ImgManage.getInstance();
img_res.addResourcesBag([["129_1_1", "/Images/actionicon/56/1/2.png"]]);

游戏中NPC 人工智能对话技术实现

其实就是08年,设想的,针对上班族,开发一个MSN机器人,通过对MSN机器人发送指令,来玩策略类网页游戏。 当初已经完成了MSN机器人的所有程序部分。通过MSN发送指令,可以完成游戏中几乎所有的建设、军事、消息指令…..

当继续想完善时候,发现完全使用中文是实现,目前缺少完善的AIML中文语料库,这个很难有现有资源利用……

# -*- coding: utf-8 -*-

import aiml
import sys
import time
import os.path
import thread
import re
from datetime import datetime
import marshal

loginemail="xinze@live.cn" # that robot will login to
loginpassword="11111" # account password
botname="Xinze...." # Robot's nickname
admin_email="xinze@live.cn" # emailaddress for admin the robot

# ==== normally nothing needs to be changed below ====

rootdir=os.getcwd()
configfile="%s/chatbot.ini" % rootdir
sessiondir="%s/sessions/%s" % (rootdir,loginemail)
os.system("mkdir -p %s" % sessiondir)
logfilename="%s/log" % sessiondir
sessionfilename="%s/session" % sessiondir

os.system("mkdir -p %s/tmp/" % rootdir)
msn_fortune="%s/tmp/msn-fortune" % rootdir
msn_fortune_zh="%s/tmp/msn-fortune-zh" % rootdir

blacklist=['sample@blacklist.org' ] # put here email addresses you want to block
blacklist=set(blacklist)
adminlist=[admin_email] # the 'admin' account's email address from which you send admin command
adminlist=set(adminlist)

dlist=[]
talkedto=[]

use_brain=True

def config(configfile, k):
    # setup bot properties such name, birthplace etc
    f=open(configfile)
    g=f.readlines()
    f.close()
    for i in g:
        h=i.split('=')
        if len(h)==2:
            k.setBotPredicate(h[0].strip(), h[1].strip()) 

    print sessionfilename
    # load session
    if os.path.exists(sessionfilename):
        f=open(sessionfilename)
        g=f.read()
        f.close()
        g=g.split('\n')
        for i in g:
            if i!='':
                talkedto.append(i)
                sessionFile = file("%s/%s.ses" %(sessiondir, i), "rb")
                session = marshal.load(sessionFile)
                sessionFile.close()
                for pred,value in session.items():
                    k.setPredicate(pred, value, i)

def dolog(message):
	global logfile
	logfile.write(message)
	logfile.flush()

def filter(message):
	message=message.replace("ALICE", botname)
	return message

def test_msg(senderemail, message):
    global dlist

    sender=senderemail.split("@")

    if senderemail in blacklist:
        return	

    dlist=[]

    if not senderemail in set(talkedto):
        talkedto.append(senderemail)

    logtime='%s/%s/%s %s:%s:%s' %( datetime.now().month, datetime.now().year, datetime.now().day, datetime.now().hour, datetime.now().minute, datetime.now().second)

    if not senderemail in adminlist:
        dolog('=== %s === Recv from %s < %s> ===\n%s\n' % (logtime, sender[0], senderemail, message))
    if message=='admquit' and senderemail in adminlist:
        message="%s is offline!" % botname
        #quit()

    if message=='admlist' and senderemail in adminlist:
        return

    if k.getPredicate("name", senderemail) =='':
        dispname=senderemail.split("@")
        if len(dispname) ==2:
            k.setPredicate("name", dispname[0], senderemail)
    remsg=k.respond(message, senderemail)
    remsg=filter(remsg)

    logtime='%s/%s/%s %s:%s:%s' %( datetime.now().month, datetime.now().year, datetime.now().day, datetime.now().hour, datetime.now().minute, datetime.now().second)
    if not senderemail in adminlist:
        dolog('=== %s === Send to %s < %s>===\n%s\n\n' % (logtime, sender[0], senderemail, remsg))

    print remsg

def savesession():
    # =========== save session
    f=open(sessionfilename, 'w')
    for i in talkedto:
        session = k.getSessionData(i)
        sessionFile = file("%s/%s.ses" % (sessiondir, i), "wb")
        marshal.dump(session, sessionFile)
        sessionFile.close()
        f.write("%s\n"% i)
    f.close()

def do_work():
    time.sleep(5)
    savesession() # save session data every 10 min
    thread.start_new_thread(do_work, ())

thread.start_new_thread(do_work, ())

# ================== Initialization
if __name__ == '__main__':
    k = aiml.Kernel()
    config(configfile, k)
    #k.verbose(False)

    # ================== load brain
    if use_brain and os.path.isfile("standard.brn"):
        k.bootstrap(brainFile = "standard.brn")
    else:
        k.bootstrap(learnFiles = "startup.xml", commands = "load aiml b")
        k.saveBrain("standard.brn")

    if os.path.exists(logfilename):
        logfile=open(logfilename, "a")
    else:
        logfile=open(logfilename, "w")

    player_email="alex@live.cn"

    while True:
        message = raw_input('>')
        test_msg(player_email, message)

php handlersocket

一、安装php-handlersocket模块:

php-handlersocket, PHP extension for interfacing with MySQL Handler Socket.

wget http://php-handlersocket.googlecode.com/files/php-handlersocket-0.1.0.tar.gz
tar zxvf php-handlersocket-0.1.0.tar.gz
cd php-handlersocket
phpize
./configure
make
make install

二、php-handlersocket 使用示例:

	/*
	 * String  $host:MySQL ip;
	 * String  $port:handlersocket插件的监听端口,它有两个端口可选:一个用于读、一个用于写
	 */
	$hs = new HandlerSocket($host, $port);
	打开一个数据表:
	/*
	 * Int       $index:这个数字相当于文件操作里的句柄,HandlerSocket的所有其他方法都会依据这个数字来操作由这个	 openIndex打开的表,
	 * String  $dbname:库名
	 * String  $table:表名
	 * String  $key:表的“主键”(HandlerSocket::PRIMARY)或“索引名”作为搜索关键字段,这就是说表必须有主键或索引
	 *                 个人理解:要被当做where条件的key字段,这样可以认为handlersocket只有一个where条件
	 * String  $column:'column1,column2' 所打开表的字段(以逗号隔开),就是说$table表的其他字段不会被操作
	 */
	$hs->openIndex($index, $dbname, $table, $key, $column);
	查询:
	/*
	 * Int     $index: openIndex()所用的$index
	 * String  $operation:openIndex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '< =', '>',and '< ';可以理解为where条件
	 * Array   $value
	 * Int       $number(默认是1):获取结果的最大条数;相当于SQL中limit的第二个参数
	 * Int     $skip(默认是0):跳过去几条;相当于SQL中limit的第一个参数
	 */
	$retval = $hs->executeSingle($index, $operation, $value, $number, $skip);
	插入(注意:此处的openIndex要用$port_wr,即读写端口):
	/*
	 * Int     $index: openIndex()所用的$index
	 * Array   $arr:数字元素数与openIndex的$column相同
	 */
	$retval = $hs->executeInsert($index, $arr);
	删除(注意:此处的openIndex要用$port_wr,即读写端口):
	/*
	 * Int     $index: openIndex()所用的$index
	 * String  $operation:openIndex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '< =', '>',and '< ';可以理解为where条件
	 * Array   $value
	 * Int     $number(默认是1):获取结果的最大条数;相当于SQL中limit的第二个参数
	 * Int     $skip(默认是0):跳过去几条;相当于SQL中limit的第一个参数
	 */
	$retval = $hs->executeDelete($index, $operation, $value, $number, $skip);
	更新(注意:此处的openIndex要用$port_wr,即读写端口):
	/*
	 * Int     $index: openIndex()所用的$index
	 * String  $operation:openIndex方法中指定的$key字段所用的操作符,目前支持'=', '>=', '< =', '>',and '< ';可以理解为where条件
	 * Array   $value
	 * Int       $number(默认是1):获取结果的最大条数;相当于SQL中limit的第二个参数
	 * Int     $skip(默认是0):跳过去几条;相当于SQL中limit的第一个参数
	 */
	$retval = $hs->executeUpdate($index, $operation, $value, $number, $skip);
CREATE TABLE `user` (
  `user_id` int(10) unsigned NOT NULL,
  `user_name` varchar(50) DEFAULT NULL,
  `user_email` varchar(255) DEFAULT NULL,
  `created` datetime DEFAULT NULL,
  PRIMARY KEY (`user_id`),
  KEY `INDEX_01` (`user_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES ('1', 'aaa', 'aaa@dsf.com', '2011-04-07 18:26:03');
INSERT INTO `user` VALUES ('2', 'bbb', 'bbb@dsf.com', '2011-04-07 18:26:03');
INSERT INTO `user` VALUES ('3', 'ccc', 'ccc@test.com', '2011-04-07 18:26:03');
< ?php
$host = '192.168.5.28';
$port = 9998;
$port_wr = 9999;
$dbname = 'test';
$table = 'user';

//GET
$hs = new HandlerSocket($host, $port);
if (!($hs->openIndex(1, $dbname, $table, HandlerSocket::PRIMARY, 'user_id,user_name,user_email,created')))
{
    echo $hs->getError(), PHP_EOL;
    die();
}

$retval = $hs->executeSingle(1, '>=', array('0'), 10, 0);

var_dump($retval);

$retval = $hs->executeMulti(
    array(array(1, '=', array('1'), 1, 0),
          array(1, '=', array('2'), 1, 0)));

var_dump($retval);

unset($hs);

//UPDATE
$hs = new HandlerSocket($host, $port_wr);
if (!($hs->openIndex(2, $dbname, $table, '', 'user_name,user_email,created')))
{
    echo $hs->getError(), PHP_EOL;
    die();
}

if ($hs->executeUpdate(2, '=', array('2'), array('aaa', 'xun@dsf.com', '2011-04-07 18:26:03'), 1, 0) === false)
{
    echo $hs->getError(), PHP_EOL;
    die();
}

unset($hs);

//INSERT
$hs = new HandlerSocket($host, $port_wr);
if (!($hs->openIndex(3, $dbname, $table, '', 'user_id,user_name,user_email,created')))
{
    echo $hs->getError(), PHP_EOL;
    die();
}

if ($hs->executeInsert(3, array('5', 'aaa5', 'xun@dsf.com', '2011-04-07 18:26:03')) === false)
{
    echo $hs->getError(), PHP_EOL;
}
if ($hs->executeInsert(3, array('6', 'aaa6', 'xun@dsf.com', '2011-04-07 18:26:03')) === false)
{
    echo 'A', $hs->getError(), PHP_EOL;
}
if ($hs->executeInsert(3, array('7', 'aaa7', 'xun@dsf.com', '2011-04-07 18:26:03')) === false)
{
    echo 'B', $hs->getError(), PHP_EOL;
}

unset($hs);

//DELETE
$hs = new HandlerSocket($host, $port_wr);
if (!($hs->openIndex(4, $dbname, $table, '', '')))
{
    echo $hs->getError(), PHP_EOL;
    die();
}

if ($hs->executeDelete(4, '=', array('1')) === false)
{
    echo $hs->getError(), PHP_EOL;
    die();
}
?>

JW Player 5.5 去水印破解

自从根据JW Player源代码,编译破解去掉了官方水印之后,有很多网友下载使用了,但是从JW Player 5.3之后,我就再没有去编译,认为按照我们说的方法,很简单就编译出来,但是仍不停收到E-mail,求破解JW Player的最新版本………. 所以我就编译了最新版本的JW Player 5.5 去水印破解版本!

采用GPU加速的JW Player 5.5最新版本flash视频播放器,编译破解去除水印! 最新jw player 5.5下载

根据源代码编译方法见:去掉JW Player水印及右键官方菜单

Android and HTML5 开发手机应用

作为一个WEB开发者,HTML5让我兴奋,因为它可以将桌面应用程序功能带入浏览器中。但在国内,看着到处横行的IE8版本以下的浏览器,觉得到能大规模使用HTML5技术的那天,还遥遥无期。但面对iOS及Android等平台的手机用户越来越多,基于Webkit内核的移动浏览器一定能让HTML5先大规模应用起来。这将对对移动 Web 应用程序开发具有重大影响。

作为非常看好未来手机网络的我,也在一直研究Android平台的应用的开发,也许是因为自己更熟悉HTML及CSS、JS,并受到之前使用HTML和VC开发程序的影响,我也更愿意使用HTML来做Android程序的UI….

09年,在开发《华夏风云》游戏的时候,使用了基于Google Gear插件来做了很多离线应用,可惜Gear已经不在更新开发,被HTML5取代。下面介绍基于HTML 5 的Web 应用程序的本地存储,不再废话,例子说明一切。

 

一、离线应用缓存 HTML 5 Offline Application Cache

  • 在服务器上添加MIME TYPE支:text/cache-manifest
  • 如果在Apache下添加:

    AddType text/cache-manifest manifest

    如果为Nginx,在添加:

     text/cache-manifest                   manifest;

    或者通过动态程序生成:

    header('Content-type: text/cache-manifest; charset=UTF-8');
  • 创建 NAME.manifest:
  • 新建清单文件 manifest

    CACHE MANIFEST
    # This is a comment.
    # Cache manifest version 0.0.1
    # If you change the version number in this comment,
    # the cache manifest is no longer byte-for-byte
    # identical.
    
    /app/static/default/js/models/prototype.js
    /app/static/default/js/controllers/init.js
    
    NETWORK:
    # All URLs that start with the following lines
    # are whitelisted.
    
    http://a.com/
    
    CACHE:
    # Additional items to cache.
    /app/static/default/images/main/bg.png
    
    FALLBACK:
    demoimages/ images/
  • 给 <html> 标签加 manifest 属性
  • 建立manifest文件之后,需要在HTML文档中声明:
    声明清单文件 manifest

    
    
    <!doctype html> 
    <html manifest="notebook.manifest"> 
        <head> 
            <meta charset="UTF-8" /> 
    		<meta name = "viewport" content = "width = device-width, user-scalable = no"> 
            <title>NoteBook</title> 
        </head> 
        <body> 
        </body> 
    </html>

二、Key-Value Storage

三、Using the JavaScript Database

四、Android下使用WebView来做基于HTML5的App

见如下AndroidManifest.xml

< ?xml version="1.0" encoding="utf-8"?>

    
        
            
                
                
            
        
    
	

注意:

, 允许网络应用,必须!!

Android主程序代码:

package com.xinze.joke;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;

import android.content.DialogInterface;

import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import android.webkit.WebStorage ;

public class Joke extends Activity {

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		final WebView wv = new WebView(this);

		// 覆盖默认后退按钮的作用,替换成WebView里的查看历史页面
		wv.setOnKeyListener(new View.OnKeyListener() {

			@Override
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if (event.getAction() == KeyEvent.ACTION_DOWN) {
					if ((keyCode == KeyEvent.KEYCODE_BACK) && wv.canGoBack()) {
						wv.goBack();
						return true;
					}
				}
				return false;
			}
		});

		// 设置支持Javascript
		wv.getSettings().setJavaScriptEnabled(true);

		wv.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
		wv.getSettings().setDatabaseEnabled(true);
		wv.getSettings().setDatabasePath("/data/data/com.xinze.joke/databases"); 

		// 创建WebViewClient对象
		WebViewClient wvc = new WebViewClient() {

			@Override
			public boolean shouldOverrideUrlLoading(WebView view, String url) {
				wv.loadUrl(url);
				// 记得消耗掉这个事件。给不知道的朋友再解释一下,Android中返回True的意思就是到此为止吧,事件就会不会冒泡传递了,我们称之为消耗掉
				return true;
			}
		};

		// 设置WebViewClient对象
		wv.setWebViewClient(wvc);

		// 创建WebViewChromeClient
		WebChromeClient wvcc = new WebChromeClient() {

			// 处理Alert事件
			@Override
			public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
				// 构建一个Builder来显示网页中的alert对话框
				Builder builder = new Builder(Joke.this);
				builder.setTitle("笑死不偿命");
				builder.setMessage(message);
				builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						result.confirm();
					}
				});
				builder.setCancelable(false);
				builder.create();
				builder.show();
				return true;
			}

			// 处理Confirm事件
			@Override
			public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
				Builder builder = new Builder(Joke.this);
				builder.setTitle("删除确认");
				builder.setMessage(message);
				builder.setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						result.confirm();
					}

				});
				builder.setNeutralButton(android.R.string.cancel, new AlertDialog.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						result.cancel();
					}

				});
				builder.setCancelable(false);
				builder.create();
				builder.show();
				return true;
			}

			// 处理提示事件
			@Override
			public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
					JsPromptResult result) {
				// 看看默认的效果
				return super.onJsPrompt(view, url, message, defaultValue, result);
			}

			@Override
		       public void onExceededDatabaseQuota(String url, String
		    		   databaseIdentifier, long currentQuota, long estimatedSize, long
		    		   totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) {
		    		                   quotaUpdater.updateQuota(204801);
		    		               } 

		};

		wv.loadUrl("http://192.168.1.14/index.html");

		// 设置setWebChromeClient对象
		wv.setWebChromeClient(wvcc);
		setContentView(wv);
	}
}

使用 JavaScript Database 的时候,需要特别注意:setDatabaseEnabled 以及 onExceededDatabaseQuota!

Ajax 二进制

javascript如何处理二进制数据?
Ajax 有没有读取二进制流的好办法?

通过ajax与服务器交互过程中,我们大部分传递html,xml,json等文本数据根式,能否以二进制的形式来传递数据? 比如,通过ajax,来处理amf格式的二进制数据?

AS3下面,通过ByteArray来操作二进制数据非常方便,在JS下,可以根据算法,搞一份JS下的ByteArray。
在传输二进制数据的时候,需要注意在不同浏览器下发送不同的头文件信息:

注意要点:

	this.options.overrideMimeType = "text/plain; charset=x-user-defined";
	this.options.overrideHeaders = ["Accept-Charset", "x-user-defined"];

	if (!Prototype.Browser.IE && this.options.overrideMimeType)
	{
		if (this.options.overrideMimeType && this.transport['overrideMimeType'])
		{
			this.transport.overrideMimeType(this.options.overrideMimeType);
		}
		else
		{
			this.transport.setRequestHeader(overrideHeaders[0], overrideHeaders[1]);
		}
	}

通过在各种浏览器下测试,都可以正常运行,哈哈。
这是Ajax 读取二进制流示例:ajax 通过二进制方式传输数据 demo

win7修改%userprofile%路径

Android 开发环境安装失败问题总结 win7下中,提到在运行程序, 在手机模拟器中查看结果的时候,发现如下错误:

emulator: ERROR: unknown virtual device name: ’****’
emulator: could not find virtual device named ’****’

具体原因,是因为我修改了用户文档目录,修改到了F盘目录下。 我将“F:\Users\账号\”下面的“.android”复制一份到到“C:\Users\ 账号\”下即可。

问题是,我修改了用户文档目录,为什么Android开发环境程序仍然下“C:\Users\ 账号\”下寻找“.android”呢? 后来我发现%userprofile%的值为“C:\Users”, 于是我修改了%userprofile%,这些所有的都不在系统盘了。 修改过程如下:

打开注册表,在“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList”中将Default,ProfilesDirectory,Public中的 %SystemDrive% 修改成F:。 然后修改SID中”ProfileImagePath“值为”F:\Users\Xinze“即可。

一般而言,SID像以下形式:”S-1-5-21-3877960078-4078276580-425308375-1000“

注意,不要忘记将“C:\Users”目标拷贝到“F:\Users”。

FastCGI开发学习

1. 下载fastcgi开发包,编译安装

http://www.fastcgi.com/dist/fcgi-current.tar.gz

wget http://www.fastcgi.com/dist/fcgi-current.tar.gz
tar zvzf fcgi-current.tar.gz
cd fcgi-current
./configure
make
make install

2. 下载spawn-fcgi,编译安装

http://www.lighttpd.net/download/spawn-fcgi-1.6.0.tar.gz

wget http://www.lighttpd.net/download/spawn-fcgi-1.6.0.tar.gz
tar zxvf spawn-fcgi-1.6.0.tar.gz
cd spawn-fcgi-1.6.0
./configure
make
make install

3. 编写测试的c fastcgi代码,存为 hello.c

#include 
int main( int argc, char *argv[] )
{
    while( FCGI_Accept() >= 0 ) {
        printf( "Content-Type: text/plain\n\n" );
        printf( "Hello FastCGI\n" );
    }
    return 0;
}

编译c源文件,运行时有可能会报找不到lib包,这里我复制了一份,也可以做一个软链接。我这里用的是64位的机器,所以复制到了:/usr/lib64,32位的用:/usr/lib。

gcc -o hello hello.c -lfcgi

4. 修改nginx.conf配置文件,重新启动nginx

server {
            listen   80;
            server_name _;

            location / {
                  root   /home/user/www;
                  index  index.html;
                  fastcgi_pass 127.0.0.1:9000;
            }
}

5. 启动hello

spawn-fcgi -a127.0.0.1 -p9000 -n ./hello

6. 访问nginx服务器,浏览器就会输出:Hello FastCGI

一个nginx c fastcgi学习环境搭建完毕。

fastcgi 开发学习资料:

FastCGI中文参考手册

http://man.lupaworld.com/content/develop/Perl/FastCGI_handbook_cn.pdf

Nginx下配置FastCGI

http://202.108.59.116/docs/Nginx%CF%C2%C5%E4%D6%C3FastCGI.pdf

CentOS Ubuntu 等linux 修改IP地址, DNS, 网关

由于修改网关总是忘记在哪个地方,每次都要去查询,太麻烦,今天在此备份一下:

一、CentOS 修改IP地址

修改对应网卡的IP地址的配置文件

# vi /etc/sysconfig/network-scripts/ifcfg-eth0
修改以下内容
DEVICE=eth0 #描述网卡对应的设备别名,例如ifcfg-eth0的文件中它为eth0
BOOTPROTO=static #设置网卡获得ip地址的方式,可能的选项为static,dhcp或bootp,分别对应静态指定的 ip地址,通过dhcp协议获得的ip地址,通过bootp协议获得的ip地址
BROADCAST=192.168.0.255 #对应的子网广播地址
HWADDR=00:07:E9:05:E8:B4 #对应的网卡物理地址
IPADDR=192.168.1.2 #如果设置网卡获得 ip地址的方式为静态指定,此字段就指定了网卡对应的ip地址
IPV6INIT=no
IPV6_AUTOCONF=no
NETMASK=255.255.255.0 #网卡对应的网络掩码
#NETWORK=192.168.1.1 #网卡对应的网络地址
GATEWAY=192.168.1.1(设置本机连接的网关的IP地址。例如,网关为10.0.0.2)
ONBOOT=yes #系统启动时是否设置此网络接口,设置为yes时,系统启动时激活此设备
TYPE=Ethernet
PEERDNS=yes
USERCTL=no
~

二、CentOS 修改网关
修改对应网卡的网关的配置文件
[root@centos]# vi /etc/sysconfig/network

修改以下内容
NETWORKING=yes(表示系统是否使用网络,一般设置为yes。如果设为no,则不能使用网络,而且很多系统服务程序将无法启动)

NETWORKING_IPV6=no

HOSTNAME=localhost.localdomain(设置本机的主机名,这里设置的主机名要和/etc/hosts中设置的主机名对应)

三、CentOS 修改DNS

修改对应网卡的DNS的配置文件
# vi /etc/resolv.conf
修改以下内容

nameserver 192.168.1.1 #域名服务器
nameserver 192.168.1.2

四、重新启动网络配置
# service network restart

# /etc/init.d/network restart

修改 IP 地址
即时生效:
# ifconfig eth0 192.168.0.2 netmask 255.255.255.0
启动生效:
修改 /etc/sysconfig/network-scripts/ifcfg-eth0

修改网关 Default Gateway
即时生效:
# route add default gw 192.168.0.1 dev eth0
启动生效:
修改 /etc/sysconfig/network

修改 DNS
修改/etc/resolv.conf
修改后可即时生效,启动同样有效

修改 host name
即时生效:
# hostname centos1
启动生效:
修改/etc/sysconfig/network

+++++++++++++++++++++++++++++++++++++++++

Ubuntu 下修改:

xinze@xinze-desktop:$ vi /etc/network/interfaces

auto lo

iface lo inet loopback

auto eth0

iface eth0 inet static

address 192.168.1.11

netmask 255.255.255.0

gateway  192.168.1.1

xinze@xinze-desktop:$ /etc/init.d/network restart

Page 1 of 1012345...10...Last »