欢迎Follow我的GitHub, 关注我的CSDN, 精彩不断!

CSDN: http://blog.csdn.net/caroline_wendy/article/details/68923156

在GitHub上Clone的某开源Android项目, 下载配置, 完毕构建, 在手机上能够安装, 可是无法执行. 项目的编译版本号(compileSdkVersion)是25(7.1), 最低的兼容版本号(minSdkVersion)是19(4.4), 手机的系统版本号是21(5.0), 已经满足应用的最低执行条件. 然而, 在同样系统版本号(25, 7.1)的模拟机上, 应用执行正常.

在我的手机执行应用时, 报错例如以下:

E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.saulmm.cui/com.saulmm.cui.HomeActivity}:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
at android.support.v7.app.AppCompatDelegateImplV9.createSubDecor(AppCompatDelegateImplV9.java:359)
at android.support.v7.app.AppCompatDelegateImplV9.ensureSubDecor(AppCompatDelegateImplV9.java:328)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:289)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140)
at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:276)
at android.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:261)
at com.saulmm.cui.HomeActivity.onCreate(HomeActivity.java:42)

定位

问题起源于DataBindingUtil#setContentView, DataBindingUtil绑定layout布局.

// HomeActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_home);
// ...
}

调用AppCompatActivity#setContentView, Activity绑定layout布局.

// DataBindingUtil.java
public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId,
DataBindingComponent bindingComponent) {
activity.setContentView(layoutId);
// ...
}

终于是Activity代理实现类AppCompatDelegateImplV9实现setContentView的详细逻辑. 通过ensureSubDecor方法创建DecorView, 填充Activity的自己定义布局resId, ensureSubDecor再调用createSubDecor方法创建DecorView.

// AppCompatDelegateImplV9.java
@Override
public void setContentView(int resId) {
ensureSubDecor(); // 创建并初始化DecorView
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);
mOriginalWindowCallback.onContentChanged();
} private void ensureSubDecor() {
if (!mSubDecorInstalled) {
mSubDecor = createSubDecor();
// ...
}
}

createSubDecor方法, 依据应用的样式主题(Theme)设置根布局DecorView的样式, 并执行初始化. 当未含有AppCompatTheme_windowActionBar属性时, 则觉得主题未设置, 并抛出异常IllegalStateException.

// AppCompatDelegateImplV9.java
// 依据布局样式Style设置根布局DecorView的样式
private ViewGroup createSubDecor() {
TypedArray a = mContext.obtainStyledAttributes(R.styleable.AppCompatTheme); // 没有布局属性
if (!a.hasValue(R.styleable.AppCompatTheme_windowActionBar)) {
a.recycle();
// 问题所在!
throw new IllegalStateException(
"You need to use a Theme.AppCompat theme (or descendant) with this activity.");
}
// ...
}

为什么API 25的模拟器能够启动, 我的手机(API 21)就不能启动呢? 原因非常easy, 就是由于开源项目的主题资源设置有误. 默认主题在AndroidManifesttheme属性中设置.

<application android:theme="@style/AppTheme">

点击IDE的AppTheme跳转至声明, 发现仅仅有一处, 即在values-v23中声明.

原因

对于资源属性而言, 系统默认查找与匹配低于当前API等级的属性, 保证高版本号属性不会在低版本号中执行. 由于高版本号会加入很多其它的新接口, 低版本号无法找到, 强制使用可能导致异常甚至崩溃, 所以禁止訪问高版本号的属性.

解决

理解了问题的所在, 解决方式就非常easy. 为了支持最低API以上的所有系统, 在默认的values/themes.xml中, 加入AppTheme属性就可以.

<style name="AppTheme" parent="Base.AppTheme"/>

问题虽小, 但不可忽视, 否则就仅仅能在某些手机可用, 在某些手机崩溃, 摸不着头脑. 在开发中, 优先在默认values目录中加入属性, 假设须要额外支持, 在其它高版本号values-vXX中再加入. Do you get it?

That’s all! Enjoy it!

