体会3G生活

这些日子失业在家,本想会大兴住一阵子,但是苦于大兴的ADSL被我取消了,再开通需要下月生效,没法上网感到生活煞是不方便。今天到中国电信营业申请了一张3G无线上网卡,每年(13个月)1760元,链接速度可以到3.1Mbps。带回大兴家中试了试感觉还是相当不错的,打开魔兽世界平均ping值是205(由于链接到网通的服务器,电信区的服务器可能会更快一点),下载了一个文件,大概130KBps速度,且速度还是很稳定的。第一次体验3G生活感觉相当不错,哈哈~!

Nikon SB900 SpeedLight 使用心得

SB900 5月1日同学婚礼,早就想买个外闪了正好借此机会买一个,原本看上SB800这个老灯神,不料Nikon在推出SB900后SB800停产了,市场上现在很难买到SB800了。SB600指数又不够,于是乎只好选择SB900。拿到这个灯的时候,感觉这个灯好大呀,D90加上70-200 2.8再加上这个灯,重量着实让我有点吃不消,不过这个组合倒是酷毙了,拿着这套家伙在大街上一走,回头率90%以上,自己也有种专业摄影师的感觉。

由于是新买的灯,控制上不是很熟悉,所以同学的那场婚礼拍的不尽如人意。于是开始苦读SB900的说明书,SB900提供了两本使用手册,其中一本写的比较详细但是比较难懂,另一本是一本小画册,参照图例讲解如何使用SB900,当然最好两本书都看一下,这样会有很大的帮助,还有相机机身的说明书最好也再看看,里面有关于通过相机机身控制外闪的说明,比如同步慢闪,后帘同步,都是通过相机机身完成的,相机机身上最重要的设置就是将自通同步FP设置成开启状态,这样在使用M档时最快快门可以突破1/200秒,这点很关键。

开始总以为外闪只适用于室内或是晚上,在看了一篇国外介绍如何使用闪光灯的文章后,我的看法彻底改变了,文章说到了自然光线很少是完美的,所以在拍摄的时候或多或少的需要才有一些补救措施,闪光灯就是很好的解决方案。

白天的时候我们在户外拍摄任务肖像的时候,想要拍摄出人物的眼神光,可以让被拍摄者站到阴凉的地方,眼睛朝向有亮光的地方,这样拍拍摄才可能拍摄出人物的眼神光,但是这样做局限性很大,这时候如果使用外闪这个问题将会轻易解决。Nikon S900提供了一种TTL BL模式可以在白天均匀的进行补光处理。

白天户外拍摄的时候,可以使用外闪突出主体。先对拍摄物体测光,在测光的基础上减1-2档曝光,这样排出的照片主体会突出出来,背景会很暗,不过这样处理有一个条件就是被拍摄物体和背景之间的距离要大一些,若是人物和背景距离很近,这样拍摄可能会失败。

使用外闪补光,在逆光拍摄的时候,由于外界光线很强,拍摄出来的照片人物的脸会发黑或者背景是一片惨白,若想让背景和人物都得到正取的曝光,就要对人物进行补光,传统的方法是使用反光板,但是使用放光板需要有一个摄影助理,在没有摄影助理的情况下,可以使用闪光灯进行补光处理,对背景正常测光进行拍摄就可以得到人物和背景曝光正取的照片,若是距离很近可以考虑使用柔光罩或者散射片,完成拍摄。

以上就是我对SB900,对白天使用外闪的一点使用心得,欢迎大家指正。

对微软渐生好感

以前对于微软产品总是很不屑,感觉他不开源,总高一些自己的标准。今日在家待业,在家学习偶尔用Windows Live Writer写些博客,其实我很早就开始用Windows Live Writer了,这可能是我继Windows以外用的最多的微软产品。Windows Live Writer不光支持Live空间,还支持很多别的博客离线接口,于是乎想找找看看国内的Blog提供商是否也在支持标准之内,找了一圈发现无一支持,没想到这么多国内的知名的博客都在闭门造车,让人很是不爽,或许他们有他们自己的理由和初衷,但是还是觉的在Web上写Blog很是不方便。

