前言:我學了一年多的C#(從學編程算起,也沒有兩年,我現在大二下),中間也一直在學WP開發,雖然技術不咋地,很渣渣,但微軟在Build大會上宣布的策略讓我覺得有必要學習一下安卓開發了。關於微軟的策略,沒什么好說的,只有平台強大了,開發者才能存活,對於微軟和.NET開發者來說,這是一榮俱榮,一毀都毀的事。目前來看WP開發者或許內心有一點受傷,不過在個人看來這都沒什么,我們還是多學一門技術來豐富一下自己好了。我在學習安卓的同時還是會繼續學習.NET方面的技術,對於Java,大二上學期上過這門課,學的內容很淺顯,而且當時也沒怎么學,現在看來還是得補補了,趁着大二下剛好有安卓這么課好好學習一下了。
安卓的開發環境之前已經搭建好,現在直接來了解一下安卓應用程序結構以及運行的原理。
1.Android工程的文件系統結構
src: java源代碼存放的目錄。在src文件夾里面可以建立若干個包,用以分類存放Java源程序(.java文件)
gen: 自動生成目錄 gen目錄中存放所有由Andriod開發工具自動生成的文件。目錄中最重要的就是R.java文件(gen\包名\R.java)。開發工具會自動根據你放入res目錄的資源,同步更新修改R.java文件。由於R.java文件是由開發工具自動生成,應避免手工修改R.java。R.java在應用中起到了字典的作用,它包含了各種資源的id,通過R.java,應用可以很方便地找到對應資源。
assets: 資源目錄,Andriod除了提供/res目錄存放資源文件外,在/assets目錄也可以存放資源文件,而且/assets目錄下的資源文件不會再R.java自動生成id,所以讀取/assets目錄下的文件必須指定文件的路徑,而assets中的資源文件不會被編譯,直接打包到應用中,assets文件夾支持任意深度的子目錄。
bin:用於存放編譯后的應用程序
libs:存放應用程序用到的第三方JAR。
res: 資源(Resource)目錄 在這個目錄中可以找到應用使用到的各種資源。如xml界面文件,圖片或數據等。res文件夾內的資源文件最終會被打包到編譯后的.java文件中,res文件夾不支持深度的子目錄。
res/layout:存放拓展名為.xml的布局文件,每一個布局文件對應一個Activity。
res/values:strings.xml是這個文件夾最重要的文件,存放着布局文件中控件對象的屬性值,與應用程序的國際化相關。
res/drawable:圖片文件夾
res/raw:存放音頻資源文件等
AndriodManifest.xml:項目清單文件 這個文件列出了應用程序所提供的功能,開發好的各種組件(Activity、ContentProvider、Broadcast、Service)需要在該文件中進行配置,如果應用使用到了系統內置的應用(如電話服務、互聯網服務、短信服務、GPS服務等等),還需在該文件中聲明使用權限。(安裝的時候被操作系統讀取)
2.編譯結果
.java--》.class--》.dx--》.dex--打包(簽名)--》.apk
編譯結果放在項目根目錄下的bin文件夾下
bin/classes:存放編譯后的Java類文件
bin/classes.dex:存放基於編譯后的Java類創建的可執行文件
bin/resources.ap_:存放應用程序的資源
bin/XXX.apk:實際的Android應用程序。.apk文件其實是一個ZIP壓縮文件,包含.dex、資源的編譯版(resources.arsc)、其他未編譯的資源以及AndriodManifest.xml文件。
3.AndriodManifest.xml文件詳解
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.dialogdemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" 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> </manifest>
根節點<manifest>中的package屬性指明清單文件所對應的應用程序包,android:versionName是應用程序的版本名或編號,可以是任意合適的值,android:versionCode則必須是一個整數,表明應用程序的版本號。系統可以根據這個特性來確定應用程序是不是另一個版本的更新。
<uses-sdk>:表示當前應用程序基於哪個版本的SDK構建。
<application>:定義與當前描述文件對應的應用程序的細節信息。
<activity>:相當於Windows編程里面的一個窗體(Form)。android:name表示實現Activity的類,android:label表示用於顯示的Activity的名字。 <intent-filter>子元素用於描述顯示當前Activity在什么情況下被調用。 它里面的
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
這兩項參數將我們的應用程序顯示在手機應用程序的啟動列表上,表示應用程序的入口,使用的時候應該注意它們僅能夠出現在一個Activity里面,這個Activity就是應用程序的主Activity。
在這個清單文件里面還有一些沒有出現,但以后會經常使用的元素:
<uses-permission>:指出應用程序正常運行所需的權限。
<permission>:為活動和服務聲明權限,表示其他應用程序要使用當前應用程序的數據或邏輯必須具有的權限。
<instrumentation>:表示需要在關鍵系統事件中需要調用的代碼。
<uses-library>:引入可選的Android組件,例如地圖服務。
4.Android應用程序生命周期
與大部分傳統應用程序平台不同,Android應用程序不能控制它們自己的生命周期。應用程序組件必須監聽應用程序狀態的變化並做出適當的反應,還要為隨時被終止做好准備。默認情況下,每個Android應用程序都是通過它們自己的進程運行的,每一個進程都運行在獨立的Dalvik實例中。每一個應用程序的內存和進程管理都是由運行時專門進行處理的。
Android會主動管理它的資源,它會采取任何措施來保證穩定流暢的用戶體驗。這就意味着在必要的時候,進程(以及它們的應用程序)有時候會在沒有警告的情況下被終止,為高優先級的應用程序釋放資源。
活動進程:正在和用戶進行交互的應用程序進程。
可見進程:駐留“可見”Activity的進程。
啟動服務進程:已經啟動的Service進程。
后台進程:不可見、並且沒有任何正在運行的Service的Activity的進程。
空進程:應用程序的生命周期已經結束,但仍保留在內存中的進程。Android通過維護這個緩存來減少應用程序再次啟動時的啟動時間。
5.一個簡單的Android應用程序
先New一個Android Application Project,在工程對應的src文件夾的最內層找到生成的.java文件,添加如下代碼:
public class MainActivity extends ActionBarActivity implements View.OnClickListener{ Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); btn=new Button(this); btn.setOnClickListener(this); updateTime(); setContentView(btn); } private void updateTime() { // TODO Auto-generated method stub btn.setText(new Date().toString()); } @Override public void onClick(View arg0) { updateTime(); } }
這個類里面的OnCreate方法會在應用程序啟動的時候自動被系統調用,它傳入參數是savedInstanceState,類型是Bundle,Bundle是一個數據參數,一般用於Activity之間的數據傳送。在這個方法里面,首先做的是與超類聯系起來,以完成整個Activity的初始化。隨后又創建了一個按鈕實例,並為按鈕設置事件監聽器,接着調用updateTime()方法,最后把按鈕設置為內容視圖。
這個程序最終的效果就是頁面內只有一個按鈕,用於顯示最后一次按下它的時間(如果沒有按就顯示應用程序啟動的時間)。
我們知道Android將用戶界面和資源從業務邏輯中分離出來,並使用XML文件來進行界面布局,而復雜的業務邏輯交給java代碼來完成,所以我們一般很少采用上面的方法來構建我們的應用程序。接下來我們把上面的應用程序來改動一下。
res/layout/activity_main.xml:
<Button xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/btn" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="" />
xmlns:android="http://schemas.android.com/apk/res/android"這個只能出現在布局文件的頂層元素里面,而頂層元素一般是一個布局容器。我們這里只有一個Button元素就直接放Button里了。
android:id屬性為Button指定一個唯一標識符,我們在.java文件里獲取布局文件里的元素時就需要這個屬性。
android:text指示按鈕上顯示的文本。
android:layout_width和android:layout_height指示按鈕的寬度和高度與父元素的關系,我們這個實例中按鈕會占據整個屏幕。
.java文件:
public class MainActivity extends ActionBarActivity implements View.OnClickListener{ Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn=(Button)findViewById(R.id.btn); btn.setOnClickListener(this); updateTime(); } private void updateTime() { // TODO Auto-generated method stub btn.setText(new Date().toString()); } @Override public void onClick(View arg0) { updateTime(); } }
setContentView(R.layout.activity_main);這個和我們之前傳入一個View的子類(即Button)的實例是一樣的。布局中的所有資源都可以通過R.layout加上布局文件的名字來訪問;例如:R.layout.activity_main訪問的就是res/layout/activity_main.xml
btn=(Button)findViewById(R.id.btn);//通過findViewById方法來獲取布局文件中標識為@+id/btn的Button元素
運行效果與原來的一樣。
至此已經了解了安卓開發的一些基礎知識,包括Android工程的文件系統結構、編譯的結果、還有Manifest清單文件以及應用程序的生命周期和簡單Android應用程序的詳解。感覺寫得還是比較亂,由於是新手,錯誤不足請大家多多指教。
之前一頭扎進C#,用着VS的確很舒服,現在用Eclipse很不習慣,感覺安卓寫起來也確實比WP復雜很多,加油吧!