为什么手机无法执行应用? Values之谜的更多相关文章

  1. Linux下的Jenkins作为hub,Windows作为node节点,在Android手机上执行自动化脚本

    1.在Linux上放selenium-server-standalone-2.53.0.jar,在jar包目录下执行命令java -jar selenium-server-standalone-2.5 ...

  2. 【初体验】macos下android ndk交叉编译hello world,并拷贝到android手机上执行

    1.机器上以前安装了java 1.8(貌似android ndk不需要java) 2. 下载android ndk,版本是android-ndk-r14b (比较奇怪,我下载了最新的android-n ...

  3. 使用Java让android手机自动执行重复重启

    public static void main(String[] args)throws IOException,Exception { for(int j=0;j<10;j++) { Thre ...

  4. C#跨平台手机应用开发工具Xamarin尝试 与Eclipse简单对比

    Xamarin 支持使用C#开发基于Android.IOS.WindowsPhone应用开发,最大特点C#+跨平台,详细说明问度娘. 安装 研究 想体验研究的点击查看页面 Xamarin For Vi ...

  5. x86架构手机跑安卓好吗?(脑补)

    华硕低价位手机ZenFone一推出就掀起市场话题,许多人也对ZenFone所采用的Intel Atom处理器有所意见,深怕其相容性问题无法正确执行应用程式App,这究竟是怎么回事呢? Intel近几年 ...

  6. 技术解析:锁屏绕过,三星Galaxy系列手机也能“被”呼出电话

    近期,由两位安全研究人员,Roberto Paleari及Aristide Fattori,发布了关于三星Galaxy手机设备安全漏洞的技术细节.据称,Galaxy手机可在锁屏状态下被未授权的第三方人 ...

  7. Android手机一键Root原理分析

    图/文 非虫 一直以来,刷机与Root是Android手机爱好者最热衷的事情.即使国行手机的用户也不惜冒着失去保修的风险对Root手机乐此不疲.就在前天晚上,一年一度的Google I/O大会拉开了帷 ...

  8. 泛泰A900 刷4.4专用中文TWRP2.7.1.1版 支持自己主动识别手机版本号(全球首创)

    因本人手上的A900S已砖, 所以临时弄不了ROM了, 先上传之前已经弄好的刷4.4专用的新版TWRP recovery 2.7.1.1  这个版本号是我自己定义的,为差别之前公布的2.7.0.0版( ...

  9. 让Qt for Windows Phone 8.1在真机上执行

    让Qt for Windows Phone 8.1在真机上执行 前面几篇博文是为这篇文章做铺垫的,终于目的为的是使用Qt框架制作出可以在Windows Phone 8.1真机上执行的程序.因为Qt f ...

随机推荐

  1. imageNamed 、imageWithContentsOfFile、 initWithContentsFile区别

    [UIImage imageNamed:]只适合与UI界面中的贴图的读取,较大的资源文件应该尽量避免使用 用UIImage加载本地图像最常用的是下面三种: 1.用imageNamed方法 [UIIma ...

  2. Windows远程连接局域网内或同一个网段或同一个路由器的某台机器

    http://bbs.shendu.com/thread-1443245-1-1.html     亲自试验,具体操作如下:    我现在有三台机器和对应的ip地址(ip地址自己手动填写,不会网上搜) ...

  3. GoogleMapsV3-----基础地图(自定义消息提示OverlayView) (转)

    <html> <head> <title> </title> <title></title>    <style type ...

  4. JMeter ----请求数据参数设置-自动增长变量

    使用Jmeter性能测试的时候, 需要录入一些测试数据, 当这些数据要插入数据库的时候, 数据库通常会要求数据不能重复, 所以无法使用同一个数据反复进行测试, 这时候就需要在每次请求的时候使用不同的请 ...

  5. Remote 'attachhome' failed on nodes:XXX

    RAC安装过程中,在安装GI的时候报如下错误: 解决方法: 根据提示执行以下脚本 $ /u01/app//grid/oui/bin/runInstaller -attachHome -noCluste ...

  6. ASP.NET Helper

  7. php log类

    个人抽离出来一个超级简易但是实用的代码段 public static function WriteLog($msg,$module = null,$logLevel = "DEBUG&quo ...

  8. django打印字典

  9. jenkins 发送邮件模板

    jenkins 发送邮件模板 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  10. 安装ubuntu和windows双系统后,如何修改默认启动项

    在安装了Ubuntu16.04系统之后,系统会默认自启动Ubuntu16.04,而我们大多数情况下可能都在使用windows系统,不修改默认设置,不经意间便会启动了Ubuntu16.04,通过我的经历 ...