Android App罕见错误和优化方案

简介:   本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!1、App如果被定义一个有参数构造函数,那么需要再定义一个无参数的,如果不则会在某些情况下初始化失败2、in...



  本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


1、App如果被定义一个有参数构造函数,那么需要再定义一个无参数的,如果不则会在某些情况下初始化失败


2、include Java Exception stack in crash report 原因:webview未被destroy和置空,快进快出容易导致Crash


3、Json解析一直有反斜杠,如

    "Detail": "[\"1476438611831,120.011798,30.294126,6.5461546E-4,2.9163063E-4,0.0034914017,-0.05355559,0.080890246,9.80617,-9.765625E-4,2.1362305E-4,1.8310547E-\"]"
而实际上需要这种

    "Detail": [
        [
            "1476440497243",
            "120.011839",
            "30.294298",
            "0.0013065673",
            "0.010251816",
            "-0.07671833",
            "-0.04659828",
            "0.06689003",
            "9.806312",
            "-5.79834E-4",
            "6.866455E-4",
            "-0.0027008057"
        ]
   ]
原因:前者使用sdk本身提供的Json资源,后者使用gson提供的Json资源,如果要上传jsonArray数据只能用Gson。
默认Json使用put方法设置数据,如果值有引号则自动加上反斜杠做转译



第1张是Json直接把value以Object的方式放入LinkedHashMap,第2张是Gson把Value分类(主要对Charater即String的接口)放入LinkedTreeMap

第二个方案:

存入数据的时候,以json保存到本地(由于引号的存在,反斜杠是必要的),上传的时候读取本地文件存入jsonArray,导致对原json的反斜杠进行转译,解决方案是:在上传前使用String.replace方法把反斜杠都去掉。

4、ScrollView通过addView加入Lv,结果焦点到达页面底部,这是由于Lv获得焦点引起的,所以把Lv的焦点去掉即可

lv.setFocusable(false);

5、网络请求返回数据一直是回车+空格的组合数据,报错:java.lang.StringIndexOutOfBoundsException: length=0; regionStart=0; regionLength=1

原因:请求的接口没有收到数据,是请求框架自身返回的数据,所以格式不正确;很可能是内网接口用外网连接导致

6、

Error:Execution failed for task ':mergeAnzhiDebugResources'.
> Error: java.lang.RuntimeException: Crunching Cruncher img_bubble_default.9.png failed, see logs

主要原因是.9图片的长边是放内容的,小点代表拉伸的,原来的位置刚好相反,改过来就好。


7、华为手机读取文件后截取,再获得图片失败。

分析:这个错误很奇怪,以前开发中经常不会遇到,而目前相对来说,各大厂商对权限的要求越来越严格,更甚者在安装时即主动屏蔽若干权限,同时部分权限用时需要申请;说到这里你可能就明白了,这里主要是权限被剥夺的问题,要断点到出错的位置,提示赋予应用读写权限。


8、4.0以上版本,RadioGroup两个子RadioButton均处于选中状态

原因在于:设计某一个radio为true时,另外一个没有id,因此系统原因导致两个均被选中。

需要做的就是给radio设置id。


9、list不能addAll空数据,否则报空指针异常。系统层次的错误。


10、获得system权限,实现静默安装。设置 android:sharedUserId="android.uid.system" ,在当前模块的MakeFile中添加LOCAL_CERTIFICATE := platform,然后在安卓源码环境下使用原生make命令编译


11、App界面的Editext被弹出的输入法窗口挡住,使用android:windowSoftInputMode="adjustResize"(让键盘浮在界面上)可以处理,也有人用adjustPan(键盘将界面顶上去),但后者在webView中有编辑框非全屏情况失效,沉浸式时两者设置皆无效,可以通过下面方法来解决

AndroidBug5497Workaround.assistActivity(this) 

原理前两者让屏幕主动适应键盘,后者将界面的可视部分强制减少一个键盘的高度

   private int computeUsableHeight() {
        Rect rect = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(rect);
        // rect.top其实是状态栏的高度,如果是全屏主题,直接 return rect.bottom就可以了
        return (rect.bottom - rect.top);
    }

