Android学习笔记

Android是一个由Google开发的一个开放应用软件平台,适用于智能手机、平板电脑、机顶盒等嵌入式设备,其特征是基于Linux内核、集成有众多开源库、并提供了一个变异的Java虚拟机。有不少人称之为操作系统,这是不恰当的,因为Android显然不符合教科书对操作系统的定义。

起步

若自上而下的话,当从应用开发始。

准备工作

  1. JDK:Java开发工具包,内含一套Java开发工具,包括编译器,调试器等;还有一个Java运行环境,包括虚拟机和一些标准的JAR库等(Android不用这些)。可以从Oracle的官网下载。
  2. Android SDK: Android开发包,内含整套Android开发工具,包括调试桥ADB、模拟器、监测器DDMS、Dalvik字节码转换器dx、打包器aapt等;还有一个android.jar库。可以从Android开发者网站下载。
  3. Eclipse IDE:这是一个扩展性极强的多用途开放IDE,可以从Eclipse官网下载。
  4. Eclipse插件ADT:ADT将Andriod开发工具和调试监测工具集成到Eclipse中,可以从Android开发者网站下载,也可以在Eclipse的”Install New Software”中安装。

获取以上工具之后,即可以使用Eclipse IDE中创建Android应用工程,在模拟器中运行之并进行Java层面的调试。迄今为止,所有一切都是免费的。

Hello World

还是从经典的“Hello World”程序开始。对于基于GUI的Android应用程序,“Hello World“的形态是多样的,在开始编写代码之前,需要首先对Android的GUI框架有所了解。

Activity类是Android GUI的基础组件,用于管理一个GUI行为场景。每一个基于GUI的Android应用程序至少需要定义一个派生自Activity类的子类,负责行为场景的界面绘制和用户行为交互。这个Activity派生类维护着一个状态机,抽象了一个行为场景从启动到退出,失去焦点、被其他场景覆盖而进入后台、恢复焦点、回到前台等各种行为以及这些行为所导致的状态转换。就此官方的SDK文档给出了清晰的描绘:

因此,一个最简单的Android Hello程序可以写成:

package com.test.hello;
 
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
 
public class MyTest extends Activity {
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    Log.d("TEST", "Hello");
	}
 
	@Override
	protected void onStop () {
		super.onStop();
    	Log.d("TEST", "Bye");	
	}
 
}

当启动该程序时,从DDMS的Logcat中可以看到“Hello”,而当按退出键退出程序时,Logcat中可以看到“Bye”。而在运行过程中,这个应用什么都不做,不响应任何其他按键和点击、甚至都没有一个自己的图形界面。

Android的图形界面是通过布局来设置的,主要依赖于res/layout内的xml文件。例如有若干xml布局文件a.xml、b.xml等,则系统自动生成的UI控制文件R.java内会含有R.layout.a、R.layout.b等id,在java源代码中需要借助于如是id来引用相应的布局。

布局中的各种控件对应Android的View类,可以通过Activity类的方法findViewById来获取View对象,以实现各种控件的交互功能。

通过新建一个控制布局的文件layout.xml,可以建立一个简单的GUI来显示一行文字:

<?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>

并在onCreate中将该布局设置为MyTest行为场景的视图:

package com.test.hello;
 
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
 
public class MyTest extends Activity {
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    Log.d("TEST", "Hello");
 
	    setContentView(R.layout.layout);
	}
 
	@Override
	protected void onStop () {
		super.onStop();
    	Log.d("TEST", "Bye");	
	}
}

Android为了减少UI和应用程序的耦合性,使用XML文件来管理字符、图片的的资源数据,因此,我们还需要建立一个xml资源文件来设置要显示的文字如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, MyTest!</string>
    <string name="app_name">MyTest</string>
</resources>

