Android入门文档

该文章为网络材料整理,部分内容经过重新编写。

一、 名词介绍

JDK:Java Development Kit Java 语言的软件开发工具包
JRE:Java Runtime Environment Java运行环境
SDK:Software Development Kit 软件开发工具包,Android SDK即Android 软件开发包
NDK:Native Development Kit 原生软件开发包,即在SDK前面又加上“原生两个字”
JNI:Java Native Interface 允许Java代码和其他语言写的代码进行交互的一种机制
ADT:Android Developer Tools Android开发工具集合
adb:Android Debug Bridge Android调试桥
APK:AndroidPackage Android程序安装包
JVM:Java Virtual Machine JVM虚拟机
JIT:Just-In-Time Compiler 即时编译器
JAR:Java Archive Java Java归档文件

二、 Android层次划分

android 平台大的方面的层次可以划分成三个层次,包括一个操作系统,中间件和应用程序,android 的系统框架图如下:

这里写图片描述

图中的软件层次自上而下分成4个层次

  • 应用程序(Application)
  • 用用程序框架(Application Framework)
  • 各种类库(Libraries)和android运行时(Adnorid Runtime)
  • 操作系统(OS)

1. 应用程序(Application)

应用层是和用户交互的一个层次,用户可以看得见的一些应用,用户可以操作。这类应用基本都是通过Java语言编写的独立的能够完成某些功能的应用程序。Android本身提供了桌面(Home),联系人(Contacts),拨打电话(Phone),浏览器(Browers)等很多基本的应用程序。开发人员可以使用应用框架提供的API编写自己的应用程序,普通开发人员要做的事情就是开应用层的程序提供该广大消费者使用。

2. 应用程序框架(Application Framework)

普通开发者可以使用Android基本应用程序使用的系统API,android 应用框架中的各个模块都可以被复用,各种服务也可以被复用,理解了这个机制,开发人员可以更好的更轻松的开发出优秀的android应用。开发过程中常用到的基本框架组件如下:

一组View(UI 组件),这些UI组件包括Button(按钮),EidtView(文本框),TextView(标签),List(列表)等等,灵活运用这些组件可以快速方便的创建良好的用户交互界面。

Content Providers(内容提供者),听起来有点抽象,通俗的理解Content Provider 就是提供一种服务,通过这种服务应用程序之间可以实现数据的互相 访问和共享,比如通讯录的存储就使用了这种服务,其它应用也可以访问通讯录中存储的联系人信息。

Resource Manager 顾名思义就是资源管理,android中的资源很多包括图片,用户界面(Layout xml),字体,颜色,UI组件的Id等等都可以称之为资源,这些丰富的资源,都是通过Resource Manager来统一进行管理。

Notification Manager(消息通知管理),它在不影响用户正常操作和使用设备的时候在状态栏上提供消息的提示。比如有短信来的时候,android自动会将这个消息提示在状态栏上,用户可以及时的看到。

Activity Manager(活动管理),Activity管理着应用程序的生命周期,并且控制着应用的导航,扮演控制器的角色。每个Activity类似于Windows应用中的一个wendow。一般的应用都是通过一个个Activity交互构成的。

  • Window Manager(窗口管理),管理所有启动的窗口。
  • Location Manager(位置管理),用来管理地图服务的相关功能。
  • Telephoney Manager(电话管理),用来管理有关的电话的相关功能。
  • Package Manager(包管理),管理所有的安装在android系统内的应用程序。

3. 库(Libraries)和运行环境(RunTime)

这部分内容开始涉及底层,开发普通的应用不会直接对这个层进行操作。这层中包含了一组类库(Libraries)和运行时(RunTime),系统C库(libc),一个从BSD集成来的标准C系统函数库(libc)它是专门为基于嵌入式Linux的设备定制的。

  • 媒体库(Media Framework),基于PackeVideo
    OpenCore,该库支持多种常用的音频,视频格式以及回放和录制,同时支持静态图像文件。编码格式包括:MPEG4、H.264,MP3、AAC、AMR、JPG、PNG。
  • Surface Manager 对显示子系统的管理,并且为多个应用提供2D,3D图层的无缝融合。
  • WebKit,一个最新的web浏览器引擎,用来支持Andiroid浏览器或者嵌入的web视图。
  • SGL 底层的2D图形引擎。
  • OPENGL|ES,基于OpenGL ES 1.0 APIs实现,该库可以使用硬件3D加速或者使用高度优化的3D软加速。
  • FreeType,位图(bitmap)和适量(vector)字图显示支持。
  • SQLite,一个对所有应用程序可用,功能强大的轻量级关系型数据库引擎。
  • Core Libraries 该核心库提供了Java编程语言核心库的大多数功能。
  • Dalvik VM, android平台的一个虚拟机,它相当于PC中Java的虚拟机JVM。