详见:https://www.diycode.cc/topics/383

Lint自定义工具,用来查找需要继续的基类,而未继承的

http://alexq.farbox.com/post/andrlintwatchdog-custom-lint-zi-ding-yi-lint-ti-gao-dai-ma-zhi-liang


12、5.1以后,短信接收权限会被剥夺而出现安全错误,如果添加需要谨慎处理。

android.provider.Telephony.SMS_RECEIVED

13、apk安装失败

INSTALL_FAILED_USER_RESTRICTED :厂商系统原因

  if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) {
        try {
            observer.packageInstalled(, PackageManager.INSTALL_FAILED_USER_RESTRICTED);
        } catch (RemoteException re) {
        }
        return;
    }
INSTALL_FAILED_CANCELLED_BY_USER: 有的机型默认会认用户选择是否安装,不点击则取消


14、获得简单的Root权限

 android:sharedUserId="android.uid.system"
将当前应用进程设置为系统级进程(不推介随意这么做,会产生很多隐患)。拥有此属性后,我们的应用就可以无视用户,无法无天地处理很多事情,比如擅自修改手机system分区的内容、静默安装等。之前开发过一个类似切换多套开关机动画和音效的模块,添加此属性后,就可以明目张胆地将我们的数据节点存在system分区,可以让用户恢复出厂设置都清空不了我们的数据。
但是添加此属性后,我们需要在当前模块的MakeFile中添加LOCAL_CERTIFICATE := platform,然后在安卓源码环境下使用原生make命令编译才能生效(原生编译虽然比使用ide工具麻烦很多,但是却能使用很多ide工具无权限使用的api)。
如果非要在ide工具中使用则必须通过系统密钥重签名生成的apk才行(未亲自验证)。 

系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加android:sharedUserId="android.uid.system",然后在Android.mk中增加LOCAL_CERTIFICATE := platform。可以参见Settings等

系统中所有使用android.uid.shared作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.uid.shared",然后在Android.mk中增加LOCAL_CERTIFICATE := shared。可以参见Launcher等

系统中所有使用android.media作为共享UID的APK,都会在manifest节点中增加android:sharedUserId="android.media",然后在Android.mk中增加LOCAL_CERTIFICATE := media。可以参见Gallery等。



15、AbsListView的notifysetChanged与notifysetInvalidate()方法之间的区别,大家都知道listview刷新主要是因为list发生变化,而前者用于刷新局部的改变,后者用于list失效后刷入新的list(想像一下整个listf都失效,还能部分部分的刷新吗?)
    /**
     * This method is called when the entire data set has changed,
     * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
     */
    public void onChanged() {
        // Do nothing
    }

    /**
     * This method is called when the entire data becomes invalid,
     * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
     * {@link Cursor}.
     */
    public void onInvalidated() {
        // Do nothing
    }
前者最终调用onChanged(此方法在整块数据发生变化时-就像调用cursor查询列表)
后者最终调用onInvalidated(此方法在整块数据失效时-就像关闭cursor,重新取值)

16、RecyclerView使用Glide加载图片,出现错乱的问题
初级方案,将其变成ListView

设置holder.setIsRecyclable(false);

终极方案:由于ImageView是异步加载的,而Holder不断的被回收,则判断设置图片时ImageView的tag与传过来的tag是否一致即可。

//Holder加入
   holder.mTitleIv.setTag(R.id.img_url, shop.ListImg);


//Glide加载
  final T sourceTag = source;//解决异步加载错乱的问题
   mGlide.with(context).load(source).into(new SimpleTarget<GlideDrawable>() {//防止第一次图片未显示
                @Override
                public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                    Object tag = imageView.getTag(R.id.img_url);//解决异步加载错乱的问题
                    final boolean isTagEqual = tag == null || sourceTag.equals(tag);
                    if (isTagEqual)
                        imageView.setImageDrawable(resource);
                }
            });