则程序运行时就会显示“Hello World, MyTest!”。在这种情况下,如果要更改显示的文字,不需要更改代码,只需要更改资源文件即可。如果要动态地修改控件的属性,则需要使用findViewById函数。在OnCreate中添加以下代码后,“Hello World, MyTest!”会成为红色的大号字:

	    TextView textview = (TextView) findViewById(R.id.text);
	    textview.setTextSize(80);
	    textview.setTextColor(Color.rgb(255, 0, 0));

这里涉及到的最主要的两个API是setContentView和findViewById,其中,前者根据布局文件为当前activity建立并绘制View;后者依据View的ID获得View的引用。

应用程序和行为意图

所有Android应用工程都可以打成一个apk包,包含了编译后的java包及其依赖的共享库、数据和资源,这样一个apk文件可以作为一个应用安装到Android系统中。在运行过程中,系统会为每一个应用分配独立的运行沙盒,一个特定的Linux用户、至少一个Linux进程以及JAVA虚拟机。

Android应用程序支持四种基础组件,除了上文提到的Activity之外,还包括Service,Content Provider以及Broadcast Receiver,每个应用程序至少包含一个基础组件。

其中,Activity指的是拥有GUI并支持用户交互的行为场景,基类为android.app.Activity;而Service指的是某种后台服务,基类为android.app.Service,Service没有GUI,但可以同Acitvity进行交互;Content Provider负责应用程序数据的存取管理,基类为ContentProvider;Broadcast Receiver则赋值接收来自系统和应用程序的广播事件,基类为BroadcastReceiver。

要激活Android应用程序中任意一个除去Content Provider的基础组件,都必须给出一个行为意图,即一个android.content.Intent对象,其实就是一个消息的封装。Intent对象的属性包括:Component Name、Action、Data及Category等。如果设定了Intent对象的Component Name,那么这个Intent就是一个显式的Intent,要激活的组件是明确的;否则,系统会在全局范围内根据Intent的Action、Data以及Category进行匹配,并列出所有符合条件的组件。

基础组件的描述——包括Intent匹配声明——都写在一个AndroidManifest.xml文件中,这是一个Android应用程序工程中的全局文件,该文件除了描述应用包含的基础组件之外还用于声明应用程序的全局属性如权限要求等。其基本结构如:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.hello"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".MyTest"
            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>

以上其实就是Hello World程序的声明文件,由ADT自动生成。可以看出,application标签内只有一个activity标签,表示这个应用只有一个activity,它的名字为“.MyTest”,对应MyTest类,如果以一个组件名设定为“com.test.hello.MyTest”的Intent启动Activity,则系统会找到它;它的label设定为资源中的一个字符串,可以显示在界面中;接下来是intent-filter,允许这个activity在特定条件下被非显式地启动。

行为意图Intent提供了一种消息机制。Intent对象封装的消息包含以下信息:

  • Component Name:组件名。这是一个包含包路径的完整类名称。
  • Action:行为。声明如何处理给定的Intent,在android.intent.action中定义。譬如MAIN表示启动一个新的Activity。
  • Category:类别。指定可以处理该Intent的应用组件的类别,在android.intent.category中定义。
  • Data:
  • Extras:
  • Flags:

View及GUI

View是Android GUI中最重要的一个类,它实现了屏幕中某个矩形区域的绘制和事件响应机制,通过使用各种View的派生类,可以实现丰富而友好的各种人机交互。

GUI控件

Android的GUI控件在android.widget包中,均派生自View类。首先,每个控件都具备各种xml属性,用于在定义布局的xml文件中定制控件;其次,每个控件又是一个java类,拥有多种方法来实现与用户的交互。以TextView为例,在Android SDK文档中,会同时给出各种xml属性及与之对应的java方法:

Attribute Name Related Method Description
android:autoLink setAutoLinkMask(int)Controls whether links such as urls and email addresses are automatically found and converted to clickable links.
android:autoTextsetKeyListener(KeyListener)If set, specifies that this TextView has a textual input method and automatically corrects some common spelling errors.

