大家都知道刻舟求剑的寓言故事,说的是事物是发展变化着的,如果拘泥于原来的情况,那随着情况的改变,就不会得到预期的结果。同样,影响app运行的因素,并不只是外部环境(如硬件、系统、权限等等),还包括app自身的运行信息。如果app的运行状态发生了变化,那么原先处理正确的逻辑也可能处理失败,所以在特定的情况下,我们得对app的运行情况进行检查。

apk安装信息

启动app的时候,常常会检查当前apk的安装信息,以此判断接下来要做哪些准备工作,举例如下:
1、获得apk的版本号,针对不同版本,分别对SQLite的数据库表做相应的变更操作。
2、获得apk的签名,据此判断安装包是否为合法来源。签名的介绍参见《 Android开发笔记(七十三)代码混淆与反破解》。
3、获得apk的申请权限,从而判断app是否申请了相应的权限。权限的介绍参见《 Android开发笔记(七十九)资源与权限校验》。

PackageManager类便是获取apk安装信息的工具,该类的getPackageInfo方法即可获得相应的安装信息。下面是getPackageInfo方法中常用标志位参数的说明:
GET_ACTIVITIES : 获取活动Activity列表。列表信息是PackageInfo对象的activities参数。
GET_RECEIVERS : 获取广播接收器Receiver列表。列表信息是PackageInfo对象的receivers参数。
GET_SERVICES : 获取服务Service列表。列表信息是PackageInfo对象的services参数。
GET_SIGNATURES : 获取签名列表。列表信息是PackageInfo对象的signatures参数。
GET_PERMISSIONS : 获取权限列表。列表信息是PackageInfo对象的requestedPermissions参数。

获得PackageInfo实例的代码如下:

PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0);

下面是PackageInfo类常用的通用参数说明:
packageName : 包名
versionName : 版本名称
versionCode : 版本代码
firstInstallTime : 首次安装时间
lastUpdateTime : 最后更新时间

多进程时判断是否为主进程

通常我们会在Application的扩展类中初始化全局变量,方便后续的信息交互,Application的介绍参见《 Android开发笔记(二十八)利用Application实现内存读写》。有时候我们又会使用多进程模式,让服务运行在单独的进程中,这样就造成一个问题:新进程是由主进程原样fork出来,即新进程也会执行Application的onCreate方法。但是按照我们的本意,新进程只是为了运行单独的服务,并不需要初始化不相关的全局变量,因此这时候就得判断当前进程是否为主进程。
下面是判断是否为主进程的示例代码:

 public static boolean isMainProcess(Context ctx) {String processName = "";ActivityManager actMgr = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);for (ActivityManager.RunningAppProcessInfo appProcess : actMgr.getRunningAppProcesses()) {if (appProcess.pid == Process.myPid()) {processName = appProcess.processName;Log.d(TAG, "packageName=" + ctx.getPackageName());Log.d(TAG, "processName=" + processName);}}if (ctx.getPackageName().equals(processName)) {return true;} else {return false;}}

下面是Application扩展类中的调用代码:

public class MainApplication extends Application {private final static String TAG = "MainApplication";@Overridepublic void onCreate() {super.onCreate();if (ActivityUtil.isMainProcess(getApplicationContext()) == true) {//下面初始化主进程的参数Log.d(TAG, "当前是主进程");} else {//这里是分支进程,不处理主进程的参数Log.d(TAG, "当前是分支进程");}}}

Activity是否存在

一般在Activity代码中都是直接操作页面上的元素,不过有时候得小心,页面在操作UI前就不存在了,其中的一个例子可见《 Android开发笔记(七十五)内存泄漏的处理》。在上面这篇文章中,我们为了防止Handler的内存泄漏,给Activity加了个弱引用对象,由于弱引用是可以被回收的,因此在使用前得判断弱引用对象是否为空,只有对象非空,才能操作其上的UI元素。

除了上面的例子,还有其它情况可能导致操作UI时的页面丢失,基本上都是些异步操作造成的,比如说处理线程消息的Handler,以及广播接收器BroadcastReceiver。这些情况要想判断Activity页面是否存在,就得借助于ActivityManager的getRunningTasks方法,详细代码如下:

 public static boolean isActivityWork(Context ctx, String activityName) {boolean isWork = false;ActivityManager actMgr = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);List<RunningTaskInfo> taskList = actMgr.getRunningTasks(1024);for (int i = 0; i < taskList.size(); i++) {String name = taskList.get(i).topActivity.getClassName();Log.d(TAG, "i="+i+", activity name="+name);if (name.equals(activityName) == true) {isWork = true;break;}}return isWork;}

Service是否存在

与Activity类似,Service也可能被安全软件杀死,导致使用该服务报空指针异常(比如接收广播后调用startForeground方法)。判断后台服务是否存在,与活动的判断一样,都是采用ActivityManager工具类,不同的是,该工具获取服务列表调用的是getRunningServices方法,详细代码如下:

 public static boolean isServiceWork(Context ctx, String serviceName) {boolean isWork = false;ActivityManager actMgr = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);List<RunningServiceInfo> serviceList = actMgr.getRunningServices(1024);for (int i = 0; i < serviceList.size(); i++) {String name = serviceList.get(i).service.getClassName().toString();Log.d(TAG, "i="+i+", service name="+name);if (name.equals(serviceName) == true) {isWork = true;break;}}return isWork;}

点击下载本文用到的运行状态检查的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(八十)运行状态检查相关推荐

