九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

【转载】ubuntu搭建ssh服务器

昨天的文章里,我记录了搭建一个小型 Ubuntu 服务器的过程,相信如果各位按照我写的做了,您的 Ubuntu Server 已经可以跑起来了。不过,现在这个系统只是个基本的系统,算不上服务器,因为什么都没法做。如果需要让它行使服务器的职能,还需要给它装一些软件。

因为我需要的服务器最终会被“抛弃”在实验室的某个角落,无论是后期设置还是维护的需要,都必须安装一个远程管理的工具。在 Linux 系统中,不二的选择就是 openssh 了。在 Ubuntu 中安装 openssh 实在是再简单不过的一件事情了,下面的内容也只是纯记录,给我这个菜鸟备个份。如果是高手直接绕过就好。

安装前的准备

Ubuntu 之所以好用,就是因为它继承了 debian 的 apt 系统,这一点相信您在昨天装系统的教程中已经感受到了。但是 apt 需要依赖网络,昨天我们装好的系统是暂时上不了网的,我们需要先设置一下。

首先,激活服务器的网卡,命令如下:

sudo nano /etc/network/interfaces

在 interfaces 中添加以下内容:

auto eth0
iface eth0 inet static
address 202.113.235.181
netmask 255.255.255.0
gateway 202.113.235.1

这其中,斜体部分标注的 IP 地址是我服务器的设置,您需要根据您的具体情况修改。当然,如果您的服务器使用的是 DHCP 来分配 IP 地址,只需要写上 iface eth0 inet dhcp 就可以了,无需设置 address/netmask/gateway。

然后,修改 resolv.conf 配置 DNS 服务器:

sudo nano /etc/resolv.conf

添加您的 DNS 服务器地址:

nameserver 202.113.16.10
nameserver 202.113.16.11

完成后,重新启动 networking 服务:

sudo /etc/init.d/networking restart

这样应该就可以连通网络了。如果您使用的是 ADSL,可能还需要装上 pppoe 之类的东西,考虑到服务器很少用这样的配置,这里就不讨论了,需要的话可以在网上查找。

安装和设置 OpenSSH Server

Ubuntu 下安装 OpenSSH Server 是无比轻松的一件事情,需要的命令只有一条:

sudo apt-get install openssh-server

随后,Ubuntu 会自动下载并安装 openssh server,并一并解决所有的依赖关系。当您完成这一操作后,您可以找另一台计算机,然后使用一个 SSH 客户端软件(强烈推荐 PuTTy),输入您服务器的 IP 地址。如果一切正常的话,等一会儿就可以连接上了。并且使用现有的用户名和密码应该就可以登录了。

事实上如果没什么特别需求,到这里 OpenSSH Server 就算安装好了。但是进一步设置一下,可以让 OpenSSH 登录时间更短,并且更加安全。这一切都是通过修改 openssh 的配置文件 sshd_config 实现的。

首先,您刚才实验远程登录的时候可能会发现,在输入完用户名后需要等很长一段时间才会提示输入密码。其实这是由于 sshd 需要反查客户端的 dns 信息导致的。我们可以通过禁用这个特性来大幅提高登录的速度。首先,打开 sshd_config 文件:

sudo nano /etc/ssh/sshd_config

找到 GSSAPI options 这一节,将下面两行注释掉:

#GSSAPIAuthentication yes
#GSSAPIDelegateCredentials no

然后重新启动 ssh 服务即可:

sudo /etc/init.d/ssh restart

再登录试试,应该非常快了吧 :)

利用 PuTTy 通过证书认证登录服务器

SSH 服务中,所有的内容都是加密传输的,安全性基本有保证。但是如果能使用证书认证的话,安全性将会更上一层楼,而且经过一定的设置,还能实现证书认证自动登录的效果。

首先修改 sshd_config 文件,开启证书认证选项:

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

修改完成后重新启动 ssh 服务。

下一步我们需要为 SSH 用户建立私钥和公钥。首先要登录到需要建立密钥的账户下,这里注意退出 root 用户,需要的话用 su 命令切换到其它用户下。然后运行:

ssh-keygen

这里,我们将生成的 key 存放在默认目录下即可。建立的过程中会提示输入 passphrase,这相当于给证书加个密码,也是提高安全性的措施,这样即使证书不小心被人拷走也不怕了。当然如果这个留空的话,后面即可实现 PuTTy 通过证书认证的自动登录。

ssh-keygen 命令会生成两个密钥,首先我们需要将公钥改名留在服务器上:

cd ~/.ssh
mv id_rsa.pub authorized_keys

然后将私钥 id_rsa 从服务器上复制出来,并删除掉服务器上的 id_rsa 文件。

服务器上的设置就做完了,下面的步骤需要在客户端电脑上来做。首先,我们需要将 id_rsa 文件转化为 PuTTy 支持的格式。这里我们需要利用 PuTTyGEN 这个工具:

点击 PuTTyGen 界面中的 Load 按钮,选择 id_rsa 文件,输入 passphrase(如果有的话),然后再点击 Save PrivateKey 按钮,这样 PuTTy 接受的私钥就做好了。

打开 PuTTy,在 Session 中输入服务器的 IP 地址,在 Connection->SSH->Auth 下点击 Browse 按钮,选择刚才生成好的私钥。然后回到 Connection 选项,在 Auto-login username 中输入证书所属的用户名。回到 Session 选项卡,输入个名字点 Save 保存下这个 Session。点击底部的 Open 应该就可以通过证书认证登录到服务器了。如果有 passphrase 的话,登录过程中会要求输入 passphrase,否则将会直接登录到服务器上,非常的方便。

好了,今天就写到这,以后逐步再写 AMP,Proftpd 和 Squid 的安装和设置。

阅读全文....

【转载】linux下的samba安装及配置

以前配置samba一直是我的噩梦,甚至一度放弃samba,直接使用ssh+winscp来管理文件,今天找到一篇好文,顺利配置成功,感谢原作者。

在Ubuntu中设置samba共享可读写文件夹 收藏
首先当然是要安装samba了,呵呵: 代码:
sudo apt-get install samba sudo apt-get install smbfs
下面我们来共享群组可读写文件夹,假设你要共享的文件夹为: /home/ray/share 首先创建这个文件夹 代码:
mkdir /home/ray/share chmod 777 /home/ray/share
备份并编辑smb.conf允许网络用户访问 代码:
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf_backup sudo gedit /etc/samba/smb.conf
搜寻这一行文字 代码:
; security = user
用下面这几行取代 代码:
security = user username map = /etc/samba/smbusers
将下列几行新增到文件的最后面,假设允许访问的用户为:newsfan。而文件夹的共享名为 Share 代码:
[Share] comment = Shared Folder with username and password path = /home/ray/share public = yes writable = yes valid users = newsfan create mask = 0700 directory mask = 0700 force user = nobody force group = nogroup available = yes browseable = yes
然后顺便把这里改一下,找到[global]把 workgroup = MSHOME 改成 代码:
workgroup = WORKGROUP display charset = UTF-8 unix charset = UTF-8 dos charset = cp936
后面的三行是为了防止出现中文目录乱码的情况。其中根据你的local,UTF-8 有可能需要改成 cp936。自己看着办吧。 现在要添加newsfan这个网络访问帐户。如果系统中当前没有这个帐户,那么 代码:
sudo useradd newsfan
要注意,上面只是增加了newsfan这个用户,却没有给用户赋予本机登录密码。所以这个用户将只能从远程访问,不能从本机登录。而且samba的登录密码可以和本机登录密码不一样。 现在要新增网络使用者的帐号: 代码:
sudo smbpasswd -a newsfan sudo gedit /etc/samba/smbusers
在新建立的文件内加入下面这一行并保存 代码:
newsfan = "network username"
如果将来需要更改newsfan的网络访问密码,也用这个命令更改 代码:
sudo smbpasswd -a newsfan
删除网络使用者的帐号的命令把上面的 -a 改成 -x 代码:
sudo testparm sudo /etc/init.d/samba restart
最后退出重新登录或者重新启动一下机器。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/joliny/archive/2008/07/13/2646420.aspx

 

另外还有两篇备用的:

第一篇:

root根用户进行操作,如果您不是,请在每条命令前加上sudo

步骤1:安装samba
#apt-get install samba
#apt-get install smbfs