常见控件及其派生关系如下:

  • android.widget.AnalogClock
  • android.widget.ProgressBar
    • android.widget.AbsSeekBar
      • android.widget.RatingBar
      • android.widget.SeekBar
  • android.widget.TextView
    • android.widget.Button
      • android.widget.CompoundButton
        • android.widget.CheckBox
        • android.widget.RadioButton
        • android.widget.ToggleButton
    • android.widget.CheckedTextView
    • android.widget.Chronometer
    • android.widget.DigitalClock
    • android.widget.EditText
      • android.widget.AutoCompleteTextView
        • android.widget.MultiAutoCompleteTextView
  • android.widget.ImageView
    • android.widget.ImageButton

Android还定义了一个特殊的View的子类ViewGroup,它可以充当其他View对象的容器,从而实现多个View对象的可控布局。派生自ViewGroup用于控制布局的类主要包括:

  • android.widget.AbsoluteLayout
    • android.webkit.WebView
  • android.widget.RelativeLayout
  • android.widget.LinearLayout
    • android.widget.RadioGroup
    • android.widget.TabWidget
    • android.widget.TableLayout
    • android.widget.TableRow
  • android.widget.FrameLayout
    • android.widget.DatePicker
    • android.widget.HorizontalScrollView
    • android.widget.MediaController
    • android.widget.ScrollView
    • android.widget.TabHost
    • android.widget.TimePicker
  • android.widget.AdapterView<T extends Adapter>
    • android.widget.AdapterView<ListAdapter>
      • android.widget.AbsListView
        • android.widget.GridView
        • android.widget.ListView
          • android.widget.ExpandableListView
    • android.widget.AdapterView<SpinnerAdapter>
      • android.widget.AbsSpinner
        • android.widget.Gallery
        • android.widget.Spinner

其中,AdapterView是一个用途广泛的ViewGroup,借助Adapter接口可完成复杂数据集在用户界面上的体现。

SurfaceView和TextureView

数据存储

Shared Preference

文件

SQL Lite

Content Provider

网络存储

平台及配置

为一个Android工程配置合适的目标平台可以有效地提高应用的兼容性。如果一个Android应用的目标平台比较新,则应用可以使用较新的API接口,但无法适应老的设备;而如果一个Android应用的目标平台设置比较老,则应用可以适应更多的设备,却无法使用最新的API。这个问题可以通过Android支撑库解决,通过在工程中导入一个合适的Android支撑库,可以在老的平台上支持某些新功能。

一个API级别对应一次Android发布,譬如,Android 4.0对应的API级别为14,而Android 4.1.2对应的API级别为16。在Eclipse中,可以通过SDK Manager管理下载不同级别的API包。

亲手冲一杯好红茶

使用C和C++

深入Framework

获取源码

Android是开放源码的,Andy Rubin曾用一个著名的推来说明这一点:

the definition of open:“mkdir android ; cd android ; repo init -u git://android.git.kernel.org/platform/manifest.git ; repo sync ; make”

虽然现在Android的代码已经转移到了自己的服务器上,但Andy的推仍旧管用,而这里可以拿到更详细的关于如何下载源代码的信息。

编译

官方推荐的主机编译环境是Ubuntu,在进行编译之前,需要安装一系列必要的软件包,关于细节,官方也提供了足够详细的指导

编译生成的二进制文件分为两类:一类在宿主机上运行,位于out/host目录,如SDK工具adb等,这些文件目前针对的是32位i386架构,如果编译环境为x86-64架构,则需要安装大量的32位库以保持兼容;另一类在目标板上运行,位于out/target目录,其中包含了bootloader、Linux kernel和整个Android平台及应用,除去Java应用和库,其它部分都遵循arm eabi规范(目前Google官方不提供Android向其它非arm平台的移植)。

 
tech/os/android.txt · Last modified: 2014/11/10 08:22 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki