以下所有内容都是平时遇到过的问题和总结的经验,记录自己踩过的坑,以免再一次踩坑!
1、启动activity可以搜索ActivityManager: Start的log
2、输出某处的调用栈的log,log.e("csf info", "csf info", new Exception());
3、要查看安装在手机的apk用了什么分辨率的资源,连上adb后可在文件系统中看/system/priv-app,把相应的apk取出来,改后缀为.tar文件,解压出来基本就可以看到是什么分辨率的了。
4、adb reboot download进入download模式
5、FC问题在log中搜索fatal、err、error等关键字
6、安装apk失败后可以查看log的关键字PackageManager:result of install,-112表示前后安装apk的签名不同,具体的错误码可以查看安卓源代码packageManager.java文件,在里面搜索错误码就可以知道原因了,比如搜索-112。如果是版本低于原来的版本而导致安装失败,可搜索Downgrade detected关键字,查看当前的版本号
7、activity返回后回调到onActivityResult函数
8、改变屏幕方向、弹出软键盘和隐藏软键盘时,如果声明了activity的onConfigurationChanged函数,则执行该函数,否则执行onCreate函数。所以最好是需要声明onConfigurationChanged函数。
10、sharePreferences的本质是一个xml文件,存储key-value,sharePreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。其存储位置在/data/data/<包名>/shared_prefs目录下
11、doInBackground、onPostExecute是调用AsyncTask.execute后的回调
12、如果有native crash, log文件夹里应该有dumpstate_native_xxx生成
13、一个java文件可以有多个类,但只能有一个public类,而且类名与文件名相同
14、如果一个类testClass是一个抽象类,现在不知道具体的实现类,可以这样获取:
Log.d("csf", testClass.getClass().toString());
或者
Log.d("csf", testClass.getClass().getName());
15、adb发送key事件adb shell input keyevent KEYCODE
16、webview
//打开本包内asset目录下的index.html文件
wView.loadUrl("file:///android_asset/index.html ");
//打开本地sd卡内的index.html文件
wView.loadUrl("content://com.android.htmlfileprovider/sdcard/index.html");
//打开指定URL的html文件
wView.loadUrl("OSCHINA - 中文开源技术交流社区");
17、查看进程使用内存的情况
①adb shell ps查出对应进程的pid
②adb shell dumpsys meminfo pid列出pid所占用的内存
18、实时打印某一进程的内存使用情况,这个技巧在分析内存泄露时十分有用
①adb shell
②while true;do dumpsys meminfo pid | grep TOTAL;sleep 1;done;
19、查看有哪些service
adb shell dumpsys | grep "DUMP OF SERVICE"
20、内存分析工具MAT
21、
运营商制式 | |||
CTC电信 | CMCC移动 | CU联通 | |
2G | CDMA | GSM | GSM |
3G | CMDA2000 | TD-SCDMA | WCDMA |
4G | FDD-LTE | TDD-LTE | FDD-LTE |
双卡:两张卡
双模:CDMA与GSM
双待:一般指同一模式下的双待,如GSM网络双卡双待
双通:通话和数据网络同时可以进行
IMEI:一般分配给GSM、WCDMA制式的手机(移动、联通)
MEID:主要分配给CDMA制式的手机(电信)
22、APP使用什么分辨率的资源和屏幕像素密度有关,ldpi、mdpi、hdpi、xhdpi、xxhdpi对应到ppi分别是120ppi、160ppi、240ppi、320ppi、480ppi,如果不知道这台手机使用什么分辨率的资源,可以先查屏幕ppi,再对应到dpi
23、(和第三点相同)查app使用什么分辨率的资源,除了上面的方法,还可以解压/system/priv-app/路径下面的apk,解压出来后看里面的RES使用什么资源
24、安卓源码android\frameworks\base\core\java\android\provider这里保存了android系统的content-provider
25、发生ANR一般是因为下面两种情况
①界面操作按钮的点击等待响应时间超过5秒
②HandleMessage回调函数执行超过10秒,BroadcastReceiver里的onReceive()方法处理超过10秒
③service的生命周期函数超过20秒
26、ANR问题可以搜索log的一些关键字,如“ANR ”,带空格可过滤很多无用信息,“LAST ANR”,"Application is not responding",“ActivityManager: ANR”
27、log中搜索Dalvik Thread可以看虚拟机信息,每一段都是一个线程
28、log中搜索DUMP OF SERVICE cpuinfo:,可看到cpu的使用情况
29、log中搜索PACKAGE LIST,可看到手机上所有的包
30、开发一个app时,到底选择content-provider还是database存储数据,有这些标准
①希望向其他程序提供复杂的数据和文件,则用contentProvider
②希望用户从程序复制复杂数据到其他程序则用contentProvider
③希望提供用搜索引擎框架提供自定义搜索提示则用contentProvider
④如果数据完全只用于程序内部,用database比较合适
31、写代码时注意下面这点会引起的内存泄露
query数据库时,返回的cursor一定要及时close,一般用try catch finally这样的方式来query数据库,cursor的close放在finally执行,这样无论是否出现exception都可close掉cursor
32、查询数据库的时候,最好设定projection的参数,只查询所需要的数据,如果把所有的列都查询出来,会损耗较多的内存。
33、线程间的消息传递是通过handler进行的,handler把消息放入消息队列,looper去循环消息队列,只有UI线程才有looper,子线程没有looper,也就是说,只能在UI线程创建handler,不能在子线程创建handler,当然也可以通过这样的方式在子线程创建handler,new Handler(Looper.getMainLooper()),不过这样子线程使用的还是UI线程的looper,哈哈。至于子线程为什么没有looper,可查看Handler的源码,在子线程创建handler的时候,会catch到运行时错误"Can't create handler inside thread that has not called Looper.prepare()"
34、更正33点的说法,子线程想要拥有looper,可以通过Looper.prepare()创建looper对象和MeesageQueue对象,HandlerThread就是一个例子。
35、intent传送数据时,比如传送bitmap,数据不能超过40k,否则会出现JavaBinder: !!! FAILED BINDER TRANSACTION !!!的错误
36、source insight control --> 打开文件所在路径并选择该文件explorer /e,/select,%f
37、把view设ripple波纹效果,要把view的onClickable设为true,否则有时波纹效果不生效
38、xml的布局中不能直接使用ViewGroup标签,因为ViewGroup是抽象类,不能实例化
39、无论在代码还是xml中,listview都不能addView,因为listview继承了adapterView,这是个抽象类。比如在xml中,listview标签下面不能有child view,比如在listview的adpater中getview的时候,inflate出来的child不能这样写newView = Inflater.inflate(R.layout.xxxx, parent, true);//不能是true,只能是false
40、Android系统进行GC时,所有线程的任何操作都会暂停,等待GC完成后,再进行操作。当出现内存泄漏时,内存中可用的Heap size越来越少,GC操作就会越来越频繁,所以内存泄漏是会影响性能的。
41、测试app的启动时间adb shell am start -W packageName/activityName
42、layout_marginStart和layout_marginLeft的区别是:当布局为left-to-right时,两者无差别,当布局为right-to-left时,layout_marginStart就代表右边的margin了。开发者模式中可选择RTL layout,在某些open项目选择某些国家语言时也会切换到RTL layout
43、打开开发者模式的strict mode,当界面有可能出现ANR时,会闪红框,说明当前界面UI thread处理工作量较多。
44、操作SharePreference时如果无需返回值使用apply代替commit
45、改ANR问题时,可搜索trace文件wait,看是否有线程在等待,从而造成死锁。
46、看ANR的log,从LOG可以看出ANR的类型,CPU的使用情况,如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR,如果CPU使用量很少,说明主线程被BLOCK了,如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的
47、录像adb shell screenrecord /sdcard/test.mp4输入后开始录像,CTRL+C停止录像
48、手机连接eclipse,出现ADB server didn't ACK *fail to start daemon*或者DDMS显示不出进程列表的解决方案:任务管理器杀掉adb进程 -> adb start-server,或者杀掉adb进程后,在DDMS reset adb
49、快速搜索email进程的虚拟机信息Cmd line: com.samsung.android.email.provider
50、arrayList遍历remove时,注意每次remove一个,arraylist的size都会发生变化,所以不能简单的用position来遍历。
51、当在一个线程对hashMap或者list这样的结构进行iterator操作时,不允许在另外的线程对这个结构进行修改操作,否则会出现ConcurrentModificationException的异常
52、有时在gradle中需要加入support的包,想要查看support包中控件有哪些版本,比如查看CardView的版本,可在SDK_PATH\extras\android\m2repository\com\android\support\cardview-v7这个路径查看
53、xml里面的配置如android:color,这个color的名字的定义可在\android\frameworks\base\core\res\res\values\attrs.xml中找到,实际上就是一个自定义的属性,只不过通过android这个命名空间找到,xml里面的配置是初始化view时通过构造函数的AttributeSet传进去的
54、对于一些渐变色的图片作为背景时要注意大小,如果控件比图片的size要大,图片就会被拉伸,这种情况往往在界面上会显示奇怪意想不到的效果,还以为代码写得有问题呢。本人在功能机和android上都踩过这个坑了。
55、adb shell后查看开机动画setprop ctl.start bootanim,关闭动画setprop ctl.stop bootanim
56、adb截图命令/system/bin/screencap -p /sdcard/screenshot.png
57、AS加入so库的方法是在src/main中新建jniLibs目录,把so拷贝到这个目录
58、sw360 sw411这个smallWidth值的计算:
smallWidth表示最小宽度,是屏幕宽和高的较小值,一般宽比高小,所以这个值一般是 = 屏幕宽度(px) / 屏幕密度
屏幕宽度和屏幕密度这两个值在DEV Tools -> Configuration 这个app可以查看到,比如C5,当显示比例是Larger的时候,
从Dev Tools -> Configuration 可以看到屏幕宽度是1080,屏幕密度density = 3, 1080 / 3 = 360,所以引用的资源是sw360dp-***dpi。
当显示比例是smaller的时候,从Dev Tools -> Configuration 可以看到屏幕宽度是1080,屏幕密度density = 2.625, 1080 / 2.625 = 411,
所以引用的资源是sw411dp-***dpi
59. Binder是一种架构,提供了服务端、Binder驱动、客户端接口三个模块。一个Binder服务端实际上就是一个Binder类的对象,
该对象一旦创建,内部就启动一个隐藏线程。该线程会接收Binder驱动发送的消息,收到消息后,会执行Binder对象中的onTransact()函数,
并按照该函数的参数执行不同的代码。因此,要实现一个binder服务,就必须重载onTransact()方法。onTransact()函数的主要内容是
把onTransact()函数的参数转换为服务函数的参数,而onTransact()函数的参数是客户端调用transact()函数时输入的。
任意一个服务端Binder对象被创建时,同时会在Binder驱动中创建一个mRemote对象,
客户端要访问远程服务时,都是通过mRemote对象。binder驱动中transact()的具体实现:
①向服务端线程发送调用消息
②挂起当前线程,等待服务端执行完毕后的通知
③接到通知,继续客户端线程,并返回执行结果。
60. 启动activity的过程中如果调用者被意外杀掉,则startActivity也会不成功。
61. Android studio已下载gradle版本\Android\Android Studio\gradle\m2repository\com\android\tools\build\gradle
62. adb shell getprop dalvik.vm.heapgrowthlimit可以查看系统为每个java进程分配多少heap
63. 这样可检测数据库泄露
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
64. keytool -list -printcert -jarfile xxxx.apk查看apk签名
65. 加密的作用是防止被查看数据,签名的作用是防止被篡改数据
66. 即使申请了静态和动态权限,dirFile.mkdirs()依然返回False,可以在AndroidManifest的Application下添加
android:requestLegacyExternalStorage="true"
67. 有些Android版本的文件名不支持冒号“:”,如果文件命名有冒号,打开文件会提示FileNotFoundException
68. 过滤log
^(?!.*(AAA|BBB)).*$