步骤2:添加linux用户
#useradd user1
     //添加用户名user1
#passwd user1 //
给用户名user1添加密码
#mkdir /home/user1 //
建立user1home目录,如果不用这个用户名来登陆linux,此步骤不是必需
#chown -R user1:user1 /home/user1
   //user1home目录设置好权限

步骤3:给samba服务器添加用户
说明:登陆samba的用户必须已经是linux中的用户
#smbpasswd -a user1 //
添加并给user1设置samba密码

步骤4smb.conf设置
#cd /etc/samb //
进入设置目录
#mv smb.conf
 smb.conf.bak //做好备份,直接将系统默认配置文件改名
#vim smb.conf //
建立和配置smb.conf文件

[global]
workgroup=x1 //X1为你局域网中的工作组名
server string=x2 //x2
为你linux主机描述性文字,比如:samba server
security=user //samba
的安全等级,user代表需要输入用户名和密码,改成share则不需要输入用户名和密码

[x3] //方框号中的x3这个名字可以随便取,只是在win的网上邻居中显示的共享文件夹名
path=/home/x4 //x4
为你要共享的文件夹名,在共享前还要建立这个文件夹,并设好权限以便访问,下面会说明。
valid users=user1 //
这个x4共享目录只允许user1这个用户进入
public=no
     //no表示除了user1这个用户,其它用户在进入samba服务器后看不见x4这个目录,如果为yes,虽然能看见x4这个目录,但除了user1这个用户能进入这个目录,其它人进不了。
writable=yes
   //允许user1x4目录中进行读和写操作,反之no

//存盘退出
#testparm //
检查一下语法错误,比如拼错

步骤5:建立共享目录
#mkdir /home/x4
#chown -R user1:user1 /home/x4 //
因为是root建立的目录,其它用户只有读的权限,所还得把权限改一下。当然也可以简单的用#chmod 777 /home/x4。还有个问题就是共享里目录的文件如果有些能访问有些不能访问,那肯定也是权限的问题,进入/home/x4,直接#chmod 777 *来解决。

步骤6:重启samba服务
#/etc/init.d/samba restart

设置samba服务要注意以下两点(即两个两次):
1.
添加两次用户:一次添加系统用户#useradd user1;再一次是添加samba用户#smbpasswd -a user1;
2.
设置两次权限:一次是在smb.conf中设置共享文件夹的权限:再一次是在系统中设置共享文件夹的权限#chmod 777 文件夹名。

 

按照楼主的做法设置, WINDOWS登陆到samba的时候报错, 显示如//10.x.x.x 无法访问, 你可能没有权限使用网络资源.... 这样的错误. 请问这是怎么回师?

如果设置passdb backend = tdbsam 则可以访问

 

passdb backend = tdbsam
tdbsam的时候,密码文件是放在 /var/lib/samba/passdb.tdb

而没有这句,当然也就找不到SMB用户和密码,即提示没用权限了。

 

第二篇:

#rpm -q samba     //查看SAMBA是否安装,如未安装,则执行下列安装

#rpm -ivh  samba-3.0.25b-0.4E.6.i386.rpm

#vi /etc/services    //查看以netbios开头的是否可用,必须要全部可用

 

 

  //linux防火墙要关闭

#ls /etc/samba //无smbpasswd文件

#smbpasswd -a tom //创建tom用户

#ls /var/log/samba //smb服务器的日志文件

#vi /etc/samba/smb.conf //编辑smb服务器的主配置文件

 

  Workgroup = WORKGROUP //windows工作组名

  server string = samba server //samba服务器简要说明

  hosts allow = 192.168.1. 192.168.0. 127. //设置允许访问的子网,默认都允许,可不设置

  hosts allwo = client1,alarm.com,192.168.16. EXCEPT 192.168.16.4 //举例说明

  security = user //设置安全级,默认为user。五个级别分别为"share,user,server,domain,ads"

  interfaces = eth0 //多网卡SAMBA服务器设置监听的网卡

  interfaces = 192.168.16.177/24 //举例说明

  wins support = yes //设置将samba服务器作为wins服务器,默认不使用

 

  //wins服务器由微软开发,功能是将NetBIOS名称转换为对应的ip地址

  username map = /etc/samba/smbusers //去掉前面的;号,用于用户映射

  然后编辑文件/etc/samba/smbusers,将需要映射的用户添加进去,格式为

  单独的linux用户 = 要映射的windows用户列表

  例: test = alarm back //test用户对应windows下的alarm和back两个用户

  encrypt password = yes 或 no //yes表示采用加密方式发送密码,no为不采用

  若此项为no,则windows系统必须响应的修改注册表项,注册表文件存放在/usr/share/doc/samba-2.2.7a/docs/Registry下

 

  [homes] //设置共享目录

  comment = Home Directories //简要说明

  browseable = no //是否允许用户浏览所有人的主目录

  writable = yes //是否允许用户写入自己的主目录

 

  [share] //设置一个共享目录

  comment = Samba's share Directory //简要说明

  read list = test //只读用户或组

  write list = @share //可写用户或组

  path = /home/share //共享文件夹目录路径

 

  //设置共享目录后需要做以下操作

  1.root登录,使用命令groupadd share 建立share组,并用usermod -g share abc命令将abc用户添加到share组

  2.mkdir /home/share在/home下建立目录share

  3.chown :share /home/share设置share目录所属组为share组,chmod 777 /home/share 设置share组对该目录有最大权限

  :wq //保存退出

 

 

  #testparm //测试smb.conf文件是否有语法错误

  #su - //切换root用户

  #service smb start restart stop //启动 重启 停止samba服务器

  #ntsysv //设置samba服务器开机启动

阅读全文....

【转载】jdk-6-doc安装失败的解决办法

去这个地址

http://java.sun.com/javase/downloads/

下载 jdk-6-doc.zip(英文) 或者 jdk-6-doc-ja.zip(日文) 包(二者选一即可)

sudo chown root:root jdk-6-doc.zip 改变文件所有者为root

cp jdk-6-doc.zip /tmp 下 然后再执行安装程序

/tmp 目录下面的东西会在系统关闭的时候被删除,所以如果想保存jdk-6-doc.zip请把它备份到其他位置

 

http://forum.ubuntu.org.cn转载过来的

阅读全文....

简单图形编程的学习(1)---文字 (small basic实现)

简单图形编程的学习(1)---文字 (small basic实现)

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

一、   全部简单图形编程的学习说在前面的话

      此系列文章均假设读者已经具备一定的对应的程序编写知识,无论是最简单的small basic,还是因为常用而被人熟知的Windows GDI,或者是Linux下用的更多的Qt(一般我用PyQt),甚至是现在国内知道的人并不多的Android,我都不准备讲太多基础的语法,或者与平台相关的太多背景知识,这些靠读者先行学习,我仅仅准备在自己学习的过程中找点乐子:)看看我用一些简单的接口都能想出干什么事情,然后展示给大家看看,图形程序实在是最好展示的一类程序了,不像其他程序一样,哪怕我讲了一堆的boost,真正见识到boost强大的又有几个呢?-_-!要知道,今天起,所有程序都是窗口程序,不再是命令行!!!!人类用了多久才走到这一步我不知道。。。。我用了25.......(从我出生算起)或者1年(从工作开始)

       另外,想要看怎么编写窗口应用程序的就不要走错地方了,这里不是想怎么描述怎么使用一个又一个的控件,这里都是讲绘图的-_-!

 

二、   谈谈Small Basic

由于今天是第一篇,所以谈谈Small Basic

