Android初级开发知识点归纳

本文深入介绍了Android系统的架构,包括Linux Kernel、Android Runtime、Libraries、Application Framework和Applications等各层的功能与作用。此外,还详细解析了Activity和Service的生命周期,以及Broadcast Receiver的工作原理和应用场景。
一、Android 系统的架构
从底层往上层主要包含: 
1. Linux Kernel:Android 基于 Linux 2.6 提供核心系统服务,例如:安全、内存管理、进程 管理、网络堆栈、驱动模型。Linux Kernel 也作为硬件和软件之间的抽象层,它隐藏具 体硬件细节而为上层提供统一的服务。 
2. Android Runtime:Android 包含一个核心库的集合,提供大部分在 Java 编程语言核心类 库中可用的功能。每一个 Android 应用程序是 Dalvik 虚拟机中的实例,运行在他们自己 的进程中。Dalvik 虚拟机设计成,在一个设备可以高效地运行多个虚拟机。Dalvik 虚拟 机可执行文件格式是.dex,dex 格式是专为 Dalvik 设计的一种压缩格式,适合内存和处 理器速度有限的系统。 
3. Libraries:Android 包含一个 C/C++库的集合,供 Android 系统的各个组件使用。这些功 能通过 Android 的应用程序框架(application framework)暴露给开发者。主要包含:系 统 C 库、媒体库、界面管理、LibWebCore、SGL(2D) 、3D 库、FreeType、SQLite 
4. Application Framework:所有的应用程序其实是一组服务和系统,包括: 视图(View) 、内容提供者(Content Providers) 、资源管理器(Resource Manager) 、通知管 理器(Notification Manager) 、活动管理器(Activity Manager) 、通讯、定位、消息提醒等。 5. Applications

二、activity 的生命周期

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

Android Service 生命周期与 Activity 生命周期是相似的,但是也存在一些细节上也存在着重 要的不同:


onCreate 和 onStart 是不同的 
通过从客户端调用 Context.startService(Intent)方法我们可以启动一个服务。如果这个服务还 没有运行,Android 将启动它并且在 onCreate 方法之后调用它的 onStart 方法。如果这个服 务已经在运行, 那么它的 onStart 方法将被新的 Intent 再次调用。 所以对于单个运行的 Service 它的 onStart 方法被反复调用是完全可能的并且是很正常的。 


onResume、onPause 以及 onStop 是不需要的 回调一个服务通常是没有用户界面的, 所以我们也就不需要 onPause、 onResume 或者 onStop 方法了。无论何时一个运行中的 Service 它总是在后台运行。 


onBind 
如果一个客户端需要持久的连接到一个服务,那么他可以调用 Context.bindService 方法。如 果这个服务没有运行方法将通过调用 onCreate 方法去创建这个服务但并不调用 onStart 方法 来启动它。相反,onBind 方法将被客户端的 Intent 调用,并且它返回一个 IBind 对象以便客 户端稍后可以调用这个服务。同一服务被客户端同时启动和绑定是很正常的。


onDestroy 
与 Activity 一样,当一个服务被结束是 onDestroy 方法将会被调用。当没有客户端启动或绑 定到一个服务时 Android 将终结这个服务。与很多 Activity 时的情况一样,当内存很低的时 候 Android 也可能会终结一个服务。如果这种情况发生,Android 也可能在内存够用的时候 尝试启动被终止的服务,所以你的服务必须为重启持久保存信息,并且最好在 onStart 方法 内来做。

总结: 



1. startService()的目的是回调 onStart()方法, onCreate() 方法是在 Service 不存在的时候调用的,如果 Service 存在(例如之前调用了 bindService,那么 Service 的 onCreate 方法已经调用了)那么 startService()将跳过 onCreate() 方法。 


2. bindService()目的是回调 onBind()方法,它的作用是在 Service 和调用者 之间建立一个桥梁,并不负责更多的工作(例如一个 Service 需要连接服务器的 操作),一般使用 bindService 来绑定到一个现有的 Service(即通过 StartService 启动的服务)。 