4. 操作系统(OS)

Android 的核心系统服务依赖于Linux 2.6 内核,操作系统为Android提供的服务包括:

  • 安全性(Security)。
  • 内存管理(Memory Management)
  • 进程管理(Process Management)
  • 网络堆栈(Network Stack)
  • 驱动程序模型(Driver Model):详见5.3
  • -

5. Android系统对Linux的修正

Android是执行于Linux kernel之上,但并不是GNU/Linux。因为在一般GNU/Linux里支持的功能,Android大都没有支持,包括Cairo、X11、Alsa、FFmpeg、GTK、Pango及Glibc等都被移除掉了。Android又以bionic取代Glibc、以Skia取代Cairo、再以opencore取代FFmpeg等等。Android为了达到商业应用,必须移除被GNU GPL授权证所约束的部份,例如Android将驱动程序移到userspace,使得Linux driver与Linux kernel彻底分开。

(1) 它没有glibc支持,而使用自己开发的Bionic

Bionic是Android的C/C++ library, libc是GNU/Linux以及其他类Unix系统的基础函数库,最常用的就是GNU的libc,也叫glibc。Android之所以采用bionic而不是glibc,有几个原因:

  • 版权问题,因为glibc是LGPL
  • 库的体积和速度,bionic要比glibc小很多。
  • 提供了一些Android特定的函数,getprop LOGI等

(2) 它并不包括一整套标准的Linux使用程序

Android并没有完全照搬Liunx系统的内核,除了修正部分Liunx的Bug之外,还增加了不少内容,比如:它基于ARM构架增加的Gold-Fish平台,以及yaffs2 FLASH文件系统等。

(3) Android专有的驱动程序

Android Ashmem
为用户空间程序提供分配内存的机制,为进程间提供大块共享内存,同时为内核提供回收和管理这个内存。
设备节点:/dev/ashmen .主设备号 10.
源码位置: include/linux/ashmen.h Kernel /mm/ashmen.c
相比于 malloc 和 anonymous/named mmap 等传统的内存分配机制,其优势是通过内核驱动提供了辅助内核的内存回收算法机制(pin/unoin)
Android Logger
无论是底层的源代码还上层的应用,我们都可以使用 logger 这个日志设备看、来进行调试。
设备节点: /dev/log/main /dev/log/event /dev/log/radio
源码位置:include/linux/logger.h include/linux/logger.c
Android Binder
IPC Binder 一种进程间通信机制。他的进程能够为其它进程提供服务 —– 通过标准的 Linux 系统调用 API。
设备节点 :/dev/binder
源码位置:Kernel/include/linux/binder.h Kernel/drivers/misc/binder.c
Android Power Management
一个基于标准 linux 电源管理的轻量级 Android 电源管理系统。
源码位置:drivers/android/power.c kernel/power/
Low Memory Killer
它在用户空间中指定了一组内存临界值,当其中某个值与进程描述中的 oom_adj 值在同一范围时,该进程将被Kill掉(在parameters/adj中指定oome_adj 的最小值)。它与标准的Linux OOM机制类似,只是实现方法不同
源码位置:drivers/misc/lowmemorykiller.c
Android PMEM
PMEM 主要作用就是向用户空间提供连续的物理内存区域。
1.让 GPU 或 VPU 缓冲区共享 CPU 核心。
2.用于 Android service 堆。
源码位置:include/linux/android_pmem.h drivers/android/pmem.c
USB Gadget
基于标准 Linux USB gaeget 驱动框架的设备驱动。
源码位置:drivers/usb/gadet/
Ram Console
为了提供调试功能,android 允许将调试日志信息写入这个设备,它是基于 RAM 的 buffer.
源码位置: drivers/staging/android/ram_console.c
Time Device
定时控制,提供了对设备进行定时控制的功能。
源码位置:drivers/staging/android/timed_output.c(timed_gpio.c)
Android Alarm
提供一个定时器,用于把设备从睡眠状态唤醒,同时它还提供了一个即使在设备睡眠时也会运行的时钟基准。
设备节点:/dev/alarm
源码位置:drivers/trc/alarm.c

