AndroidApplication Fundamentals(Android应用基础)

Android应用采用Java编程语言来编写,AndroidSDK工具编译我们的代码,连同任何数据和资源文件一起打包成一个APK(一个Android package),后缀名为.apk的文件时归档文件。一个APK文件包含一个Android 应用的所有内容,且是Android设备用来安装应用的文件。

一旦安装到设备中,每个Android应用都工作在自己安全的沙箱中(securitysandbox):

(1)    Android操作系统是多用户的linux系统,每个应用都是一个不同的用户。

(2)    默认情况下,系统为每个应用分配一个唯一的linux用户ID(这个ID只能被系统使用,对于应用来说是未知的)。系统为一个应用的所有文件设置权限,所以只有被非配了用户ID的应用才能够访问这些文件。

(3)    每个进程都有自己的虚拟机(VM),所以一个应用的代码运行在和其他应用相互隔离的空间中。

(4)    默认情况下,每个应用运行在它自己的linux进程中,任何应用的组件(比如activity)需要被执行时Android就会开启进程,并在不在需要或是系统为其他应用必须回收内存是关闭这个进程。

基于上面这些特点,Android系统实现了最小权限原则,也就是说,每个应用默认只能访问它需要用来实现功能的组件。这样可以创造一个非常安全的环境,在此环境下,一个应用不能访问没有经过授权的系统其他部分。

但是,有几种方式可以让一个应用共享数据给其他应用,和一个应用可以访问系统服务:

(1)    为了让不同应用可以互相访问彼此的文件,系统可以安排两个应用共享同一个linux用户ID。为了节省系统资源,拥有相同用户ID的应用程序运行在相同的linux进程和共享相同的VM(应用程序也必须使用相同的证书)。

(2)    一个应用能够请求访问设备数据的权限,比如用户的联系方式(contacts)、短信信息(SMS message)、存储卡(SD卡)、camera、蓝牙、等等,所有应用的权限必须在安装时由用户来授权

上面的这些描述覆盖了一个Android应用如何在系统中存在的基础知识,这个文档的剩余部分为我们介绍:

(1)    定义了我们应用程序的核心框架组件(core framework components)。

(2)    我们在应用的manifest文件声明组件(比如activity等)和需要的设备特征(比如拍照)。

(3)    资源独立于应用代码,并允许我们的应用程序优雅地优化其行为以适用于多种设备配置。

1.      应用组件(App Components)

应用程序组件式一个Android应用程序的基本构建块,每个组件是个不同点,系统可以通过它们进入我们的应用程序(Each component is a different point through which the system canenter your app)。不是所有的组件都是用户的实际入口点,而是一些组件相互依赖,但是每一个作为自己的实体存在和扮演一个特定的角色(每个组件是唯一的构建块,有助于定义我们APP的整体行为)。

Android系统支持4个不同的APP组件,每种类型组件有明显的目的和定义了组件如何被创建和销毁的不同的生命周期。

四种APP组件类型如下:

(1)    Activities

Activity我们理解为活动,一个Activity代表用户界面的一个独立屏幕,比如,一个邮件APP有一个activity来显示新邮件列表,另一个activity用于写一封邮件,并且还有一个activity用于读邮件。虽然这些activities协同工作以构成邮件APP的紧密结合的用户体验,但是每个activity是相互独立的。因此,一个不同的APP可以启动这些activities(只要邮件APP允许这样做)。比如,一个拍照APP为了用户能够分享照片,它能够启动邮件APP的组件来写新邮件。

一个activity作为Activity的子类来实现,我们可以通过开发者指南的Activities部分来学习更多关于activity的功能