由于 Service 的 onStart()方法只有在 startService()启动 Service 的情况下 才调用,故使用 onStart()的时候要注意这点。


四、 BroadCast Receiver,注册广播有几种方式,这些方式有何优缺点?请 , 注册广播有几种方式,这些方式有何优缺点? 引入广播机制的用意。 谈谈 Android 引入广播机制的用意。

广播(Broadcast) - 用于发送广播 

广播接收器(BroadcastReceiver) - 用于接收广播 
Intent - 用于连接以上各个组件,并在其间传递消息 


Broadcast
Receiver 在 Android 中,Broadcast 是一种广泛运用的在应用程序之间传输信息的机制。而 BroadcastReceiver 是对发送出来的 Broadcast 进行过滤接受并响应的一类组件。下面将详细 的阐述如何发送 Broadcast 和使用 BroadcastReceiver 过滤接收的过程:


    首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如 Action、Category) 装 入 一 个 Intent 对 象 , 然 后 通 过 调 用 Context.sendBroadcast()、 sendOrderBroadcast()或 sendStickyBroadcast()方法,把 Intent 对象以广播方式发送出去。 
    当 Intent 发送以后, 所有已经注册的 BroadcastReceiver 会检查注册时的 IntentFilter 是否 与发送的 Intent 相匹配, 若匹配则就会调用 BroadcastReceiver 的 onReceive()方法。 所以当我 们定义一个 BroadcastReceiver 的时候,都需要实现 onReceive()方法。 有两种方式: 注册 BroadcastReceiver 有两种方式 
    一种方式是,静态的在 AndroidManifest.xml 中用标签生命注册,并在标签内用标签设 置过滤器。 
    另一种方式是,动态的在代码中先定义并设置好一个 IntentFilter 对象,然后在需要注 册的地方调 Context.registerReceiver()方法,如果取消时就调用 Context.unregisterReceiver()方法。 如果用动态方式注册的 BroadcastReceiver 的 Context 对象被销毁时, BroadcastReceiver 也就自动取消注册了。 
    另外, 若在使用 sendBroadcast()的方法是指定了接收权限, 则只有在 AndroidManifest.xml 中用标签声明了拥有此权限的 BroascastReceiver 才会有可能接收到发送来的 Broadcast。 
    同样,若在注册 BroadcastReceiver 时指定了可接收的 Broadcast 的权限,则只有在包内 的 AndroidManifest.xml 中用标签声明了,拥有此权限的 Context 对象所发送的 Broadcast 才 能被这个 BroadcastReceiver 所接收。 
    动态注册:
IntentFilter intentFilter = new IntentFilter(); 
    intentFilter.addAction(String);--为 BroadcastReceiver 指定 action,使之用于接收同 action 的广播 registerReceiver(BroadcastReceiver,intentFilter);
一般:在 onStart 中注册,onStop 中取消 unregisterReceiver 发送广播消息: 
发送广播消息: 
    指定广播目标 Action:Intent Intent = new Intent(action-String) --指定了此 action 的 receiver 会接收此广播 需传递参数(可选) putExtra(); 发送:sendBroadcast(Intent);

五、Content Provider
创建 Content Provider: 

要创建我们自己的 Content Provider 的话,我们需要遵循以下几步: 
1. 创建一个继承了 ContentProvider 父类的类 


