Android Heroes Reading Notes 5



第八章Activity和Activity调用栈分析

1.Activity生命周期

理解生命周期就是两张图:第一张图是回字型的生命周期图

第二张图是金字塔型的生命周期图

注意点

(1)从stopped状态重新回到前台状态的时候会先调用onRestart方法,然后再调用后续的onStart等方法; (2)启动另一个Activity然后finish,先调用旧Activity的onPause方法,然后调用新的Activity的onCreate->onStart->onResume方法,然后调用旧Activity的onStop->onDestory方法。 如果没有调用finish那么旧Activity会调用onPause->onSaveInstanceState->onStop方法,onDestory方法不会被调用。 (3)如果应用长时间处于stopped状态并且此时系统内存极为紧张的时候,系统就会回收Activity,此时系统在回收之前会回调onSaveInstanceState方法来保存应用的数据Bundle。当该Activity重新创建的时候,保存的Bundle数据就会传递到onRestoreSaveInstanceState方法和onCreate方法中,这就是onCreate方法中Bundle savedInstanceState参数的来源(onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原)。 onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的。 onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据。 onRestoreInstanceState被调用的前提是,activity“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity,这种情况下activity一般不会因为内存的原因被系统销毁,故activity的onRestoreInstanceState方法不会被执行。

2.Activity任务栈 应用内的Activity是被任务栈Task来管理的,一个Task中的Activity可以来自不同的应用,同一个应用的Activity也可能不在同一个Task中。默认情况下,任务栈依据栈的后进先出原则管理Activity,但是Activity可以设置一些“特权”打破默认的规则,主要是通过在AndroidManifest文件中的属性android:launchMode或者通过Intent的flag来设置。

standard:默认的启动模式,该模式下会生成一个新的Activity,同时将该Activity实例压入到栈中(不管该Activity是否已经存在在Task栈中,都是采用new操作)。例如: 栈中顺序是A B C D ,此时D通过Intent跳转到A,那么栈中结构就变成 A B C D A,点击返回按钮的 显示顺序是 D C B A,依次摧毁。

singleTop:在singleTop模式下,如果当前Activity D位于栈顶,此时通过Intent跳转到它本身的Activity(即D),那么不会重新创建一个新的D实例(走onNewIntent()),所以栈中的结构依旧为A B C D,如果跳转到B,那么由于B不处于栈顶,所以会新建一个B实例并压入到栈中,结构就变成了A B C B B。应用实例:三条推送,点进去都是一个activity。

singleTask:跟singleTop类似,只不多singleTop是检测站定元素是否是需要启动的Activity,而singleTask是检测整个Activity栈中是否存在当前需要启动的Activity.如果存在,而将该Activity置于栈顶,并将该Activity以上的Activity都销毁(单任务栈情况下)。
在singleTask模式下,Task栈中只能有一个对应Activity的实例。例如:现在栈的结构为A B C D,此时D通过Intent跳转到B(走onNewIntent()),则栈的结构变成了:A B。其中的C和D被栈弹出销毁了,也就是说位于B之上的实例都被销毁了。如果系统已经存在一个实例,系统就会将请求发送到这个实例上,但这个时候,系统就不会再调用通常情况下我们处理请求数据的onCreate方法,而是调用onNewIntent方法。通常应用于首页,首页肯定得在栈底部,也只能在栈底部。

singleInstance:singleInstance模式下会将打开的Activity压入一个新建的任务栈中。例如:Task栈1中结构为:A B C,C通过Intent跳转到了D(D的启动模式为singleInstance),那么则会新建一个Task 栈2,栈1中结构依旧为A B C,栈2中结构为D,此时屏幕中显示D,之后D通过Intent跳转到D,栈2中不会压入新的D,所以2个栈中的情况没发生改变。如果D跳转到了C,那么就会根据C对应的启动模式在栈1中进行对应的操作,C如果为standard,那么D跳转到C,栈1的结构为A B C C,此时点击返回按钮,还是在C,栈1的结构变为A B C,而不会回到D。

3.Intent Flag启动模式 (1)Intent.FLAG_ACTIVITY_NEW_TASK:使用一个新的task来启动Activity,一般用在service中启动Activity的场景,因为service中并不存在Activity栈。 (2)Intent.FLAG_ACTIVITY_SINGLE_TOP:类似andoid:launchMode="singleTop" (3)Intent.FLAG_ACTIVITY_CLEAR_TOP:类似andoid:launchMode="singleTask" (4)Intent.FLAG_ACTIVITY_NO_HISTORY:使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在task栈中。例如A B,在B中以这种模式启动C,C再启动D,则当前的task栈变成A B D。