17、出现Caused by: java.lang.UnsupportedOperationException
原因在于Arrays.asList产生的ArrayList是Arrays$ArrayList,而非util包下的ArrayList,不具备add和remove功能
方案:解析出其中的个体,放入一个新的ArrayList中去(可使用List.AddAll方法操作)。

18、SharePreference.Editor中apply和commit的区别
前者是异步处理,没有返回处理结果;后者同步处理,会返回处理结果。
19、    java.lang.ExceptionInInitializerError
Enum中初始化时,使用Application的单例,实际上它未初始化
20、setTextColor(0xff0000ff),0x|ff|00|00|ff 指0x代表16进制,ff代表透明度alpha,0000ff代表rgb值
21、open failed: EROFS (Read-only file system)
第一、是否有写入权限
第二、文件是否存在(参数要求是文件路径)
22、Error:Could not get unknown property 'release' for SigningConfig container.
解决方案:处理放置先后次序即可,1-SigningConfigs,2-buildTypes,3-defaultConfig

23、cordova中前端无法调用Android端,报错:CordovaBridge: Ignoring exec() from previous page load.
解决方案:
第一、判断url是否是内部APP的url,将此权限放开即可。 
public Boolean shouldAllowNavigation(String url) {
    //judge url
    return true;
}

第二、给feature设置onload=true

<feature name="Service">
    <param name="android-package" value="ServicePlugin"/>
    <param name="onload" value="true"/>
</feature>

24、startActivityForResult,无返回,即在onActivityForResult里收不到返回值。

原因由于两个activity不在同一个栈中,导致收不到信息;修改方案:将跳到的activity的launchMode改为startdard,不要用singleTask或singleInstance。


优化方案:

1、能用FrameLayout的,都换成这个(因为Android会对此layout进行merge操作),同时能不用layout的也尽量不用


2、纯色图片,能用xml写的,换用xml写,图片命令均以img_x_x.png


3、中文都写到string文件里,有相同中文的,去掉其中一个,命名尽量短且通用,尽量用Html的from格式和String的format格式来处理字符串,两个方法均可在CMYStringUtil方法里找到


4、上述两者不用的,你们暂时可以不处理,且命令尽量通用,如可以命名为alipay_str_finish就不命令为alipay_str_service_finish


5、文字输入框,只能输入哪些类型,做一个限制android_limit,另外,监听一下回车键,看应该跳下一行就把回车键命名为“下一行”,当前表单填完,命名为“完成”,并触发提交按钮,数据进行验证


6、Exception尽量去掉,原因是要找到错误处理掉,而非简单的加try..catch,并且加入log日志,并上传日志。


7、写intent传递数据,对象用TransferData传递,基本数据类型用putExtra来传递,注意key都要用IConstants里的intent_key


8、方法都命名为有意义的命名,具体参考“新人必读”里的规则,以及变量名,全局、局部、静态变量等,另外不用的字段都删掉


9、findId尽量都改成getEelement,使用Ctrl+F来替换,尤其适配器里,尽量用getInflateView和getEelement来代替


10、把公用的布局或代码提出来,尽量多用include、viewStub、merge


11、有网络请求的,都要加上onRefresh方法,避免请求失败,需要重新加载,当前页面无方法


12、优化语法逻辑,全面考虑出现问题的情况,具备产品思维


读这篇文章同时也要注意一下系统升级的问题,里面同样埋有不少坑:Android高级第十一讲之不同系统间的区别

另外内存是个亘古不变的老难量,参考:Android高级之十二讲之如何降低应用内存消耗


开发小技巧:

1、开发xml文件时,使用如下代码,既可以清楚的显示文字,又可以打release版本时自动去掉

tools:text="1"

更多:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0309/2567.html

tools :text= "1"

目录
相关文章
|
11天前
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
38 10
|
12天前
|
API Android开发
Android P 性能优化:创建APP进程白名单,杀死白名单之外的进程
本文介绍了在Android P系统中通过创建应用进程白名单并杀死白名单之外的进程来优化性能的方法,包括设置权限、获取运行中的APP列表、配置白名单以及在应用启动时杀死非白名单进程的代码实现。
33 1
|
12天前
|
Ubuntu Android开发
安卓系统调试与优化:(一)bootchart 的配置和使用
本文介绍了如何在安卓系统中配置和使用bootchart工具来分析系统启动时间,包括安装工具、设备端启用bootchart、PC端解析数据及分析结果的详细步骤。
27 0
安卓系统调试与优化:(一)bootchart 的配置和使用
|
16天前
|
IDE Java 开发工具
探索安卓开发之旅:打造你的第一款App
【8月更文挑战第24天】在这篇文章中,我们将一起踏上激动人心的安卓开发之旅。不论你是编程新手还是希望扩展技能的老手,本文将为你提供一份详尽指南,帮助你理解安卓开发的基础知识并实现你的第一个应用程序。从搭建开发环境到编写“Hello World”,每一步都将用浅显易懂的语言进行解释。那么,让我们开始吧!
|
8天前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
54 0
|
8天前
|
Android开发 iOS开发 C#
Xamarin:用C#打造跨平台移动应用的终极利器——从零开始构建你的第一个iOS与Android通用App,体验前所未有的高效与便捷开发之旅
【8月更文挑战第31天】Xamarin 是一个强大的框架,允许开发者使用单一的 C# 代码库构建高性能的原生移动应用,支持 iOS、Android 和 Windows 平台。作为微软的一部分,Xamarin 充分利用了 .NET 框架的强大功能,提供了丰富的 API 和工具集,简化了跨平台移动应用开发。本文通过一个简单的示例应用介绍了如何使用 Xamarin.Forms 快速创建跨平台应用,包括设置开发环境、定义用户界面和实现按钮点击事件处理逻辑。这个示例展示了 Xamarin.Forms 的基本功能,帮助开发者提高开发效率并实现一致的用户体验。
15 0
|
8天前
|
存储 缓存 前端开发
安卓开发中的自定义控件实现及优化策略
【8月更文挑战第31天】在安卓应用的界面设计中,自定义控件是提升用户体验和实现特定功能的关键。本文将引导你理解自定义控件的核心概念,并逐步展示如何创建一个简单的自定义控件,同时分享一些性能优化的技巧。无论你是初学者还是有一定经验的开发者,这篇文章都会让你对自定义控件有更深的认识和应用。
|
12天前
|
存储 XML Linux
深入理解操作系统:进程管理与调度策略探索安卓应用开发:从零开始构建你的第一个App
【8月更文挑战第28天】在数字世界里航行,操作系统是掌控一切的舵手。本文将带你领略操作系统的精妙设计,特别是进程管理和调度策略这两大核心领域。我们将从基础概念出发,逐步深入到复杂的实现机制,最后通过实际代码示例,揭示操作系统如何高效协调资源,确保多任务顺畅运行的秘密。准备好了吗?让我们启航,探索那些隐藏在日常电脑使用背后的奥秘。 【8月更文挑战第28天】在这个数字时代,拥有一款自己的移动应用程序不仅是技术的展示,也是实现创意和解决问题的一种方式。本文将引导初学者了解安卓开发的基础知识,通过一个简单的待办事项列表App项目,逐步介绍如何利用安卓开发工具和语言来创建、测试并发布一个基本的安卓应用
|
13天前
|
Java 程序员 Android开发
探索安卓开发:构建你的第一个App
【8月更文挑战第27天】在数字化时代的浪潮中,移动应用成为人们生活不可或缺的一部分。对于渴望进入软件开发领域的新手而言,掌握如何构建一款简单的安卓App是开启技术之旅的关键一步。本文旨在通过浅显易懂的语言和步骤分解,引导初学者了解安卓开发的基础知识,并跟随示例代码,一步步实现自己的第一个安卓App。从环境搭建到界面设计,再到功能实现,我们将一同揭开编程的神秘面纱,让每个人都能体会到创造软件的乐趣。
|
15天前
|
Docker 容器
【Azure 应用服务】App Service for Container 无法拉取Docker Hub中的镜像替代方案
【Azure 应用服务】App Service for Container 无法拉取Docker Hub中的镜像替代方案