Category Archives: Android

Andrord Market Filters base on Device configuration

http://developer.android.com/guide/appendix/market-filters.html

In this document it described the filtering rules. But what exactly it is? In the past year, I payed lots of time to debug the market, gapps.So I decide to write a small tool to show Android Market collect your device configuration , mainly use for Android porting debug. You can easily to see why your device can’t search some apps in Android Market if it has not the featrues meets the market filter. The quick way to find out what happen is that compares with other phone install this same app

The QR code as bellow, your android version should be >= 2.2

Code Review

每周六下午都对自己的代码进行一次 code review.通过 svn log记录,总结主要修改的:

1. 先阅读一遍Android编码风格
2. 添加文件头版权信息
3. 添加注释
4. tab to 4 spaces , 通过 trac 阅读代码,很容易找出。
5. 重命名函数名及参数,让它看起来更合理。
6. 去掉 magic number
7. 删除重复的代码,没用的代码
8. 减少大函数,拆分成小函数
9. 源代码后面要空一行
10. 更新设计文档

对于第7点,比如boolean 函数力求简凑,

-            if (deviceRegistrationId == null) {
-                return false;
-            } else {
-                return true;
-            }
+
+            return (deviceRegistrationId != null);

下面是对应的 ddx 格式

133     .local v0, deviceRegistrationId:Ljava/lang/String;
134     if-nez v0, :cond_0
135     
136     .line 383
137     const/4 v2, 0x0
138     
139     .line 385
140     :goto_0
141     return v2
142 
143     :cond_0
144     const/4 v2, 0x1
145 
146     goto :goto_0
147 .end method


133     .local v0, deviceRegistrationId:Ljava/lang/String;
134     if-eqz v0, :cond_0
135 
136     const/4 v2, 0x1
137 
138     :goto_0
139     return v2
140 
141     :cond_0
142     const/4 v2, 0x0
143 
144     goto :goto_0

编译器编译出来的 ddx是一样的。

解决android 2.2 market搜索结果偏少的问题

那是很久很久以前的事了,大概花了两个星期去折腾,整理整理,与朋友们分享一下。

我们开始移植到 2.2时,market运行很好,过一段时间测试组提出bug。问题现象:Android market 搜素记录严重偏少,比如搜索 qq,在我们的broncho a1上,只有1条记录。

首先,确定apk包是没有问题的。同样的包安装在G1上,可以找到300多条记录。此外,特意让上海龙旗的一位网友看了他们公司的手机,说可以搜索到25条qq记录,他们的分辨率是 800 * 600, 我们的是480 * 320。他把apk包发给我,在我们机器上还是同样的结果。

其次,在javaeye上,有网友说跟机器有 root权限有关,他发布一款软件到market上,他的机器是root权限,搜索不到他刚发布的程序,改为普通用户后,就可以了。这有可能,因为我们的机器一直是root权限,重新编译kernel,改为普通用户,还是不行。

后来有人说,跟market上设置的protected权限有关。我为此还花了25$注册 market开发者,写个小程序放上去,关闭权限,结果还是没有生效。

解决问题最好的方法是找差异。为此,getprop 获取G1系统参数做比较,还是没有找到有异常嫌疑之处。gpps包是从cm上获取的,我们没有通过正规的渠道拿到,怀疑是跟授权有关,如果真的是这样,那就没办法了,不过,上海龙旗既然可以搜索到25条记录,我想应该跟这没关系。

用 tcpdump与 wireshark 工具观察 market请求发出的数据包找出url,那是一串经过序列化然后再经过base64加密后的字符串。有开源的 android market api,基于protobuf协议,之前也是运行好好的,最近就不行了。翻遍它的 google groups,说什么帐号跟手机的deviceId挂钩了,我重新注册个gmail帐号,还是一样。又有说根据ip来源,返回不同的搜索结果。我干脆把程序放在美国的服务器上跑,还是没成功。

绝望,绝望!!! 一个android手机,如果电子市场不能使用,那简直是暗淡无光。

正值网络上爆出android暗含高达40% 的扣费短信。wusong童鞋无聊给我发个帖子链接《近期 Android 平台扣费软件检测的分析心得与思路分享》,说是如何扫描apk包含扣费短信的,文章中说通过反编译apk,插入 Log.v 打印出非法信息。灵光一闪,既然我无法全部理解那长长的url,那何不如让它自己打印出自己的信息呢?

修改ProtoBuf里的insertObject函数,添加Object toString()打印对象,如果是vector,就遍历打印。

结果发现,我们只有这个信息:

1222 insertObject: W tag=10 index=0com.google.android.feature.GOOGLE_BUILD

相应的g1的有很多信息,经查询, 问题出现在 FeatureInfo[] systemAvailableFeatures =
packageManager.getSystemAvailableFeatures(); 这个函数。

运行时,PackageManagerService.java 从 /system/etc/permissions/ 下所有
的文件读取 features/permissions。这个目录下,我们只有一个features.xml, 而这个文件还是从gapps里拷贝过来的。
所以,应该把以下文件

frameworks/base/data/etc:
android.hardware.camera.autofocus.xml
android.hardware.location.gps.xml
android.hardware.telephony.gsm.xml
android.hardware.touchscreen.multitouch.xml
android.hardware.wifi.xml
handheld_core_hardware.xml

生成image时拷贝到

/system/etc/permissions/

如果是cdma,
请把 android.hardware.telephony.gsm.xml
替换为
android.hardware.telephony.cdma.xml

测试,OK。

我把问题解决后,才发现一下别人的帖子:
APAD IMX515 安装 Android Market 方法

Working Android market and all google app (for 2.2)

问题解决后再回顾:

