上次把andriod的环境搭建好后一直因为有其他的要紧事搁着暂时把Andriod的学习扔一边了,今天有空,来写第一个Andriod程序,和刚写第一个java程序一样,我HelloWorld的程序做实例。
1. 新建一个 Android 项目,点击 “ New ” --- “ Android Project (因为MyEclipse装ADT插件的时候出了点问题,我特意装了Eclipse,感觉做andriod开发还是Eclipse专业一点吧,因为MyEclipse本身就集成了基于J2EE开发的许多插件,再装其他插件就显得有些臃肿了,所以要装插件还是选择Eclipse好,废话多了,见者勿怪),”,在“ Java ” 透视图下new新工程时没见到“ Android Project ”则点击 “ Other ”,到创建向导中的 “ Android ”目录下,选择 “ Android Project ”即可。
2.因为这里只是做测试 ,我们创建好这个Android 项目创建后,其实就可以运行了,
下面我们将对第一个andriod的进行发布运行,这里要用到Android 提供的模拟器来测试。
3. 创建模拟器,点击图标:
在模拟器列表界面,点击 New ,进入到创建向导:
参数说明:
(1)Name:模拟器的名称。 (2)Target: SDK的版本,上面Min SDK Version的版本要高于这个。
(3)SD Card size:SD卡的大小。根据需要自行设置 (4)Skin Built-in:分辨率,一般取默认值
创建了之后,将回到模拟器列表页面,选中创建的模拟器,点击“ Start ”,再在弹出界面中点击“ Launch ”,如图: :
4 . 启动要一段时间,要耐心等待一会
5 .下面部署我们的 HelloWorld ,选中项目,右键点击“ Run As ” — “ Android Application ”
6. 等候运行结果,查看模拟器,运行后,模拟器画面为:
7.我的 HelloWorld项目截图:
“ src ”用来存放源文件的。
“ res ”“ Resources ”的缩写,一res文件夹中则包含了项目中的所有资源,比如:程序图标(drawable)、布局文件(layout)、常量(values)等。
“ gen ”下是一些由系统控制的资源。gen目录下有个R.java文件,R.java是在建立项目时自动生成的,这个文件是只读模式,不能更改,R.java文件是定义该项目所有资源的索引文件
(1)
package com.sky.lganggang131;
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;
}
}
可以看到,它的机制类似于这样,每一个 res 目录下的子目录都对应 R 这个类 中的一个静态内部类( drawable-hdpi 等三个对应一个 drawable 类)。
例如, layout 文件夹下我们观察到有一个 main.xml 文件,于是观察 R 文件,果然是有一个 layout 内部类,它里面又有一个 main 静态变量。
那么是不是我们通过 R.layout.main 就可以访问到 main.xml 呢。因为我们的分析结果不是 R 文件里的变量都是到某一个具体资源的索引么 ? 完全正确!说 R.java.main 可以访问到 main.xml 完全没问题。只不过这个访问是由 Android 内部完成的。
相当于送快递一样,寄的人给个地址,说送到某某某地某某街某某门牌某某公司某某人,因为这个地址足够详细,所以快递很快找到目标,然后完成任务。
那么 Android 为什么要采取这种机制呢?将应用的资源与应用本身剥离,有什么好处?我觉得首先有一个好处就是,加载资源这一行为由 Android 来做,它肯定比程序员更了解该怎样来管理这个资源 ,例如,资源过大,不能持久保存、资源很小,我加载在内存里,先保存着,下次有人用的时候,我再拿出来。操作系统本身最了解自己的内存状态和运行效率 ,因此,它也更会管理内存和优化软件的运行效率。
(2)
文件:AndroidManifest.xml
这个文件我将他看成应用的功能清单,类似于 struts 中的 struts-config.xml 。每当我们要到一种组件时,总是要现在这个文件中声明(或者说注册)。它初始时就默认定义了应用的一些基本属性,文件内容为:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sky.lganggang131"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>
先介绍跟元素 manifest ,这是站在整个程序角度来描述整个应用,此元素内部可以声明组件,申请权限等等,其属性:
xmlns:android :命名空间,这没什么说的,照着写就是了。
package :应用所在的包,包名要尽量避免大众化——我的意思是,要尽量降低你的应用和世界上其它应用包名相同的情况。因为当应用安装软件到手机后,包名将作为操作系统的进程名。这个应用包名仿佛承载着区别应用与应用的一个标志。只要遵守一般 Java 项目中的包命名规范,这种情况应该也很少,就算有,让这本来几率就低的两个软件正好运行在同一部手机上,几率更是直逼彩票获奖率。
而且也许 Android 有处理这种问题的机制,我还在查。
android:versionCode :应用的版本号,默认为 1
android:versionName :版本名称
application :此标签用来描述应用中的组件声明和应用的全局属性。此标签只能有一个。
android:icon :应用的图标: @drawable/donkey 这个表达式将在后面进一步说明。
android:label : @string/app_name 对应了一个字符串,也可以给这个标签直接写上一个字符串,如“宇宙级五子棋”等。这个属性设置的值,将出现在用户的手机软件标题上,例如用户安装了你的软件,那么他的软件列表里就将出现你的软件,那么显示的软件名称就是这家伙。这个值还将默认作为主窗口的默认标题。
Activity 标签 :一个 Activity 通常表现为软件上一个单独的屏幕界面,它们或者独占软件的整个屏幕,或者被改造为一个对话框。它通常对应一个继承了 Activity 的类,因此,若我们要新建一个窗口,一个办法是新建一个类,继承 Activity ,再将此 Activity 照猫画虎注册在本 XML 文件中,并在合适的实际,激活它就可以了。
Activity 这个名字乍看有点怪,起个名字叫“活动“,明明就是一个界面嘛。
其实这是另一个角度的抽象,我们想,其实一个程序,不就是一个“大的活动”么,这个“活动”里又包含了多个“子活动”。
那么 Android 将一个通常作为窗口这样一个控件称之为“活动”,那么,肯定是将它看做一个“活动”的容器,它可以承载很多活动。
例如,“鼠标点击”,“键盘按下”等等。或者从另一个角度,例如“用户输入数据”、“用户想看一个对话框”、“用户想把一个控件拖动一下”等等活动。这些活动都是发生在“窗口”上的,或者是通过“窗口”来触发的(其实这种情况下,也可以看成是窗口在处理活动,只是它调用了另一个控件来辅助而已)。于是,从这个角度来看,将这个控件取名为 Activity 再合适不过了。
android:name :这个属性指定 Activity 的类名。 ”.MainActivity” 中的 “ . ” ( 点 ) 就表示当前应用的包名,也就是 manifest 标签的 package 属性的值: wjh.android.helloworld 。这样 ”.MainActivity” 就成了:
android:label :既然上面分析 Activity 可以看着一个屏幕窗口,那么,这个窗口也应该有标题,此属性设置的值将作为窗口的标题。这里可以直接写上想显示在窗口上的标题的字符串。
intent-filter: 这个标签有体现了一个 Android 的设计思想,它将用户与软件组件之间、组件与组件之间的交互行为抽象为 Intent (意图)。很形象也很抽象。 例如,用户想看到另一个窗口,于是他点击了现在的窗口的 “ Open New Window ”,另一个窗口打开了。这其中,经历了一个转换,就是程序,将用户的“意图”转换成了程序能描述出来的、并能执行的指令。
(3)
文件: vulues/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, MyActivity!</string>
<string name="app_name">My First Andriod Application</string>
</resources>
这个文件首先有点意思的是,我们观察知道: stringx.xml 这个文件最终在 R 文件中对应了一个名为 string 的内部类。并且每一个有效的 <string> 标签,对应其内部的一个常量。
那么上文中我在描述“大概目录结构”时的说法是有误的 ,我说, res 目录下的子目录都对应了 R 文件的一个静态内部类。应该说这个情况在大多数时候是这样的,但是在 values 文件夹却除外 (并不严谨,因为我没有做很仔细的实验,有可能还有其它情况也排除在外)。首先我们并没有看到在 R 类中新添加一个 values 子类。哦,那么它肯定是用文件名来做为静态内部类的类名的 ~~~ 额,可是,我这个文件名叫 strings 也,而 R 文件中对应的内部类却是 string 。如果说这个还不能说明问题的话,那么我们再在这个文件夹下新建一个文件,右键 — 新建 Android XML File ,然后选择文件类型为 Values —— 这文件夹下只能放这种类型的 XML 文件,其实也就是,这个文件夹下,只能放以 <resources> 作为根元素的 XML 文件。
于是我们新建一个 aaa.xml 的 values 文件,打开看,果然自动添加了一对 <resources></resources> 。
那按照我们的猜想, R 文件中,应该产生一个 aaa 的内部类吧。打开一看,希望落空,没有这东西。
那么我们在 aaa.xml 中写点东西吧,也许是没有东西才没生成呢?
于是我们写一对 : <string name="ns">sss</string>
再看 R 类。还是没有 aaa 这个类。那 ns 这个定义的字符串资源哪去了呢?——跑到 string 里面去了。
我觉得我这说得有点偏了,于是直接说结论吧: values 下只能放 Values 这种类型的 XML 文件,也就是说,此文件夹下虽然有多少个 xml 文件不确定,但是有几种标签是确定的,因为他们都是 <resources></resources> 的子元素嘛, Android 规定了其下面只能有八种标签(但是 Item 除外),都是用来定义一些常量的。例如颜色值,样式等等。
实际上是每一种标签对应一个静态类,比如,我们在 aaa.xml 写上一对:
<color name="dialog_back">#330000FF</color>
看 R 文件,马上发现生成了一个 color 类。当写第二个这种标签时,就只是在原有基础上添加常量,不会新建类。其它六种都是这样。
为什么 Item 标签除外呢,它干的事吧,我写一段大家就明白:
<item type="string" name="nihao"> 您好 </item>
<item type="string" name="c1">#7f040000</item>
这种写法,同样会在 R 类的 string 和 color 中添加两个新的变量。
有什么用呢?倒确实会在有时候用到,例如我们可以这样写:
<item type="cus" name="My"> 我自己分类的资源类型 </item>
查看 R 文件,发现新建了一个 cus 类。
这是我至今发现的唯一一个能自己在 R 中添加静态类的方法。
(4)
layout/main,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>
<LinearLayout> :布局方式——线性布局。关于几种布局的详细情况请参看文档:
<TextView>: 相当于 html 中的 <label> 标签,显示一段文本。
android:layout_width="fill_parent" :控件宽度为填充父元素,在这里,父元素就是整个屏幕,所以就是满屏宽。
android:layout_height="wrap_content" :控件高度为包裹内容,就是刚刚好能够满足内容正常显示的高度。
package com.sky.lganggang131;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
这里是自定义一个 MainActivity 继承了 Activity 。表示这是一个可当做窗口展示的控件。并且我们希望它作为启动窗口,于是在定义它的配置文件里,为他定义了一个意图过滤器。
但是,这个控件到底怎样显示东西呢?
首先:
onCreate 方法:表示 Activity 已经准备就绪,只差显示了,这个时候系统会自动调用这个方法,因此它不由程序员管理。这个方法在 Activity 的整个生命周期内只会被调用一次。但是,这时候 Activity 还一片空白,什么也没有,我们希望让它能显示一个我们定义的界面,在这个时机就加上去最合适不过。于是:
调用 setContentView() 方法,这个方法能为整个 Activity 设置一个界面。而,这个界面被我们定义在了 layout/main,xml 里面了,怎样才能访问这个文件呢 ? 显然是 R.layout.xml ——注意此处的 R 是我们自己应用下的 R 类。系统本身也有这样一个类,因此,使用的时候,要按包名区分清楚。
于是 setContentView(R.layout.main); 这句代码的意思再清楚不过,就是将 main.xml 定义的内容,作为 MainActivity 的界面。
(5)
存放图片资源的目录:
drawable-hdpi :用于存放高分辨率的图片。
drawable-ldpi :用于存放低分辨率的图片。
drawable-mdpi :用于存放中等分辨率的图片。
它们对应 R 中的 drawable 子类。
为什么要有这样的区分。因为手机的特殊性,款式不同,它的分辨率差别可能很大:有的屏幕很小,有的很大。我需要能灵活的自动适应这种情况。
于是就把分辨率不同的但是文件名相同 的几幅图片分别存放在对应分辨率等级的文件夹下 ,例如,我们打开这几个文件夹,可以看到系统自带的 icon.png 图片,它作为了应用的图标。 Android 内部会自动根据用户手机的分辨率而挑选适合的图片挂上去。这也是将资源交给 Android 统一管理的另一个好处,它比我们更懂每个用户的手机特征 ,因此只有它最适合完成屏幕适配和国际化。这里就是屏幕适配。
这个机制不但适用于图片,还适应于所有 res 目录下的资源。例如新建 layout-320x240 文件夹, 就表示此文件夹下的界面文件,适配 320x240 这种分辨率的手机。