本人所用small basic是最新的0.5(到2009-8-8今天为止),谈到small basic我又想多说几句,作为一个如此简单的语言,small basic的强大让人印象深刻,不仅仅体现在其对语法,图形接口的简化上,并且这也是唯一一个目前我推荐给女朋友而她能主动学习的一种语言(Python都太复杂)。。。。。。。。。呵呵,题外话了,个人感觉,不作为专业程序员,(即便是真的准备做专业程序员)以此入门,感受一下程序应该是什么样子,也是很好的事情,要知道,今天多少的大师级人物,其实当年还不是在APPLE或者PC上鼓捣着Basic啊,不要因为其名叫basic,(甚至是small basic)就鄙视它:)编程的思维都是一样的。最最不要认为的就是basic学了没有用,最近Google都推出了用于Android平台使用的basic语言,名为Simple:)Small Basic语言可以从我以前的文章《初学编程该怎么学?——对初学者程序设计语言学习的思考(1》《初学编程该怎么学?——对初学者程序设计语言学习的思考(2)》中了解一下,MSIntroduce文档也真是初学者的福音。(因为习惯于专业术语,我实在没有办法将程序语言讲的如此通俗)。最后,我一直被MS一句简单描述Small Basic的语言所打动。。。“Microsoft Small Basic is a project that’s aimed at bringing “fun” back to programming.”相信当过一年程序员的兄弟姐妹们都会有和我同样的感动。。。。bringing “fun” back to programmingthat’s our aim.

另外,微软还未Small Basic提供了一种新的publish方式,虽然这样做就会导致所有的程序完全开源了(呵呵),那就是直接上传到MS的网站上,然后给你一个唯一的标识,任何人都可以再Small BasicIDE中通过Importcode取出你的代码来看。网页上也提供了查看方式,所以,以后复杂点的值得展示的Small Basic的代码,我都会pubish并提供code编号。那样,你就可以通过多种方式获取到我的代码。

 

三、   进入今天的正题,首先是文字

文字好像都不像是图形编程中应该学习的东西,但是别忘了,文字可都是由象形文字发展过来的。。。中文至今还是象形文字呢,文字在远古的时代可本来就是图形啊,为啥学习图形编程的时候不要学习怎么显示文字啊?呵呵,前面的都是废话,其实你编点啥程序都会碰到需要在图形中显示文字的情况,所以我们先来看看文字的显示。另外,其实在显示文字的时候,假如需要对文字的显示进行设置,也能学到很多普通图形的设置方式,这点以后就能看到

 

四、   Small Basic的文字显示

其实MS的《Introducing Small Basic》都没有描述到图形窗口下的文字显示的接口。。。。。我还是自己通过intellisense自己找到的。。。。有两个函数,DrawTextDrawBoundText呵呵,从简单的开始,一个最最简单的文字显示程序:

small basic graphic ex1:

GraphicsWindow.Show()

GraphicsWindow.DrawText(0,0,"Hello World In Graphic Window")

GraphicsWindow.DrawBoundText(0, 100, 100, "Hello World In Graphic Window")

显示效果如插图1

DrawBoundText的效果很有意思,多只指定了文字的宽度,并且为文字自动换行,换行的时候还按照单词分割,这在一般的程序中就是直接截断了。。。。(如Window自己普通的GDI),参数没有什么好说的,就是指定文字显示的左上角坐标和内容。

对于文字总还是要有点控制能力的,Small Basic也有。见下例:

small basic graphic ex2(Code: KXK447)

GraphicsWindow.show()
GraphicsWindow.BackgroundColor = "midnight"
GraphicsWindow.DrawText(0,0,"Hello World In Graphic Window")
GraphicsWindow.BrushColor = "Red"
GraphicsWindow.DrawText(0,50,"Hello World In Graphic Window")
GraphicsWindow.FontSize = 30
GraphicsWindow.DrawText(0,100,"Hello World In Graphic Window")
GraphicsWindow.FontBold = 1
GraphicsWindow.DrawText(0,150,"Hello World In Graphic Window")
GraphicsWindow.FontItalic = 1
GraphicsWindow.DrawText(0,200,"Hello World In Graphic Window")
GraphicsWindow.FontName = "新宋体"
GraphicsWindow.DrawText(0,250,"Hello World In Graphic Window")

 

由于这些API都没有在文档中说明,我都是自己试出来的,这些大概就是我能找到的Small Basic中能改变文字显示的接口了。分别是几个FontX属性和Brush的颜色。显示效果如插图2.

 

最后,关于文字,来个复杂点的示例。。。呵呵,即便仅仅只有文字,也可以让程序比较炫。

small basic graphic ex3(Code:GDS718)

GraphicsWindow.show()
GraphicsWindow.BackgroundColor = "midnight"
gw = GraphicsWindow.Width
gh = GraphicsWindow.Height
While ("True")
  
Program.Delay(100)
  
GraphicsWindow.BrushColor = GraphicsWindow.GetRandomColor()
  
GraphicsWindow.FontSize = Math.GetRandomNumber(100)
  
GraphicsWindow.FontBold = Math.GetRandomNumber(2) - 1
  
GraphicsWindow.FontItalic = Math.GetRandomNumber(2) - 1
  
GraphicsWindow.DrawText(Math.GetRandomNumber(gw),Math.GetRandomNumber(gh),"Hello World")
EndWHile

 

考虑到我们只能用文字接口,并且仅仅用了那么几行代码,效果已经比较炫了。见插图3.

 

 

 

插图1:

 

插图2:

 

插图3:

 

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

回归游戏的世界,简单图形编程学习的开始

回归游戏的世界,简单图形编程学习的开始

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

这个系列是我对游戏开发的重新认识导致的。。。。按《那是飞扬的青春—小评《DOOM启示录》》中所描述过的,以前其实我排斥过游戏开发,所以选择了服务器端程序的开发。但是,慢慢的,从Small Basic画几个图形开始,加上看了《DOOM启示录》。。。。我开始有了新的认识,既然血液中流着游戏的气息,既然到目前为止一辈子就一直和游戏没有办法脱离关系,为啥还要这样强制让自己痛苦呢?必要的时候,还有游戏界开发的宗师的话安慰我,凡是沉迷于游戏的人,那都是家庭原因.......呵呵,说来也是,以前游戏浪费了我很多时间,导致现在感觉时间浪费的不值,但是想想,那时候我不玩游戏我会干什么?真的就会天天耐下心来学习?没有到那一步之前,那是不可能的,起码,那时候,游戏还给了我快乐,那就足够了。人一辈子,快乐的时候又能多少呢?也许那些因为家庭原因的孩子,在没有游戏的时候,会变得比现在更加恶劣。。。起码他们现在还能安静的沉迷在游戏的虚拟世界中-_-!虽然感觉这样的说法实在是有点自欺人。。。。。

既然这样想了,那么就很明确了,真正的游戏开发还是客户端最能体会,服务器这个曾经用来远离游戏的选择就不那么合适了,客户端。。。。从图形编程学起吧。。。。呵呵,又是一个新的领域,我喜欢。

个人学习,总是学习多路并进。。。。对于同一个主题的反复学习,有助于自己的思考,同时也发现了很多不同的思维方式,就像以前学习算法的时候,考虑用C++,python,lua,bash来完成同一个算法一样,现在简单的图形编程学习我还是希望用四种方式来完成。。。。。C++的Windows GDI/GDI+,Python/C++的PyQt/Qt,JAVA的Android,最后,也许在恰当的时候加上small basic,呵呵,之所以加上small basic,纯粹是因为它也算是为我重新发现编程乐趣的语言:)