今天有尝试了一下Windows Live的其他产品Mail和图片库感觉做的也是很方便,Mail可以对多个邮件帐户进行支持,而且配置帐户也很方便,特别值得一提的就是对Gmail的支持,众所周知微软向来与Google不和,在配置Gmail帐户的时候Windows Live Mail还特别给出了配置Gmail帐户的流程,真是我对其倍增好感,甚至对微软的那种不屑的态度也有所转变,今后要多接触一下微软的产品了,至少Live系列是相当出色的。

Future and Callable

有的时候我们需要将一个问题分解成若干的小问题,假如每个小问题可以独立运算,运算后将结果进行合并,这样的话我们可以使用多个线程处理每一个小问题后,将每个运算结果合并,这样可以极大的发挥计算机的性能,缩短运算时间,Java中提供者这样两个接口Callable和Future,可以最大程度的简化上述问题的开发过程。

先来看一下Callable接口,Callable接口类似Runnable,都是为了能被另一个线程执行而设计的,Callable与Runnable不同,Callable可以返回一个运行结果,Runnable则不会返回,且Runnable不会抛出与各经过检查的异常。Callable包含一个类似Runnable的方法:

public <V> call() throws Exception;

这个方法用法和Runnable的run的用法一致,所不同的是其增加了返回值,并且允许抛出异常。

Future接口表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。

下面的例子展示了如何使用Future、Callable和Executor完成求1-100以内和:

MyCallable.class

package net.chinaideal.concurrency.callable;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Long> {

    private Long start;
    private Long end;

    public MyCallable(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    public Long call() throws Exception {
        long sum = 0;
        for (long i = start; i <= end; i++) {
            sum += i;
        }

        System.out.println(Thread.currentThread().getName() + " " + start
                + " - " + end + " = " + sum);

        return sum;
    }
}

CallableFutures.class:

package net.chinaideal.concurrency.callable;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class CallableFutures {
    private static final int NTHREDS = 10;

    public static void main(String[] args) {

        ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
        List<Future<Long>> list = new ArrayList<Future<Long>>();
        for (long i = 0; i < NTHREDS; i++) {
            Callable<Long> worker = new MyCallable(i * NTHREDS + 1, (i + 1)
                    * NTHREDS);
               Future<Long> submit = executor.submit(worker);
            list.add(submit);
        }
        long sum = 0;
        for (Future<Long> future : list) {
            try {
                sum += future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }

        executor.shutdown();
        while (executor.isTerminated()) {
        }
        System.out.println("sum=" + sum);

    }

}

Callable中定义了两个成员变量start和end,分别代表运算的起始值和终止值,每一个线程需要完成的从start至end之和的运算。

通过调用ExecutorService.submit方法提交Callable任务,此方法返回一个Future对象,这个Future对象代表对应Callable返回的值,最后再将全部的Future求和完成对全部Callable结果的合并。

java.util.concurrent.Executors学习

前些天到一家公司去面试,被问到几个关于Java中多线程的问题,在以往的工作中使用Java开发的都是关于WEB方面的应用,Java中多线程还是多年前那一点点关于Object.wait(), Object.notify(), synchronized的一点点印象,对于java.util.concurrent也只有一点点印象,想到这次面试的时候被面试官问道的窘相,决定发奋图强一下深入研究一下Java多线程,不应该说是深入研究一下Java。

面试的时候面试官出了这样一道题目,写一个程序要求主线程等待子线程运行结束后退出,且子线程同时运行。乍一听以为可以用Thread.join()的解决,但是这样的方法忽略掉了同时运行,Thread.join()这样的方式每一个子线程将逐个运行,这样的解题是错误的。

另一种思路共享一个计数标志位,每个线程结束后都去更新这个计数标志位,主线程判断该计数标志位是否所有的线程都已经工作完成,但是为了不去浪费过多的CPU,主线程需要进行Thread.sleep(),但是Thread.sleep()也会倒是效率的下降,所以这样的方法并不完美。

回家后查了很多资料,发现java.util.concurrent包中有个名为Executors的类,可以创建线程池,于是仔细研究了一下,发现使用这个类构造一个线程池,可以很简单的解决这个问题。

先看一下用Executors实现上述问题的完整代码:

Main.class

package net.chinaideal.concurrency.executor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    private static final int NTHREDS = 10;

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
        for (int i = 0; i < NTHREDS; i++) {
            Runnable worker = new MyRunnable();
            executor.execute(worker);
        }
        executor.shutdown();
        while (!executor.isTerminated()) { }
        System.out.println("Finished all threads");
    }

}