  1. Android开发笔记(十八)书籍翻页动画PageAnimation

    前面几节的动画都算简单,本文就介绍一个复杂点的动画--书籍翻页动画.Android有自带的翻页动画ViewPager,不过ViewPager只实现了平移效果.即便使用补间组合动画或者属性动画,也只是把 ...

  2. Android开发笔记(十五)淡入淡出动画TransitionDrawable

    说到淡入淡出动画,可能大家会想到补间动画里面的AlphaAnimation,不过这个深浅动画只能对透明度做渐变效果,也就是只能对一个图形做深浅的颜色变换.如果我们想要从A图片逐渐变为B图片,也就是要实 ...

  3. Android开发笔记(十九)底部标签栏TabBar

    底部标签页实现思路 现在的APP,大多在页面底部显示标签栏Tabbar,用于切换不同栏目的页面.Tabbar起源于iOS,iOS的Tabbar自动位于页面下方,可是Android搬过来的时候做了改动, ...

  4. Android开发笔记(十六)秋千摇摆动画SwingAnimation

    上节博主介绍了AlphaAnimation和淡入淡出动画的使用,其实AlphaAnimation只是四种补间动画中的一种.那么为了加深对其他补间动画的理解,我想说说旋转动画RotateAnimatio ...

  5. Android开发笔记(十四)圆弧进度动画CircleAnimation

    一个好看的APP,都有不少精致的动画效果.熟练运用各种动画技术,可让我们的APP灼灼生辉.Android在技术上把动画分为了三类,分别是帧动画FrameAnimation.补间动画TweenAnima ...

  6. Android开发笔记(十二)测量尺寸与下拉刷新

    尺寸测量的配置 控件宽和高的设置方式 大家知道,自定义视图的目的就是要在屏幕上显示期望的图案,那在绘制图案之前,我们得先知道这个图案的尺寸(如宽多少高多少). 一般在xml中给控件的宽和高有三种赋值方 ...

  7. Android开发笔记(十)常用的图片加工操作

    APP开发自然少不了各种图片的加工处理,虽然说加工图片是美工干的活,但是码农会些简单的操作总归是好事.一些简单的加工如缩放.旋转.裁剪.格式转换,使用ACDSee就够用了,不过有些稍微复杂的操作得借助 ...

  8. android开发标签栏应该设置多少,Android开发笔记(十九)底部标签栏TabBar

    底部标签页实现思路 现在的APP,大多在页面底部显示标签栏Tabbar,用于切换不同栏目的页面.Tabbar起源于iOS,iOS的Tabbar自动位于页面下方,可是Android搬过来的时候做了改动, ...

  9. Android开发笔记(八十六)几个特殊的类

    接口interface interface是一些功能的集合,但它只定义了对象必须实现的成员,而不包含成员的实现代码,成员的具体代码由实现接口的类提供.Android对接口的使用场景主要有三类:事件监听 ...

  10. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

最新文章

  1. 设计模式 之美 -- 面向对象(C/C++分别实现)
  2. PyCharm vs VSCode,是时候改变你的 IDE 了!
  3. oracle怎么查看一个表或一个索引占用多少空间
  4. [转]Servlet3.1规范
  5. Java 字节数组(byte[])和整型(int)的相互转换
  6. java_IO流之SequenceInputStream合并流的使用
  7. JAVA中的字符串操作
  8. 将当前的head推送到远程_Git 通俗易懂系列 三、远程仓库和标签
  9. android uboot log,RK3288 Android 8.1系统uboot logo过渡到kernel logo会花一下
  10. 题解 POJ 2559-SP1805 【HISTOGRA - Largest Rectangle in a Histogram】
  11. ActiveMQ (一):安装启动及测试
  12. 打游戏时领悟了“向死而生”,这个AI算法真的不虚强化学习
  13. AndroidManifest.xml 注意事项
  14. MFC编程——Where is WinMain?
  15. java9之后,String为何从char类型数组转成byte类型数组
  16. 4.3.1 划分子网
  17. 大数量级组合数的快速计算方法
  18. DirectX11 纹理采样
  19. 华为手机计算机模式切换,华为m6切换电脑模式操作方法
  20. 华为OBS通过ObjectKey生成临时的url地址

热门文章

  1. Leetcode每日一题:面试题17.12 binode
  2. 深度学习发展与机器学习
  3. 关于稀疏矩阵转化为稠密矩阵问题 (scipy.sparse格式和tensor稀疏张量格式)
  4. 【译】Tim Rose 的kibana插件教程-自定义App插件
  5. apt-get常见错误
  6. oracle中schema是什么,ORACLE中的两个概念:user和schema的区别和联系
  7. mysql数据库版本常用_推荐:经典版本常用MySQL的命令集锦_MySQL
  8. java环境变量的配置_一文带你学会Java环境变量配置(小白向)
  9. 911计算机专业基础综合,青岛大学10数据结构911计算机专业综合
  10. 哈工大c语言作业系统,2015秋C语言程序设计