对了,这里所谓的简单,就是指除了DirectX和OpenGL意外的,系统远程的图形接口绘图的方式完成图形的绘制,DirectX和OpenGL自然是肯定要学的,但是,我希望在学习了这些简单的以后。虽然,我很确定的知道,对于游戏开发来讲,DirectX在Windows下会几乎完全代替GDI的使用,OpenGL的强大功能也足以使Qt,Android的其他绘图方式黯然失色,但是,不知道为啥,我还是想好好的学习一下这些系统/框架的原生绘图方式。其实,从small basic中一些简单,但是让人惊艳的程序中我体会到,其实,最最简单的图形技术,也能产生让人直呼惊艳的程序,重要的是你使用技术的思想。。。。。(参考我以前关于Small basic的文章:《初学编程该怎么学?——对初学者程序设计语言学习的思考(2)

另外,这次不像以前学习数据结构一样了,将3,4种语言的程序同时放在一起,呵呵,那是种自己比较痛快的方式,但是估计不希望了解那么多语言的人看到估计是无用噪音大于有用信息的,就图自己的痛快了,这一次,我虽然还是用几种语言/框架去实现也许一样的功能,但是,我还是为每个单独建立文章 ,然后在文章中建立链接,让有用的人查看吧,这样做,我可能累点,因为也许我的文章中主要的思路都是一样的(我就需要拷贝几份),不一样的仅仅是源代码和截图而已。这样做的好处就是,我不必等几种语言实现的都出来了才可以发文章。

JAVA的Android实现放在这里属于比较大胆的行为,毕竟其实我对JAVA和Android了解的都比较有限,在任何时候我都会实话说,其实本质上我仅仅是一个靠C++吃饭的网络游戏服务器端程序员而已,其实踏足图形编程领域(是不是说的太大了-_-!)都是因为自己的兴趣使然,没有办法。

另外。。。其实,我老是学那么多语言,框架。。。最近甚至因为Android还学了JAVA。。。。。个人感觉,学习C++的人一般不会学JAVA。。。。。就像我学了VIM就不想学Emacs一样。。。呵呵,但是。。。Google的号召力嘛,因为Google app以前只能用Python来开发,我耐心的学习了Python,(其实也不全是,还有当时学习完LUA对脚本语言很感兴趣的原因,但是这也是很大的原因吧),现在Google的Android手机只能用JAVA开发(其实最近用C++开发的NDK也出来了),那么我就学习JAVA。。。。。唉。。。何苦呢。。。。但是,不学点东西也没有啥事干,不是嘛?工作虽然辛苦,但是能学到的新东西毕竟少了,自己不学习,工作后干点啥呢?学习一种新的语言,踏入一个新的领域那是多么让人愉快的事情啊,一路走来,我不就是因为这样才走上了开发程序的道路吗?

学的太多太杂,有很大的贪多嚼不烂的风险,但是作为程序员,多了解几种语言还是有助于开拓思路的,并且,我能够在正确的时候,选择我认为最正确的语言去做一件事情。举例而言,没有学bash之前,在Linux下我用Python作批量运行程序的脚本语言用(其实也没有什么不好),但是学了bash后,可以用更简洁的代码,更快的完成同样的事情。(虽然再复杂点的程序bash就是噩梦),学过bash的时候,回头来回看到makefile文件的语言是何其的亲切,再也不是以前认为的 $乱飞了,即便是看到VS2005中的工程定义,那些宏$()的样子也是如此的熟悉。Python中发现的很多有趣性质,我感觉的C++想做但是不敢做的事情,在学习JAVA的时候再次碰到,也就习以为常了,等等等等,太多太多,即便是Windows API中以前很多看起来非常古怪的使用方式,在开发多了程序后都能感觉正常了(也理解了MS的苦衷,很多时候其实是实现手段的限制),同时也能想到,假如这个接口是Python实现的,那就该怎样简单啊。。。呵呵,其实说了那么多,都仅仅是为自己辩护而已,其实我认为总有一天我会在某个领域深入的学习下去,但是,那一天还没有到来之前,多学点东西,不是能让我更早的发现那样一个领域吗?毕竟我还只工作一年多一点,太早盲目的为自己定下方向,也许不见的会多么正确,就像我直到大学毕业后,才发现我真的是准备走上程序开发的道路,一共用了20多年,那么我又怎么能在仅仅进行程序开发1年多就能发现我准备在程序开发中选择什么样的道路呢?呵呵,在自己还没有老去的时候,随性而去吧,趁自己还对那么多新鲜事物感兴趣并且精力比较旺盛的时候去多学点东西吧,哪怕以后我不会再用到。。。。当你学习你感兴趣的事情时,学习过程,本身也是一件很愉快的事情,不是吗?

 

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

OPhone/Android的学习(3)—再熟悉几个常用的Widget

OPhone/Android的学习(3)—再熟悉几个常用的Widget

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

 

一、   综述

其实相对来说,学习一个UI库(其实AndroidAPI最重要的就是这一部分,其他的可以用原有的JAVA标准库)最最主要的是了解其大致框架,并不一定要了解了每一个控件/Widget的用法,因为所有的控件/Widget都是在同样的框架下展开的,了解了一种两种,其他的需要用到的时候看看文档,基本也就知道怎么用了,可以等到实际开发的时候再去学习。整体的框架大概需要了解哪些呢?包括整体程序的执行流程,控件/Widget的创建,销毁流程,消息/事件 的响应及处理方式等,知道了这些,其他的都可以算是枝叶末节。

前面几节Android的学习虽然非常基础,但是都是围绕着整体框架的,其实一般来说一个Hello Wolrd就已经说明了一个程序的一半,这里,再通过几个Widget来熟悉一下上述流程。解释就不多说了,具体的东西参考文档。

 

 

二、   Message:

刚开始我一直在找Android弹出类似Windows MessageBox的对话框的办法,后来找到两种:

example1

package com.JTianLing;

 

import android.app.Activity;

import android.content.Context;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.Toast;

 

public class DevXMLUI extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        LinearLayout layout = new LinearLayout(this);

       

        Button button = new Button(this);

        button.setText("I'm So great Button");

        button.setOnClickListener(new OnClickListener(){

           @Override

           public void onClick(View v) {

            Context context = getApplicationContext();

            CharSequence text = "Hello toast!";

            int duration = Toast.LENGTH_SHORT;

 

            Toast toast = Toast.makeText(context, text, duration);

            toast.show();

           }

        });

        layout.addView(button);

        setContentView(layout);

    }

}

运行效果见插图1,点击按钮的时候弹出一个Toast,为啥叫这个,我也不明白。类似于一个Notice的效果,可以自动消隐。

 

另外一种比较正规,也就是通过对话框,只不过Android里面没有类似MessageBox一样使用简单的对话框,相对来说复杂一点。

Example2:

package com.JTianLing;

 

import android.app.Activity;

import android.app.AlertDialog;

import android.app.Dialog;

import android.content.DialogInterface;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;

 

public class DevXMLUI extends Activity {

    static final int DIALOG_PAUSED_ID = 0;

    @Override protected

    Dialog onCreateDialog (int id)

    {

       AlertDialog.Builder builder = new AlertDialog.Builder(this);

       builder.setMessage("Are you sure you want to exit?")

              .setCancelable(false)

              .setPositiveButton("Yes", new DialogInterface.OnClickListener() {

                  public void onClick(DialogInterface dialog, int id) {

                     DevXMLUI.this.finish();

                  }

              })

              .setNegativeButton("No", new DialogInterface.OnClickListener() {

                  public void onClick(DialogInterface dialog, int id) {

                       dialog.cancel();

                  }

              });

       AlertDialog alert = builder.create();

       return alert;

    }

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        LinearLayout layout = new LinearLayout(this);

        

        Button button = new Button(this);

        button.setText("I'm So great Button");

        button.setOnClickListener(new OnClickListener(){

           @Override

           public void onClick(View v) {

              showDialog(DIALOG_PAUSED_ID);

           }

        });

        layout.addView(button);

        setContentView(layout);

    }

}

还是单击那个伟大的按钮,才能弹出对话框,效果如插图2

至于这个复杂程序,我是比较有意见的。。上面那一大堆程序,其实在Windows这种已经是宇宙中最复杂的操作系统中实现都只需要12句话。。。。唉。。。。曾经多么常用的MessageBox啊。。。我甚至看到最极端的使用情况----一次我们游戏在一个玩家的机器上就是跑补起来,甚至连日志都打不出来,总监于是在每隔几行弹出一个MessageBox在玩家的机器上跟踪程序运行情况-_-!

暂告一段落

至此,对于一般的AndroidWidget不再进一步的深入学习,原理上基本上差不多,碰到需要的时候再去翻文档学习就好了。。。。毕竟我是来尝鲜的-_-!用了我45天的下班时间熟悉了一下Android,本质上。。。我还是个靠C++开发网络游戏服务器端程序的程序员,虽然由于工作需要,又碰巧刚开始工作的时候开发过客户端,所以经常到客户端客串编写一些与服务器交互性比较强的模块。

以后,考虑学习自己感兴趣的东西,对于我来说基本也就两部分,作为服务器端程序员,我关心网络,作为开发游戏的程序员我关心图形接口,这些以后就不放入这个系列,另开一个系列。

 

 

 

插图1:

插图2:

 

 

 

write by 九天雁翎(JTianLing) -- www.jtianling.com



阅读全文....

OPhone/Android的学习(2)—从分析Eclipse自动生成的代码到以XML控制UI

OPhone/Android的学习(2)—从分析Eclipse自动生成的代码到以XML控制UI

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

一、   综述