三、 java和c/c++的交互(JavaCallBackC,JavaConnectC)

在一些Android应用的开发中,需要通过JNI和 Android NDK工具实现JAVA和C/C++之间的相互调用。

Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI是本地编程接口,它使得在 Java 虚拟机 (VM)内部运行的 Java代码能够与用其它编程语言(如 C、C++和汇编语言)编写的应用程序和库进行交互操作。

由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Bytecode之后,必须靠Dalvik虚拟机(VM: Virtual Machine)来执行。在执行Java类的过程中,如果Java类需要与C组件沟通时,VM就会去载入C组件,然后让Java的函数顺利地调用到C组件的函数。此时,VM扮演着桥梁的角色,让Java与C组件能通过标准的JNI介面而相互沟通。

在实际应用中这两者之间的调用关系可以归纳为以下四种方式:
在应用的JAVA代码中调用NDK中C/C++实现的函数。
2、在NDK开发中的C/C++代码调用应用中JAVA类的静态函数。
3、在NDK开发中的C/C++代码调用应用中JAVA类当前传入NDK中的实例的函数。
4、在NDK开发中的C/C++代码调用应用中JAVA类新建实例的函数。

1. java调用C++

要想让java调用C++,必须让C++函数按着命名规则来。命名规则为
返回值 Java_包路径类名函数名(JNIEnv* env,jobject obj);示例代码如下:

/**
 *  Java 中 声明的native getTime 方法的实现
 */
void Java_com_duicky_MainActivity_getTime(JNIEnv* env, jobject thiz)
{
    if(jniEnv == NULL) {
        jniEnv = env;
    }
    GetTime();
}

/**
 *  Java 中 声明的native sayHello 方法的实现
 */
void Java_com_duicky_MainActivity_sayHello(JNIEnv* env, jobject thiz)
{
    if (jniEnv == NULL) {
        jniEnv = env;
    }
    SayHello();
}

2. C++调用java

C++调用java就会比较复杂,其原理是从JVM中获取Java对象,再从Java对象中获取Java方法,或者直接根据Java对象获取Java方法。示例代码如下:

    JNIEnv* env;
    //对用java的Class
    jclass cls;
    jobject obj;
    //映射方法
    jmethodID mid;
    //构建一个Class
    cls = jniEnv->FindClass("com/ndk/testndk/TestHello");//写上类的路径
    //实例化对象
    //方法一
    obj = env->AllocObject(cls);
    //方法二
    jmethodID obj_id = env->GetMethodID(cls,"<init>", "()V");
    TestProvider mTestProvider = env->NewObject(cls,obj_id);
    //映射方法
    //其中"()Ljava/lang/String;",括号是参数,Ljava/lang/String;是返回值,如有  参数string,即为"(Ljava/lang/String;)Ljava/lang/String;"
    //静态
    mid = env->GetStaticMethodID(cls,   "getStaticString","()Ljava/lang/String;");
    //非静态
    mid = env->GetMethodID(cls, "getString","()Ljava/lang/String;");
    //调用方法
    //静态:
    env->CallStaticObjectMethod(cls, mid);
    //非静态:
    env->CallVoidMethod(obj, mid,jstr);

3. JNI 4.0后所做的更改

注:这章是要点,详细文档在另一博文中《Android 入门文档_Android 4.0后JNI所做的更改

每个开发者都想要一个好用垃圾回收器(garbage collector,简称GC)。做的好的GC是会随时移动对象(objects)的。这样就能便于提供更高效的内存分配和批量内存回收,避免堆内存碎片,并可能提高定位性能(locality)。如果你把指向这些对象的指针递交给原生代码的话,随时移动对象就是个问题了。JNI使用像jobject这样的类型来解决这个问题:不是直接递交指针,而是给你一个能够在必要时兑换为实际指针的透明句柄(opaque handle,概念上对开发人员透明)。通过使用句柄,当GC移动对象时,只需要更新句柄对应表使其指向对象的新位置就可以了。这就意味着原生代码不用在每次GC运行时被留下一堆不可用的指针了。

