Introductions.App Fundamentals

Introductions.App Fundamentals

android是一个多用户操作系统,每个app就是一个用户

系统默认给每个应用分配一个唯一的用户id,(应用自己并不知道这个id,只有系统知道)。系统给应用中的文件分配权限使得只有该应用对应的userid才能访问这些文件。

每个进程有自己的虚拟机,so 每个应用都是独立于其他应用运行

默认情况下,每个应用都运行在自己的linux进程里,android系统在app的任意组件需要被执行的时候就会start一个进程,如果进程不再需要被执行或者内存不够用,系统会shut down这个进程。

基于此,android实现了最小特权原则(POLP,principle of least privilege是将访问权限限制到最低水平但仍能保证正常运作的做法)。即,每个应用默认情况下,只能访问到进行它的工作所必须的组件,别的不可以。这样,对于系统没有给权限的资源,应用并不能访问,由此创造一个极为安全的系统环境(是吗...?)

当然,想要访问并不是没办法,以下几种方法可以让应用实现与其他应用分享数据,及访问系统服务:

~对于两个应用需要互相访问对方的文件的情况,可以为其分配相同的userid。节省资源而论,也可以将其运行于同一linux进程&同一虚拟机下(当然,也应该为两应用分配同样的证书)
~应用同样可以申请权限去访问设备数据(如用户联系人,短信,可挂载的sd卡,摄像头,蓝牙。。等),这些申请的权限必须在用户安装应用时经过用户同意。

四大组件
组件是android应用的基本组成部分。每个组件都是一个系统可以通过其来访问你的应用的point。当然实际中不是所有组件都是用户访问的入口,并且某些组件还依赖于其他组件。但是每个组件都是一个独立存在的实体,都是一个独一无二的定义应用功能的组成部分。

活动:
一个活动表示一个带ui的屏幕。比如某个email program有一个活动show邮件列表,另一个活动来发邮件,再来个读邮件活动。虽然这些活动提供了一个紧密结合的用户体验,但实际上他们是独立于each other的。即在该应用允许的情况下,另一个应用也只能start这些活动当中的一个。如,拍照应用就可以start一个发信活动,实现分享照片的功能~~
活动都是继承于activity类
服务:
服务是运行在后台实现长时间运行的操作的组件,也可为远程进程实现某些功能。服务没有ui。比如后台放音乐或者后台下载这都可以用服务实现。而其他组件,如活动,则可以start一个服务让它运行起来或者绑定到某个服务与之交互。
服务都是继承于service类
内容提供者:
内容提供者管理一堆要分享的数据。你可以将数据存到你的应用可以访问的任意地方(文件,数据库,网上,或者blablabla)其他应用可通过内容提供者查询甚至修改这些数据(只要内容提供者允许。。)比如,系统中提供了一个内容提供者供其他应用访问用户的联系人。so只要某应用有合适的权限,就可以通过内容提供者读写某个联系人数据。
内容提供者对于其他应用访问你的私有数据也很管用
内容提供者都继承于ContentProvider类
广播接收者:
广播接收者是响应系统全局广播的组件。很多广播都是系统发出来的:锁屏了、电量低了、截图了。。。当然应用也可以发起广播,如让另外一个应用知道数据准备好了blabla。。虽然广播接收者没有ui,但他收到广播的时候可以发一个状态栏通知去提醒用户。当然,往往receiver就是一个通往其他组件的通道,一般来讲它只做些零碎活,如响应某事件启动一个服务
都继承于BroadcastReceiver,且广播都是以Intent对象的形式发送的。


android系统设计的一个比较吊的东西是任一应用都可以start其他应用的组件。比如你想调用摄像头拍照,就可以直接启用自带的拍照应用而不是自己写一个。启用自带应用拍完照它甚至可以给你把照片返回,就好像这个拍照应用是你自己应用集成的一样。

系统启动组件的时候,会启动其应用的进程(如果当前并没有在运行)并且把该组件需要的类实例化。比如,你的应用要启动拍照的activity,然后启完之后这个activity运行在拍照应用的进程里,而不是你的应用进程。也就是你启这个activity会自动把拍照应用的进程启动起来。 so,对于安卓的应用,它并没有一个特定的“入口”(main函数的什么之类的)。

由于系统都是在每个应用对应的进程里运行应用,并且通过文件权限限制了应用对其他应用的访问。所以你的应用并不能直接的激活(activate)一个其他应用的组件,但是android系统可以做到。所以你需要给系统发送一个信息并将你的intent指定到某个特定的组件上,然后系统会为你激活这个组件。