XML来控制UI我们已经不陌生了,这样的方式比硬代码方式(即将UI的控制完全放在代码中)更加灵活,更加易于管理及改变。特别是在用C++编写UI的时代,这简直就是突飞猛进似的进步。虽然XML也有很多缺点,并因此被人诟病,但是其对UI控制方面带来的好处确实是非常实在的,并且是今日非常流行的网页技术AJAX的核心组成部分之一(X就代表XML)。事实上,不仅是网页技术的应用,用过CEGUI这样著名开源UI的人也能知道,XML对界面的控制简直就是其UI控制的核心。再辅以LUA/Python脚本语言处理界面逻辑及事件响应,对界面层及其逻辑的开发效率可以比用C++这样的语言快上N倍。。。。。

Android提供了一种比较原生的方式来让我们使用XML控制界面,并且配置了很多可以用XML控制的界面Widget属性,我们不需要去了解XML解析和配置的一套系统,(什么SAX,DOM,我们都不用去管了)Google为我们将所有额外复杂的功能都做了,我们需要做的就是编写一个文本文件,然后实现我们想要的功能!虽然XML这样的所谓标记文本文件其实并不是太直观。。。。。(被人诟病的地方)

 

二、    分析ADT生成的HelloWorld

从一个HelloWorld程序来看,ADT生成的程序是比较复杂的了。但是这里不再排斥XML引入带来的复杂性(仅仅是还不了解的时候会这样感觉),重新建立一个程序,并审视我们的程序。

程序由src,gen,res三个主要的目录组成。

1.      res目录下面就是资源:

从我们今天的主题最相关的资源部分入手,因为XML文件在OPhone/Android程序中属于资源。

资源又分成三个组成部分:

drawable

可以绘制的元素,初次生成的程序中带有一个icon.png的图标,这个图标就是最后我们生成的应用程序在OPhone/Android中的图标。

layout

XML文件组成,如其名,用XML文件在此描述了我们的应用程序的框架构成。初次生成的程序中带有一个main.xml的文件。双击此文件打开的话会进入ADT的可视化XML编辑器,这样可以使的编辑XML文件更为容易一点,但是我们直接来看看源代码,毕竟还是比较简单的:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

<TextView 

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:text="@string/hello"

    />

</LinearLayout>

 

对于完全不懂XML语言的人了解HTML也会有帮助,无非就是以一堆尖括号括起来的一堆属性而已(XML算不上完全的编程语言,虽然可以完成一些这样的任务)。

首先,我们可以看到,此程序中有一个LinearLayout,一个TextView,这些都是很熟悉的东西,不熟悉的看看此系列前面的文章。

OPhone/Android的学习(1)—初步知识,TextView,Button,Layout及事件响应

原来,一个默认生成的程序中已经包含了一个LinearLayout了。。。害得我以前找那么久。它有3个有效的属性:分别是

    android:orientation="vertical"

    android:layout_width="fill_parent"

android:layout_height="fill_parent"

 

意思很明确,方向是“vertical垂直的,大小都填充父窗口。android表示的是类似命名空间的概念。

xmlns:android那一句是说明此程序用的是通常的android的命名空间属性,在Google的文档中明确描述道:

The outermost tag in every Android layout file must have this attribute.即最外层的layout文件必须有此属性。

TextView其他属性与layout类似,text属性表示的是TextView的文字。这里的使用就如同我们用TextView对象的setText方法一样

@string/hello表示的意义见下面关于values的描述。

 

values

       也是由XML文件构成,如其名所述,这里定义了一些我们用到的values,不过这里的values更加像平时我们在编程语言中用到常量,类似C++中的const,JAVA中的final

       目前只有一个strings.xml文件,双击也会进入ADT特有的XML可视化编辑器,使用非常方便,这里不多描述了,我们看看源码:

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

<resources>

    <string name="hello">Hello World, DevXMLUI!</string>

    <string name="app_name">DevXMLUI</string>

</resources>

 

内容很简单,我们有两个resources,分别是名为helloapp_namestringstring的内容如上面的黑体字描述的内容。我们可以在这里方便的修改,统一的管理,当程序规模扩大的时候才能看到这样的好处,那时候在这里修改一个string比去程序里面漫天的查找一个字符串要容易的多。这里的资源怎么被其他部分利用呢?在其他资源中利用的方式其实我们已经看到过了。TextView的属性android:text="@string/hello" 即是使用了string类型的名为hello的字符串,从strings.xml中我们可以看到,就是Hello World, DevXMLUI!了。

详细的资源的描述可以从Google的在线文档中查看:Resources and Internationalization

这里的资源怎么被程序利用呢?这是个问题。包括layout怎么被程序利用其实我们也遗漏了。那么我们再来看源码。

 

2.      src目录下面就是源代码:

src下面的源码将是我们主要的程序代码编辑区。

目前所有的程序代码如下

package com.JTianLing;

 

import android.app.Activity;

import android.os.Bundle;

 

public class DevXMLUI extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

    }

}

 

程序主要逻辑的意思我们应该了解了,这里大概再描述一下,DevXMLUI类继承自Activity,属于整个程序的代表类(类似MFC中的CApp),ActivityonCreate会在程序创建的时候自动调用,(类似MFC中窗口的OnCreate)。setContentView的意思是指定此程序的内容显示。我们以前也用过了,不过那个时候用的是直接创建的TextView对象,这里是R.layout.mainR.layout.main指的是什么呢?看下节的描述。

 

gen表示是Google为我们自动生成的代码

Google的文档明确的表示不希望我们手工改动此目录下的代码,此代码都有程序自动生成(在Eclipse中及时生成,不是IDE时在调用aapt时生成),目前所有的代码如下;

 

/* AUTO-GENERATED FILE.  DO NOT MODIFY.

 *

 * This class was automatically generated by the

 * aapt tool from the resource data it found.  It

 * should not be modified by hand.

 */

package com.JTianLing;

 

public final class R {

    public static final class attr {

    }

    public static final class drawable {

        public static final int icon=0x7f020000;

    }

    public static final class layout {

        public static final int main=0x7f030000;

    }

    public static final class string {

        public static final int app_name=0x7f040001;

        public static final int hello=0x7f040000;

    }

}

注释中也明确的表示了DO NOT MODIFY.!这里,类R的名字表示了其代表的即是我们通过XML编辑的资源,Rresource的首字母大小。

这里我们可以看到我们编辑过的XML属性,包括icon.png都能在这里一一找到对应的int值,OPhone/Android程序就是通过这些整数找到对应的属性的。了解MFC的话,这里可以做一个对比,这里不就是我们在Resource.h头文件中定义的那一堆宏的升级版嘛?其实总的看来,整个的AndroidResource都可以看做MFC Resource的升级版,之所以说升级,是因为XMLrc那样的格式更加通用,更加易于管理,其实从新版开始,VS自己都开始利用XML来管理配置和属性了,Office2007不都开始用XML格式来保存文件了吗?

讲述完上面的部分,我们应该能猜到了setContentView(R.layout.main); 中的R.layout.main不就是上面R类的layout类的main属性吗?因为都是static的,我们可以这样不通过对象直接使用,这点不用我多说了吧。

 

三、   通过修改程序运行印证分析

总体的分析了一下ADT为我们生成的Hello World程序,大概也知道了OPhone/Android程序的总体结构了。为了印证一下,我们来修改一些内容,看看是否运行后符合我们的设想。

1.      字符串内容的改变

先来将hello改变如下:

<string name="hello">Hello World, XML UI Application!</string>

运行后:

效果不错,如我们所想。

 

2.      框架的改动

TextView改为我们同样熟悉的Button,效果如下:

效果也不错:)

 

一、   了解XMLUI的控制力

现在基本可以肯定我们的分析是正确的了,那么我们具体使用的XML的时候是怎么样的呢?比如,现在设定一个目标,我们给此程序加上三个Button,排成一横排,每点击其中一个Button,三个Button同时向左边移动的效果。(前面一篇文章的升级版:))

首先在可视化的XML编辑器中编辑layoutADT的可视化XML编辑器几乎相当于一个RAD工具。。。相当强大,如下图:

从左边拖放适当的Button放在右边,按钮会按实际适用的layout放在恰当的位置,因为我先将LinearLayoutOrientation属性改成了

horizontal,所以这里自动将按钮排成了水平的了。可以看看生成的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"

    android:orientation="horizontal">