在之前的Android版本中,我们并没有使用间接句柄;我们用的是直接指针。由于我们并没有实现会移动对象的GC所以这看起来没嘛大问题,可是这却会导致开发人员写出看似工作正常而实际是有bug的代码。在ICS中,即使我们依然没有实现一个会移动对象的GC,可我们已经转为使用间接引用了所以你们也会开始检查出你们原生代码中的bug了。

ICS提供了一种JNI bug兼容模式:只要AndroidManifest.xml中的targetSdkVersion版本号是低于ICS的(14-),你的代码就能得到“豁免”。可是一旦你更新了targetSdkVersion的话,你的代码就必须是正确的!

CheckJNI已经被更新为会检测并报告这些错误,并且在ICS中,如果manifest中的debuggable=”true”的话CheckJNI默认就已经开启了。

四、 Android的专用驱动

1. Binder机制(Fibonacci)

Binder(简要介绍,以前的文档有详解):基于OpenBinder框架的一个驱动,用于提供 Android平台的进程间通信(InterProcess Communication,IPC)功能。Binder通信是一种client-server的通信结构。从表面上来看,是client通过获得一个server的代理接口,对server进行直接调用;实际上,代理接口中定义的方法与server中定义的方法是一一对应的;client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成为Parcel对象;.代理接口将该Parcel发送给内核中的binder driver.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回;整个的调用过程是一个同步过程,在server处理的时候,client会block住。

(1) AIDL机制

由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象。在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界。通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作,AIDL是Binder机制在Java层的封装。
AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl,保存在src目录下。如果其他应用程序需要IPC,则那些应用程序的src也要带有这个文件。Android SDK tools就会在gen目录自动生成一个IBinder接口文件。service必须适当地实现这个IBinder接口。那么客户端程序就能绑定这个service并在IPC时从IBinder调用方法。每个aidl文件只能定义一个接口,而且只能是接口的声明和方法的声明。

2. Ashmem机制

Ashmem:为进程间提供大块共享内存,同时为内核提供回收和管理这个内存的机制。使用了Binder机制进行内存共享。 Android系统的匿名共享内存子系统的主体是以驱动程序的形式实现在内核空间的,同时,在系统运行时库层和应用程序框架层提供了访问接口,其中,在系统运行时库层提供了C/C++调用接口,而在应用程序框架层提供了Java调用接口。这里,我们将直接通过应用程序框架层提供的Java调用接口来说明匿名共享内存子系统Ashmem的使用方法,毕竟我们在Android开发应用程序时,是基于Java语言的,而实际上,应用程序框架层的Java调用接口是通过JNI方法来调用系统运行时库层的C/C++调用接口,最后进入到内核空间的Ashmem驱动程序去的。

(1) Memoryfile 文 ###件

MemoryFile是Android上的一种高性能I/O读写文件,其采用了Android的Ashmem机制。MemoryFile是对Ashmem驱动的封装器,而Ashmem本职上是基于共享内存的,在dev目录下对应的设备为\dev\ashmem.相比于传统的内存分配机制,如malloc,Ashmem的好处是提供了辅助内核内存回收算法的pin\unpin机制,使通过MemoryFile进行I/O操作可以在很大程度上提高效率。
MemoryFile类直接对native方法进行封装,通过JNI调用底层C++方法,下面对构造函数进行分析。

public MemoryFile(String name, int length) throws IOException {
    mLength = length;
    mFD = native_open(name, length);
    if (length > 0) {
        mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE);
    } else {
        mAddress = 0;
    }
}

这里直接调用native方法native_mmap对name文件进行内存映射,这里的native_mmap方法调用JNI方法android_os_MemoryFile_open,这个函数又通过运行库提供的ashmem_create_region来创建内存共享映射,这个函数的实现在system/core/libcutils/ashmem-dev.c中。

3. Logger作用

