本文还有配套的精品资源,点击获取
简介:安卓基础知识课程为初学者及进阶开发者提供安卓系统架构、关键开发技术以及最新开发工具的全面介绍。课程涵盖了从系统架构层面的核心概念如HAL、系统库、应用框架、应用程序层,到应用开发的关键组件,包括Dalvik/ART虚拟机、UI设计、Intent通信机制、资源管理、权限系统、进程与线程处理、Android Studio/Gradle集成、应用调试与测试,以及Android NDK/JNI使用。课程还涉及了安卓版本更新和兼容性处理,以确保应用在不同设备上的良好运行。两个附带的电子书《深入理解Android 卷 I - 邓凡平》和《深入理解Android 卷 II - 邓凡平》深入解析这些知识点,而SumatraPDF-2.5.8625.exe工具支持阅读电子书文件,便于深入学习安卓开发。
安卓(Android)操作系统是一个基于Linux内核的开源移动操作系统。它由操作系统层、中间件和应用框架层组成,最上层则是各种应用程序。安卓系统架构的设计目标是允许开发者利用其庞大的功能库来快速开发各种类型的移动应用程序。
在安卓系统架构中,最底层是Linux内核层。它负责硬件抽象、内存管理、进程管理、安全机制等核心功能。安卓基于Linux内核的优势在于其成熟性和稳定性,同时具备良好的网络功能和驱动程序支持。
// Linux内核的命令行操作示例
$ uname -r // 查看内核版本
$ lsmod // 列出已加载的模块信息
安卓系统架构的中间层由系统运行库组成,包括安卓运行时库、硬件抽象层(HAL)以及C/C++库。这些运行库提供了系统运行所需的基本服务,例如OpenGL ES用于图形渲染,Webkit用于网页浏览等。
应用程序框架层为开发者提供了构建应用所需的API,其中包含了Activity管理器、视图系统、包管理器、资源管理器等关键组件。这一层的设计允许开发者轻松访问核心功能,并能够根据需求快速创建新的应用程序。
最顶层是应用程序层,安卓系统预装了包括拨号器、短信应用、联系人应用等基础应用程序。开发者可以利用上文提及的应用程序框架,开发出满足各种功能需求的应用程序,如社交媒体应用、游戏等。
安卓系统架构的核心在于其分层设计,这不仅保证了系统良好的模块化和可扩展性,而且为开发者提供了一个丰富的开发环境。随着安卓系统的不断演进,每一层都在不断优化,以适应日益增长的移动计算需求。
安卓应用程序框架建立在Linux内核之上,提供了丰富的API用于实现各种功能,包括但不限于用户界面构建、数据存储、网络通信等。该框架的核心设计原则之一是组件化,这使得开发变得模块化且可重用。框架由以下几个主要组件构成:
每个组件对应着Android系统中的特定功能和场景。例如,Activity是对应于单一屏幕的一个界面;Service负责后台任务,不提供用户界面;Broadcast Receiver用于接收系统和应用的广播通知;Content Provider则管理应用的数据访问。
在进一步了解组件之前,理解组件间如何交互是十分重要的。以下是每个组件是如何工作的:
Activity :这是用户交互的中心,每一个Activity通常表示一个独立的屏幕,它有自己的生命周期。开发者需要管理Activity的创建、销毁和重新创建(比如在屏幕旋转时)。Activity通过Intent与其他组件相互通信。
Service :Service是一种没有用户界面但可以在后台长时间运行的组件。它可以执行如音乐播放、文件下载等长时间运行的任务。Service可以绑定到一个应用程序或者被多个应用程序使用。
Broadcast Receiver :这个组件负责接收应用程序和系统的广播通知。例如,当电池电量低或接收到短信时,系统发送广播,Broadcast Receiver可以监听这些事件并作出相应的反应。
Content Provider :它管理应用程序访问数据的途径,例如访问其他应用或系统服务的数据。它提供了一套统一的数据访问机制,使得不同的应用程序能够交换数据。
Activity的生命周期是Android应用开发中非常关键的概念。从创建到销毁,Activity会经历多个状态。这些状态分别对应不同的回调方法,允许开发者处理生命周期事件。主要的生命周期方法包括:
onCreate()
:在Activity首次创建时调用。开发者需要在此方法中初始化Activity。 onStart()
:当Activity对用户可见时调用。 onResume()
:当Activity开始与用户交互时调用。 onPause()
:当Activity失去焦点并处于Activity栈顶时调用。 onStop()
:当Activity不可见时调用。 onDestroy()
:当Activity即将被销毁时调用。 为了有效管理Activity的生命周期,开发者需要合理安排资源的释放和获取,特别是在 onStop()
和 onPause()
中处理好资源的释放,以避免内存泄漏。
Service的启动模式取决于它被启动的方式以及它要完成的任务。Service可以是启动(Started)或绑定(Bound)的。
启动Service :通过调用 startService()
方法启动,这种方式不需要与任何Activity绑定。即使启动它的Activity被销毁了,Service依然可以运行,直到调用 stopService()
或 stopSelf()
方法。
绑定Service :通过调用 bindService()
方法启动,这种方式会创建Service与客户端Activity之间的通信连接。当Activity不再需要Service时,它可以调用 unbindService()
断开连接,此时Service会自动停止。
Service的启动和绑定模式的选择取决于应用的具体需求。通常,如果Service只是为其他组件提供单一操作的结果,那么绑定模式更为合适。如果Service需要执行后台任务,不管是否有组件正在使用它,启动模式会是更好的选择。
Broadcast Receiver是一个用于接收系统或应用层面的广播信息的组件。它通过接收Intent来执行对应的操作。使用Broadcast Receiver的场景很多,主要包括:
Broadcast Receiver在后台异步处理消息,可以配置成有序或无序。有序Broadcast允许广播发送者指定接收优先级,而无序Broadcast接收者不能指定接收顺序。
Content Provider为存储和检索数据提供了统一的接口。它使得不同应用间数据的共享变得可能,同时不需要暴露数据源的具体实现。Content Provider的功能包括:
当开发者创建一个Content Provider时,需要实现它的标准接口,包括query()、insert()、update()、delete()和getType()方法。Content Provider还支持URI权限,这允许其他应用通过授权才能访问特定的Content Provider。
通过以上章节的详细解析,您应该已经对Android应用程序框架的核心组件有了深入的理解。这些组件是构建任何一个Android应用的基础,理解它们的工作原理和使用场景对于任何Android开发者来说都是至关重要的。接下来,我们将进一步探讨Dalvik虚拟机与ART运行时优化,了解Android底层的工作原理和性能提升的方法。
Dalvik虚拟机是Android系统的核心组件之一,它是为了运行专门为Android平台设计的应用程序而专门开发的。Dalvik虚拟机将应用程序编译为Dalvik可执行文件格式(DEX),这种格式经过优化,能够在有限的存储空间和内存中高效运行。Dalvik虚拟机使用了称为寄存器的优化技术,而不是Java虚拟机的栈,这允许它更有效地处理指令。Dalvik虚拟机基于即时编译(JIT)技术,这意味着字节码在应用程序运行时被编译成机器码,从而提高了执行速度。
Dalvik虚拟机的另一个关键特性是它的进程管理。每个Android应用程序运行在一个独立的Dalvik虚拟机进程中,这为应用程序提供了良好的隔离性,同时也便于系统管理资源和应用程序的生命周期。Dalvik虚拟机还负责执行垃圾回收操作,它采用了一种称为mark-sweep的算法,有效地管理内存使用,减少了内存泄漏的可能性。
Dalvik字节码和Java字节码虽然都源自于Java语言,但在设计上存在显著差异。Dalvik字节码专门为移动设备优化,而Java字节码则更广泛地适用于多种平台。Dalvik字节码是专为Android的DEX文件格式设计的,它通过减少方法数量、优化指令集和使用更紧凑的数据结构来减少文件的大小。
Dalvik字节码和Java字节码之间不能直接兼容,因此Android提供了一个名为dx的工具,用于将Java字节码转换为Dalvik字节码。在转换过程中,dx工具会优化类、方法和字段名称,去除Java字节码中不必要的信息,并进行代码优化,如内联函数和优化循环。
随着Android系统的发展,Dalvik虚拟机的某些局限性开始显现,尤其是在应用程序启动速度和执行效率方面。为了改善这些问题,Android 4.4(KitKat)引入了ART(Android Runtime)作为替代Dalvik的新运行时环境。从Android 5.0(Lollipop)开始,ART成为了默认的运行时。
ART的引入带来了多项改进,其中包括提前编译(AOT),这种编译方式在应用程序安装时就将字节码编译成机器码,而不是在运行时。这显著提升了应用程序的启动速度和性能。ART还改进了垃圾回收机制,使用了一个更加高效和增量的垃圾回收器,这减少了应用程序的暂停时间,提高了用户体验。
ART引入了多种代码优化和性能提升策略,以确保Android应用程序运行更加流畅。首先,ART实现了更细致的垃圾回收策略,它能够根据应用程序的需要动态调整垃圾回收的频率和范围。其次,ART对内存分配进行了优化,它提供了对象池来减少内存碎片化。
在代码优化方面,ART包括了一个性能监控服务,可以监控应用程序的运行时行为,并将这些信息用于优化。它还能够执行一些深层次的优化,例如内联缓存和方法内联,这些优化可以通过减少方法调用开销来提高效率。
此外,ART为开发者提供了工具和接口来进一步优化自己的应用程序。例如,通过使用Android Profiler工具,开发者可以监控应用程序的CPU、内存和网络使用情况,以识别和解决问题。还有ProGuard工具用于减小应用的大小和复杂性,通过移除未使用的代码和优化类、方法和字段,来提高应用的运行效率。
在ART环境下,性能分析与调试是通过一组工具来实现的。开发者可以使用Android Studio的Profile工具来分析应用的CPU、内存和网络使用情况。这些工具能够提供详细的性能报告,包括方法执行时间、内存分配和垃圾回收活动。
除了分析工具,ART还提供了一套调试接口,使得开发者能够更深入地理解代码执行情况。例如,通过Android Debug Bridge (ADB) 工具,开发者可以进行远程调试,这包括设置断点、单步执行和查看调用栈。在Android Studio中,还有专门针对ART的调试视图,比如Heap Viewer,用于分析应用的内存使用情况。
这些性能分析和调试工具对于识别和解决性能瓶颈至关重要。开发者可以利用这些工具进行持续的性能优化,确保应用在用户设备上运行顺畅,提高用户满意度。
尽管ART已成为Android的默认运行时,但为了兼容性,Android仍然支持Dalvik。开发者可以在同一设备上安装同时支持Dalvik和ART的应用程序。这种共存策略对于旧设备尤为重要,因为这些设备可能无法支持ART运行时或者某些特定的ART特性。
共存策略还允许开发者在ART设备和Dalvik设备之间进行测试,确保应用程序在两个不同的运行时环境中都能正常工作。这意味着开发者需要将应用程序编译为两种不同的可执行格式,并在安装时根据运行时环境来选择合适的格式。Android提供了Gradle插件来自动处理这种共存策略,确保开发者的工作负担最小化。
此外,ART还引入了一种称为兼容层的机制,这允许Dalvik字节码在ART上运行。这意味着旧的应用程序不需要任何修改就可以在新的ART设备上运行。虽然这种兼容层可能会带来一些性能损失,但它保证了应用的后向兼容性,从而维持了Android生态系统的稳定性。
随着技术的不断进步,Android运行时环境也在不断发展。ART未来的发展方向将包括进一步的性能提升、资源管理优化以及安全性增强。开发者社区对编译技术和性能调优工具的需求也在推动ART的持续改进。
例如,ART未来可能会引入更先进的编译技术,如即时编译(JIT)与提前编译(AOT)的融合,以平衡应用程序的启动速度和执行效率。在资源管理方面,ART可能会采用更加精细的内存管理技术,以减少内存占用并提升设备的多任务处理能力。
安全方面,ART可能会继续改进应用的沙箱隔离机制,增强其防范恶意软件的能力。这可能包括引入更复杂的安全策略和强化代码签名机制,以确保应用的来源和完整性。
总之,随着Android系统的发展和用户对高性能移动应用需求的增长,ART运行时环境将继续进化,以提供更快、更安全、更高效的运行环境。对于开发者而言,这意味着需要持续关注ART的最新进展,以充分利用这些新技术来优化他们的Android应用程序。
在安卓应用的开发中,良好的用户界面设计不仅能够提升用户的体验,还能直接影响到应用的受欢迎程度和下载量。安卓系统提供了一套完整的UI设计标准和指南,即Material Design设计语言。开发者应当遵循这些指南,以此确保应用具有一致且直观的用户体验。
Material Design的设计原则包括:
为了创建更加直观和易于操作的用户界面,开发者需要运用以下优化技巧:
在安卓开发中,常用的布局管理器包括 LinearLayout
、 FrameLayout
、 RelativeLayout
和 ConstraintLayout
。开发者应根据具体需求选择合适的布局管理器:
LinearLayout
:按行或列排列子视图,适合简单的布局设计。 FrameLayout
:主要用于绘制单个子视图的场景,如背景图。 RelativeLayout
:允许子视图之间的相对定位,适合布局较为复杂的界面。 ConstraintLayout
:基于约束的关系布局,适应性最强,适合复杂的布局设计。 在设计复杂界面时,可以考虑以下步骤和技巧:
ConstraintLayout
:利用其强大的约束系统,应对复杂的布局需求。
在上述代码块中,通过使用 ConstraintLayout
的约束属性 app:layout_constraintTop_toTopOf
等,定义了一个文本视图的位置。这种方式可以灵活应对不同屏幕尺寸和方向的变化。
此外,要保证布局的性能,开发者需要:
标签。
和
标签以复用布局。 通过以上策略,开发者可以构建既美观又高效的安卓应用界面。
Intent是Android系统中不同组件之间进行交互的一种机制,可以认为是一种消息传递机制,它扮演了不同组件之间的粘合剂的角色。Intent用于启动一个Activity、Service,或者发送一个Broadcast。在Android系统中,四大组件中的三个(Activity、Service、BroadcastReceiver)之间的交互都是通过Intent来实现的。
Intent有几种类型,主要分为显式Intent和隐式Intent:
显式Intent :直接指定要启动的组件的类名称。当开发者知道需要启动的组件的确切名称时,就会使用显式Intent。例如,从一个Activity启动另一个Activity时,就可以使用显式Intent指定要启动的目标Activity。
java Intent intent = new Intent(CurrentActivity.this, TargetActivity.class); startActivity(intent);
在这段代码中, CurrentActivity.this
表示当前Activity的上下文, TargetActivity.class
是要启动的Activity的类对象。这种方式直接指明了Intent的目标组件,因此属于显式Intent。
隐式Intent :不指定具体的组件名称,而是指定一组操作和数据类型,由系统根据这些信息去查找合适的组件进行处理。这种方式经常用于启动一个Activity或者发送一个Broadcast,但并不关心具体是哪一个Activity或者Service。例如,用户点击了一个分享按钮,应用可能会发送一个分享内容的隐式Intent,具体的分享应用(如短信、邮件或社交应用)由用户设备上的应用决定。
java Intent shareIntent = new Intent(); shareIntent.setAction(Intent.ACTION_SEND); shareIntent.putExtra(Intent.EXTRA_TEXT, "分享的文本内容"); shareIntent.setType("text/plain"); startActivity(Intent.createChooser(shareIntent, "选择分享应用"));
在这个例子中,我们创建了一个Intent对象,然后设置了动作 ACTION_SEND
以及需要分享的文本内容,并指定了内容类型为纯文本。接着,我们启动了一个 Intent.createChooser
来让用户选择要使用的应用。
隐式Intent的解析依赖于组件的 intent-filter
配置。在Android应用的Manifest文件中,开发者可以为Activity、Service、BroadcastReceiver声明一组Intent Filter,来告诉系统哪些Intent是该组件愿意处理的。
Intent Filter是一个组件声明的XML标签,可以包含action、category、data三个子元素:
action :定义组件能够响应的行为。例如,一个浏览器应用可能会包含一个能响应 Intent.ACTION_VIEW
的Activity。
xml
在这个例子中, WebActivity
组件声明了一个能响应 ACTION_VIEW
的Intent Filter,并且只接受指向 www.example.com
的HTTP链接。
category :定义组件希望被如何调用。例如, android.intent.category.DEFAULT
表示该组件可以作为默认的响应者。
data :指定数据类型,可以是MIME类型、URI等。
xml
在上面的Intent Filter配置中,组件声明了它能够处理类型为 image/*
的数据,并且能响应 ACTION_SEND
动作。
系统在接收到一个隐式Intent时,会根据Intent Filter中声明的action、category和data信息,来确定哪个组件能够处理这个Intent。如果一个Intent能够通过多个组件的Intent Filter,用户通常会得到一个选择对话框,来选择一个合适的应用来处理这个Intent。
Activity是Android应用中用于展示用户界面的组件,而Service是用于执行后台任务的组件。在很多场景下,Activity需要启动和管理Service,而Service也可能需要向Activity传递信息。以下是Activity与Service进行交互的几种方式:
启动Service :Activity可以通过调用 startService()
方法启动一个Service。启动Service时,通常需要传递一个包含必要信息的Intent。
java Intent serviceIntent = new Intent(this, MyService.class); serviceIntent.putExtra("extra_data", "数据"); startService(serviceIntent);
在这个例子中, MyService
是我们要启动的服务,通过 putExtra
方法我们向Service传递了需要的数据。
停止Service :当Activity不再需要Service时,可以通过 stopService()
方法来停止它。如果Service正在执行的后台任务可以被中断,它应该能响应停止请求。
java Intent stopServiceIntent = new Intent(this, MyService.class); stopService(stopServiceIntent);
Service无法直接更新UI,它通常需要通过回调机制通知Activity。以下是几种常见的Service与Activity通信的方法:
使用BroadcastReceiver
Service可以通过发送广播通知Activity,Activity可以注册一个BroadcastReceiver来接收这些广播。
```java
// 在Service中发送广播
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(“com.example.ACTION_SERVICE_MSG”);
broadcastIntent.putExtra(“msg”, “Service完成工作”);
sendBroadcast(broadcastIntent);
// 在Activity中注册BroadcastReceiver接收广播
BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra(“msg”);
// 更新UI
}
};
IntentFilter intentFilter = new IntentFilter(“com.example.ACTION_SERVICE_MSG”);
registerReceiver(myReceiver, intentFilter);
```
在这个例子中,Service通过 sendBroadcast
发送了一个带有自定义action的Intent,Activity通过注册的BroadcastReceiver来接收这个action并处理。
使用EventBus或其他事件总线框架
使用事件总线框架,如EventBus,可以解耦Service和Activity之间的直接通信。Service发布事件,而Activity订阅这些事件。
```java
// 在Service中发布事件
EventBus.getDefault().post(new ServiceCompletedEvent(“Service完成工作”));
// 在Activity中订阅事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onServiceCompletedEvent(ServiceCompletedEvent event) {
// 更新UI
}
// 注册EventBus
EventBus.getDefault().register(this);
// 取消注册EventBus
EventBus.getDefault().unregister(this);
```
在这个例子中,Service通过EventBus发布了一个事件,Activity通过订阅该事件来接收消息,并更新UI。
Broadcast Receiver主要用于接收来自系统的广播消息,也可以接收来自应用内部或应用间的自定义广播。Content Provider是Android中用于管理数据共享的组件,它提供了数据的访问接口。通常,Broadcast Receiver用于监听变化事件,而Content Provider用于查询和管理数据。
当Content Provider中的数据发生变化时,系统或应用可以发送一个广播。Broadcast Receiver可以监听这些变化,并执行相应的操作。
public class DataChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.CONTENT_CHANGED")) {
Uri contentUri = intent.getData();
// 根据contentUri查询Content Provider中的变化数据,并进行处理
}
}
}
在这个例子中,我们创建了一个Broadcast Receiver,它监听了所有内容变化的广播。当检测到数据发生变化时,它可以获取到 contentUri
,然后进行进一步处理。
Content Provider可以设置访问权限,以控制其他应用或组件对其数据的访问。通过在Content Provider中声明 android:grantUriPermissions
属性,可以授予临时权限。
在这个例子中,DataProvider是定义的数据提供者,其他应用可以被授予读写权限。开发者可以利用这些权限控制机制,确保数据的安全访问。
结合Broadcast Receiver与Content Provider,我们可以构建一个简单的应用场景。假设有一个天气信息应用,它使用Content Provider存储天气数据,并为其他应用提供数据服务。同时,这个应用需要在天气数据发生变化时,通过Broadcast Receiver通知用户。
// 广播接收器监听数据变化
public class WeatherChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 假设Content Provider已经定义了天气信息的数据uri
Uri weatherUri = Uri.parse("content://com.example.weather.provider/weather");
Cursor cursor = context.getContentResolver().query(weatherUri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
// 更新UI显示新的天气信息
}
cursor.close();
}
}
// 在Content Provider中定义数据变化的广播意图
public class WeatherProvider extends ContentProvider {
// ...
@Override
public void insert(Uri uri, ContentValues values) {
// 数据插入逻辑
// ...
// 发送数据变化的广播
Intent intent = new Intent("android.intent.action.WEATHER_CHANGED");
context.sendBroadcast(intent);
}
// ...
}
在这个例子中,当天气数据发生变化时(例如通过Content Provider的insert方法插入新的数据),WeatherProvider通过发送自定义广播 WEATHER_CHANGED
来通知所有注册了该广播的WeatherChangeReceiver。然后,WeatherChangeReceiver接收到广播后,查询Content Provider获取最新的天气数据,并更新UI显示。这样的设计不仅能够使得数据的提供和使用分离,同时也保证了模块之间的解耦。
通过这样的设计,我们可以看到组件间交互在实际应用中的强大功能,以及它们如何协同工作来提供一致的用户体验。
随着安卓设备的多样化,为不同设备和屏幕尺寸提供良好的用户体验已经成为了安卓应用开发中的一项关键任务。本章节将详细介绍安卓资源管理以及如何在多设备之间进行适配,确保应用的兼容性和可维护性。
资源管理是安卓开发中极为重要的一部分,它涉及到应用中所有的非代码元素,如图片、布局文件、字符串等。通过合理地组织和优化资源,开发者不仅能够使应用更加模块化,还能提高应用的性能。
安卓平台上的资源文件主要分为以下几种类型:
layout
:包含用户界面布局的XML文件。 drawable
:存放图像和其他可绘制对象(如shape、selector等)。 values
:存放字符串( strings.xml
)、尺寸( dimens.xml
)、样式( styles.xml
)等。 raw
:存放未被处理的原始文件,如音频、视频等。 menu
:存放应用菜单项的XML文件。 每种资源类型都有其特定的用途,它们共同工作来实现应用的多样性和灵活性。
为了优化资源管理,开发者需要遵循以下策略:
res/values-xxhdpi
、 res/values-fr
等)。 为了实现对多设备的适配,安卓开发需要解决不同设备屏幕尺寸、分辨率、屏幕方向等问题。
安卓使用屏幕密度和尺寸的独立维度来描述屏幕大小,按照从最小到最大分为 small
, normal
, large
, xlarge
等类别。在 res
目录下,可以创建相应的资源文件夹,比如 layout-large
、 layout-xlarge
等。
为了解决不同尺寸屏幕的适配问题,推荐使用以下方法:
为了处理设备方向和分辨率的变化,需要考虑以下几点:
layout-land
。 AndroidManifest.xml
中为支持不同屏幕方向的Activity指定 android:screenOrientation
属性。 drawable
文件夹下创建不同分辨率的资源文件夹,如 drawable-hdpi
、 drawable-xhdpi
等。 在上述策略的支持下,开发者能够为各种设备提供良好的用户体验。总之,合理的资源管理和多设备适配,对于一个成功安卓应用来说至关重要。通过不断优化和实践,开发者可以显著提升应用的性能和兼容性。
本文还有配套的精品资源,点击获取
简介:安卓基础知识课程为初学者及进阶开发者提供安卓系统架构、关键开发技术以及最新开发工具的全面介绍。课程涵盖了从系统架构层面的核心概念如HAL、系统库、应用框架、应用程序层,到应用开发的关键组件,包括Dalvik/ART虚拟机、UI设计、Intent通信机制、资源管理、权限系统、进程与线程处理、Android Studio/Gradle集成、应用调试与测试,以及Android NDK/JNI使用。课程还涉及了安卓版本更新和兼容性处理,以确保应用在不同设备上的良好运行。两个附带的电子书《深入理解Android 卷 I - 邓凡平》和《深入理解Android 卷 II - 邓凡平》深入解析这些知识点,而SumatraPDF-2.5.8625.exe工具支持阅读电子书文件,便于深入学习安卓开发。
本文还有配套的精品资源,点击获取