<Button android:text="Button01" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:text="Button02" android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:text="Button03" android:id="@+id/Button03" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

</LinearLayout>

 

还算是比较直观的,仅仅是id命名的方式有点奇怪,需要特别注意一下,我们留待以后再描述,不过有了上面的蓝本,依样画葫芦,手动编辑XML文件也不是不可行的。现在运行程序看看:

 

通过手动修改XML文件来生成字符串及换上对应的string值,此时对应的文件分别为:

strings.xml:

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

<resources>

    <string name="hello">Hello World, DevXMLUI!</string>

    <string name="button1">I'm Button 1</string>

    <string name="button2">I'm Button 2</string>

    <string name="button3">I'm Button 3</string>

    <string name="app_name">DevXMLUI</string>

</resources>

 

main.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"

    android:orientation="horizontal">

<Button android:text="@string/button1" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:text="@string/button2" android:id="@+id/Button02" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

<Button android:text="@string/button3" android:id="@+id/Button03" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>

</LinearLayout>

 

会发现R类也自动做出的相应的更改:

package com.JTianLing;

 

public final class R {

    public static final class attr {

    }

    public static final class drawable {

        public static final int icon=0x7f020000;

    }

    public static final class id {

        public static final int Button01=0x7f050000;

        public static final int Button02=0x7f050001;

        public static final int Button03=0x7f050002;

    }

    public static final class layout {

        public static final int main=0x7f030000;

    }

    public static final class string {

        public static final int app_name=0x7f040004;

        public static final int button1=0x7f040001;

        public static final int button2=0x7f040002;

        public static final int button3=0x7f040003;

        public static final int hello=0x7f040000;

    }

}

 

此时,从

public static final int Button01=0x7f050000;

public static final int Button02=0x7f050001;

public static final int Button03=0x7f050002;

从平时xml文件引用变量的方式是类似@string/的语法和上面的三句代码可以推断@+id/的意思了,意思就是没有对应的变量引用,创建新的变量。。。。。呵呵,+嘛,不就是添加嘛,还算是比较直观

运行程序看看:

 

果然如同我们设想的一样。现在就差时间的响应了,UI都布置好了。。。。(别看我上面描述的非常复杂,其实真正的操作可以1分钟内完成,实际的操作效果不说比RAD工具好,其他也差不到哪去)

剩下的就是实际的点击响应了,这点暂时XML没有办法帮你做了,呵呵,程序源代码如下:

DevXMLUI.java:

package com.JTianLing;

 

import java.util.Random;

 

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

 

public class DevXMLUI extends Activity implements OnClickListener{

    Random random = new Random();

    Button button1;

    Button button2;

    Button button3;

    @Override

    public void onClick(View v)

    {

       // 3个中没有使用过的boolean数组

       boolean[] testUse = { false, false, false };

       int i = random.nextInt(3);

       testUse[i] = true;

       button1.setText("I'm Button " + (i+1));

       while(true) {

           i = random.nextInt(3);

           if (!testUse[i]) {

              testUse[i] = true;

              break;

           }

       }

      

       button2.setText("I'm Button " + (i+1));

       if (!testUse[0]) {

           i = 1;

       }

       else if (!testUse[1]) {

           i = 2;

       }

       else

       {

           i = 3;

       }

       button3.setText("I'm Button " + i);

    }

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

       

        button1 = (Button) findViewById(R.id.Button01);

        button2 = (Button) findViewById(R.id.Button02);

        button3 = (Button) findViewById(R.id.Button03);

       

        // 三者的消息响应都设为一致的

        button1.setOnClickListener(this);

        button2.setOnClickListener(this);

        button3.setOnClickListener(this);

    }

}

 

onClick的响应程序用了random来随机生成一个0~2的整数,并通过一个boolean的数组来保证不会重复,基本的思想还是比较简单的,这里还可以看出一点,实际上OnClickListener是比较单纯的,也是足够可以复用的。

今天就到这里了。。。。

 

write by 九天雁翎(JTianLing) -- www.jtianling.com



阅读全文....

OPhone SDK初体验

OPhone SDK初体验

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

背景说明

中国伟大的垄断龙头,世界上也是顶尖的中移动终于出手了,出手不凡,成为了世界上第一个开发自由操作系统的移动运行商。操作系统的名字叫做OPhone,从CSDN上知道此重大消息后,我放下了手头的一切,全身心地开始追随中国移动领域的领头羊。

OPhone:官方的描述如下;

什么是OPhone:

OPhone是基于Linux、面向移动互联网的终端基础软件及系统解决方案。

OPhone SDK是专为OPhone平台设计的软件开发套件,它包括OPhone API,OPhone模拟器,开发工具,示例代码和帮助文档。

 

恩,不是Windows的东西,这点我比较满意,Linux是较为自由的,再加上众所周知的,OPhone是基于Google的Android系统的二次开发(因为如此的总所周知,所以中移动甚至都不需要提醒大家这一点,并且,这种决心不依赖Android这颗相对成熟的大树乘凉,不依靠Google名声去光耀自己招牌的作风更加让我佩服---PS:在中国中移动似乎也没有必要去依赖Google这种国外公司的名声,中国谁不知道中移动?除了搞IT的知道Google的又有多少?)

作为搞IT的,我个人是比较喜欢Google公司的,而且也对Android早有耳闻,所以虽然作为一个网络游戏服务器端程序员,我也为此专门的熟悉了一下Eclipse和JAVA,但是一直没有决心和毅力投身此行业,仅仅作为业余的爱好玩玩而已,毕竟国内甚至连一款Android的手机都没有!但是移动一出手,就知道有没有,随着联想的OPhone手机即将推出,OPhone在中国的开发应用环境已经远胜Android,于是,再加上中移动在中国雄踞南北的霸气,将来OPhone在中国的市场将远大于Android。今日,我决心追随中移动的脚步。。。。再加上OPhone的开发实际是建立在Android之上的,(下面马上就能看到)这样,我学习OPhone的经验永远不会白费,走在世界上任何一个角落,在国外也是有生存余地的,因为上面那么多的原因,我决心投身OPhone领域,谁也拦不住我了。今日是个起点,阿门。

 

    安装OPhone SDK

安装前自然要下载,但是下载前首先要在中移动那里注册,网址是"http://www.ophonesdn.com/",就我的理解,是OPhone-software-develepment-net。首先注册,然后通过验证,然后登录,闲话少说了,直接进入正题,下载,Windows版本下载地址为:

"http://dl.oms-sdn.com/sdk/ophone-sdk_windows-1.0-setup.jar"

Linux下载版本为:

"http://dl.oms-sdn.com/sdk/ophone-sdk_linux-1.0-setup.jar"

jar格式的问题,属于标准的JAVA包的格式,不用说,OPhone下的开发为了方便广大已经熟悉了Android和世界上最流行的语言JAVA的用户,用的是JAVA语言,知道这一点,我窃喜,前段时间为Android看了2,3天的《JAVA编程思想》没有白费。

 

文件不大,就100多M,接着自然就是安装了,OPhone的安装虽然极为简单及人性化,但是中移动还是更为人性化的提供了详细的安装步骤,力求做到傻瓜似教学。

首先,前提条件,需要下载如下东西:

 

先全部下来并安装再说吧。

然后再在安装目录下输入如下命令(以Windows版本为例):

java -jar ophone-sdk_windows-1.0-setup.jar

然后按管理狂按下一步就好

安装后的属性如下:

大小:200 MB (210,116,917 字节)

占用空间:205 MB (215,261,184 字节)

 

比Android最新版1.5 r3的占用大小:

大小:446 MB (468,160,733 字节)

占用空间:461 MB (484,167,680 字节)

 

要小的多,这也体现了中移动对于Android的优化,(从体积上都能看出来),体现了二次开发的成果。最后我通过比较,两者唯一相似的仅仅是Tools的名字及一些库了,相同的库如下:

/tools/lib/jcommon-1.0.12.jar

/tools/lib/jfreechart-1.0.9-swt.jar

/tools/lib/jfreechart-1.0.9.jar

/tools/lib/org.eclipse.core.commands_3.2.0.I20060605-1400.jar

/tools/lib/org.eclipse.equinox.common_3.2.0.v20060603.jar

