查看Android系统信息的软硬件信息
学习内容
由于Android手机的可开发性,市场上“拼配置”也成了手机厂商重要宣传点。
要获取系统的配置信息,通常从以下两个方面获取
9.1.1android.os.Build
android.os.Build类里面的信息非常丰富,包含了系统编译时的大量设备,配置信息,下面列举了一些常用的信息。
Build.BOARD:主板
Build.BRAND:Android系统定制商
Build.SUPPORTED_ABIS:CPU指令集
Build.DEVICE:设备参数
Build.DISPLAY:显示屏参数
Build.FINGERPRINT:唯一编号
Build.SERIAL:硬件序列号
Build.ID:修订版本列表
Build.MANUFACTURER:硬件制造商
Build.MODEL:版本
Build.HARDWARE:硬件名
Build.PRODUCT:手机产品名
Build.TAGS:描述Build的标签
Build.TYPE:Builder类型
Build.VERSION.CODENAME:当前开发代号
Build.VERSION.INCREMENTAL:源码控制版本号
Build.VERSION.RELEASE:版本字符串
Build.VERSION.SDK_INT:版本号
Build.HOST:host值
Build.USER:User名
Build.TIME:编译时间
1.2SystemProperty
包含了许多系统配置属性值和参数,很多信息与上面通过android.os.Build获取的值是相同的,下面同样列举了一些常用的信息
os.version:OS版本
os.name:OS名称
os.arch:OS架构
user.home:Home属性
user.name:Name属性
user.dir:Dir属性
user.timezone:时区
path.separator:路径分隔符
line.separator:行分隔符
file.separator:文件分隔符
java.vendor.url:Java vender Url属性
java.class.path:Java Class属性
java.class.version:Java Class版本
java.vendor:Java Vender属性
java.version:Java版本
java.home:Java Home属性
1.3Android系统信息实例
二:Android Apk应用信息获取之PackgeManager
2.1PackageManager
AndroidMainifest结点中的信息被PackageInfo来进行封装。Android系统也提供了PackageManager来负责管理所有已安装的App。
-ActivityInfo
ActivityInfo封装在了Mainfest文件中的< activity >和< eceiver>之间的所有信息,包括name、icon、label、launchMode等。
ServiceInfo
ServiceInfo与ActivityInfo类似,封装了< service>之间的所有信息。
ApplicationInfo
它封装了< application>之间的信息,特别的是,ApplicationInfo包含了很多Flag
FLAG_SYSTEM表示为系统应用
FLAG_EXTERNAL_STORAGE表示为安装在SDcard上的应用
PackageInfo
PackageInfo与前面三个Info类类似,都是用于封装Manifest文件的相关节点信息,而PageageInfo包含了所有的Activity和Service信息。
ResolveInfo
ResolveInfo包含了< intent>信息的上一级信息,所以它可以返回ActivityInfo、ServiceInfo等包含了< intent>的信息
PackageManager中封装的用来获取这些信息的方法:
getPackageManager():通过这个方法可以返回一个PackageManager对象
getApplicationInfo():以ApplicationInfo的形式返回指定包名的ApplicationInfo
getApplicationIcon():返回指定包名的Icon
getInstalledApplications():以ApplicationInfo的形式返回安装的应用
getInstalledPackages():以PackageInfo的形式返回安装的应用
queryIntentActivities():返回指定Intent的ResolveInfo对象、Activity集合
queryIntentServices():返回指定Intent的ResolveInfo对象、Service集合
resolveActivity():返回指定Intent的Activity
resolveService():返回指定Intent的Service
下面通过一个实际的例子通过PackageManager筛选不同类型的App,利用ApplicationInfo中的FLAG_SYSTEM来判断:
app.flags & ApplicationInfo.FLAG_SYSTEM
如果当前应用的flags & ApplicationInfo.FLAG_SYSTEM != 0则为系统应用
如果flags & ApplicationInfo.FLAG_SYSTEM <= 0 则为第三方应用
特殊的,当系统应用升级后,也将会成为第三方应用: flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP != 0
如果当前应用的flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0 则为安装在SDCard上的应用
我们封装一个Bean来保存我们所需的字段:
public class PMAppInfo {
private String appLabel;
private Drawable appIcon;
private String pkgName;
public PMAPPInfo(){
}
public String getAppLabel() {
return appLabel;
}
public void setAppLabel(String appLabel) {
this.appLabel = appLabel;
}
public Drawable getAppIcon() {
return appIcon;
}
public void setAppIcon(Drawable appIcon) {
this.appIcon = appIcon;
}
public String getPkgName() {
return pkgName;
}
public void setPkgName(String pkgName) {
this.pkgName = pkgName;
}
}
接下来,通过上面所说的判断方法来判断各种类型的应用:
private List<PMAppInfo> getAppInfo(int flag) {
// 获取PackageManager对象
pm = this.getPackageManager();
// 获取应用信息
List<ApplicationInfo> listAppcations = pm
.getInstalledApplications(
PackageManager.GET_UNINSTALLED_PACKAGES);
List<PMAppInfo> appInfos = new ArrayList<PMAppInfo>();
// 判断应用类型
switch (flag) {
case ALL_APP:
appInfos.clear();
for (ApplicationInfo app : listAppcations) {
appInfos.add(makeAppInfo(app));
}
break;
case SYSTEM_APP:
appInfos.clear();
for (ApplicationInfo app : listAppcations) {
if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
appInfos.add(makeAppInfo(app));
}
}
break;
case THIRD_APP:
appInfos.clear();
for (ApplicationInfo app : listAppcations) {
if ((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
appInfos.add(makeAppInfo(app));
} else if ((app.flags &
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
appInfos.add(makeAppInfo(app));
}
}
break;
case SDCARD_APP:
appInfos.clear();
for (ApplicationInfo app : listAppcations) {
if ((app.flags &
ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
appInfos.add(makeAppInfo(app));
}
}
break;
default:
return null;
}
return appInfos;
}
private PMAppInfo makeAppInfo(ApplicationInfo app) {
PMAppInfo appInfo = new PMAppInfo();
appInfo.setAppLabel((String) app.loadLabel(pm));
appInfo.setAppIcon(app.loadIcon(pm));
appInfo.setPkgName(app.packageName);
return appInfo;
}
三:Android Apk应用信息获取之ActivityManager
PackageManager重点在于获取应用的包信息,而ActivityManager在于获取在运行的应用程序信息。
ActivityManager获取应用程序信息封装了不少Bean对象:
ActivityManager.MemoryInfo
MemoryInfo有几个非常重要的字段:availMem(系统可用内存),totalMem(总内存),threshold(低内存的阈值,即区分是否低内存的临界值),lowMemory(是否处于低内存)
Debug.MemoryInfo
这个MemoryInfo用于统计进程下的内存信息
RunningAppProcessInfo
运行进程的信息,存储的字段有:processName(进程名),pid(进程pid),uid(进程uid),pkgList(该进程下的所有包)
RunningServiceInfo
运行的服务信息,在它里面同样包含了一些服务进程信息,同时还有一些其他信息,activeSince(第一次被激活的时间、方式),foreground(服务是否在后台执行)
下面同样通过例子来看看如何使用ActivityManager,我们封装一个Bean来保存我们所需的字段:
public class AMProcessInfo {
private String pid;
private String uid;
private String memorySize;
private String processName;
public AMProcessInfo() {
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getMemorySize() {
return memorySize;
}
public void setMemorySize(String memorySize) {
this.memorySize = memorySize;
}
public String getProcessName() {
return processName;
}
public void setProcessName(String processName) {
this.processName = processName;
}
}
接下来,调用getRunningAppProcesses方法,返回当前运行的进程信息,并将我们关心的信息保存到Bean中:
private List<AMProcessInfo> getRunningProcessInfo() {
mAmProcessInfoList = new ArrayList<AMProcessInfo>();
List<ActivityManager.RunningAppProcessInfo> appProcessList =
mActivityManager.getRunningAppProcesses();
for (int i = 0; i < appProcessList.size(); i++) {
ActivityManager.RunningAppProcessInfo info =
appProcessList.get(i);
int pid = info.pid;
int uid = info.uid;
String processName = info.processName;
int[] memoryPid = new int[]{pid};
Debug.MemoryInfo[] memoryInfo = mActivityManager
.getProcessMemoryInfo(memoryPid);
int memorySize = memoryInfo[0].getTotalPss();
AMProcessInfo processInfo = new AMProcessInfo();
processInfo.setPid("" + pid);
processInfo.setUid("" + uid);
processInfo.setMemorySize("" + memorySize);
processInfo.setProcessName(processName);
mAmProcessInfoList.add(processInfo);
}
return mAmProcessInfoList;
}
四:解析Packages.xml获取系统信息
系统初始化的时候,PackagesManager的底层实现类PackageManagerService会去扫描系统中的一些特定的目录,并解析其中的Apk文件。同时,Android把它获得的应用信息,保存在XML文件中,做成一个应用的花名册,当系统安装,删除,升级时,它也会更新。这个花名册就是位于/data/system/目录下的——packages.xml文件,
通过ADB Pull命令把它导出到本地,如图
< permissions>标签
permissions标签定义了目前系统所有的权限,并分为两类:系统定义的和Apk定义的。
< package>标签
package代表的是一个apk的属性,其中各节点的信息含义大致为
name:APK的包名
cadePath:APK安装路径,主要在system/app和data/app两种,前者是厂商定制的Apk,后者是用户安装的第三方Apk
userid:用户ID
version:版本
< perms>标签
对应Apk的AndroidManifest文件中的< uses-permission>标签,记录Apk的权限信息
五:Android安全机制
Google建立了一层层堡垒,保护Android的核心安全,免遭外界的攻击。
5.1Android安全机制简介
5道防线来保护Android系统的安全。
第一道防线——代码安全机制——代码混淆proguard——由于Java语言的特殊性,即使是编译成Apk的应用程序也存在被反编译的风险。而proguard则是在代码层面上对Android应用程序App的第一重保护,它可以混淆关键代码,替换命名让破坏者阅读困难,同时可以压缩代码,优化编译后的字节码。
第二道防线——应用接入权限控制——AndroidMainifest文件权限声明,权限检查机制——任何应用程序App在使用Android受限资源的时候,都需要显示向系统声明所需要的权限,只有当一个应用app具有相应的权限,才能在申请受限资源的时候,通过权限机制的检查并使用系统的BInder对象完成对系统服务的调用。但是也有先天性的不足,如下
在这里插入代码片
用之间能够互不影响,即使一个应用崩溃,也不会导致其他应用异常。虽然通过上面的五道防线,仍不能100%保证Android的核心安全,但却可以在最大程度上给破坏者增加破坏难度。从另一方面来说,这些破坏者的破解也正是推动Android安全机制逐渐健全的动力。
5.2Android系统安全隐患
5.3Android Apk反编译
Android应用程序apk文件,就是一个压缩文件,。先使用解压工具解压apk文件,会发现资源文件等xml文件基本无法打开,即使打开也是乱码,乱码是经过android进行加密过的文件。且找不到源代码文件src。
三个反编译工具,负责反编译不同的部分。
apktool.jar可以把xml那些资源文件解析出来,dex2jar可以把dex文件转成jar文件,最后通过jdgui把jar文件转成src源代码(自己在网上下载的akptoolaid)
5.4Android Apk加密
由于Java字节码的特殊性,使得它非常容易被反编译。为了更好的对Java Class文件进行一些保护,通常会使用ProGuard来对Apk进行混淆处理,用无意义的字母来重命名类,字段,方法和属性。当然ProGuard不仅仅可以用来混淆代码,还可以删除无用的类,字段,方法,和属性,以及删除无用的注释,最大限度地优化字节码文件。
Android Studio中,可以非常方便地使用ProGuard,在Gradle Scripts文件夹下,打开build.gradle(Module:app)文件,显示如下所示
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
minifyEnabled设置为true就可以打开ProGur=ard功能,getDefaultProguardFile是系统默认的混淆规则,它位于SDK目录 /tools/proguard/proguard-android.txt目录下,大部分情况使用这个默认的混淆规则就可以了;后面一部分是项目中自定义的混淆文件
在这个文件里可以定义引入第三方依赖包的混淆规则。配置好后使用AS导出Apk,就可以生成混淆。