MyRunnable.class

package net.chinaideal.concurrency.executor;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
}

通过Executors.newFixedThreadPool(n);创建制定个数的工作线程池。java.util.concurrent.ExecutorService接口继承自java.util.concurrent.Executor接口,而Executor.execute的方法提供了一个运行Runnable类的方法。

因此在这个程序的实例中,使用Executors.newFixedThreadPool获得一个ExecutorService的实例,并通过执行ExecutorService.execute的方法运行定义好的MyRunnable实例。

通过不断运行ExecutorService.isTerminated()方法检测全部的线程是否都已经运行结束,ExecutorService.shutdown()将使之前通过Executor.execute()提交的任务运行结束后关闭线程池。ExecutorService还提供了一个与ExecutorService.shutdown()对应的方法名为ExecutorService.shutdownNow()该方法试图将结束已经提交的任务并结束线程池。

如果我们不调用ExecutorService.shutdown()或者ExecutorService.shutdownNow()方法,主线程将会一直阻塞住。

将System.out和System.err重定向

昨天去面试,被问到System.out和System.err如何被重定向,脑海中隐约有点印象,好像在哪里看到过似的,但是死活想不起来,面试的考官提示在Tomcat的源码中可以找到答案,尽早起来连忙下载Tomcat源码,终于在AprImpl.java文件中找到了些许蛛丝马迹,此文件中有这样一个方法:

public static void setOut( String filename ) {
        try{
            if( filename !=null ){
               System.setOut( new PrintStream(new FileOutputStream(filename )));
            }
        }catch (Throwable th){
        }
}

JDK还提供了对System.err重定向的方法,System.setErr(PrintStream stream);

不料原来重定向如此简单,JDK已经提供了对应的方法,只愿自己对JDK API不是非常熟悉,以后对Java的研究还要再下些功夫才行。

Apache + Tomcat on Fedora9

本文介绍在Fedora9上通过mod_jk完成Apache和Tomcat的整合,实现Apache + Tomcat负载均衡的设置。

所需主要软件:

  1. Fedora9
  2. Apache(httpd-2.2.8-3.i386.rpm)
  3. Tomcat6
  4. JDK6
  5. mod_jk

JDK的安装十分简单,这里就不再赘述了,在安装JDK后,我们需要这是JAVA_HOME环境变量。由于要实现Tomcat的负载均衡,我们设置2个Tomcat实例,为了启动方便我将TOMCAT_HOME这个环境变量直接放入Tomcat的bin/startup.sh脚本中,分别指向各自的TOMCAT所在位置。

接下来调整TOMCAT的监听端口:

TOMCAT1端口配置:

原端口 修改后端口 说明
8080 8080 HTTP监听端口
8009 8009 AJP13监听端口
8005 8005 Tomcat关闭端口
8443 8443 SSL端口

TOMCAT2端口配置:

源端口 修改后端口 说明
8080 8081 HTTP监听端口
8009 8010 AJP13监听端口
8005 8006 Tomcat关闭端口
8443 8444 SSL端口

按照上述列表对Tomcat的conf/server.xml进行端口修改,示例如下:

  1. <Server port="8005" shutdown="SHUTDOWN"> #TOMCAT关闭端口
  2. <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"  redirectPort="8443" /> #TOMCAT HTTP监听端口和SSL端口,若是应用没有使用SSL可以不用修改
  3. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> #TOMCAT AJP13监听端口

完成修改后将Tomcat1和Tomcat2同时启动,通过浏览测试Tomcat是否成功启动,若是没有问题进入下一步配置Apache。(这里可以使用浏览器访问这两个Tomcat进行测试)

1

Apache的配置,在RedHat Linux中会将Apache Http Server编译出来的文件的放置到不同的目录中,Fedora也不例外,下表列出了Apache个文件所在目录的名称和作用。

