参考:http://blog.sina.com.cn/s/blog_62ef2f140101j6q2.html

安装任意第三方的一个apk,恢复出厂设置,再次安装相同的apk,提示安装失败,通过打印LOG发现,安装失败的错误反回值是24,public static final int INSTALL_FAILED_UID_CHANGED = -24 ; 进一步跟踪发现,在恢复出厂设置后/data/data目录下的第三方应用的文件夹还在,手动删除此文件后再次安装就会成功,按正常逻辑恢复出厂设置后应该清除系统所有数据文件(包括第三方应用的一切都被清除才对)。
问题原因:恢复出厂设置后改变了之前安装第三方应用的UID,导致安装失败

我们经常在一个activity中去start另一个activity,或者与另一个acitivity的结果进行交互(startActivityForResult)。但有没有想过可能会出现的permission问题呢?如果你遇到了permission denial的Exception,那么你需要读读这篇文章啦。

我们在同一个application内部,可以随意的startActivity from Activity A to Activity B,而官方的文档中说startActivity可能会报NotFoundException,表示被start的Activity不存在。因此,我们很容易忽略另一个可能的Exception,Permission Denial。

当我们在不同的application中,如application A中的Activity去start一个application B中的Activity,也许你什么Exception都不会得到,也可能会直接Force Close掉。因为再Start Activity时,代码是有去检验permission的。

如下情况,可以成功startActivity而不会得到permission denial

1、同一个application下

2、Uid相同

3、permission匹配

4、目标Activity的属性Android:exported=”true”

5、目标Activity具有相应的IntentFilter,存在Action动作或其他过滤器并且没有设置exported=false

6、启动者的Pid是一个System Server的Pid

7、启动者的Uid是一个System Uid(Android规定android.system.uid=1000,具有该Uid的application,我们称之为获得Root权限)

如果上述调节,满足一条,一般即可(与其他几条不发生强制设置冲突),否则,将会得到Permission Denial的Exception而导致Force Close。

现在,我来解释一下Uid机制

众所周知,Pid是进程ID,Uid是用户ID,只是Android和计算机不一样,计算机每个用户都具有一个Uid,哪个用户start的程序,这个程序的Uid就是那个那个用户,而Android中每个程序都有一个Uid,默认情况下,Android会给每个程序分配一个普通级别互不相同的 Uid,如果用互相调用,只能是Uid相同才行,这就使得共享数据具有了一定安全性,每个软件之间是不能随意获得数据的。而同一个application 只有一个Uid,所以application下的Activity之间不存在访问权限的问题。

如果你需要做一个application,将某些服务service,provider或者activity等的数据,共享出来怎么办,三个办法。

1、完全暴露,这就是android:exported=”true”的作用,而一旦设置了intentFilter之后,exported就默认被设置为true了,除非再强制设为false。当然,对那些没有intentFilter的程序体,它的exported属性默认仍然是false,也就不能共享出去。

2、权限提示暴露,这就是为什么经常要设置usePermission的原因,如果人家设置了 android:permission=”xxx.xxx.xx”那么,你就必须在你的application的Manufest中 usepermission xxx.xxx.xx才能访问人家的东西。

3、私有暴露,假如说一个公司做了两个产品,只想这两个产品之间可互相调用,那么这个时候就必须使用shareUserID将两个软件的Uid强制设置为一样的。这种情况下必须使用具有该公司签名的签名文档才能,如果使用一个系统自带软件的ShareUID,例如Contact,那么无须第三方签名。

这种方式保护了第三方软件公司的利益于数据安全。

当然如果一个activity是又system process跑出来的,那么它就可以横行霸道,任意权限,只是你无法开发一个第三方application具有系统的Pid(系统Pid不固定),但是你完全可以开发一个具有系统Uid的程序,对系统中的所有程序任意访问,只需再Manufest中声明shareUserId为 android.system.uid即可,生成的文件也必须经过高权限签名才行,一般不具备这种审核条件的application,google不会提供给你这样的签名文件。当然你是在编译自己的系统的话,想把它作成系统软件程序,只需在Android.mk中声明 Certificate:platform则可以了,既采用系统签名。这个系统Uid的获得过程,我们把它叫做获得Root权限的过程。所以很多第三方系统管理软件就是有Root权限的软件,因为他需要对系统有任意访问的权限。那么它的Root签名则需要和编译的系统一致,例如官方的系统得用官方的签名文件,CM的系统就得用CM的签名文件。

