Android应用开发中的兼容性问题整理.docx
《Android应用开发中的兼容性问题整理.docx》由会员分享,可在线阅读,更多相关《Android应用开发中的兼容性问题整理.docx(12页珍藏版)》请在冰豆网上搜索。
Android应用开发中的兼容性问题整理
Android应用开发兼容性问题整理
(仅供内部使用)
关键词:
Android,兼容性问题
摘要:
Google的战略造成Android生态系统的混乱,混乱给Android应用开发带来阻力,本案例总结了几个本人工作中遇到的Android兼容性问题,提供一些解决思路,避免浪费时间。
由于本人工作是Android的应用开发,本案例不讨论硬件方面的问题。
1
案例描述
Android应用开发的同学,在工作中一定会经常遇到这样的场景:
测试人员拿着手机,气势汹汹的过来,“这个bug刚改好,怎么又有了?
”,开发的同学皱起眉头找原因,同样的程序在三星手机上策马奔腾,却在魅族手机上折戟沉沙。
做web开发的尤其做前端的同学,都知道各浏览器之间存在兼容性问题。
Android应用开发中同样存在令人头疼的兼容性问题,如鬼魅一般如影随形,隐匿在开发的各个角落。
本篇案例,就以本人艰苦卓绝的一年Android应用开发经验为基础,整理出一些Android兼容性问题。
希望能够为开发人员提供一些解决思路,少走弯路。
需求人员可以以此为参照,在做需求的时候避免一些兼容性问题频发的地方,不要折腾。
测试人员也可以阅读此案例,做好测试Android应用的思想准备。
在案例最后,也会总结一下几个厂商的手机在兼容性上的表现,需求、开发、测试人员在做Android应用相关工作的时候,多加注意。
2案例分析
2.1解决兼容性问题的利器
Android操作系统由于Google的开源推广,惨遭各大手机生产厂商修改折腾,同一版本号的Android系统在不同的手机上会出现差别。
再者,Android一出世便身负重任,版本更新的速度非常快,这也导致了不同Android版本会有差别。
甚者,同一家手机厂商推出不同型号的手机采用不同的Android系统版本、是否修改Android源码,都会引起应用程序的一些表现差异。
所以,我们在碰到了兼容性问题的时候,找寻的直接原因要从系统版本、手机厂商、手机型号等方面入手。
幸好,Androidapi提供的android.os.Build类能够为我们提供这些信息,从而根据这些信息对应用程序做适当的处理。
下面列举了,android.os.Build类中比较常用的静态成员变量。
android.os.Build.MANUFACTURER:
生产厂商
android.os.Build.MODEL:
设备名
android.os.Build.VERSION.SDK:
sdk版本号
android.os.Build.VERSION.SDK_INT:
sdk版本号,int类型
2.2Dialog.setMessage(Stringstr)
贴代码:
publicvoidopenVersionDialog(finalContextcontext,finalStringmessage,
StringfileName,StringfileSize){
AlertDialog.Builderdialog=newAlertDialog.Builder(context);
dialog.setTitle(context.getString(R.string.new_version));
Stringmsg=context.getString(R.string.version_info)+message
+context.getString(R.string.install_package,fileSize);
dialog.setMessage(msg);
dialog.create();
dialog.show();
}
上面的代码,是为了进行一个弹出框提示,同样的代码,不同手机上dialog.setMessage(msg)的表现不同。
图2-2-1Meizu手机图2-2-2Philips手机
对于dialog.setMessage(msg)的处理,Meizu手机中的字段是居中对齐的,而目前测试到别的厂商的手机都是左对齐,三星、Philips、Htc都是左对齐。
如果开发人员被要求修改Meizu手机的表现,有两种解决思路。
一种思路是:
通过android.os.Build.MANUFACTURER判断是否是Meizu手机,如果是Meizu手机则不用dialog.setMessage(Stringmsg)方法,而创建一个显示文字的view,然后用dialog.setView(Viewlayout)方法。
第二种思路是不采用dialog.setMessage(Stringmsg)方法,全部采用dialog.setView(Viewlayout)方法。
第三种思路则不用Dialog类,弹出框采用自定义Activity。
2.3不要用AutoCompleteBox组件
大家在平时上网的时候,都会有这样的经历,在Baidu的搜索框中,输入字符串,Baidu会弹出一个下拉框,下拉框中有跟你输入的字符串相联系的一些字符串。
这在web中是一个常见的应用,你输入一个字符,页面发送ajax请求给后端,后端经过处理,返回相关的字符串,然后显示在前端页面。
那么有人,就会问,能不能把这种应用搬到手机应用上。
答案是可以的,而且Google也给我们提供这样的组件。
但只能说,这人有联想,但没经验。
2.2中介绍的问题,目前测试只Meizu手机出现,如果是AutoCompleteBox组件,则多种手机会出现不同的症状。
图2-3-1AutoCompleteBox示例
如图2-3-1,AutoCompleteBox组件包括textbox、drop-down、selectionadapter三个部分。
图中,adapter中有四个Item,Item中可以设置背景图片。
单独的一个AutoCompleteBox组件感觉不错,但在实际的测试中,同一代码在不同的机型会出现各种差异,这些差异存在于组件的不同的地方。
例如:
1)Item与selectionadapter左边框、右边框的距离。
2)只有一个Item时,selectionadapter的上下边框遮住一个Item。
3)selectionadapter的边框与drop-down边框的距离。
4)textbox的位置表现影响到当软件盘弹出时drop-down是在textbox的上方还是下方,如图2-3-2。
5)如果Item中有背景图片,那么背景图片的透明度可能引起别的问题。
解决这些问题,是耗费时间精力体力的,组件的每个属性都要试,据测试修改的经验,越老版本的系统、越老型号的手机问题越多。
这里就不一一贴图,往事不堪回首。
所以,在应用中,快刀斩乱麻,大胆去之。
图2-3-2drop-down在上方的AutoCompleteBox
2.4快捷方式
应用程序有了创建快捷方式的功能,经常有人抱怨自己手机上出现多个桌面图标。
且听本人娓娓道来。
不同于iOS,Android操作系统在安装一个软件安装包的时候,并不会为软件包创建桌面快捷方式,要实现创建桌面快捷方式的功能,只能在程序安装成功后第一次运行的时候创建快捷方式。
而且,Android系统是允许系统启动后选择桌面的,区别于其他系统在启动后是默认桌面,这也就导致了qq桌面、91桌面等各种桌面应用的丛生。
再者,Android的开源性,某些自称国际品牌的手机厂商标新立异,不仅修改桌面,而且修改与桌面相关的java类。
1)添加桌面快捷方式的代码:
//添加当前应用的桌面快捷方式
publicstaticvoidaddShortcut(Contextcontext,inticonId,intappId,Classtarget,
booleanmany){
IntentaddIntent=newIntent("com.android.launcher.action.
INSTALL_SHORTCUT");
//获取快捷键的图标
Parcelableicon=Intent.ShortcutIconResource.fromContext(context,
R.drawable.icon);
Stringlabel=context.getString(appId);
IntentmyIntent=newIntent(Intent.ACTION_MAIN);
myIntent.addCategory(Intent.CATEGORY_LAUNCHER);
if(target!
=null){
myIntent.setClass(context,target);
}
//快捷方式的标题
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME,label);
//快捷方式的图标
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,icon);
//是否允许重复创建--fase-->否
addIntent.putExtra("duplicate",false);
myIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
myIntent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
//快捷方式的动作
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT,myIntent);
//发送广播
context.sendBroadcast(addIntent);
}
添加name="com.android.launcher.permission.INSTALL_SHORTCUT"/>许可。
这段代码就是创建桌面快捷方式的代码,做为应用开发人员,能做的事情只是调用Android提供的api。
而且,已经用addIntent.putExtra("duplicate",false)方法,设置创建方式的时候不重新创建,即如果桌面上已经有了桌面,那么就不创建新的桌面快捷方式。
在实际的测试中,有的手机addIntent.putExtra("duplicate",false)方法是没效果的,即已经有快捷方式,仍会创建快捷方式,桌面上出现多个快捷方式。
如果一个手机上安装了多个桌面应用的话,有的桌面对addIntent.putExtra("duplicate",false)方法也是没效果。
既然创建桌面快捷方式的代码产生多个快捷方式,那么能否有方法先判断是否已经创建快捷方式,如果有快捷方式,则不创建快捷方式。
下面是判断是否已经创建快捷方式的代码:
2)判断是否创建快捷方式的代码:
try{
Uriuri=null;
Stringspermi;
if(android.os.Build.VERSION.SDK_INT<8){
spermi="com.android.launcher.settings";
}else{
spermi="com.android.launcher2.settings";
}
uri=Uri.parse("content:
//"+spermi+"/favorites?
notify=true");
finalContentResolvercr=context.getContentResolver();
Cursorcursor=cr.query(uri,newString[]{"title","iconResource"},"title=?
",
newString[]{context.getString(R.string.app_name).trim()},null);
if(cursor!
=null&&cursor.getCount()>0){
cursor.close();
returntrue;
}else{
returnfalse;
}
}catch(Exceptione){
Log.e("ShotCutUtil","ShotCutUtilException",e);
returnfalse;
}
添加name="com.android.launcher.permission.READ_SETTINGS"/>权限。
从这段代码可以看出,Android系统为每个快捷方式指定的app的名字、图标等存在本地的数据库中,我们可以通过查询app的名字,如果查询的结果集数量大于0,则说明app的快捷方式已经创建。
对于android.os.Build.VERSION.SDK_INT<8即版本号低于2.2的Android系统,存放于"com.android.launcher.settings"中,对于android.os.Build.VERSION.SDK_INT>=8的版本,存放于"com.android.launcher2.settings"中。
而在实际的测试中,Zte、Meizu、Huawei等国产手机是遵守这一规则的。
三星手机有的机型在版本号的数字上即是否为8略有差别。
而Htc手机重写桌面的同时,也将launcher修改,并修改了这一规则,Htc命名为"com.htc.launcher.settings",在进行查询的时候,需要添加name="com.htc.launcher.permission.READ_SETTINGS"/>,这或许与Htc招聘有大量Android驱动、应用开发人员瞎折腾有关,有的型号的Htc手机依旧是查不到的。
3)手机上存储是否第一次运行的标志
为解决上面的问题,采用应用程序在手机上保留存储一个标识,记录是否是第一次运行应用程序。
存储标识的方式可以自由选择。
如果是第一次运行,调用1)中创建快捷方式的代码;如果不是第一次运行,则不创建快捷方式。
但这样会产生另一个问题,即如果在手机的应用管理器中选择该app,然后清理数据的话,会把标识清空的,再次运行程序,会认为是第一次运行,调用1)代码创建,就会出现1)中的问题,可能出现多个快捷方式。
4)综合方案
最后采用查询数据库+本地标识结合的方案,可以有效的减小出现多个快捷方式的概率。
如果标识不是第一次运行或者"com.android.launcher.settings"、"com.android.launcher2.settings"、"com.htc.launcher.settings"任意一个能够查询获得结果集,则不创建快捷方式;反之,创建快捷方式。
2.5Android类库中.InetAddress的差异
在Androidapp开发中,可能会需要进行dns的解析,用到.InetAddress,那么要注意下面的差异。
目前测试中,android.os.Build.VERSION.SDK_INT<15即低于4.0的Android版本中,域名和ip键值对存放的位置是.InetAddress类的私有静态变量addressCache中的map变量;
publicclass.InetAddress{
privatestaticfinal.AddressCacheaddressCache=
new.AddressCache();
…….
}
publicclass.AddressCache{
privatefinaljava.util.Mapmap;
……
}
在android.os.Build.VERSION.SDK_INT>=15即不低于4.0的Android版本中,.AddressCache类的内部结构有所不同,加入了libcore.util.BasicLruCache类型的cache成员变量,最终域名和ip的键值对存放在cache中java.util.LinkedHashMap类型的map成员变量中。
publicclass.InetAddress{
privatestaticfinal.AddressCacheaddressCache=
new.AddressCache();
…….
}
publicclass.AddressCache{
privatefinallibcore.util.BasicLruCachecache;
……
}
publicclasslibcore.util.BasicLruCache{
privatefinaljava.util.LinkedHashMapmap;
……
}
有兴趣的同学可以研究一下,Google在Android4.0以上修改.InetAddress的原因。
有用到.InetAddress类的app,可以注意一下。
2.6手机厂商兼容性评分
下面对一年来测试过的手机厂商在兼容性方面的表现进行一个总结,在做Androidapp的时候要多加注意问题严重的厂商,由于一些手机厂商并未进行大量测试,所以并未包含在内。
5分为满分,分数越高,兼容性问题越少。
手机厂商
评分
备注
Meizu、Moto
2
Meizu一般都是界面上存在问题
Moto越老的机型问题越多,难怪被收购
Htc
3.5
Htc界面一般没问题,看来其研发实力高于Meizu
Samsung、Zte、Huawei
4.5
Zte、Huawei对系统修改较少,在网络切换方面优于Meizu、Moto
Samsung无愧于叫板Apple的公司
3总结
有位叫麦克莱恩的警官,总是在错误的时间出现在错误的地点。
兼容性问题的解决耗费时间精力人力,需要大量的测试,所以,不要在错误的时间让开发的同学折腾这些问题,开发、测试、需求的同学共勉。