目录名称 说明
/etc/httpd/conf Apache 主配置文件(httpd.conf)做在位置。
/etc/httpd/conf.d 由于Redhat在Apache主配置文件(httpd.conf)中定义Include conf.d/*.conf,因此Apache在启动时加载完httpd.conf后会自动加载这个目录中以conf为扩展名的的配置文件,这样做的可以使Apache的配置更简洁更结构话。
/var/log/httpd Apache 日志所在位置。
/usr/lib/httpd/modules Apache Modules目录,我们接下载使用编译的mod_jk会被安装到这个目录中。
/usr/sbin Apache的bin目录,这里值得说明的是在RedHat Linux中部使用apachectl这个命名起停Apache,而是启用service httpd start/restart/stop起停Apache。

我们使用service httpd start测试一下,Apache Http Server是否能正常运行,若是没有问题我们开始进行mod_jk的编译和安装。

在编译mod_jk前我们要确认一下我们的系统中是否安装了apr和apr-utils,这两个库的安装文件可以在Fedora9 DVD中的Packages目录找到,使用rpm –ivh filename安装,具体示例如下:

rpm -ivh apr-1.2.12-2.fc9.i386.rpm

rpm -ivh apr-util-1.2.12-5.fc9.i386.rpm

注意:以上两个安装文件可能在不同版本的Redhat Linux中版本出现不一致的情况,没关系我们只需找到apr和apr-utils对应的文件进行安装即可。

由于我们要编译mod_jk所以我们需要Apache Http Server的开发包,在以往的RedHat系统中Apache Http Server的开发包是一个名为httpd-devel*.rpm的文件,该文件存放在安装光盘的Packages或Server目录中,在Fedora9中Packages中没有找到httpd-devel*.rpm这样的文件,而且apr和apr-utils的开发也没有找到,所以我们需要在Google找一下这3个文件。

  1. httpd-devel-2.2.8-3.i386.rpm
  2. apr-util-devel-1.2.12-5.fc9.i386.rpm
  3. apr-devel-1.2.12-2.fc9.i386.rpm

这三个文件存在依赖关系,需要按照apr-devel、apr-util-devel、httpd-devel这样的顺序进行安装,安装完成后就可以编译mod_jk了。

编译mod_jk

下载mod_jk并解压,进入到native目录中进行编译configure,运行configure脚本时候需要指明apxs所在位置,apxs在/usr/sbin,configure命令如下:

#./configure –with-apxs=/usr/sbin/apxs

运行成功后,进行make和make install对mod_jk进行编译和安装

#make all && make install

编译和安装成功后,在Apache的Modules目录中可以找到mod_jk.so,接下来我们来对jk进行配置。

在Apache的conf.d目录中(/etc/httpd/conf.d)添加jk的配置文件jk.conf,jk.conf的内容如下:

# 加载mod_jk.so
LoadModule    jk_module  modules/mod_jk.so
# 指定JkWorker的配置文件的路径 workers.properties
JkWorkersFile /etc/httpd/conf/workers.properties
# Where to put jk shared memory
JkShmFile     /var/log/httpd/mod_jk.shm
# Where to put jk logs
JkLogFile     /var/log/httpd/mod_jk.log
# Set the jk log level [debug/error/info]
JkLogLevel    info
# Select the timestamp log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

这里面比较重要的文件就是定义了JkWorker的配置文件,保存退出。接下来添加最重要的workers.properties,这个文件定义jk和Tomcat的映射关系,我们可以将Tomcat理解成一个worker。

首先我们配置Apache和Tomcat级联,然后再配置Apache同Tomcat的负载均衡。

Apache和Tomcat级联

我在/etc/httpd/conf/workers.properties加入如下内容:

worker.list=tomcat1
#定义worker tomcat1的类型为ajp13
worker.tomcat1.type=ajp13             

#定义worker tomcat1所在的主机,由于Tomcat和Apache处于同一台机器所以定义成localhost
worker.tomcat1.host=localhost

#定义worker tomcat1的AJP13监听端口
worker.tomcat1.port=8009

保存退出,这样我们就定义好了worker tomcat1,接下来我还要做一件事情就是告诉Apache什么样的请求需要通过mod_jk传递给tomcat,我们需要使用JkMount这个指令完成以上的工作,JkMount命令格式如下

JkMount URI workername

我们在在Apache的conf.d目录中添加jk_mount.conf文件,文件内容如下:

JkMount  /examples/* tomcat1

这条指令告诉Apache examples路径下的所有请求交由worker tomcat1处理。配置好后我们重新启动Apache。

#service httpd restart

在浏览器中输入http://localhost/examples/访问Tomcat的示例页面,若配置成功显示如下页面:

2

接下来我们来配置Apache和Tomcat的负载均衡,首先要修改workers.properties文件,定义一个停工负载均衡的worker。workers.properties内容如下:

worker.list=balancer

#定义worker balancer的类型为lb(lb,load balance)
worker.balancer.type=lb

#定义负载均衡是都是用那些已有的worker
worker.balancer.balance_workers=tomcat1 , tomcat2

#定义worker tomcat1的类型为ajp13
worker.tomcat1.type=ajp13
#定义worker tomcat1所在的主机,由于Tomcat和Apache处于同一台机器所以定义成localhost
worker.tomcat1.host=localhost
#定义worker tomcat1的AJP13监听端口
worker.tomcat1.port=8009
#定义worker tomcat1的负载均衡的权重,该数值越大请求的数量越多
worker.tomcat1.lbfactor=50

#定义worker tomcat2的类型为ajp13
worker.tomcat2.type=ajp13
#定义worker tomcat2所在的主机,由于Tomcat和Apache处于同一台机器所以定义成localhost
worker.tomcat2.host=localhost
#定义worker tomcat2的AJP13监听端口
worker.tomcat2.port=8010
#定义worker tomcat2的负载均衡的权重,该数值越大请求的数量越多
worker.tomcat2.lbfactor=50

保存退出,最后别忘了修改jk_mount.conf文件,将tomcat1修改成balancer,

JkMount /examples/* balancer

重新启动Apache。

为了演示负载均衡的效果,我在Tomcat1和Tomcat2放置两个文件名相同但是现实内容不同的测试页面hello.jsp

Tomcat1的$TOMCAT_HOME/webapps/examples/hello.jsp内容为

<%
        out.println("Hello Tomcat1");
%>

Tomcat2的$TOMCAT_HOME/webapps/examples/hello.jsp内容为

<%
        out.println("Hello Tomcat2");
%>

这样我们在用反复浏览器访问http://localhost/examples/hello.jsp,将会交替显示Hello Tomcat1和Hello Tomcat2,这说明Apache会将/examples/hello.jsp分配到Tomcat1和Tomcat2上,从而使之完成负载均衡。

现在Apache还可以通过Apache本身带有的Proxy模式同Tomcat整合,但是AJP13可以实现对Tomcat的检测上述提到配置方法,若是有一个Tomcat宕机了Apache会自动将请求发送给另一个Tomcat。

题外话,在设计一个Java Web应用的时候,最好考虑一下静态资源的问题,往往在高访问量的情况下Web的瓶颈出现于静态资源的IO上,可以通过Apache设置静态资源的expires,或者采用反向代理方式提高在高访问量下静态资源的处理能力。

Ubuntu Live USB

今天同事买了2个上网本,由于没有CDROM所以只能通过U盘进行系统安装。以前在DOS时代制作自启动软盘只需要输入如下命令format /s a:。但是制作有盘的自启动这样的方式就不行了,于是在网上找了找关于U自启动的制作,主要是关于制作Live Ubuntu in usb,Ubuntu 8.10后提东了一个usb-creator工具,可以直接制作Live CD,我企图在VMare上实现,usb-creator始终处于不响应状态,也许是跟我的VMWare配置有关。

现在手中没有Ubuntu系统,只能在Windows上制作U盘版的Ubuntu Live CD,继续Google,最终找了一个KUbuntu Live CD是在Windows的安装方法,下载以后按照安装提示进行操作,但是这个Kubuntu.bat这个批处理命令总是提示我找不到U盘。

打开kubuntu.bat看了看,发现原理很简单,修改了一下,我将U盘的盘符写死,修改后脚本如下

@echo off

cls
7-Zip\7z x kubuntu-8.10-desktop-i386.iso -y -x!bin -x!programs -x![BOOT] -oG:
mkdir G:\sysl\win32
copy sysl\win32\*.* G:\sysl\win32
copy makeboot.bat G:
copy text.cfg G:
copy casper-rw G:
G:
cls
ren isolinux syslinux
ren syslinux\isolinux.cfg syslinux.cfg
copy text.cfg syslinux\text.cfg
echo  Moving on to the makeboot script...
call G:\makeboot.bat

这个脚本中G:是我的U盘的盘符,实际中替换成自己的盘符就可以了。这个方法也可以制作Gnome版的Ubuntu,只需要替换iso的文件名称即可。

写给即将到来的27岁

再过十几个小时我就要告别的我的26岁了。我的生日是1月26日,所以在我心中26就是我的幸运数字。

还记得2008年的今天,那是我25岁的最后一天,那时候正在为mSpaces而忙碌,生日那天还加了一天班,那时候全心全意的希望把mSpaces做好,但是事与愿违,我们最后没有把mSpaces延续下去,不过我还是很期待mSpaces上线的那一天,因为我为她全身心付出过。

26岁中我有了自己的房子,在收房后的三个月中我和GG筹建着我们未来的家,看着自己房子一天天变漂亮,强烈的幸福感觉,让我们很快乐。26岁我终于和GG踏上神圣的婚姻殿堂,开始我们新的生活,愿我们的生活更加幸福快乐。

最后,我希望在新的一年中,我爱的和爱我的人幸福快来。

PyS60 in Action

PyS60 in Emulator中介绍了如何在模拟器上测试Python程序,本文介绍PyS60在手机上部署过程。

首先,需要在手机上安装PyS60 Runtime,目前第五版S60对应的PyS60版本是1.9.0这个版本,第三版对应1.4.5这个版本,找到对应的版本将其安装到手机的C:,开始我一直将PyS60 Runtime安装在手机的存储卡上,PythonForS60Shell始终无法打开,安装到C:上一切正常。

接下来我们准备一个Python测试程序,这个程序很简单,使用Note显示当前剩余电量,程序如下:

import sysinfo
import appuifw

format = "Battery: %d"
text = format %  sysinfo.battery()

appuifw.note(text.decode("utf8"))

将上面的程序保存为battery.py,可以将该文件上传到手机C:\Python目录下使用PythonForS60Shell测试该脚本,若是运行正确,我们就可以对该程序进行打包。

接下来我们将使用py2sis,打包battery,在执行py2sis之前需要将S60 C++ SDK安装好,可以通过编译SDK自带的Helloworld程序确认SDK是否安装正确,安装SDK是需要注意配置EPOCROOT,需要将其设置为EPOC32的上一级目录。

将pysis复制到EPOCROOT所指向的目录,然后使用subst将EPOCROOT所指向的目录,虚拟成一个独立的盘符,命令如下

subst v: C:\S60\devices\S60_5th_Edition_SDK_v0.9\

最后一步,对py文件进行打包,命令如下

C:\>V:

V:\>cd py2sis

V:\>py2sis.py --uid=0x01234567 battery.py –sdk30 –leavetemp

Creating SIS for SDK3.0 and later
Processing template V:\py2sis\build\00000000.rss.template
Processing template V:\py2sis\build\Icons_aif.mk.template
Processing template V:\py2sis\build\PyTest.cpp.template
Processing template V:\py2sis\build\PyTest.rss.template
Processing template V:\py2sis\build\PyTest_reg.rss.template
Processing template V:\py2sis\build\app.mmp.template
Compiling...
Done.
makesis V:\py2sis\temp\battery.pkg V:\py2sis\battery.sis
Unique vendor name not found.

Note: Sign the created SIS file prior installation (tool "SignSIS")

打包成功后我们还需要到https://www.symbiansigned.com/app/page,对battery.sis进行签名。

打开https://www.symbiansigned.com/app/page页面选择Open Signed Online,输入测试手机的IMEI,Email,选择好做需要的权限,和battery.sis文件,点击send,这时候网站会发一个确认函到刚才输入的Email地址里面,我们需要点击发送过来的地址进行确认,确认后系统会对上传的battery进行签名,签名完成后会发送一封电子邮件提示下载,签名好的应用,至此我们就可以将签名好的battery.sis安装到手机上运行了。

可能遇到问题,在是py2sis进行打包的时可能会提示有某些路径找不到,出现该提示的时候,只需要将S60 SDK所在根目录中的epoc32目录复制到EPOCROOT所指向的目录,就可以解决该问题了。

以上这个方法在Nokia S60第三版系统上测试,通过第五版还未通过测试,这可能和我们用的py2sis版本有关。

聚合内容