4.清空任务栈 (1)clearTaskOnLaunch:每次返回该Activity时,都将该Activity之上的所有Activity都清除。通过这个属性可以让task每次在初始化的时候都只有这一个Activity。 (2)finishOnTaskLaunch:clearTaskOnLaunch作用在别的Activity身上,而finishOnTaskLaunch作用在自己身上。通过这个属性,当离开这个Activity所在的task,那么当用户再返回时,该Activity就会被finish掉。 [暂时还不明白这个有什么作用] (3)alwaysRetainTaskState:如果将Activity的这个属性设置为true,那么该Activity所在的task将不接受任何清理命令,一直保持当前task状态,相当于给了task一道”免死金牌”。

第九章 Android系统信息与安全机制

1.获取系统信息:android.os.BuildSystemProperty

String board = Build.BOARD;
String brand = Build.BRAND;
String supported_abis = Build.SUPPORTED_ABIS[0];
String device = Build.DEVICE;
String display = Build.DISPLAY;
String fingerprint = Build.FINGERPRINT;
String serial = Build.SERIAL;
String id = Build.ID;
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
String hardware = Build.HARDWARE;
String product = Build.PRODUCT;
String tags = Build.TAGS;
String type = Build.TYPE;
String codename = Build.VERSION.CODENAME;
String incremental = Build.VERSION.INCREMENTAL;
String release = Build.VERSION.RELEASE;
String sdk_int = "" + Build.VERSION.SDK_INT;
String host = Build.HOST;
String user = Build.USER;
String time = "" + Build.TIME;

String os_version = System.getProperty("os.version");
String os_name = System.getProperty("os.name");
String os_arch = System.getProperty("os.arch");
String user_home = System.getProperty("user.home");
String user_name = System.getProperty("user.name");
String user_dir = System.getProperty("user.dir");
String user_timezone = System.getProperty("user.timezone");
String path_separator = System.getProperty("path.separator");
String line_separator = System.getProperty("line.separator");
String file_separator = System.getProperty("file.separator");
String java_vendor_url = System.getProperty("java.vendor.url");
String java_class_path = System.getProperty("java.class.path");
String java_class_version = System.getProperty("java.class.version");
String java_vendor = System.getProperty("java.vendor");
String java_version = System.getProperty("java.version");
String java_home = System.getProperty("java_home");

2.Apk应用信息:PackageManager和ActivityManager 在AndroidManifest文件中,Activity的信息是通过ActivityInfo类来封装的;整个Manifest文件中节点的信息是通过PackageInfo类来进行封装的;此外还有ServiceInfo、ApplicationInfo、ResolveInfo等。 其中ResolveInfo封装的是包含信息的上一级信息,所以它可以返回ActivityInfo、ServiceInfo等包含的信息,它经常用来帮助我们找到那些包含特定Intent条件的信息,如带分享功能、播放功能的应用。

PackageManager侧重于获取应用的包信息,而ActivityManager侧重于获取运行的应用程序的信息。 PackageManager常用的方法: getPackageManger、getApplicationInfo、getApplicationIcon、getInstalledApplications、getInstalledPackages、queryIntentActivities、queryIntentServices、resolveActivity、resolveService等 ActivityManager封装了不少对象,每个对象都保存着一些重要信息。 ActivityManager.MemoryInfo:关于系统内存的信息,例如availMem(系统可用内存)、totalMem(总内存)等; Debug.MemoryInfo:该MemoryInfo主要用于统计进程下的内存信息; RunningAppProceeInfo:运行进程的信息,存储的是与进程相关的信息,例如processName、pid、uid等; RunningServiceInfo:运行服务的信息,存储的是服务进程的信息,例如activeSince(第一次被激活时间)等。

3.packages.xml文件(位于/data/system目录下) 在系统初始化的时候,PackageManager的底层实现类PackageManagerService会去扫描系统中的一些特定的目录,并解析其中的apk文件,最后把它获得的应用信息保存到packages.xml文件中,当系统中的应用安装、删除或者升级时,它也会被更新。

4.Android安全机制 五道防线: (1)代码安全机制——代码混淆proguard (2)应用接入权限机制——AndroidManifest文件权限声明、权限检查机制 系统检查操作者权限的顺序:首先,判断permission名称,如果为空则直接返回PERMISSION_DENIED;其次,判断Uid,如果uid为0或者为System Service的uid,不做权限控制,如果uid与参数中的请求uid不同,那么返回PERMISSION_DENIED;最后,通过调用PackageManagerService.checkUidPermission方法判断该uid是否具有相应的权限,该方法会去xml的权限列表和系统级的platform.xml中进行查找。 (3)应用签名机制——数字证书:系统不会安装没有签名的app,只有拥有相同数字签名的app才会在升级时被认为是同一个app (4)Linux内核层安全机制——Uid、访问权限控制 (5)Android虚拟机沙箱机制——沙箱隔离:每个app运行在单独的虚拟机中,与其他应用完全隔离