1. 如果我早用 Quick system info 这个工具,会很快找到问题,这个工具可以显示 system availabe features信息,两机器都同时安装,跟G1一对比,一目了然。

2. 如果把 market的数据清空,再抓数据包,在 base64 decode,虽然不能看出所有的含义,但至少也看到 xxx.xx.xx 这样可显示的字符串,也可以尽快找出问题。market 手机系统信息,是第一次运行时才收集,后面的url请求只需要从cache里获取系统信息即可。

3. DeviceConfiguration.java 有 toString(),注入调试信息也可以显示出来。

4. 仔细阅读官方文件 http://developer.android.com/guide/appendix/market-filters.html, 有提到getSystemAvailableFeatures()这个函数.

直接修改Market包显示支持收费软件,首页推荐软件

目前用MarketEnable,MarketAccess 之类的软件可以做到,但也有缺点:被修改apn,重启后无效。

大陆第三方ROM,一般都直接修改了电子市场包,观察一下安卓网自制的ROM,build.prop中都多了两行代码:

hiapk.vending.operator.name=T-Mobile
hiapk.vending.operator=310260

把运营商改为美国的。然后用

SystemProperties.get("hiapk.vending.operator.name");
SystemProperties.get("hiapk.vending.operator");

替换

TelephonyManager.getSimOperatorName();
TelephonyManager.getSimOperator()

下面是我修改的2.2.7版本的patch:

$ colordiff Vending_o/smali/com/android/vending/VendingApplication\$ApiClientContext.smali Vending/smali/com/android/vending/VendingApplication\$ApiClientContext.smali 
239,245c239
<     iget-object v2, p0, Lcom/android/vending/VendingApplication$ApiClientContext;->this$0:Lcom/android/vending/VendingApplication;
< 
<     invoke-static {v2}, Lcom/android/vending/VendingApplication;->access$100(Lcom/android/vending/VendingApplication;)Landroid/telephony/TelephonyManager;
< 
<     move-result-object v2
< 
<     invoke-virtual {v2}, Landroid/telephony/TelephonyManager;->getSimOperatorName()Ljava/lang/String;
---
>     const-string v2, "T-Mobile"
247c241
<     move-result-object v7
---
>     move-object/from16 v7, v2
259,265c253
<     iget-object v2, p0, Lcom/android/vending/VendingApplication$ApiClientContext;->this$0:Lcom/android/vending/VendingApplication;
< 
<     invoke-static {v2}, Lcom/android/vending/VendingApplication;->access$100(Lcom/android/vending/VendingApplication;)Landroid/telephony/TelephonyManager;
< 
<     move-result-object v2
< 
<     invoke-virtual {v2}, Landroid/telephony/TelephonyManager;->getSimOperator()Ljava/lang/String;
---
>     const-string v2, "310260"
267c255
<     move-result-object v9
---
>     move-object/from16 v9, v2

重新打包,签名即可。

Android Market 之 deviceId

有时候我们在market上无法下载软件,总停留在 downloading… 界面,有时候恢复出厂设置又可以下载了,这是为什么呢?

在market上下载一个应用程序发出的URL请求,可以参考Tim Strazzere的博文 Downloading market applications without the vending app

其中涉及到一个参数手机设备号,与Android_ID有关,这个Android_ID可以参看官方文档

http://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID

“A 64-bit number (as a hex string) that is randomly generated on the device’s first boot and should remain constant for the lifetime of the device. (The value may change if a factory reset is performed on the device.) ”

AndroidId,通常用做识别唯一设备。可以通过下面的函数获取:
String androidId = Settings.System.getString(getContentResolver(),
Settings.Secure.ANDROID_ID);

具体的函数实现与系统环境变量”ro.serialno”有关,大概过程是:

/system/core/init/init.c 读取kernel启动参数 /proc/cmdline 获取 androidboot.serialno, 然后是设置系统变量

property_set(“ro.serialno”, serialno[0] ? serialno : “”);

下面是 HTC G1的kernel启动参数:

~ # cat /proc/cmdline
board_trout.disable_uart3=0 board_trout.usb_h2w_sw=0 board_trout.disable_sdcard=0 smisize=64 androidboot.baseband=2.22.19.26I androidboot.cid=T-MOB010 androidboot.carrier=TMUS androidboot.keycaps=qwerty androidboot.mode=normal androidboot.serialno=HT839GZ04643 androidboot.bootloader=1.33.2005 no_console_suspend=1 console=null
~ # getprop |grep serialno
[ro.serialno]: [HT839GZ04643]

adb shell devices
列出的就是ro.serialno , 如果为空,用默认的值: “1234567890ABCDEF”.
注意,有些机器总是显示 9774d56d682e549c,说明系统环境变量”ro.serialno”没有设置,最近的Android 2.2代码已经修改这个bug.

strazzere的博文提到,可以用 tcpdump与wireshark工具观察数据包,可以得到手机的deviceId。其实也不需要那么麻烦,Android Market依赖于Downloads这个provider,那么查看sqlite数据库也是一目了然的:

$ adb pull /data/data/com.android.providers.downloads/databases/downloads.db .
$ strings downloads.db

或者可以这样找

$ adb pull /data/data/com.android.providers.settings/databases/settings.db .
$ sqlite3 settings.db
$ .tables
$ select * from secure

据观察,deviceId跟ANDROID_ID有一定的关系,deviceId是Google服务器自动生成的。 在Android 2.2之前的版本,可以为伪造一个地址蒙蔽过关,SDK上提供的是16个0。而在android 2.2之后的market,这个值与email帐号挂钩起来了,如果不一致,会收到HTTP 400 的错误码,这样只好把手机恢复出厂设置,重新生成deviceId。

Pages: Prev 1 2 3 4 5 6 7 8 9 10 11 12 Next