再附上Android中安装应用失败的25种原因:
已经安装。
public static final int INSTALL_FAILED_ALREADY_EXISTS = -1 ;

APK文件是无效的。
public static final int INSTALL_FAILED_INVALID_APK = -2 ;

所传递的URI是无效的。
public static final int INSTALL_FAILED_INVALID_URI = -3 ;

设备没有足够的存储空间来安装应用程序。
public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4 ;

包已经具有相同名称的安装。
public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5 ;

请求共享的用户不存在。
public static final int INSTALL_FAILED_NO_SHARED_USER = -6 ;

与先前安装的软件包同名,但有不同的签名。
public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7 ;

对已经安装了共享用户的设备,不具有匹配的签名。
public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8 ;

新包装采用的共享库,无法使用。
public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9 ;

新包装采用的是共享库,无法使用。
public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10 ;

优化并验证它的dex文件的新包失败,是因为没有足够的存储空间或验证失败。
public static final int INSTALL_FAILED_DEXOPT = -11 ;

因为当前的SDK版本低于程序包所需要的。
public static final int INSTALL_FAILED_OLDER_SDK = -12 ;

新包失败,因为它包含了与已经安装在系统中内容提供者(Content Provider)同等的授权。
public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13 ;

新包失败,因为当前的SDK版本比新
public static final int INSTALL_FAILED_NEWER_SDK = -14 ;

新包失败,因为它已经指定,它是一个测试,只
public static final int INSTALL_FAILED_TEST_ONLY = -15 ;

如果要安装的软件包包含本地代码,但没有一样是与设备的CPU_ABI兼容。
public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16 ;

如果新的包使用功能不可用。
public static final int INSTALL_FAILED_MISSING_FEATURE = -17 ;

一个安全容器装载点不能在外部媒体访问。
public static final int INSTALL_FAILED_CONTAINER_ERROR = -18 ;

新的软件包无法安装在指定的安装位置。
public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19 ;

新的软件包无法安装在指定的安装位置,因为媒体不可用。
public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20 ;

新的软件包无法安装,因为验证超时。
public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21 ;

新的软件包无法安装,因为验证没有成功。
public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22 ;

调用程序预期调用的包装改变了。
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23 ;

新的包被分配一个不同的UID比它先前的。
public static final int INSTALL_FAILED_UID_CHANGED = -24 ;

新包具有比目前安装的软件包的较旧版本的代码。
public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25 ;

===================================================================================================

另外一种安装失败的原因:

You have to allow unsigned applications. The install is being blocked by Android. Allow install of non-market apps in Settings.

你必须允许未签名的应用。安装被Android。允许设置非市场的应用程序安装。

更多相关文章

  1. Android(安卓)调用系统应用选文件
  2. Android(安卓)安装apk时,报错 Failure [INSTALL_FAILED_TEST_ONLY
  3. android系统进程简要分析
  4. Android模拟器常用操作
  5. Android(安卓)Studio的下载、安装与配置
  6. Android(安卓)TTS 初体验
  7. Android(安卓)Studio插件之快速findViewById butterknife和Andro
  8. 安卓Android模拟器 SDK 2.2 2.3 下载与安装教程
  9. Android中的Adapter 详解(二)

随机推荐

  1. android pull解析
  2. Android(安卓)socket网络编程要注意
  3. 国内中文Android开发者社区和论坛
  4. 三,android编码规范 & 常用布局 & 常用控
  5. Android(安卓)OpenGL ES学习
  6. ARCVM:Chrome OS 中运行 Android(安卓)应
  7. Android项目优化宝典
  8. Android(安卓)应用的自动升级、更新模块
  9. android集成语音功能
  10. 通过Android(安卓)Studio查看SDK源码