Logger:一个轻量级的日志设备,用于抓取Android系统的各种日志。Android中LOG的实现架构如图5.3.1所示,这基本上也是Android的某个模块实现各个层次的经典架构。
图5.3.1
Android应用程序通过Framework提供的机制操作;Java领域需要本地c/c++提供服务的地方,通过JNI实现;JNI调用底层库;库函数通过操作映射的设备文件操作设备,LINUX kernel中的Driver完成相应的操作。另外,抛开Java和JNI,LINUX上用户域的c/c++程序,也可以通过操作设备文件来完成。
Android的LOG也是这样实现的,并将在本系列文章中分别讲述。应用程序通过android.util.Log里的各种静态方法,输出LOG信息[系列之二中具体讲述];Log通过JNI接口调用c/c++的实现,而本地实现的写LOG,也基本就是写信息到设备文件[系列之三中具体讲述];设备文件是Android为了LOG机制而写的LINUX的一个轻量级的驱动logger[系列之四中具体讲述];LOG信息的显示可以是Emulator/Device上运行的LogCat程序如图 5.3.2所示;另外,Android的本地实现库也可利用现有机制,在c/c++的空间 直接输出LOG。
图 5.3.2

五、 Android四大组件

1. Activity

activity类处于android.app包中,继承体系如下:

  1. java.lang.Object
  2. android.content.Context
  3. android.app.Activity

activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,当activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowIsFloating的主题集合),或者嵌入到其他的activity(使用ActivityGroup)。大部分的Activity子类都需要实现以下两个接口:

onCreate(Bundle)接口是初始化activity的地方. 在这儿通常可以调用setContentView(int)设置在资源文件中定义的UI, 使用findViewById(int) 可以获得UI中定义的窗口.

onPause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于ContentProvider保存数据).

为了能够使用Context.startActivity(),所有的activity类都必须在AndroidManifest.xml文件中定义有相关的“activity”项。

activity类是Android 应用生命周期的重要部分。在系统中的Activity被一个Activity栈所管理。当一个新的Activity启动时,将被放置到栈顶,成为运行中的Activity,前一个Activity保留在栈中,不再放到前台,直到新的Activity退出为止。Activity有四种本质区别的状态:

  • 在屏幕的前台(Activity栈顶),叫做活动状态或者运行状态(active or running)
  • 如果一个Activity失去焦点,但是依然可见(一个新的非全屏的Activity 或者一个透明的Activity
    被放置在栈顶),叫做暂停状态(Paused)。一个暂停状态的Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被杀掉。
  • 如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉。
  • 如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接杀掉它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。

下面的图显示了Activity的重要状态转换,矩形框表明Activity在状态转换之间的回调接口,开发人员可以重载实现以便执行相关代码,带有颜色的椭圆形表明Activity所处的状态。
这里写图片描述
在上图中,Activity有三个关键的循环:
整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。

可见的生命周期,从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。

前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。

2. Service

Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

通过startService()启动的服务处于“启动的”状态,一旦启动,service就在后台运行,即使启动它的应用组件已经被销毁了。通常started状态的service执行单任务并且不返回任何结果给启动者。比如当下载或上传一个文件,当这项操作完成时,service应该停止它本身。

还有一种“绑定”状态的service,通过调用bindService()来启动,一个绑定的service提供一个允许组件与service交互的接口,可以发送请求、获取返回结果,还可以通过夸进程通信来交互(IPC)。绑定的service只有当应用组件绑定后才能运行,多个组件可以绑定一个service,当调用unbind()方法时,这个service就会被销毁了。

意思是service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。
这里写图片描述
通过这个图可以看到,两种启动service的方式以及他们的生命周期,bind service的不同之处在于当绑定的组件销毁后,对应的service也就被kill了。service的声明周期相比与activity的简单了许多,只要好好理解两种启动service方式的异同就行。

3. BroadcastReceiver(BroadcastReceiver)

(1) BroadcastReceiver概述:

广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

(2) BroadcastReceiver事件分类

一类为系统广播,另一类为自定义广播。
系统广播全集详见附录。

(3) BroadcastReceiver事件的编程流程

注册广播事件:注册方式有两种。一种是静态注册,就是在 AndroidManifest.xml文件中定义,注册的广播接收器必须要继承BroadcastReceiver类;在AndroidManifest.xml中用标签生命注册,并在标签内用标签设置过滤器。另一种是动态注册,是在程序中使用 Context.registerReceiver注册,注册的广播接收器相当于一个匿名类。两种方式都需要IntentFIlter。

发送广播事件:通过Context.sendBroadcast来发送,由Intent来传递注册时用到的Action。