/tools/lib/org.eclipse.jface_3.2.0.I20060605-1400.jar

/tools/lib/swing-worker-1.1.jar

/tools/lib/swt-awt-win32-3236.dll

/tools/lib/swt-gdip-win32-3236.dll

/tools/lib/swt-wgl-win32-3236.dll

/tools/lib/swt-win32-3236.dll

/tools/lib/swt.jar

可以看到,为了方便大家,也为了更好的体现开源共享的精神,中移动原封不移动的使用了google的jcommon,core等核心库,使用了swing,swt等界面库,实在是广大开发者的福音。更近一步的坚定了我追随中移动的步伐。

接着,按照文档,一步一步的添加用户库,文档啥的,都不在话下,因为以前装过ADT了,所以对我来说还算省事,最后,当我使用了中移动提供的模拟器后,感觉真是惊艳啊。。。。呵呵,这里和原有的Android的模拟器做一个对比。

左边的是OPhone,右边的是Android,从Android稀稀拉拉几个图标与OPhone满布屏幕的图标对比,可以看出OPhone更多内置的功能。OPhone模拟器有着熟悉绚烂的开启铃声,叮叮叮叮叮叮~~~,中文化的界面中可以看到飞信,Monternet,China Mobile的图标,OPhone不愧为移动深度定制的产品。。。以至于我。。。决定从这个月省吃兼用,等联想一出OPhone,一定第一时间购买!

 

Hello World

按照教程,一步一步走来,总算可以真正的尝试开发一下Android程序了,真是兴奋啊。。。呵呵,不是,是开发OPhone程序。。真是兴奋啊。。。啊?为啥开发OPhone程序要新建一个Android工程啊?这点颇为郁闷,整个Android SDK的名字都改成OPhone SDK了,一个小小的Eclipse ADT插件都不能改?在这点上,我稍微的质疑一下中移动同志们垄断3G 及智能手机市场的决心。。。。当然,仅仅是稍微质疑一下,也许ODT正在紧张的开发之中吧。

一开始我的创建新Android工程的画面与官方的有点不一样。。。难道是因为我的ADT太新?。。。。。汗-_-!

对比如下:

官方的:

我的:

在build Target和Min SDK Version两栏我实在是不知道该选什么。。。。真是郁闷啊。回过头来看看原来中移动主页上的说明:

ADT是为在Eclipse IDE下进行OPhone应用开发而提供的Eclipse插件。如果要使用Eclipse作为调试和编译的集成开发环境,则需要首先安装ADT。

下载ADT 0.8.0 zip file (不必解压该文件)。你也可以在SDK目录中找到ADT安装包:sdk_folder/tools/ophone/ADT-0.8.0.zip

晕,果然是版本太新,官方的是Eclipse3.4,ADT 0.8.0

我是EClipse3.5.0,ADT0.9.1了。。。总不能降级吧。。。。我怀着忐忑不安的心,期盼着中移动以高超的技术实现对Android新版插件的兼容。。。

先按上面那样选择再说吧。

通过上面步骤生成出来的程序还比较大,包括一个src,一个packet,一个Res,Res又包括XML格式的layout和values,甚至还有一个drawable的icon.png图标。这样的程序不需要按官方网站上的说明去改造,本身就是一个可以执行的Hello World程序,当尝试运行的时候,我发现。。。。。没有办法Run As OPhone Application.....晕,看了主页上的说明。。。原来官网的做法也是Run As Android Application。。。不去修改ADT的余毒至深矣。。。。。问题是,中移动一般人开发一个OPhone的模拟器容易吗?做来好看的?谁做的官方网页教程啊?竟然这样教人,这不是误人子弟吗?虽然我们知道OPhone的程序实际可以在Android中运行,但是我们尽然是开发OPhone程序,自然要看着它在OPhone中运行啊。。。。。。。

唉。。。。竟然如此,将string资源的hello变量值改为Android吧,运行效果如下:

 

算了,这些姑且不论,仅仅算是OPhone中的一个小瑕疵吧,先来看看中移动的OPhone对Android进行了哪些深度定制,进行了哪些改进,进行了哪些优化或者升级吧。。。。。。

参考一下文档,就能知道个大概了:

OPhone API Reference

Contents

 

恩,不错,看来,OPhone对Android进行了3大块的改造。分别是Home Screen,Local Search,Mail,听起来都是挺重要的模块嘛,一个一个来:

OPhone Home Screen is the home screen application in OPhone platform. The class defines some constants used by Home Screen API. If you want to add/change an item on home screen, you can send some Intent to the home screen application. Then the home screen application will process this action.

不错,OPhone的Home Screen给Android的改进是增加了一种对OPhone手机Home Screen的一种通信机制,看起来还不错。

Local Search这样重要的功能也有了,了不起,Mail这样的功能自然更加是需要啦,不错,果然是OPhone,就是名不虚传。

 

后来,我在OPhone SDK文档中看到了非常振奋人心的消息:

OPhone是基于Linux面向移动互联网的终端基础软件及系统解决方案。OPhone SDK是专为OPhone平台设计的软件开发套件,它包括OPhone API,OPhone模拟器,开发工具,示例代码和SDK帮助文档。OPhone SDK兼容Android SDK,因此开发者在开发OPhone应用的时候可以同时使用OPhone API和Android API。

 

展望

太强大了!!!!OPhone是兼容Android API的,伟大的设计啊。。。大家都知道,Android手机是有一些优点的,OPhone又是与之兼容的,那么我们买了一个OPhone手机,就相当于同时又买了一个Android手机,简直就是买一个顶两个,开发难度却相当于一个,这简直#@%#@%#@%太强大了,无论对于普通用户还是对于程序开发者都是天大的好消息,从此后,开发OPhone应用程序,不回头。



阅读全文....

OPhone/Android的学习(1)—初步知识,TextView,Button,Layout及事件响应

OPhone/Android的学习(1)—初步知识,TextView,Button,Layout及事件响应

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

中移动强大的号召力让我暂时停止了前段时间兴趣浓厚的图形编程学习,说起来,无论是图形编程还是Android编程都算是编程领域比较充满趣味的部分,《C语言专家编程》作者就说过,用软件控制硬件总是编程最有乐趣的部分:)图形编程这样容易出成果,让自己看到自己的程序展示的方式,也是同样充满趣味的,何况,这也算是用软件控制硬件(显卡)的一种方式。

今天继续Android的学习,因为OPhone与Android兼容,那么就是说,我也是在学习OPhone。。。。。。呵呵

昨天用ADT自动生成的Hello World程序用了很多东西,资源啊,什么的一大堆,弄得比较复杂,源代码如下:

package oms.hello;

 

import android.app.Activity;

import android.os.Bundle;

 

public class HelloOPhone extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

}

 

另外说一句,Eclipse是Windows下我用过的除了VS以外能够直接带程序着色复制的IDE程序,一般的开源的都不好用,Eclipse还算是比较强大。这个代码是简单了。。。。。。但是R.layout.main的出现将问题复杂了,我当时就没有弄清楚Hello Android是怎么来的,后来才发现实在资源里面。这点和一般我们写的程序有点不一样(可能主要是为了大型程序的设计成这样的),作为一个Hello World都这样拐弯抹角就让人受不了了,Google的Andorid教程中就交给我们了另一个较为直观的HelloWorld程序,源代码如下:

package oms.hello;

 

import android.app.Activity;

import android.os.Bundle;

import android.widget.TextView;

 

public class HelloOPhone extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

TextView tv = new TextView(this);

tv.setText("Hello, Android");

setContentView(tv);

}

}

 

这样的程序相对来说就直观多了,也符合一般的HelloWorld的简洁,这个程序即使是不了解JAVA的人应该也能一眼看明白。

    Android中的窗口都叫View,TextView自然是Android的文字显示窗口。创建TextView的时候将整个HelloOPhone这个Activity的指针传进了TextView,指定了View的范围,setText指定了View的文字内容,setContentView将此View设为Activity的内容。。。。其实程序简洁,描述反而复杂了。

既然HelloWorld用到了TextView,我们来挖掘一下有用的信息,从Android的Reference中可以看到如下内容:

Known Direct Subclasses

Button, CheckedTextView, Chronometer, DigitalClock, EditText

Known Indirect Subclasses