激活组件
四大组件中的三大(活动、服务、广播接收者)都是由一个叫做intent的异步消息激活的。intent在运行时将各自独立的组件绑定到一起(可以把intent想象成一个送信者,这个送信者传达一个需求,需要激活某组件),不管是你的应用的组件还是别的应用的组件。
intent对象可由实例化Intent类得到,这个对象定义一个了要激活特定的某个组件的消息,或者也可定义一个激活满足某条件的一类组件的消息。即显示intent和隐式intent。
对于活动和服务,intent可以定义一个需要执行的action(如查看或发送某些玩意)且可能也会指定数据的uri,这些数据用来执行前述的action(可能还包括一些被启动的组件需要知道的信息)。如,某intent传达了一个需求“显示某图像”或者“打开某网页“,某些情况下,你可以启动一个活动并可以从它接收结果(启动活动时需要把你的intent给到系统,让系统知道你的需求),而且,给你返回结果的时候它也是用intent返回的。比如,你可以发起一个intent(给到系统让系统启动对应的组件然后)让用户选择一个联系人信息然后返回给你,此时,在返回的intent中就包含了一个uri,该uri指向那个被选中的联系人。
而对广播接收者来说,intent只需要指定那个要发出去的广播就ok(比如,发一条"电池没电了"的广播只需要指定一个已知的action字符串来代表“电池没电了”就好)。
另外一大,内容提供者,则不是由intent激活的。而是当一个ContentResolver指定某内容提供者为操作目标的时候,内容提供者才会被激活。ContentResolver可以处理所有与内容提供者之间的事务,so,某个其他组件想要和内容提供者进行一些交流的话可以直接调用ContentResolver的方法。这样的话,在申请内容的组件和内容提供者之间又加了一层抽象(出于安全考虑)(这个抽象就指ContentResolver)。

下面是几种激活四大组件的方法:
~活动,可以用startActivity()或startActivityForResult()方法启动,传入一个intent。
~服务,startService()传入intent即可。或者可以通过bindService()绑定服务,也要传intent
~广播接收者,通过发送广播启动,而发广播要用到sendBroadcast(),或sendOrderedBroadcast(),或sendStickBroadcast(),依旧,传入intent。
~内容提供者,你需要通过调用ContentResolver的query()方法来对内容提供者执行查询操作。

Manifest文件:
在系统启动一个应用的组件之前,它需要明确知道这个组件是存在的。要知道这个,就需要通过AndroidManifest.xml文件。所以你需要在这里把你的应用的所有组件都声明出来,该文件必须存放在应用工程根目录下。
除了声明组件以外,AndroidManifest还可以做以下事情:
~确定应用所需的权限,比如联网权限或者读用户联系人的权限。
~规定应用所需的最小APILevel,基于应用自己所使用的APIs
~声明应用所用到的或者需要用到的软硬件配置,比如摄像头,蓝牙服务,或者多点触摸屏。
~声明除了Android框架APIs以外,应用还需要哪些API库。如Google Maps Library。
~等其他功能。。

声明组件:
manifest基本功能就是声明组件,如:
<?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>元素中,icon属性指定了应用的图标。
<activity>属性中,name属性指定了Activity子类的全类名,label属性指定了一个字符串,用来做为一个activity中用户可见的标签。
声明组件的标准姿势:
<activity> elements for activities
<service> elements for services
<receiver> elements for broadcast receivers
<provider> elements for content providers
没有经过声明的组件,你在代码里写了也没用,永远运行不起来。但是有个例外,广播接收者:它可以在 manifest文件中声明(也可叫静态注册),也可以在代码中动态创建出来(作为一个BroadcastReceiver对象),通过调用registerReceiver()注册到系统。

声明组件的功能:
前面说了,可以用intent来激活三大组件。在激活时,你可以在intent中直接显式指明目标组件的类名,然而,intent的真正奥义还是在intent actions里面。使用intent actions,你可以仅指明你想要进行的操作(以及你的操作对象——数据)然后让系统去根据你的需求找到对应的组件,然后启动之。如果系统有好几个组件都可以实现你的intent描述的操作,那你就选一个好了。

那么,系统如何根据你的intent找到对应组件呢?系统需要将你的intent中指明的需求或者意图,与其他应用的manifest文件中提供的intent filters进行比较,从而找到能匹配你的需求的组件。

当你在Manifest中声明一个组件时,作为可选项,你可以在声明当中包含一个intent filters,这个东西用来声明组件的功能然后系统便可以根据这个声明的功能拿它来响应其他应用发起的intent。可以在声明组件的标签内添加子节点<intent-filters>来声明filter。

例如,一个email应用里有个发邮件的activity,然后这个应用就可以在Manifest里声明一个intent filter,声明它可以响应"send"的intent,即谁想发邮件就可以来找我这个activity。然后你可以在你的activity里面构造一个intent,传入"send"(实际在使用中应该是ACTOIN_SEND,这里随便举个例子),然后系统就会在你调用startActivity()方法的时候,根据你的intent寻找能够匹配的activity,在本例中,它找到了email应用里那个发邮件的activity,然后开启该activity。

声明组件的要求:
为了方便使用,请把你的应用所需要的各种配置都在manifest中声明一下,系统虽然不会看这个,但是像googleplay这种扩展服务们会看这个东西,如果有缺少配置的手机想要安装你的应用,这些扩展服务会做出相应的提示。
比如你的应用需要摄像头,而且支持最低2.3的系统,然后你就要声明一下了。然后系统版本低于2.3的或者不带摄像头的手机就不能通过play市场装你这个应用了。
....底下一堆blabla先不翻了


应用的资源:
安卓应用不只有代码,还有音视频图像等资源文件。使用资源可以让你的应用提供更加丰富的功能而不用通过修改源码,同时使用资源还可以让你的应用更加灵活的适应不同语言不同屏幕大小。
对于你的项目中的所有资源,SDK build tools都会给其分配一个独一的资源ID(整型),在应用的代码里面或者在其他的资源xml文件里面都可以通过资源id获得其引用。
....又是一堆blablabla关于适配不同屏幕不同语言的东西,先不看




 posted on 2015-07-29 16:13  絮状颗粒  阅读(175)  评论(0)    收藏  举报