接收广播事件:当发送的广播被接收器监听到后,会调用它的onReceive()方法,并将包含消息的Intent对象传给它。onReceive中代码的执行时间不要超过5s,否则Android会弹出超时dialog。

4. ContentProvider

内容提供者将一些特定的应用程序数据供给其它应用程序使用。数据可以存储于文件系统、SQLite数据库或其它方式。内容提供者继承于ContentProvider 基类,为其它应用程序取用和存储它管理的数据实现了一套标准方法。然而,应用程序并不直接调用这些方法,而是使用一个 ContentResolver 对象,调用它的方法作为替代。ContentResolver可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理。

六、 组件相关类

1. Application

Application和Activity,Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。
Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。
通常我们是不需要指定一个Application的,系统会自动帮我们创建,如果需要创建自己的Application,那也很简单!创建一个类继承Application并在AndroidManifest.xml文件中的application标签中进行注册(只需要给application标签增加name属性,并添加自己的 Application的名字即可)。
启动Application时,系统会创建一个PID,即进程ID,所有的Activity都会在此进程上运行。那么我们在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,我们在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变。
Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以可以通过Application来进行一些,如:数据传递、数据共享和数据缓存等操作。
在Android中,可以通过继承Application类来实现应用程序级的全局变量,这种全局变量方法相对静态类更有保障,直到应用的所有Activity全部被destory掉之后才会被释放掉。

2. Context

它描述的是一个应用程序环境的信息,即上下文。

  • getBaseContext():获取由函数进行赋值的Context。
    举例说明:activity中getApplicationContext(),this,getBaseContext()的区别
    getApplicationContext() 返回应用的上下文,生命周期是整个应用,应用摧毁它才摧毁。

  • Activity.this的context 返回当前activity的上下文,属于activity ,activity摧毁他就摧毁。

  • getBaseContext() 返回由构造函数指定或setBaseContext()设置的上下文。

    最重要的子类:Application、Activity、Service

3. Intent和IntentFilter(BroadcastReceiver)

Intent:Intent 是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由Intent来协助完成android各个组件之间的通讯。

IntentFilter:主要是用来注册action,可以在XML中注册,也可以在代码中注册。
action:用作Intent的跳转标签,使用IntentFilter进行注册。

4. Bundle(BroadcastReceiver)

Bundle:一个键值对集合,跟Map类似,其内部数据存储格式就是Map,用于存放key-value名值对形式的值。用于组件间的数据传输,Intent可携带Bundle传输。

5. Parcel(BroadcastReceiver)

Parcel:Parcel就是一个存放读取数据的容器,其实现了对数据的序列化。

七、 Android相关配置文件

AndroidManifest.xml
AndroidManifest.xml文件是Android程序的权限申请和定义配置文件,程序员在开发时需要通过其来向系统预先定义和申请应用程序运行所需要的权限。

Android.mk
Android JNI编程中C/C++的编译配置文件,跟makefile类似。

Appllication.mk
描述Android应用程序中需要的本地模块的Application.mk的语法使用。

八、 Android常用包

1. android.app

android.app :提供高层的程序模型、提供基本的运行环境
提供Android中高层的封装类和其相应的接口,其中有四大组件中的两个Activity和service。还包含了ActivityManager(Activity管理器),Fragment,ActionBar,Diglog(非阻塞式弹出框),Notification(消息通知)。

2. android.content

android.content 包含各种的对设备上的数据进行访问和发布的类
其中包含了数据共享最重要的两个类ContentProvider和ContentResolver,除此之外还有:
Intent and IntentFilte;
广播接收者BroadcastReceiver;
对资源文件访问的类Resources;
对设备上已安装程序包信息的访问的类PackageManager。

3. android.database

android.database :通过内容提供者浏览和操作数据库,主要的类有:
查询后返回的结果集Cursor
SQLite的管理器SQLiteOpenHelper

4. android.graphics

android.graphics :底层的图形库,包含画布,颜色过滤,点,矩形,可以将他们直接绘制到屏幕上.
这个包主要是用于绘图操作,其中里面有几个比较重要的类:
图形对象Bitmap
画布Canvas
摄像头对象Camera

5. android.location

android.location :定位和相关服务的类
主要用于定位,此API谷歌不推荐使用

6. android.media