AutoCompleteTextView, CheckBox, CompoundButton, ExtractEditText, MultiAutoCompleteTextView, RadioButton, ToggleButton

这个一看就牛了,Button,EditText等都是从TextView继承过来的直接子类,既然用到了TextView了,我们也尝试用下这两个看到名字我们就能知道作用的Widget,至于更进一步的CheckBox,RadioButton,ToggleButton也是非常熟悉了,这里就不看了。

先看看Button,到底能不能有效:

package oms.hello;

 

import android.app.Activity;

import android.os.Bundle;

import android.widget.Button;

import android.widget.TextView;

 

public class HelloOPhone extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

TextView tv = new Button(this);

tv.setText("Hello, Android");

setContentView(tv);

}

}

 

上面的程序显示出来的效果如下:

 

左边的是普通显示画面,右边的是按下后的样子,很明显按钮的特性显示出来了。。。。呵呵,注意,我仅仅改变了new出来的对象,没有改变原TextView类型的tv值,因为Button从TextView继承而来,所以我们可以这样做。

这个按钮实在太大了,几乎已经看不出是个按钮了。。。。给他瘦瘦身吧。直觉反应的程序应该是下面这样的:

package oms.hello;

 

import android.app.Activity;

import android.os.Bundle;

import android.widget.Button;

 

public class HelloOPhone extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Button btn = new Button(this);

btn.setText("Hello, Android");

btn.setWidth(100);

btn.setHeight(100);

setContentView(btn);

}

}

 

事实上这个程序与上例中一模一样,还是整个按钮充满了整个Activity。思考了一下,可能问题出在setContentView一句上,因为此举设定了整个内容,这样相当于拉伸效果,否定了整个按钮的设定长宽的效果。既然是这样的思路,那么自然就需要将Button放入某个容器中,让Android显示此容器,用此容器撑满整个屏幕,然后让Button属于此容器的一个子Widget,以调整大小,有了此思路,在文档中一搜索,就出现了目标,有两个layout类,layout是多么的熟悉啊,QT中让人解脱的类,MFC中缺乏导致的对话框程序进行缩放编程就是噩梦的类。有了目标,尝试看看,是否如直觉所示。

如下程序,达到了我们的目的:

package oms.hello;

 

import android.app.Activity;

import android.os.Bundle;

import android.widget.Button;

import android.widget.LinearLayout;

 

public class HelloOPhone extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

LinearLayout layout = new LinearLayout(this);

Button btn = new Button(this);

btn.setText("Hello, Android");

layout.addView(btn, 100, 50);

setContentView(layout);

}

}

 

效果如下:

 

 

所以说,其实学的东西多了,杂了,其实还有一定作用的,毕竟很多东西是相通的,比如这次的layout,呵呵。

有按钮了,点了总要有点反应吧,响应个消息吧。

见下例:

package oms.hello;

 

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.LinearLayout;

 

public class HelloOPhone extends Activity implements OnClickListener{

/** Called when the activity is first created. */

    boolean isClicked = false;

    @Override public void onClick(View v) {

        if( v instanceof Button) {

            if(!isClicked) {

                ((Button)v).setText("Hello, New Button.");

                isClicked = true;

            }

            else

            {

                ((Button)v).setText("Hello, Old Button.");

                isClicked = false;

            }

        }

    }

 

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

LinearLayout layout = new LinearLayout(this);

Button btn = new Button(this);

btn.setText("Hello, Android");

 

// 添加一个OnClick事件响应的监听对象

btn.setOnClickListener(this);

layout.addView(btn, 100, 50);

setContentView(layout);

}

}

 

这个程序一下子复杂了很多,几点说明:要响应事件(Event),需要有监听事件的对象,这个对象在Android中属于Listener一族的接口类,实现这个类的接口,然后通过setOnxxxxListener指定Listener后,一旦有监听(Listening)的事件,则相应的函数(即实现接口的那个函数)就会被调用,并且,发生事件的对象也会通过参数传入此函数。上例中有点特殊的是HelloOPhone本身实现了OnClickListener,这样的话,直接在类中用this表示Listener比较方便(这也是Android文档中提到过的方法),上例实现了一个动态改变的按钮。效果如下:

首先显示的是第一个按钮,点击一下后,显示的是第二个按钮,再点击则显示第三个按钮,以后的点击,按钮在第二个按钮与第三个按钮间来回切换。

 

write by 九天雁翎(JTianLing) -- www.jtianling.com



阅读全文....

Windows下的进程创建API--CreateProcess使用经验漫谈


Windows下的进程创建API--CreateProcess使用经验漫谈

write by 九天雁翎(JTianLing) -- www.jtianling.com

讨论新闻组及文件

Windows下工作久了,虽然不想多么深入的去了解它,但是实际还是多少懂了一点。这里说说问题比较多用的也非常多的一个APICreateProcess,这里不准备举太多例子了,《Windows核心编程》和MSDN上讲的都比较详细了,这里只谈谈使用的经验。

基本的应用上,这里用MSDN的一个例子讲解:

#include <windows.h>

#include <stdio.h>

#include <tchar.h>

 

void _tmain( VOID )

{

    STARTUPINFO si;

    PROCESS_INFORMATION pi;

    LPTSTR szCmdline=_tcsdup(TEXT("MyChildProcess"));

 

    ZeroMemory( &si, sizeof(si) );

    si.cb = sizeof(si);

    ZeroMemory( &pi, sizeof(pi) );

 

    // Start the child process.

    if( !CreateProcess( NULL,   // No module name (use command line)

       szCmdline,      // Command line

       NULL,           // Process handle not inheritable

       NULL,           // Thread handle not inheritable

       FALSE,          // Set handle inheritance to FALSE

       0,              // No creation flags

       NULL,           // Use parent's environment block

       NULL,           // Use parent's starting directory

       &si,            // Pointer to STARTUPINFO structure

       &pi )           // Pointer to PROCESS_INFORMATION structure

       )

    {

       printf( "CreateProcess failed (%d)./n", GetLastError() );

       return;

    }

 

    // Wait until child process exits.

    WaitForSingleObject( pi.hProcess, INFINITE );

 

    // Close process and thread handles.

    CloseHandle( pi.hProcess );

    CloseHandle( pi.hThread );

}

 

1.LPTSTR szCmdline;一句很重要,而且是必须得有的,这里需要注意,因为CreateProcess的第二参数是一个非const字符串,这点比较意外,因为事实上,我也没有看到MS改动过此字符串,从理论上来讲,改动commandline也是很让人惊讶的事情。

2. CloseHandle( pi.hProcess );

    CloseHandle( pi.hThread );

后,子进程就与父进程彻底脱离关系了,在Windows下进程之间的关系比较弱,不仅没有父进程收割子进程退出状态这一回事,甚至连getppid这样的API也没有。这又导致了两个现象,

1.Windows下不用当心Linux下的僵死进程问题。

2.)当失去句柄仅仅知道进程ID时,Windows下甚至无法判断此进程是否就是原有进程,(用OpenProcess打开的句柄无法判定是否就是原来的进程)假如此进程已经结束,也无法获取到进程的退出状态。(在Windows下获取进程退出状态必须得保留进程的句柄,然后调用GetExitCodeProcess

3.现在一般的游戏都已经不允许直接运行了,这点的目的很简单,加大别人用反编译软件调试游戏主程序的难度。按照CreateProcess的默认参数的直接创建原游戏主程序时,会碰到一个问题,及当发生原程序发生缺少动态库等情况时,原有系统弹出的提示对话框会被调用CreateProcess的进程吞掉,使得这类错误被掩盖,因为此时CreateProcess返回值实际是成功的。这时候,将CreateProcess的参数Process Creation Flags设为CREATE_DEFAULT_ERROR_MODE就可以让原有的提示窗口弹出来。

4. Process Creation Flags设为CREATE_SUSPENDED时,可以将欲创建进程挂起,这时想对新进程干啥都行,甚至可以尝试更改其代码段以影响程序运行,(但是大部分带监控的杀毒软件会有警告)。然后用ResumeThread API去让原进程的主线程运行起来。

5.CreateProcess创建的进程句柄实际代表的是一个Windows核心对象,适用于Windows核心对象的操作都可以对进程句柄进行,(核心对象的概念请参考《WIndows核心编程》,其中包括WaitForSingleObject等同步API

 

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....