2. 定义一个名为 CONTENT_URI,并且是 public static final 的 Uri 类型的类变量,你必须为 其指定一个唯一的字符串值,最好的方案是以类的全名称, 如: public static final Uri CONTENT_URI = Uri.parse( “content://com.google.android.MyContentProvider”); 


3. 创建你的数据存储系统。 大多数 Content Provider 使用 Android 文件系统或 SQLite 数据库 来保持数据,但是你也可以以任何你想要的方式来存储。 


4. 定义你要返回给客户端的数据列名。如果你正在使用 Android 数据库,则数据列的使用 方式就和你以往所熟悉的其他数据库一样。但是,你必须为其定义一个叫_id 的列,它用来 表示每条记录的唯一性。 


5. 如果你要存储字节型数据,比如位图文件等,那保存该数据的数据列其实是一个表示实 际保存文件的 URI 字符串,客户端通过它来读取对应的文件数据,处理这种数据类型的 Content Provider 需要实现一个名为_data 的字段, _data 字段列出了该文件在 Android 文件系 统上的精确路径。这个字段不仅是供客户端使用,而且也可以供 ContentResolver 使用。客 户端可以调用 ContentResolver.openOutputStream()方法来处理该 URI 指向的文件资源,如果 是 ContentResolver 本身的话,由于其持有的权限比客户端要高,所以它能直接访问该数据 文件。 


6. 声明 public static String 型的变量,用于指定要从游标处返回的数据列。


7. 查询返回一个 Cursor 类型的对象。 所有执行写操作的方法如 insert(), update() 以及 delete() 都将被**。我们可以通过使用 ContentResover().notifyChange()方法来通知**器关于数据 更新的信息。 


8. 在 AndroidMenifest.xml 中使用<provider>标签来设置 Content Provider。 


9. 如果你要处理的数据类型是一种比较新的类型,你就必须先定义一个新的 MIME 类型, 以供 ContentProvider.geType(url)来返回。MIME 类型有两种形式:一种是为指定的单个记录 的,还有一种是为多条记录的。这里给出一种常用的格式: vnd.android.cursor.item/vnd.yourcompanyname.contenttype (单个记录的 MIME 类型) 比如, 一个请求列车信息的 URI 如 content://com.example.transportationprovider/trains/122 可 能就会返回 typevnd.android.cursor.item/vnd.example.rail 这样一个 MIME 类型。 vnd.android.cursor.dir/vnd.yourcompanyname.contenttype (多个记录的 MIME 类型) 比如, 一个请求所有列车信息的 URI 如 content://com.example.transportationprovider/trains 可 能就会返回 vnd.android.cursor.dir/vnd.example.rail 这样一个 MIME 类型。
六、 如果后台的 Activity 由于某原因被系统回收了,如何在被系统回收之前 保存当前状态 


onSaveInstanceState 和 onRestoreInstanceState

    在 activity 被杀掉之前调用保存每个实例的状态,以保证该状态可以在 onCreate(Bundle) 或者 onRestoreInstanceState(Bundle) (传入的 Bundle 参数是由 onSaveInstanceState 封装好的) 中恢复。 这个方法在一个 activity 被杀死前调用, 当该 activity 在将来某个时刻回来时可以恢 复其先前状态。例如,如果 activity B 启用后位于 activity A 的前端,在某个时刻 activity A 因为系统回收资源的问题要被杀掉,A 通过 onSaveInstanceState 将有机会保存其用户界面状 态 , 使 得 将 来 用 户 返 回 到 activity A 时 能 通 过 onCreate(Bundle) 或 者 onRestoreInstanceState(Bundle)恢复界面的状态。 

    不要将这个方法和 activity 生命周期回调如 onPause()或 onStop()搞混淆了,onPause()在 activtiy 被放置到背景或者自行销毁时总会被调用,onStop()在 activity 被销毁时被调用。一 个会调用 onPause()和 onStop(),但不触发 onSaveInstanceState 的例子是当用户从 activity B 返回到 activity A 时:没有必要调用 B 的 onSaveInstanceState(Bundle),此时的 B 实例永远不 会被恢复, 因此系统会避免调用它。 一个调用 onPause()但不调用 onSaveInstanceState 的例子 是当 activity B 启动并处在 activity A 的前端:如果在 B 的整个生命周期里 A 的用户界面状 态都没有被破坏的话,系统是不会调用 activity A 的 onSaveInstanceState(Bundle)的。 
    默认的实现负责了大部分 UI 实例状态(的保存),采用的方式是调用 UI 层上每个拥有 id 的 view 的 onSaveInstanceState() ,并且保存当前获得焦点的 view 的 id(所有保存 的状态信息都会在默认的 onRestoreInstanceState(Bundle)实现中恢复)。如果你覆写 这个方法来保存额外的没有被各个 view 保存的信息, 你可能想要在默认实现过程中调用或 者自己保存每个视图的所有状态。如果被调用,这个方**在 onStop()前被触发,但系统 并不保证是否在 onPause()之前或者之后触发。 


Android calls onSaveInstanceState() before the activity becomes vulnerable to being destroyed by the system, but does not bother calling it when the instance is actually being destroyed by a user action (such as pressing the BACK key)


从这句话可以知道,当某个 activity 变得“容易”被系统销毁时,该 activity 的 onSaveInstanceState 就会被执行,除非该 activity 是被用户主动销毁的,例如当用户按 BACK 键的时候。 
注意上面的双引号,何为“容易”?言下之意就是该 activity 还没有被销毁,而仅仅是一 种可能性。这种可能性有哪些?通过重写一个 activity 的所有生命周期的 onXXX 方法,包 括 onSaveInstanceState 和 onRestoreInstanceState 方法,我们可以清楚地知道当某个 activity(假定为 activity A)显示在当前 task 的最上层时,其 onSaveInstanceState 方 **在什么时候被执行,有这么几种情况: 


1、当用户按下 HOME 键时。 这是显而易见的, 系统不知道你按下 HOME 后要运行多少其他的程序, 自然也不知道 activity A 是否会被销毁,故系统会调用 onSaveInstanceState,让用户有机会保存某些非永久性的 数据。以下几种情况的分析都遵循该原则 
2、长按 HOME 键,选择运行其他的程序时。 
3、按下电源按键(关闭屏幕显示)时。 
4、从 activity A 中启动一个新的 activity 时。 
5、屏幕方向切换时,例如从竖屏切换到横屏时。 
在屏幕切换之前, 系统会销毁 activity A, 在屏幕切换之后系统又会自动地创建 activity A,所以 onSaveInstanceState 一定会被执行 
总而言之,onSaveInstanceState 的调用遵循一个重要原则,即当系统“未经你许可”时销 毁了你的 activity,则 onSaveInstanceState 会被系统调用,这是系统的责任,因为它必 须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。 
至于 onRestoreInstanceState 方法,需要注意的是,onSaveInstanceState 方法和 onRestoreInstanceState 方法“不一定”是成对的被调用的,onRestoreInstanceState 被 调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情 况下,则该方法不会被调用,例如,当正在显示 activity A 的时候,用户按下 HOME 键回到 主界面,然后用户紧接着又返回到 activity A,这种情况下 activity A 一般不会因为内存 的原因被系统销毁,故 activity A 的 onRestoreInstanceState 方法不会被执行 


另外,onRestoreInstanceState 的 bundle 参数也会传递到 onCreate 方法中,你也可以选 择在 onCreate 方法中做数据还原


七、 横竖屏切换时候 activity 的生命周期 
1、 不设置 Activity 的 android:configChanges 时: 、
模拟器这种情况切屏会重新调用各个生命周期,切横屏时会生命周期执行一次,切竖屏时生命周期会执行 两次,且横竖屏 onConfigurationChanged 未被调用。但是在 HTC DESIRE HD(G10) 这款手机上测 试结果为:生命周期都只执行一次,且横竖屏 onConfigurationChanged 未被调用。
2、 设置 Activity 的 android:configChanges="orientation"时: 、 时
模拟器这种情况切屏还是会重新调用各个生命周期,切横屏 onConfigurationChanged 未执行、竖屏时 onConfigurationChanged 执行 1 次。但是在 HTC DESIRE HD(G10) 这款手机上测试结果为:生命周 期未发生变化,且横竖屏 onConfigurationChanged 都只执行一次。
3、 设置 Activity 的 android:configChanges="orientation|keyboardHidden"时: 、 时
模拟器这种情况切屏不会重新调用各个生命周期,切横屏时 onConfigurationChanged 会执行 1 次,切 竖屏时 onConfigurationChanged 方法调用 2 次。 但是在 HTC DESIRE HD(G10) 这款手机上测试结 果为:横竖屏 onConfigurationChanged 都只执行一次。


八、android 中的动画有哪几类,它们的特点和区别是什么 中的动画有哪几类
两种: 一种是 Tween 动画、还有一种是 Frame 动画。Tween 动画,这种实现方式可以使视图组件 移动、放大、缩小以及产生透明度的变化; 另一种 Frame 动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。
对多线程的运用和理解, 的传值; 



九、 对多线程的运用和理解,及多线程之间 handle 的传值;handler 机制 的原理
Android 开发过程中为什么要线程呢? 

开发过程中为什么要线程呢 我们创建的 Service、Activity 以及 Broadcast 均是一个主线程处理,这里我们可以理解为 UI 线程。但是在操作一些耗时操作时,比如 I/O 读写的大文件读写,数据库操作以及网络下载 需要很长时间,为了不阻塞用户界面,出现 ANR 的响应提示窗口,这个时候我们可以考虑 使用 Thread 线程来解决。 
Android 中使用 Thread 线程会遇到哪些问题 线程会遇到哪些问题? 
对于从事过 J2ME 开发的程序员来说 Thread 比较简单,直接匿名创建重写 run 方法,调用 start 方法执行即可。或者从 Runnable 接口继承,但对于 Android 平台来说 UI 控件都没有设 计成为线程安全类型,所以需要引入一些同步的机制来使其刷新,这点 Google 在设计 Android 时倒是参考了下 Win32 的消息处理机制。 
1. 对于线程中的刷新一个 View 为基类的界面,可以使用 postInvalidate()方法在线程中来处 理,其中还提供了一些重写方法比如 postInvalidate(int left,int top,int right,int bottom) 来刷新 一 个 矩 形 区 域 , 以 及 延 时 执 行 , 比 如 postInvalidateDelayed(long delayMilliseconds) 或 postInvalidateDelayed(long delayMilliseconds,int left,int top,int right,int bottom) 方法, 
2. 当然推荐的方法是通过一个 Handler 来处理这些,可以在一个线程的 run 方法中调用 handler 对象的 postMessage 或 sendMessage 方法来实现,Android 程序内部维护着一个消息 队列,会轮训处理这些,如果你是 Win32 程序员可以很好理解这些消息处理,不过相对于 Android 来说没有提供 PreTranslateMessage 这些干涉内部的方法。 
3. Looper 又是什么呢? ,其实 Android 中每一个 Thread 都跟着一个 Looper,Looper 可以帮 助 Thread 维护一个消息队列,昨天的问题 Can't create handler inside thread 错误 一文中提 到这一概念,但是 Looper 和 Handler 没有什么关系,我们从开源的代码可以看到 Android 还提供了一个 Thread 继承类 HanderThread 可以帮助我们处理,在 HandlerThread 对象中可 以通过 getLooper 方法获取一个 Looper 对象控制句柄,我们可以将其这个 Looper 对象映射 到一个 Handler 中去来实现一个线程同步机制, Looper 对象的执行需要初始化 Looper.prepare 方法就是昨天我们看到的问题,同时推出时还要释放资源,使用 Looper.release 方法。 
4.Message 在 Android 是什么呢? 对于 Android 中 Handler 可以传递一些内容,通过 Bundle 对象可以封装 String、Integer 以及 Blob 二进制对象,我们通过在线程中使用 Handler 对象的 sendEmptyMessage 或 sendMessage 方法来传递一个 Bundle 对象到 Handler 处理器。对于 Handler 类提供了重写方法 handleMessage(Message msg) 来判断, 通过 msg.what 来区分每条 信息。将 Bundle 解包来实现 Handler 类更新 UI 线程中的内容实现控件的刷新操作。 
5. java.util.concurrent 对象分析,对于过去从事 Java 开发的程序员不会对 Concurrent 对象感 到陌生吧,他是 JDK 1.5 以后新增的重要特性作为掌上设备,我们不提倡使用该类,考虑到 Android 为我们已经设计好的 Task 机制,我们这里 Android 开发网对其不做过多的赘述,相关原因参考下面的介绍: 
6. 在 Android 中还提供了一种有别于线程的处理方式,就是 Task 以及 AsyncTask,从开源 代码中可以看到是针对 Concurrent 的封装, 开发人员可以方便的处理这些异步任务, 具体的 Android123 在以前的文章中有详细解释,可以使用站内搜索来了解更多。

十、 说说在 android 中有哪几种数据存储方式 
1.SharedPreferences 方式
2.文件存储方式 
3.SQLite 数据库方式 
4.内容提供器(Content provider)方式 


十一、 android 中有哪几种解析 xml 的类,以及它们的原理和区别
** API for XML(SAX) 、 Document Object Model(DOM)和 Android 附带的 pull 解析器解析 XML 文件 

1. SAX: 是一个用于处理 XML 事件驱动的“推”模型,优点是一种解析速度快并且占用内 存少的 xml 解析器,它需要哪些数据再加载和解析哪些内容。缺点是它不会记录标签 的关系,而要让你的应用程序自己处理,这样就增加了你程序的负担。 
2. DOM: DOM 解析 XML 文件时, 会将 XML 文件的所有内容以对象树方式存放在内存中, 然后允许您使用 DOM API 遍历 XML 树、检索所需的数据。使用 DOM 操作 XML 的代 码看起来比较直观,并且,在某些方面比基于 SAX 的实现更加简单。但是,因为 DOM 需要将 XML 文件的所有内容以对象树方式存放在内存中,所以内存的消耗比较大,特 别对于运行 Android 的移动设备来说 
3. PULL: Pull 解析和 Sax 解析很相似,Pull 解析和 Sax 解析不一样的地方是 pull 读取 xml 文件后触发相应的事件调用方法返回的是数字还有 pull 可以在程序中控制想解析到哪 里就可以停止解析。


十二、 如何将一个 Activity 设置成窗口的样式。
在 AndroidManifest.xml 中定义 Activity 的地方一句话: android:theme="@android:style/Theme.Dialog" 或 android:theme="@android:style/Theme.Translucent"就变成半透明的


十三、 请介绍下 Android 中常用的五种布局。 
1. FrameLayout:最简单的一个布局对象。它被定制为你屏幕上的一个空白备用区域,之
后你可以在其中填充一个单一对象 — 比如,一张你要发布的图片。所有的子元素将会 固定在屏幕的左上角;你不能为 FrameLayout 中的一个子元素指定一个位置。后一个子 元素将会直接在前一个子元素之上进行覆盖填充,把它们部份或全部挡住(除非后一个 子元素是透明的) 。
2. LinearLayout:以你为它设置的垂直或水平的属性值,来排列所有的子元素。所有的子
元素都被堆放在其它元素之后,因此一个垂直列表的每一行只会有一个元素,而不管他 们有多宽,而一个水平列表将会只有一个行高(高度为最高子元素的高度加上边框高 度) 。LinearLayout 保持子元素之间的间隔以及互相对齐(相对一个元素的右对齐、中间 对齐或者左对齐) LinearLayout 还支持为单独的子元素指定 weight 。好处就 。
是允许子元素可以填充屏幕上的剩余空间。这也避免了在一个大屏幕中,一 串小对象挤成一堆的情况,而是允许他们放大填充空白。子元素指定一个 weight 值,剩余的空间就会按这些子元素指定的 weight 比例分配给这些子 元素。默认的 weight 值为 0。例如,如果有三个文本框,其中两个指定了weight 值为 1,那么,这两个文本框将等比例地放大,并填满剩余的空间, 而第三个文本框不会放大。 

3. AbsoluteLayout:可以让子元素指定准确的 x/y 坐标值,并显示在屏幕上。(0, 0)为左上角,当向下或向右移动时,坐标值将变大。AbsoluteLayout 没有页边框,允许元素之间 互相重叠(尽管不推荐) 。我们通常不推荐使用 AbsoluteLayout ,除非你有正当理由要 使用它,因为它使界面代码太过刚性,以至于在不同的设备上可能不能很好地工作。
4. RelativeLayout: RelativeLayout 允许子元素指定他们相对于其它元素或父元素的位置(通过 ID 指定) 。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个 元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其 它元素将以屏幕中央的相对位置来排列。如果使用 XML 来指定这个 layout ,在你定 义它之前,被关联的元素必须定义。
5. TableLayout:TableLayout 将子元素的位置分配到行或列中。一个 TableLayout 由许多的 TableRow 组成,每个 TableRow 都会定义一个 row (事实上,你可以定义其它的子 对象,这在下面会解释到) 。TableLayout 容器不会显示 row 、cloumns 或 cell 的边框 线。每个 row 拥有 0 个或多个的 cell ;每个 cell 拥有一个 View 对象。表格由列和行 组成许多的单元格。表格允许单元格为空。单元格不能跨列,这与 HTML 中的不一样。


十四、 AIDL 的全称是什么?如何工作?能处理哪些类型的数据?
Android 接口定义语言 AIDL(Android Interface Definition Language)技术: 

1、把 Service 中针对 MediaPlayer 的操作封装成一个接口(.aidl 文件) 
2、在 Service 中建个子类实现这接口的存根(stub)对象 
3、并在 onBind()方法中返回这个存根对象。 
4、在 Activity 中使用绑定服务的方式连接 Service,但是不用 Intent 来传递信息,而是 在 ServiceConnection 的 onServiceConnected 方法里,获得 Service 中 Stub 对象的客户端 使用代理。我们通过操作 Activity 中的代理就可以达到操作 Service 中的 MediaPlayer 对象的目的。这样我们就可以想用本地对象一样操作 Service 中的对象了,那么进度条 一类的需求自然也就迎刃而解。 


AIDL 服务只支持有限的数据类型,因此,如果用 AIDL 服务传递一些复杂的数据就需要做 更一步处理。AIDL 服务支持的数据类型如下: 
    Java 的简单类型(int、char、boolean 等) 。不需要导入(import) 。 
    String 和 CharSequence。不需要导入(import) 。 
    List 和 Map。 但要注意, List 和 Map 对象的元素类型必须是 AIDL 服务支持的数据类型。 不需要导入(import) 。 
    AIDL 自动生成的接口。需要导入(import) 。 
    实现 android.os.Parcelable 接口的类。需要导入(import) 。 
其中后两种数据类型需要使用 import 进行导入。


十五、 系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由。
Intent intent = new Intent(); intent.setClassName("com.uc.browser", "com.uc.browser.ActivityUpdate"); intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setData(Uri.parse(visitUrl)); startActivity(intent); 



理由: action 赋值为”android.intent.action.VIEW“时可接收如下 scheme 为"http"等等类型的 在 data。所以突发奇想,启动该程序后,指定 action 及 Uri,即访问指定网页。


十六、 Android 数字签名
Android 数字签名 
    在 Android 系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书 用 于 标 识 应 用 程 序 的 作 者 和 在 应 用 程 序 之 间 建 立 信 任 关 系 , 如 果 一 个 permission 的 protectionLevel 为 signature,那么就只有那些跟该 permission 所在的程序拥有同一个数字证 书的应用程序才能取得该权限。 Android 使用 Java 的数字证书相关的机制来给 apk 加盖数字 证书, 要理解 android 的数字证书, 需要先了解以下数字证书的概念和 java 的数字证书机制。 Android 系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥 则保存在程序开发者的手中。Android 将数字证书用来标识应用程序的作者和在应用程序之 间建立信任关系, 不是用来决定最终用户可以安装哪些应用程序。 这个数字证书并不需要权 威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。 
同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。 
(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android 系统才会认为这两 个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则 Android 系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。 
(2)有利于程序的模块化设计和开发。Android 系统允许拥有同一个数字签名的程序运行在一 个进程中,Android 程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开 发,而用户只需要在需要的时候下载适当的模块。 
(3)可以通过权限(permission)的方式在多个程序间共享数据和代码。 Android 提供了基于数字 证书的权限赋予机制, 应用程序可以和其他的程序共享概功能或者数据给那那些与自己拥有 相同数字证书的程序。如果某个权限(permission)的 protectionLevel 是 signature,则这个权限 就只能授予那些跟该权限所在的包拥有同一个数字证书的程序。
在签名时,需要考虑数字证书的有效期: 
(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的 程序将不能正常升级。 
(2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命 周期。 
(3)Android Market 强制要求所有应用程序数字证书的有效期要持续到 2033 年 10 月 22 日以 后。 
Android 数字证书包含以下几个要点: 
    (1)所有的应用程序都必须有数字证书, Android 系统不会安装一个没有数字证书的应用 程序 
    (2)Android 程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签 名认证 
    (3)如果要正式发布一个 Android ,必须使用一个合适的私钥生成的数字证书来给程序 签名,而不能使用 adt 插件或者 ant 工具生成的调试证书来发布。 

    (4)数字证书都是有有效期的,Android 只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。

十七、 NDK 是什么
Android NDK 提供了一些工具,使得 Android 应用程序开发人员可以将本地代码嵌入 Android 应用程序. 

Android 应用程序在 Dalvik 虚拟机中运行. NDK 使得开发者可以将它们应用程序的一部分 使用本地代码语言--例如 C 和 C++来实现. 这可能对某些程序带来一些好处, 例如已有代码 的重用和增加执行速度. 

NDK 提供了: 
    一套工具和构建文件 用来从 C 和 C++代码生成本地代码库文件. 
    一种将本地库嵌入应用程序包(.apk)的方法.
    一套本 地系统头文件和库文件, 它们将在所有 Android 1.5 之后的 android 平台中被支持. 文档,示例和教程 

NDK 发行版支持 ARMv5TE 机器指令集并提供了 libc(C 库), libm(数学库), OpenGL ES 1.1(3D 图形库)的稳定头文件, JNI 接口 以及其它的库. 

NDK 对大多数应用程序没有好处. 作为一个开发者, 你需要衡量它的好处和坏处: 值的注 意的是, 使用本地代码不一定能提高性能, 但是一定会增加程序的复杂性. NDK 适合用来做 的事情一般是自包含的, CPU 密集型的不需要大量内存的操作 -- 例如信号处理, 物理模拟 等等. 简单的将一个方法使用 C 重写一般不会达到性能的提升. 不过, NDK 可以是一种重用 大量已有 C/C++代码的不错的方法.

十八、 开机自动运行程序
背景知识: Android 启动时, 当 会发出一个系统广播, 内容为 ACTION_BOOT_COMPLETED, 它的字符串常量表示为 android.intent.action.BOOT_COMPLETED。只要在程序中“捕捉”到 这个消息,再启动之即可。记住,Android 框架说:Don''t call me, I''ll call you back。我们要 做的是做好接收这个消息的准备,而实现的手段就是实现一个 BroadcastReceiver。 
public class BootBroadcastReceiver extends BroadcastReceiver { 
static final String ACTION = "android.intent.action.BOOT_COMPLETED"; 
@Override 
public void onReceive(Context context, Intent intent) { 
if (intent.getAction().equals(ACTION)){ 
Intent sayHelloIntent=new Intent(context,SayHello.class); 
sayHelloIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
context.startActivity(sayHelloIntent); 
}}} 
该类派生自 BroadcastReceiver,覆载方法 onReceive 中,检测接收到的 Intent 是否符合 BOOT_COMPLETED,如果符合,则启动 SayHello 那个 Activity。 
<receiver android:name=".BootBroadcastReceiver"> 
<intent-filter> 
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter> 
</receiver> 
<uses-permission 
android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission> 

注意其中粗体字那一部分,该节点向系统注册了一个 receiver,子节点 intent-filter 表示接android.intent.action.BOOT_COMPLETED 消 息 。 不 要 忘 记 配 置 android.permission.RECEIVE_BOOT_COMPLETED 权限。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值