Android开发问题汇总
Android开发问题汇总
1、用(SDK starter package)的installler安装Android SDK时提示无法找到JDK,但实际上机器上已经安装了JDK。
一个对不少人有效的解决方法是看到此提示时先点一下“回退”按钮,再点“下一步”,就会发现JDK被找到了。参考链接
但在我机器上这个方法不起作用。所以我选择不使用installer,而是下载zip格式的文件,解压缩后运行SDK Manager.exe即可。参考链接
2、在Eclipse里新建一个Android项目,运行/调试时提示“Could not find xxx.apk!”
网上提到的大部分解决方案是clean整个项目,或选fix project properties菜单项。但对我的环境不起作用。
升级到Eclipse 3.7后,新创建的android项目在Build阶段报告一个异常“sun/security/x509/X500Name”,怀疑与所用的jdk(IBM JDK6)有关。果然,卸载IBM JDK并安装SUN JDK后问题解决。
3、让程序适应不同的屏幕分辨率
可参考这个链接:Android屏幕分辨率问题。
4、在android模拟器里用10.0.2.2可访问宿主机。
5、在setWidth()方法里指定的宽度是以pixel为单位的,如何转换为使用dip(device independent pixels)为单位?
使用下面的代码,参考链接
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, r.getDisplayMetrics());
6、弹出式对话框的用法,这个链接介绍得比较详细。
7、导出apk文件时需要签名,这个链接比较详细。
8、android界面设计原则,参考这个链接。
9、使用merge(而不是layout)可以达到在避免重复写layout的同时减少layout的数量。
10、真机USB调试比用AVD调试快得多,设置也很简单,见这个链接。不过10.0.2.2不能用了,真机可以通过wifi访问局域网内的服务器。
11、android-ui-utils,一个不错的在线Android图标生成器,地址在此。
12、调试时如果出现莫名其妙的空指针错误,例如findViewByID()返回null,先试试clean一下整个project,通常都能解决。
13、让ListView里无数据时显示一行信息。
参考链接,注意ListView和TextView的id。
14、用自己的图标替换ListView里的RadioButton
在用作row的layout里添加一个图片,在java code里覆盖adapter的getView()方法,根据ListView的getCheckedItemPosition()结果设置图片的可见 性。注意不要通过setOnClickListener()方法设置view里的图片可见性,因为ListView只维护可见的那些row控件,这样做会 导致很奇怪的结果(点第一条记录结果第二条记录被选中,并且滚动ListView时选中状态还会随机变化,见此链接)。
另外一个办法是通过style设置checkMark为所需要的图标,可能是更简单的解决方案(还没试)。
Update: 以上结果基于对ListView实现不了解的情况,其实使用RadioButton是可以实现的,见#22。
15、ListView的selection和choice是完全不同的,所以不要指望ListView#clearChoice()能清楚你已经是checked状态的那些item。
16、屏幕方向变化时(横屏->竖屏,或反过来),ListView里发生变化的内容丢失,状态回到开始时的样子。
当屏幕方向发生变化时,android会重建整个Activity以便你构造更适合某个方向的UI。为了避免这种情况,在 AndroidManifest.xml里的那个Activity声明上增加 android:configChanges="orientation" 即可。详见参考链接。
17、各手机平台仿真器/模拟器的下载链接。
18、AlertDialog#show()方法是不会阻塞当前线程的。
19、让不同Activity之间进行通信,例如一个TabActivity里有多个Activity,它们之间需要传递一些消息。
可使用BroadcastReceiver机制。 参考链接。要注意的是,tab还未启动时是无法接收到消息的,所以要在tabhost所在的activity里也接收消息,当tab启动时传给它。
20、Android SDK里的style和theme文档
见此链接。
21、Tab的样式。
Android的tab样式问题比较多,不同版本的样式也不一样。这里有一个自定义样式的参考链接。
22、在ListView里使用单选/复选按钮。
问题很多,这个链接看起来解决了问题,但在我的环境里没试验成功。
Update: 以复选按钮为例,本质的问题在于ListView里的复选按钮不知道对应的model是哪个,需要事先用CheckBox#setTag(myModelObject)关联,onclick事件里用getTag()改变其选中状态。建议看这篇文档。
23、strings.xml里定义的字符串里增加参数。
在字符串里用“%1$s”、“%2$d”表示参数的序号和类型,然后用String.format()方法赋值。参考这个链接。
24、嵌入条码/二维码扫描功能
使用zxing。方法是在手机上先安装BarcodeScanner.apk,然后在程序里调用其提供的Activity,该Activity会返回扫描结果。 参考链接
25、改变ListView里每个Row的背景颜色
直接在getView()里写view.setBackgroundColor()是不行的。正确的方法是先在drawable目录里建一个xml文件,自己起名如my_row.xml,内容如下(关键是第一个和第四个<item>):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:state_selected="true"
android:drawable="@android:color/transparent" />
<item android:state_selected="true" android:drawable="@android:color/transparent" />
<item android:state_pressed="true" android:state_selected="false"
android:drawable="@android:color/transparent" />
<item android:state_selected="false" android:drawable="@color/solid_red" />
</selector>
然后在getView()里这样写就可以了:
if (item.getStopId().equals(User.stopId)) {
view.setBackgroundResource(R.drawable.my_row);
} else {
view.setBackgroundResource(android.R.drawable.list_selector_background);
}
26、在一个TableLayout里让Button宽度相同并占满表格宽度(想象一个由按钮组成的九宫格)
如果Button上的文字不长,按一般的方法就可以实现,例如这个链接。 当Button上的文字很长,还是会使布局变乱,每个列的长度将不一样。解决方案是将按钮的layout_width设为0,layout_height 设置为所需要的值,需要换行时将singleLine设置为false,最后将按钮的gravity设置为center。
27、对切换屏幕方向的处理
参考stackoverflow上的一个典型讨论。
当MyActivity位于一个TabActivity里时,我做了一些实验表明, TabActivity是否声明android:configChanges="keyboardHidden|orientation"与 MyActivity无关,只有MyActivity做了上述声明后才会在改变方向时触发onConfigurationChanged()方法。
28、strings.xml里的字符串包含html格式标签时
需要用<Data><![CDATA[...]]></Data>把html代码包起来。参考链接
29、在AlertDialog里用ListAdapter(如ArrayAdapter)时,文字不显示。
view的resourceId要用select_dialog_singlechoice而不能用simple_list_item_single_choice,否则文字颜色会与背景颜色相同而无法显示。参考链接
30、在android程序里使用第三方包的配置方法
参考这个链接成功。
31、定制tabhost的外观
这方面的需求和问题网上都很多,主要的解决方案有基于tabhost的和基于radiobutton的两大类,这里有几个可以参考的链接。链接1,链接2,链接3
32、取得当前屏幕方向
有好几个方法可以得到orientation值,但一些得到的值不对,例如 getWindowManager().getDefaultDisplay().getOrientation()和 getReqestedOrientation()。我实验下来比较靠谱的是 getResources().getConfiguration().orientation。
33、Activity里第一个View是EditText的时候,软键盘自动弹出。
似乎只是一些机型会这样做。要阻止软键盘弹出,可在onCreate()里加一行代码。参考链接
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
34、Dialog的theme问题
使用Theme.Light主题时,Dialog显示不正常。相关讨论:链接1,链接2
35、注意区分CheckBox和RadioButton的OnClickListener和OnCheckedChangeListner
使用前者时,当在代码里执行myCheckBox.setChecked(true),不会触发事件,而后者会触发事件。
36、监视GPS开启/关闭事件
用GpsStatus.Listener不可靠(事件不上来),这个链接的方法是监视Settings里的事件:参考链接
37、仿真器横屏
快捷键ctrl+f11。有人提到ctrl+f12和numpad 7也可以,但我这里不起作用。
38、用JAXB生成KML对应的Java Code时会遇到一些问题,解决方法如下:
1)写一个binding文件如bindings.xjb放在与ogckml22.xsd同一目录,内容可参考这个链接(根据错误提示要删除几行)
2)在命令行里加-extension
3)在命令行里加-target 2.1(否则生成的java类的annotation带有jdk6不识别的关键字"required")
完整的命令行如下:
xjc -xmlschema -verbose -extension -b bindings.xjb -d src -target 2.1 ogckml22.xsd
39、ListPreference的entryValues只能使用string-array
如果使用了integer-array,在点击这个preference项时会产生一个空指针异常,相关讨论见链接1、链接2。
Update: 又发现一个ListPreference的新问题,即使用string-array,defaultValue值也不能取太大的(超过 Integer.MAX_VALUE)整数,否则defaultValue不起作用(选项没有缺省被选中)。 真是问题多多。android版本2.2。
40、Android提供了方便的Share机制,但一般都是把文字share到微博或SMS,如何能"share"文字到SD卡文件呢?
这个链接描述了同样的问题,等待有人回答。 目前的想法是,在程序里自己实现一个接受ACTION_SEND的activity,做法可参考此链接、或此文章。
41、一个在线查看kml文件的网站,供参考。
42、关于onSaveInstanceState()的使用
通常与onCreate()配合,而非onRestoreInstanceState(),参考这个链接。
43、ListView里点击一个item背景色不变为橘黄(缺省的反馈颜色),各种OnClick事件不被触发。
一种可能是在item的布局文件(如foo_list_row.xml)里使用了下面的这些属性(自动滚动显示文字时常会用到),去掉后即可恢复正常:
android:ellipsize="marquee" android:scrollHorizontally="true"
android:marqueeRepeatLimit="marquee_forever" android:focusable="true"
android:focusableInTouchMode="true"
44、实现不停向上滚动的ListView
假设你有一个长长的list需要自动展示,方式是每隔几秒向上滚动一行,有点类似TextView的marquee功能(跑马灯?)。这个需求可以通过Handler实现,具体参考这个链接;当列表滚动到最后一行时,直接滚回第一行显得很生硬,可以用这个链接里提供的方法解决。
45、在Button的文字旁加图片
在<Button>里使用 android:drawableLeft="@drawable/my_icon" android:gravity="left|center_vertical" 即可,类似的可以加在右侧或上下方。但如果Button有其他状态时,需要用selector指定不同状态下的图片。此外,图片的大小是不会自动根据 Button调整的。
46、旧版本兼容
参考sdk文档里的这个文章。
47、轻松实现圆角背景
不需要做圆角图片,看看这个链接,很方便,注意把angle改为45的倍数否则运行时报错。
48、Android内存泄漏检测
在DDMS可以查看heap使用情况,大概了解是否有内存泄漏。DDMS还可以dump出.hprof文件,后者可以用Eclipse MAT打 开,进一步分析错误原因。注意,startActivity()后要根据情况决定是否调用finish()方法(如果需要back则不finish(), 在适当的时机用FLAG_ACTIVITY_CLEAR_TOP一并回收内存空间),未finish()的activity是会一直占用内存的。
49、Android的第三方library
这个链接总结了不少。
50、Android UI设计模式
参考这个链接。
51、Google Map扩展的使用。
参考这个链接。
52、当Spinner是invisible状态时,貌似调用mySpinner.setSelection(i) 不会触发其onItemSelected()事件。
53、实现gzip压缩服务器返回的json对象时,注意要 response.setContentType("application/json"),并且在server.xml里把application /json设置到compressableMimeType里才能实现。我因为前一个原因浪费了三四个小时。
54、对AlertDialog.Builder应用定制的theme
使用ContextThemeWrapper,用法参考这个链接。 但后来发现这个方法不起作用,有一种说法是这个方法只对部分android版本有效,也有说其根本无效的(都是在so上)。用 AlertDialog.Builder的setVIew()方法也是有问题的,因为你会发现在这个view的旁边一圈(假设你的view是浅色背景)还 是黑色的,效果很不好。其实如果只是要将对话框设置为白色背景,可以使用AlertDialog.Builder的 setInverseBackgroundForced(true)方法,很简单,很直接。
55、从gallery选择图片的一些可用参数
参考这个链接,和这个相关issue (文件得不到原始图片,只能得到缩小后的图片)。
56、从gallery取图片时要注意内存是有限的,而图片可能很大。
利用inSampleSize可以帮助解决,参考这个链接的代码。
57、当程序进程被系统kill掉(常常在内存紧张时发生):
HttpClient的session可以用persist方式保留;
其余数据建议保留在SharedPreferenes里;
onActivityResult()里是能够获得另一个activity传回来的intent里的参数的;
58、连接到真机时提示Unable to open sync connection!
原因未知,解决方法是在真机的设置里去掉usb调试,然后重新勾选。
59、得到GPS状态(寻星或已获得位置)
这个问题看似简单,但Android里的LocationListener#onStatusChanged()方法工作不正常,表现为在大多数版本下都不会被调用。这个链接里提供的方法试了一下好像是可以用的。
60、在Android里画统计图(柱图饼图等等)
这个链接里给出了不少解决方案,我暂时选择的是aChartEngine,用法和JFreechart比较类似,参数超多,目前的活跃度也不错。
61、进程经常被kill
可以考虑启动一个service(即使什么都不做),这样进程的“重要性”就变得很高,因此就不容易被kill了。
62、“Receiver not registered”错误
执行unregisterReceiver(myReceiver)方法时,如果之前没有注册过myReceiver,会抛出这个异常。参考链接
63、应用在后台运行,需要弹出对话框(例如触发自service产生的事件)时报错:“BadTokenException: Unable to add window”
利用isFinishing()测试activity是否在后台,参考链接
64、Emulator太慢了?
试试Android x86,据说比官方的快很多(我还没试过,正在下载)。 参考链接
<activity android:name=".SomeActivity" android:label="@string/app_name" android:screenOrientation="portrait">...</acivity>
66、几个众包模式的beta测试平台
iOS最著名的是testflight,也有其他一些类似的测试平台支持android,详见这个链接。
67、实现锁机后黑屏但不出现锁机画面
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
还有一个功能类似的flag是FLAG_DISMISS_KEYGUARD,区别在于前者只对当前activity有效,后者全局有效。另外前者对安全锁屏也有效,后者则只对普通锁屏有效。附一个参考链接。
但是前者有一个问题,就是在两个都设置了FLAG_SHOW_WHEN_LOCKED的activity间切换时,可能锁屏界面会闪一下。见此问题报告。
68、一些可用于android应用性能测试和内存泄漏检测的工具
见这个链接。
69、进度条的一个bug
重设setMax()以后显示的进度百分比不正确,至少在Android 2.1 (API Level 7)里有这个问题。 见这个链接和这个链接。
70、当ListView的item里包含控件(如按钮、复选框)时 ,这个item无法被选中。
Android不允许选中ListView里带有focusable元素的item,解决方法是将该控件的focusable属性设置为false。参考链接
71、帮助做简单web测试的工具(构造并发送各种http请求)
这个链接里总结了不少。
72、Tab放在底部(仿iphone风格)
中文的教程看了好几个都不靠谱,so上的一个链接搞定,或者这个带有源码的教程。
73、让ListView没有数据时也显示HeaderView/FooterView
技巧是让empty view包含headerview/footerview,见这个链接。
74、在Google map上添加popup的方法
最简单的方法见这个链接。
75、一个网站,可以搜索android相关项目的代码和资源。
76、Android里的Search Activity不支持返回结果到调用其的Activity(因为onSearchRequested()方法没有调用startActivityForResult()启动search activity)
SO上有若干个提出此问题的帖子,例如链接1、链接2等等,没有特别方便的办法解决,一个我没试过但看回复应该可行的方法见这个链接。
77、查看apk文件内容的工具
推荐apktool,一个命令行工具,用法如下:
>apktool.bat d my.apk
可以还原所有的资源文件,但.java文件一般无法还原。
78、Android中使用的各类图标的标准尺寸
请参考sdk自带的guideline文档。
79、Android的Searchable接口,无法让调用者获得查询结果。
参考这篇文档可以实现,思路是自己用startActivityResult() 启动搜索界面,然后再onActivityResult()里取出结果。我测试可行,但该文档有两处错误需要注意:
1) 是handleIntent()而非handleActivity()
2) 在startActivityResult()前最好intent.setAction(Intent.ACTION_SEARCH) 一下。
另外,注意按该文章中提到的官方文档实现相应的newIntent()和onCreate()方法,以及在AndroidManifest.xml里设置调用者的android:launchMode="singleTop"。
80、很诡异的问题,有时EditText无法输入文字(软键盘正常弹出但字符进不去文本框),必须切换到另一个输入法才可以输入。
经测试,有些机型存在这个问题,具体原因还不详。以下链接可能与此有关:链接1
81、定时重复执行一段程序
要执行类似闹钟这样的功能,用AlarmManager配合BroadCastReceiver即可,网上有很多例子不再赘述。值得一提的是,在这 个BroadCastReceiver里不要执行异步操作(例如异步访问一个远程服务、获取当前位置等等),因为onReceive()方法一旦执行结 束,用于容纳BroadCastReceiver的进程随时可能被系统kill掉,导致异步操作结束后出现异常。解决的办法是在onReceive()方 法里启动一个Service(我用的是startService,用bindService的方式可能也行),在Service里执行任何操作就可以了。 参考BroadCastReceiver Life Cycle
82、Monkey测试
>adb shell monkey -v -p com.my.app 100
MonkeyRunner可以进行更高级的测试。
83、用getIntent().getExtras().clear()无法清除掉extras里的数据
原因是getExtras()返回的是一个copy实例,用getIntent().removeExtra()可一个个清除。参考链接
84、用AlertDialog实现输入对话框时,若直接builder.setView(myEditText)文本框显得太长。
用dialog.setView()可以指定padding(注意是dialog.setView()而不是builder.setView()),具体见这个链接。
85、在TextView里显示图片
通过Html.fromHtml()方法可以在TextView里显示HTML格式的文本,但只支持部分tag:
myTextVIew.setText(Html.fromHtml(myHtmlStr))
要在TextView里显示远程图片,必须向fromHtml()函数里提供一个ImageGetter对象,在它的getDrawable()方法里获取远程图像并转换为Drawable类型。示例代码请参考此链接。
如果TextView设置了android:lineSpacingMultiplier属性,将导致图片显示的位置不正确(顶部多出一些空白),用android:lineSpacingExtra属性则没有这个问题。
如果图片加载比较慢将导致整个TextView空白很长时间,为解决这个问题需要异步加载图片,这样文字可以先出来,待图片下载完毕后再补充道文字中间。实现方法是扩展Drawable,具体方法参考这两个链接:链接1、链接2 ,其中链接1的方案存在图片尺寸不正确的问题,原因是TextView#invalidate()没能起作用(原因不详),用链接2提供的方法可以解决,这个链接提到用textView.setText(textView.getText())也可以工作但我没试。
86、在TextView里显示列表(<li>标签)
Android的TextView只支持一小部分的html标签(见这个链接),缺省是不支持<ol>、<ul>和<li>这样的列表标签的。通过TagHandler可以实现一个简单的列表效果(见此链接),但这个方法有个严重问题:当列表文字超过一行时,第二行的文字是顶头的没有缩进效果(见这个提问),而该问题暂时还没有好的解决方法。
87、百度地图android sdk问题
百度地图最大的问题:文档太烂!百度地图sdk版本比较多,网上充斥着各种版本的例子代码,官网上的例子代码也不清晰,在线文档含混不清。
遇到过一个奇怪的问题,与这个帖子描述的情况相同,即第二次打开地图只能显示上次缓存过区域的地图,最后删除了所有onPause()、onResume()和onDestroy()里的百度地图相关方法才解决。
88、启用Andoird设备的otg功能
在/system/etc/permissions目录里检查是否有名为android.hardware.usb.host.xml的文件,如果没有,新建一个内容如下:
<permissions>
<feature name="android.hardware.usb.host" />
</permissions>
89、命令行对一个未签名apk进行签名
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore my_application.apk alias_name
90、Pull-to-refresh控件不显示内容问题
将ListView替换为PullToRefreshListView,setAdapter()后发现列表中没有数据显示,调试发现 adapter里是有数据的,而listView的getView()方法没有被执行到。最后发现原因是在布局文件 的<com.handmark.pulltorefresh.library.PullToRefreshListView>元素中指定了 android:visibility="gone"属性(在.java文件里在setAdapter()之前先调用了 listView.setVisibility(View.VISIBLE)),在布局文件里去掉此属性,改为在activity的onCreate() 里执行listView.setVisibility(View.GONE)后恢复正常,没有深入调查这两种方式对 PullToRefreshListView有什么区别,对标准ListView是没有区别的。
91、切换fragment时fragment显示不全
在fragmentTransaction.replace(R.id.layoutRoot, newTransaction)时,发现当layoutRoot是LinearLayout时,(有时)newTransaction的高度无法充满 layoutRoot(虽然已经指定了高度为match_parent,指定高度为固定值也无效),后来将layoutRoot改为 FrameLayout问题解决。
92、利用Activity的android:process属性
在开发一个视频播放器过程中,遇到一个问题,当视频还在缓冲时按返回键退出当前activity,应用失去反应长达数秒。后来在 AndroidManifest.xml里对这个activity增加了android:process=":player"后问题解决,因为这个属性使 得此activity在一个独立的进程运行,当activity被关闭时,此进程也被杀掉。这样,即使播放器有未完成的工作,也不会影响到主程序的UI线 程了。
需要注意,用PreferenceManager.getDefaultSharedPreferences()得到的 SharedPreferences实例,是不支持跨进程访问的,因此在独立的进程里将无法向这样获得的SharedPreferences实例存取数 据。解决的办法是改为使用context.getSharedPreferences(prefName, Context.MODE_MULTI_PROCESS)获取SharedPrefences实例。
不过还是要特别注意,在多进程环境下,如果你用一个静态变量缓存了SharedPreference里的内容, 由于静态变量在多个进程间不是共享的(Application对象也不是跨进程共享的),所以取出的结果可能不是你想要的。解决办法 1)去掉这个作为缓存的静态变量,每次都直接从SharedPreferences里取 2) 有人建议使用MemoryFile作为跨进程的机制,但我没有实际测试过,而且用起来应该会比Application对象繁琐。
93、Service的START_STICKY与START_NOT_STICKY的区别
参考这个链接: 当系统由于资源不足可能会杀掉一个service,之后如果系统又有了足够资源,若被杀掉的service是START_STICKY的,则系统会调用其 onStartCommand()方法恢复这个service;若被杀掉的service是START_NOT_STICKY的,则系统不会尝试恢复这个 service。
94、如何用纯java的方式获取apk文件版本信息?
apk文件就是zip文件,解析并读取AndroidManifest.xml里的信息即可。开源项目android-apk-parser已经实现了这个功能,可以直接在java项目里使用。
101、previous process的问题
actA起actB in new proccess,B只有在onResume时A才是previous process (oom adj=7),B onPause时,A 的oom adj=9,就不是previous process了。
102、安全的Android锁屏使用FLAG_SHOW_WHEN_LOCKED与disableKeyguard
参考这个链接:
this.getWindow().setSoftInputMode( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
(待续)