平时也就只会跑程序,也不知道Android安装程序是个什么原理
Android应用安装有如下四种方式
应用安装的流程及路径
应用安装涉及到如下几个目录:
system/app 系统自带的应用程序,无法删除
data/app 用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录
data/data 存放应用程序的数据
data/dalvik-cache 将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一);
详细介绍第4 种
apk文件安装,会弹出一个安装界面,其实这是Android调用了另外一个叫PackageInstaller的APP来专门卸载和安装
apk。这个还真没想到
首先讲讲他的主界面 PackageInstallActivity
onCreate() 主要就是解析一大堆的APK信息,来判断有没有错误
initiateInstall() 检查是否安装过,有没有相同的包名
startInstallConfirm() 这里面提取权限的信息,并展示权限列表啥的,源码看的也很是头疼。。。点击确认,又到了另外一个类去进行安装的操作了。
刚开始我的想法就简单了,自己自定义个权限,第三方应用过来了我就检查它的权限列表,没有我定义的权限就不让它走后面安装的步骤,弹出了Dialog警告。
提取权限列表的代码
private List
String[] ps=pi.requestedPermissions;
if(ps!=null){
for (String str:ps) {
Log.e("AAAAAAAAAAAA",str);
}
return Arrays.asList(ps);
}
return null;
}
private void showFailDialog(){
final AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("安装提示")
.setMessage("该第三方应用缺少权限:com.example.xiefei.permission,不允许安装")
.setCancelable(false)
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
PackageInstallerActivity.this.finish();
}
});
builder.create().show();
}
=================================================================================
搞完之后发现功能是实现了,突然想到为什么不检验签名的信息呢,这样不是更加安全么
获得签名信息最为关键的就是比较公钥是不是相同的。
1.首先在系统的目录下创建个文件夹,来存放信任的.pem文件,因为.pem里通常就只包含公钥的信息,都不用加密的
http://blog.csdn.net/mycoolx/article/details/6730435 证书的介绍
2.提取第三方应用的签名信息
//PackageParser对外隐藏,所以在外面做的话可以用反射,还有就是版本不同,API可能也有差异
http://blog.csdn.net/wulianghuan/article/details/18400581 可以看看这个
private Signature showUninstallAPKSignatures(String apkPath) {//apk的路径
PackageParser pp=new PackageParser();
PackageParser.Package mPackage=pp.parsePackage(new File(apkPath),PackageManager.GET_SIGNATURES);
pp.collectCertificates(mPackage,PackageManager.GET_SIGNATURES);
return pp.mSignatures[0];
}
public String parseSignature(byte[] signature) {
String pubKey="";
try {
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(signature));
pubKey = cert.getPublicKey().toString();//公钥
String signNumber = cert.getSerialNumber().toString();//证书的序列号
} catch (CertificateException e) {
e.printStackTrace();
}
return pubKey;
}
这两个方法就可以提取第三方应用的公钥了
3.获取信任证书的公钥信息,来校验
private boolean isSystemSign(Signature sign1){
boolean isSystemSign=false;
File root=new File("/system/etc");
File[] files = root.listFiles();
for (File file:files) {
if (file.isFile()&&file.getName().endsWith(".pem")) {
if (getPublicKey(file.getAbsolutePath()).toString().equals(parseSignature(sign1.toByteArray()))) {
isSystemSign=true;
break;
}
}
}
return isSystemSign;
}
通过.pem文件获得公钥
private PublicKey getPublicKey(String filePath){
try {
CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");
FileInputStream bais=new FileInputStream(filePath);
X509Certificate Cert = (X509Certificate)certificatefactory.generateCertificate(bais);
PublicKey pk = Cert.getPublicKey();
System.out.println("pk:"+pk.toString());
return pk;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
做的这个东西 感觉很鸡肋,因为只有通过APK安装的方式,才会调PackageInstall这个程序,程序员通常用的adb 方式安装apk的话,完全不管这里,直接照样安装,哈哈,还真没多大的意义,不过还是可以防止比人乱下载东西的