(http://developer.android.com/reference/android/app/Activity.html)。

(2)    Services

Servies理解为服务,services组件运行在后台以执行长时间的操作或实话执行远程操作。一个service不提供用户界面,比如,当用户在另一个APP时,一个service可在后台播放音乐,或是从网络获取数据而不阻止用户和一个activity交互。另一种组件,比如activity可以启动service来让它运行,或是activity为了和sevice交互而绑定它。一个serice是作为Service的自来的实现。

(3)    Content providers

内容提供者,一个content provider管理一组共享的APP数据,我们可以保存这些数据到文件系统、SQLite数据库、web,或是保存在我们的应用程序能够访问的任何其他永久保存的位置。通过content provider,其他APP能够查询或甚至是修改这些共享的数据(如果content provider允许这么操作)。比如,Android系统提供一个content provider来管理用户联系人信息,因此,有适当权限的任何APP能够查询content provider的一部分(比如ContactsContract.Data)来读和写一个特定用于的信息。

content provider也有助于读写我们APP私有数据(不共享),比如记事本示例APP使用一个contentprovider来保存笔记。一个content provider作为ContentProvider的子类来实现,并且必须实现一组标准的API,这样可使其他APP执行事务。

(4)    Broadcast receivers

广播接收器,一个broadcastreceivers组件响应整个系统的广播公告,很多广播产生于系统,比如,一个广播通知屏幕要已关闭,电池低电量,或是照片被捕获。APP能够发起广播,比如通知其他APP一些数据已经下载完成并且处于可用状态。虽然broadcast receivers没有显示用户界面,但它们可以在一个广播事件发生的时候创建一个状态栏通知来警告用户。更常见的,虽然一个广播接收器只是其他组件的“网关”,且适用于用来做最少的工作。比如,它根据事件启动一个服务来执行一些工作。一个广播接收器作为BroadcastReceiver的子类来实现,每个广播以Intent对象的形式被分发出去。

Android系统设计一个独特的一面是任何APP能够启动另一个APP的组件,比如,如果我们想要用户使用带摄像头的设备来拍照,可能已经有另一个APP实现了拍照功能,并且我们的APP能够使用这个拍照功能,而不需要自己来开发一个activity来实现拍照功能,而且我们也不需要包含或是链接这个拍照程序。相反,我们能够简单的启动拍照APP的activity来拍照。当拍照完成,照片甚至能够返回到我们的APP中。对于用户来说,就像拍照工恩给你是我们APP实际的一部分一样。

当系统启动一个组件,如果这个组件所在的程序之前没有运行,那么系统就开始这个APP的进程,并且实例化(初始化)这个组件所需要的类。比如,如果我们的APP启动拍照APP的拍照功能对应的activity,这个activity运行在拍照APP的进程,而不是我们APP的进程中。所以,不想其他大部分系统的APP一样,Android系统的APP没有一个单独入口点(比如没有main函数)。

因为系统每个APP运行在自己独立的进程中,并且APP中的文件都有自己的权限来限制访问其他APP。我哦们的AP不能直接激活其他APP的组件,但是Android系统可以,为了激活其他APP的组件,我们必须发送一个说明了我们气筒一个特定组件的意图的消息给系统,这样系统就可以为你激活这个组件。

2.      激活组件(Activating Components)

Android系统4种组件类型中的3种,activity、service和broadcastreceivers这3种是由一种名为intent的异步消息来激活的,这些intents在运行时,把属于我们的APP或是其他APP的单独组件绑定在一起,我们可以把intent看做是需要其他组件action(行动)的消息。

一个intent是以一个Intent对象的形式创建,intent定义一个激活一个指定组件或是一种指定类型的组件的消息,相应地,intent可以说是显示或是隐式指定。

对于activity和service来说,一个intent定义了要执行的操作(比如要view或是send什么)和指定要操作的数据URI(除此之外,开始的组件也需要知道)。比如,一个intent可能为一个activity发送显示一张图片或是打开一个web页的请求。在某种情况下,我们可以启动一个activity来获取返回的结果,在这种情况下,这个activity也能够返回一个intent结果(比如,我们可以发出一个intent让用户选择一个个人联系人名(a personal contact)和让它返回给我们,这个返回的intent包含已选中的contact的URI)。

对于广播接收器,intent简单的定义了要广播的通知(announcement)(比如,一个指示设备电池低电量的广播,只是包含了一个已知动作的字符串(“battery is low”))。

另一组件类型内容提供者不是由intent来激活,而是由一个指定请求目标的ContentResolver来激活。这个内容解析器处理所有与内容提供者的直接事务。所以执行提供者事务的内容提供者不需要intent,而是调用ContentResolver对象上的方法来激活。这样可在内容提供者和这个组件请求的信息保持在一个抽象层(为了安全)。

每种类型的组件有自己的办法来激活相应的组件:

(1)    我们可以通过传递一个Intent给startActivity()或startActivityForResult()(如果我们需要这个activity返回结果)启动一个activity(或是给它一些新的要做的事情)。

(2)    我哦们可以通过传递一个Intent给startSevice()来开启一个service(或是给一个新指令(instructions)给正在运行的serice),或是我们可以传递一个Intent给bindService()来绑定一个service。

(3)    我们可以通过传递一个intent给sendBroadcast()、sendOrderedBroadcast()或是sendStickyBroadcast()这些方法来发起一个广播。

(4)    我们可以通关过调用一个ContentResolver对象的query()来查询一个内容提供者。

3.      Manifest文件

在Android系统能够启动一个APP组件之前,系统必须通过读取APP的AndroidManifest.xml(manifest文件)知道APP的组件。我们的APP必须在这个文件中声明所有的组件,并且这文件必须在APP工程目录的根目录下。

除了声明APP的组件之外,manifest文件还做了下面一些事情:

(1)    确定APP需要的任何用户权限,比如Internet访问权限或是读取用户联系人权限。

(2)    声明运行这个APP需要的最低API版本。

(3)    声明APP需要的硬件和软件特征,比如摄像头、蓝牙服务或是一个多点触屏。

(4)    申明该程序需要连接的API库(不是Android framework的API),比如Google Maps库。

(5)    等等。

4.      声明组件(declaring components)

Manifest文件的首要任务是通知系统关于APP中使用的组件,比如一个manifest文件能像下面一样声明activity:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:icon="@drawable/app_icon.png" ... >
        <activity android:name="com.example.project.ExampleActivity"
                  android:label="@string/example_label" ... >
        </activity>
        ...
    </application>
</manifest>

在<application>元素中,android:icon属性指向了标示这个APP的icon资源。

在<activity>元素中,android:name属性指定了Activity子类的完整类别名称,android:label属性指定了标示activity对于用户可见的label。

我们必须用下面的方式来声明APP的所有组件:

(1)    <activity>元素声明activities。

(2)    <service>元素声明services。

(3)    <receiver>元素声明broadcastreceiver。

(4)    <provider>元素声明contentprovider。

我们在程序中包含了activities、services和content providers,但没有在mainfest文件中声明,那么这些组件对系统不可见,因此,这些组件不能运行。但是,broadcast receivers不仅可以再manifest中声明,也可以在代码中动态创建(作为BroadcastReceiver对象),并通过调用registerReceiver()在系统中注册。

5.      声明组件功能(declaring component capabilities)

正如上面Activating Components部分描述的那样,我们可以使用一个Intent来启动activities、services和broadcast receivers,我们可以通过在Intent显式指定目标组件的名字(使用组件的类名)来实现。但是,intents真正强大的地方在于隐式Intent的概念。一个隐式intent简单的描述了要执行的组件的操作(并且可以有选择性地描述要执行操作的数据),允许系统在设备中找到能够执行这些操作的组件并启动它。如果有多个组件能够执行intent描述的操作,用户可以选择一个来执行。

系统通过比较接收到的intent和定义在设备其他应用manifest文件中的intent filters,从而识别能响应这个intent的组件。

当我们在manifest文件中声明一个activity,我们可选择地包含intent filters,这些intent filters表明了组件对来之其他APP的intent做出反应的能力。我们可以通过添加一个<intent-filter>元素作为组件声明元素的子元素来声明一个intent filter。

比如,如果我们已经有一个带有写邮件activity的邮件APP,我们像下面一样声明一个intent filter来响应“发送”intents(为了发送新邮件):

<manifest ... >
    ...
    <application ... >
        <activity android:name="com.example.project.ComposeEmailActivity">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <data android:type="*/*" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

然后,如果其他APP创建带有ACTION_SEND操作的intent,并传递给startActivity(),系统就能够启动找到我们的写邮件的activity,这样用户就能够编写和发送邮件。

6.      声明应用需求(declaring app requirements)

Android支持各种不同的设备 ,并且这些设备提供的特征和功能也不同。为了避免我们的APP安装在缺少所需要特征的设备上,非常重要的一点是我们通过在manifest文件中声明设备和软件需求,来清晰的定义我们APP支持的设备类型。大部分这些声明只是一些信息和系统并不会读取它们,但像谷歌市场(Google Play)这样的外部服务在用户从他们设备搜索APP是,为用户提供过滤而读取这些信息。

比如,如果我们的APP需要摄像头和使用Android 2.1的API版本,我们可以再manifest文件中像下面一样声明这些要求:

<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
    ...
</manifest>

由于设备没有摄像头和Android版本低于2.1,则不能从谷歌市场中安装我们的APP。

然而,虽然我们不需要摄像头,但也可以声明我们的APP使用拍照功能。载那种情况下,我们设置required属性为false和在运行时检查设备是否带有拍照功能,并相应的关闭任何拍照特征。

7.      应用资源(App Resources)

一个Android APP不仅仅是由代码组成,它需要和代码分离的资源,比如图片、音频文件和任何与我们APP相关的可视化内容。比如,我们可以定义动画、菜单、面板、色彩和XML文件中activity用户界面的布局。使用APP资源资源文件,可以更容易更新我们APP的特性而无需修改代码。并且通过提供多种可替换的资源文件,使我们可以优化多种配置的设备(比如不用的语言和屏幕大小)。

Android工程中每个资源,SDK编译工具定义一个唯一的整数ID,这样我们可以在APP代码或是XML定义的其他资源使用这些ID来引用对应的资源。比如,如果我们的APP包含一个名为logo.png的图像文件(保存在res/drawable/目录下),SDK工具产生一个名为R.drawable.logo的资源ID,我们可以可以使用它来引用这张图片和在用户界面中插入。

资源文件和代码分开这个机制最主要的一个方面是使我们可以为不同配置的设备提供可替换的资源。比如,在XML中定义UI字符串,我们可以翻译成其他语言的字符串并保存在独立的文件中。然后,基于语言标识符,我们添加资源文件夹名称(比如res/values-fr/对应于法语字符串)和用户语言设置,这样Android系统会为我们的UI应用合适的语言字符串。

对于我们可替换资源,Android支持多种不同的qualifiers(修饰符),限定符是包含在我们资源文件夹名称的短字符串,为了便于确定设备配置需要用的资源。再举另一个例子,对于不同的屏幕分享和大小,我们可能经常为我们的activities创建不同的布局。比如,当设备屏幕是纵向的,我们希望按键垂直排列的布局,但如果我们的屏幕是横向的,按键应当是水平排列的。为了根据方向来改变布局,我们可以定义两个不同的布局,并为每个布局文件夹名称提供适当的修饰符。这样,系统可以根据当前设备屏幕的方向来自动应用合适的布局。

Android开发者相关链接:

http://developer.android.com/guide/components/fundamentals.html

AndroidApplication Fundamentals(Android应用基础)相关推荐

  1. 2017-2018-2 20165236 实验四《Android开发基础》实验报告

    2017-2018-2 20165236 实验四<Android开发基础>实验报告 一.实验报告封面 课程:Java程序设计       班级:1652班       姓名:郭金涛     ...

  2. Android NDK基础样例

    Android NDK基础样例 NDK(Native Development Kit),用C/C++封装一些东西?好像就这么理解好了== 一.环境准备 这个好讨厌==!因为我环境都已经搭了很久了. 已 ...

  3. Android零基础入门第11节:简单几步带你飞,运行Android Studio工程

    2019独角兽企业重金招聘Python工程师标准>>> 之前讲过Eclipse环境下的Android虚拟设备的创建和使用,现在既然升级了Android Studio开发工具,那么对应 ...

  4. Android零基础入门第30节:两分钟掌握FrameLayout帧布局

    原文:Android零基础入门第30节:两分钟掌握FrameLayout帧布局 前面学习了线性布局.相对布局.表格布局,那么本期来学习第四种布局--FrameLayout帧布局. 一.认识FrameL ...

  5. Android零基础入门第25节:最简单最常用的LinearLayout线性布局

    原文:Android零基础入门第25节:最简单最常用的LinearLayout线性布局 良好的布局设计对于UI界面至关重要,在前面也简单介绍过,目前Android中的布局主要有6种,创建的布局文件默认 ...

  6. qtdesigner怎么实现菜单栏跳转_人人都可写代码-Android零基础编程-app 入口菜单栏实操08...

    欢迎来到人人都可写代码,大家好,我是杨晓华,今天我们的课程内容是项目实操,以智者精选项目为例,编写一个Android app的入口关联菜单栏逻辑. 这是要实现的菜单栏组件展示效果,下面就是教大家如何制 ...

  7. Android零基础入门第44节:ListView数据动态更新

    2019独角兽企业重金招聘Python工程师标准>>> 经过前面几期的学习,关于ListView的一些基本用法大概学的差不多了,但是你可能发现了,所有ListView里面要填充的数据 ...

  8. Android零基础入门第38节:初识Adapter

    2019独角兽企业重金招聘Python工程师标准>>> 在上一节一起了解了ListView的简单使用,那么本节继续来学习与ListView有着千丝万缕的Adapter. 一.了解MV ...

  9. Android零基础入门第77节:Activity任务栈和启动模式

    2019独角兽企业重金招聘Python工程师标准>>> 通过前面的学习,Activity的基本使用都已掌握,接下来一起来学习更高级的一些内容. Android采用任务栈(Task)的 ...

最新文章

  1. Mybatis常见面试题(三)
  2. LeetCode OJ:Pascal's TriangleII(帕斯卡三角II)
  3. Citrix VDI实战攻略之八:测试验收
  4. mybatis 缓存总结以及遇到的问题
  5. 那些侵占我碎片时间的“强盗”
  6. pual_bot 天气插件编写
  7. HDU - 5441 Travel 离线处理+并查集
  8. CLion 输出遇到乱码解决办法,GBK和utf-8的转换
  9. oracle cascade是什么意思啊,Oracle外键(Foreign Key)之级联删除(DELETE CASCADE)
  10. mac系统linux不能ping外网,Mac上配置Linux网络适配器(NAT模式),无法ping通
  11. clover写入efi_黑苹果安装核心文件-四叶草引导Clover EFI 配置文件结构讲解
  12. 离线光学字符识别(OCR)技术简介
  13. 2022华为机试真题 C++ 实现【九宫格按键输入法】
  14. Excel进阶(2)
  15. 小学期 BlueSky学长与友人帐
  16. 【Flutter实战静态页面】--在线点餐app(8)——详情框架1
  17. 未来人工智能发展面临的问题
  18. 微信小程序开发——动态改变按钮背景颜色
  19. 小白学习MySQL - 增量统计SQL的需求
  20. 在线测试视频地址(flv,m3u8,rtsp)

热门文章

  1. 024_JDK的equals方法
  2. oracle中判断是否为季末,Oracle中取月初,月末,季初,季末及年初,年末时间总结...
  3. 自定义View:测量measure,布局layout,绘制draw
  4. Oracle表空间查询及扩充表空间
  5. 搭建nginx服务、nginx的升级安装、Nginx配置文件的解析、web页面用户认证
  6. python生成器和迭代器作用_浅谈Python中的生成器和迭代器
  7. mysql 内存引擎_MySQL常见的三种存储引擎(InnoDB、MyISAM、MEMORY)
  8. c程序设计语言第五章,c程序设计语言第五章第7题答案
  9. win7系统怎么样在计算机里找桌面,如何在64位win7电脑中创建一个“显示桌面”的快捷方式...
  10. mysql数据清洗_mysql数据库如何实现亿级数据快速清理