android.media :提供一些类管理多种音频、视频的媒体接口
Android获取和播放音频流的重要类:AudioRecord和AudioTrack;
Android获取和播放视频流的重要类;MediaRecorder和MediaPlayer;
新API硬件解码类:MediaCodec

7. android.net

android.net :提供帮助网络访问的类,超过通常的java.net.* 接口
Bonjour服务发现协议的实现:nsd包;
http协议的实现:http包;
实时传输协议rtp;rtp包;
sip协议的实现:sip包;
p2p协议的实现:wifi.p2p包;
wifi管理:WiFi包;

8. android.os

android.os :提供了系统服务、消息传输、IPC机制,其中主要的类有:
Parcel;
Bundle;
进程间通信Binder机制:Binder;
消息队列机制的相关类:Handler、Looper、Message、MessageQueue

9. android.opengl

android.opengl :提供OpenGL的工具,3D加速,主要类有:
OpenGL 视图显示窗口:GLSurfaceView;
各版本的OpenGL ES协议;

10. android.provider

android.provider :提供类访问Android的内容提供者
主要提供Android内部存储数据的访问地址和相应数据字段,如通讯录数据库类:ContactsContract.Contacts

11. android.telephony

android.telephony :提供与拨打电话相关的API交互,主要类有:
短信管理类:SmsManager;
电话服务访问类:TelephonyManager

12. android.view

android.view :提供基础的用户界面接口框架,主要类或者接口有:
视图绘制相关类和接口: Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback;
按键事件类:KeyEvent;
界面组件的父类:View;
可包含组件的父类:ViewGroup;

13. android.util

android.util :涉及工具性的方法,例如时间日期的操作,主要类有:
Base64的编解码:Base64;
常用的Log打印工具类:Log;
XML解析类:XML;
时区处理类:TimeUtils

14. android.webkit

android.webkit:默认浏览器操作接口,主要类有:
内置浏览器组件:WebView;
WebView消息处理类:WebViewClient;
辅助处理渲染,解析JS语言:WebChromeClient

15. android.widget

android.widget:包含各种UI元素(大部分是可见的)在应用程序的屏幕中使用,主要控件有:
按钮:Button;
列表:ListView;
复选框:CheckBox;
文本框:TextView
文本输入框:EditText

附录:系统广播大全

Intent.ACTION_AIRPLANE_MODE_CHANGED;
//关闭或打开飞行模式时的广播
Intent.ACTION_BATTERY_CHANGED;
//充电状态,或者电池的电量发生变化
//电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过Context.registerReceiver()注册
Intent.ACTION_BATTERY_LOW;
//表示电池电量低
Intent.ACTION_BATTERY_OKAY;
//表示电池电量充足,即从电池电量低变化到饱满时会发出广播
Intent.ACTION_BOOT_COMPLETED;
//在系统启动完成后,这个动作被广播一次(只有一次)。
Intent.ACTION_CAMERA_BUTTON;
//按下照相时的拍照按键(硬件按键)时发出的广播
Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
//当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏时,android系统都会广播此Action消息
Intent.ACTION_CONFIGURATION_CHANGED;
//设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
Intent.ACTION_DATE_CHANGED;
//设备日期发生改变时会发出此广播
Intent.ACTION_DEVICE_STORAGE_LOW;
//设备内存不足时发出的广播,此广播只能由系统使用,其它APP不可用?
Intent.ACTION_DEVICE_STORAGE_OK;
//设备内存从不足到充足时发出的广播,此广播只能由系统使用,其它APP不可用?
Intent.ACTION_DOCK_EVENT;
//当前底座状态发生改变时发出此广播
//发出此广播的地方frameworks\base\services\java\com\android\server\DockObserver.java
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE;
移动APP完成之后,发出的广播(移动是指:APP2SD)
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
//正在移动APP时,发出的广播(移动是指:APP2SD)
Intent.ACTION_GTALK_SERVICE_CONNECTED;
//Gtalk已建立连接时发出的广播
Intent.ACTION_GTALK_SERVICE_DISCONNECTED;
//Gtalk已断开连接时发出的广播
Intent.ACTION_HEADSET_PLUG;
//在耳机口上插入耳机时发出的广播
Intent.ACTION_INPUT_METHOD_CHANGED;
//改变输入法时发出的广播
Intent.ACTION_LOCALE_CHANGED;
//设备当前区域设置已更改时发出的广播
Intent.ACTION_MANAGE_PACKAGE_STORAGE;
//
Intent.ACTION_MEDIA_BAD_REMOVAL;
//未正确移除SD卡(正确移除SD卡的方法:设置–SD卡和设备内存–卸载SD卡),但已把SD卡取出来时发出的广播
//广播:扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)
Intent.ACTION_MEDIA_BUTTON;
//按下”Media Button” 按键时发出的广播,假如有”Media Button”按键的话(硬件按键)
Intent.ACTION_MEDIA_CHECKING;
//插入外部储存装置,比如SD卡时,系统会检验SD卡,此时发出的广播?
Intent.ACTION_MEDIA_EJECT;
//已拔掉外部大容量储存设备发出的广播(比如SD卡,或移动硬盘),不管有没有正确卸载都会发出此广播?
//广播:用户想要移除扩展介质(拔掉扩展卡)。
Intent.ACTION_MEDIA_MOUNTED;
//插入SD卡并且已正确安装(识别)时发出的广播
//广播:扩展介质被插入,而且已经被挂载。
Intent.ACTION_MEDIA_NOFS;
//
Intent.ACTION_MEDIA_REMOVED;
//外部储存设备已被移除,不管有没正确卸载,都会发出此广播?
// 广播:扩展介质被移除。
Intent.ACTION_MEDIA_SCANNER_FINISHED;
//广播:已经扫描完介质的一个目录
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE;
//
Intent.ACTION_MEDIA_SCANNER_STARTED;
//广播:开始扫描介质的一个目录
Intent.ACTION_MEDIA_SHARED;
// 广播:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。
Intent.ACTION_MEDIA_UNMOUNTABLE;
//
Intent.ACTION_MEDIA_UNMOUNTED
// 广播:扩展介质存在,但是还没有被挂载 (mount)。
Intent.ACTION_NEW_OUTGOING_CALL;
//
Intent.ACTION_PACKAGE_ADDED;
//成功的安装APK之后
//广播:设备上新安装了一个应用程序包。
//一个新应用包已经安装在设备上,数据包括包名(最新安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_CHANGED;
//一个已存在的应用程序包已经改变,包括包名
Intent.ACTION_PACKAGE_DATA_CLEARED;
//清除一个应用程序的数据时发出的广播(在设置--应用管理--选中某个应用,之后点清除数据时?)
//用户已经清除一个包的数据,包括包名(清除包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_INSTALL;
//触发一个下载并且完成安装时发出的广播,比如在电子市场里下载应用?
//
Intent.ACTION_PACKAGE_REMOVED;
//成功的删除某个APK之后发出的广播
//一个已存在的应用程序包已经从设备上移除,包括包名(正在被安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_REPLACED;
//替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧,都会发出此广播?)
Intent.ACTION_PACKAGE_RESTARTED;
//用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
Intent.ACTION_POWER_CONNECTED;
//插上外部电源时发出的广播
Intent.ACTION_POWER_DISCONNECTED;
//已断开外部电源连接时发出的广播
Intent.ACTION_PROVIDER_CHANGED;
//
Intent.ACTION_REBOOT;
//重启设备时的广播
Intent.ACTION_SCREEN_OFF;
//屏幕被关闭之后的广播
Intent.ACTION_SCREEN_ON;
//屏幕被打开之后的广播
Intent.ACTION_SHUTDOWN;
//关闭系统时发出的广播
Intent.ACTION_TIMEZONE_CHANGED;
//时区发生改变时发出的广播
Intent.ACTION_TIME_CHANGED;
//时间被设置时发出的广播
Intent.ACTION_TIME_TICK;
//广播:当前时间已经变化(正常的时间流逝)。
//当前时间改变,每分钟都发送,不能通过组件声明来接收,只有通过Context.registerReceiver()方法来注册
Intent.ACTION_UID_REMOVED;
//一个用户ID已经从系统中移除发出的广播
//
Intent.ACTION_UMS_CONNECTED;
//设备已进入USB大容量储存状态时发出的广播?
Intent.ACTION_UMS_DISCONNECTED;
//设备已从USB大容量储存状态转为正常状态时发出的广播?
Intent.ACTION_USER_PRESENT;
//
Intent.ACTION_WALLPAPER_CHANGED;
//设备墙纸已改变时发出的广播

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值