Category Archives: Android

android 2.2 market显示热门付费应用

有 root 权限的,直接编辑

/data/data/com.android.vending/shared_prefs/vending_preferences.xml 

<boolean name="metadata_paid_apps_enabled" value="false" />

修改为:

<boolean name="metadata_paid_apps_enabled" value="true" />

重启机器,即可。

也可以安装 MarketEnable或MarketAccess。

主页面显示:”Android 电子市场没有符合请求的内容“, 解决方法请参考 Android market FAQ 最末尾那段,只能暂时的通过setpro 设置一些属性,重启就失效了。

参考: http://forum.cyanogenmod.com/topic/1972-paid-apps-tab-missing/

反编译Android market Vending.apk包

主要是工作的缘故,Market时不时登录不了,东试这个rom,西试那个rom也不是解决办法,横下心来,决定fuck 她一下。

从今年5月份开始到现在,断断续续的干这事,用反编译工具apktool,ddx左右开工,下班回宿舍常常搞到两三点,弄得身心疲惫,已经完成了90%,2.5w行的代码,最后的10%将是最难的,集中分布在 try catch throw, 多层的if for 结合,不好处理。都是用最原始的方法: edit-compile-decompile-diff-edit,一直循环。手工反编译出来的代码已经可以阅读,需要再搞清楚它的protobuf协议,api,慢慢消化。有时间,用Rails写个网页,提供web浏览。反编译的Vending.apk是1.5版本的,跟最新的2.2差别太大了,也许最初的决定,是一种错误。这过程,除了锻炼我的牛力,学习熟悉Java之外,剩下的是无尽的空虚,浮云,都是浮云!

这事就这样暂停吧,接下来花时间去阅读Android的代码,过段时间有力气了再回头继续fuck。

转眼到了10月中旬,快过年了,三年的工作合同将满,下一步不知道去哪好,也向往搞一个像 37signals那样的公司,两三个人,崇尚简单即是美,上帝赐予我力量吧。

Android设置显示本机号码

本机号码,我觉得是没有多大的用处,几乎谁都会知道自己的手机号码,但也有用户真的需要这个功能。有个对讲机软件tikl – touch to talk,可以通过网络进行多方通话,需要用到本机号码。 测试短信的脚本,自己给自己发短信,也需要本机号码。

Android手机在 设置-关于手机-状态消息,可以查看到本机号码,很多情况是显示未知。 很多模组用AT+CNUM 这组AT命令可以设置与查询本机号码。一般的手机在查看本机号码的界面都可以添加本机号码的,比如MTK/展信手机都提供这个功能。 Android对卡的操作,都是直接读写卡上的信息,用比较底层的AT+CRSM,而不是常用的AT,比如 AT+CMBR, AT+CMBW,AT+CNUM等。

Android手机设置本机号码,目前我还没发现有工具可以设置,很多人是把SIM卡拿到可以设置的手机上设置,然后把卡重新插上。 不过,Froyo提供了内部接口方法Phone.setLine1Number(),CM6的通话设置里就加入了本机号码设置功能:

具体的代码,在这里看清清楚楚:

http://github.com/CyanogenMod/android_packages_apps_Phone/commit/5351ce8247eb9fc9a3bf2ec751d14dcd373ab92e

可能需要到github注册个帐号,才可以浏览代码,主要是在phone里面添加处理,独立写个小程序的话,比较麻烦,因为要访问PhoneApp。

更新: (2010-11-15) 今天试了一下,参考Settings, 共享一个sharedUserId,也可以写个独立的程序,在g1 2.2,HTC desire上测试通过。注意:Android 2.2以下的无法使用。

代码献上: https://github.com/lytsing/MyPhoneNumber

解决donut Gtalk、Market登录不了的问题

拿到一个开发板,研究一下为什么gtak,market都登录不了的问题。折腾了许久,很纠结,试过几个ROM的包都不行。今天再搞不定,明天还计划准备对market进行反编译。

Gtalk界面提示:无法连接到服务器。请稍后重试。
logcat是:
1050 GTalkService W [GTalkConnection.12] doConnect: caught java.lang.IllegalStateException: empty JID resource

market界面出现这样的提示:出现服务器错误,请重试,或者取消并返回上一屏幕。
后台logcat是:

1190 vending D com.android.vending.BaseActivity$BaseAction.run(): ApiException:
1190 vending D com.android.vending.api.FatalCommunicationException: Sent a bad request.
1190 vending D at com.android.vending.api.RequestDispatcher.throwException(RequestDispatcher.java:371)
1190 vending D at com.android.vending.api.RequestDispatcher.performRequestsOverNetwork(RequestDispatcher.java
212)
1190 vending D at com.android.vending.api.RequestDispatcher.performRequests(RequestDispatcher.java:174)
1190 vending D at com.android.vending.api.RequestManager.doRequestsOverNetwork(RequestManager.java:244)
1190 vending D at com.android.vending.api.RequestManager.doRequests(RequestManager.java:230)
1190 vending D at com.android.vending.BaseActivity$BaseAction.run(BaseActivity.java:1476)
1190 vending D at com.android.vending.BaseActivity$BaseAction$BackgroundThread$1.run(BaseActivity.java:1556)
1190 vending D at java.lang.Thread.run(Thread.java:1060)
1190 vending I om.android.vending.BaseActivity$BaseAction.displayErrorUi(): General error in com.android.vend
ng.AssetBrowserActivity$NetworkDataLoadAction
1190 vending I om.android.vending.api.FatalCommunicationException: Sent a bad request.
1190 vending I at com.android.vending.api.RequestDispatcher.throwException(RequestDispatcher.java:371)
1190 vending I at com.android.vending.api.RequestDispatcher.performRequestsOverNetwork(RequestDispatcher.java
212)
1190 vending I at com.android.vending.api.RequestDispatcher.performRequests(RequestDispatcher.java:174)
1190 vending I at com.android.vending.api.RequestManager.doRequestsOverNetwork(RequestManager.java:244)
1190 vending I at com.android.vending.api.RequestManager.doRequests(RequestManager.java:230)
1190 vending I at com.android.vending.BaseActivity$BaseAction.run(BaseActivity.java:1476)
1190 vending I at com.android.vending.BaseActivity$BaseAction$BackgroundThread$1.run(BaseActivity.java:1556)
1190 vending I at java.lang.Thread.run(Thread.java:1060)
1024 GTalkSerice E createAccountFromSettings caughtjava.lang.NumberFormatException: unable to parse 'null' as integer, use default port 5228

首先tcpdump获取数据包,然后用wireshark分析,发现

POST /market/api/ApiRequest HTTP/1.1\r\n
version=2&request=ClIxxxxxxxxxxxxxxxxxxxxxxxxAggBFA (中间有个人信息,用xxx替代)

总是返回 404错误,肯定是参数问题。request的参数,是经过base64加密过的,一直琢磨不出到底是哪个参数错了。

到了下午,痛定思痛,整理一下思路:

1. market与gtalk都登录不了,而gmail可以正常使用,从wireshark分析的数据包来看,DNS解析正常,没有被盾。
2. market与gtalk都登录不了,两者共有的东西是什么?是gtalkservice。
3. 同样的包,在模拟上,gtalk 可以登录使用,market却不行。

好,再仔细分析log:

[GTalkConnection.9] doConnect: caught java.lang.IllegalStateException: empty JID resource

开始也注意到这条log,但上面说的第三点因素,加上 Google这条错误信息,没有搜索记录,别人没遇到这问题,所以就没在意。

GTalkConnection是不是在gtalkservice里面? 用apktoo 反编译 gtalkservice.apk,搜索”empty JID resource” 字符串,还真在这个文件GTalkConnection.smali,代码大概是:

String resource = Settings.getJidResource();

if (TextUtils.isEmpty(resource )) {
    throw new IllegalStateException("empty JID resource");
}

搜索一下getJidResource, 文档写:

public static String getJidResource()

Returns the GTalk JID resource associated with this device.

Returns:
String the JID resource of the device. It uses the device IMEI in the computation of the JID resource. If IMEI is not ready (i.e. telephony module not ready), we’ll return an empty string.

哈哈哈,太明显了,IMEI!!! 在设置里,查看手机的IMEI,显示是未知,90%应该是这个问题了,先做个假的测试一下。

frameworks/base/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java

 897     public String getDeviceId() {
 898         return mImei;
 899     }
 

用模拟器上的值,改为:

 897     public String getDeviceId() {
 898         /*return mImei;*/
 899         return "000000000000000";
 900     }
 

到 frameworks/base目录下,mm -B , 重新生成frameworks.jar, push 到手机,重启,ok,market, gtalk可正常使用 :)

总结一下,给我一杯凉水,我需要冷静,log很重要,搞php我每次都先看apache error log, 搞C/C++, gdb无敌,一到android,没能潜移默化,可能是最初对Java的抵触,反感。现在发现用Java写程式也是蛮是享受的事。

Android 2.2系统在线升级的移植

之前我们自己做过一个在线T卡升级的应用程序,设计思路是非常简单的,获取本地手机版本号,获取并解析服务器上json格式的最新信息,如果服务器上的版本号大于本地手机的版本号,则可以下载并md5验证升级包,然后调用系统函数升级即可。

从Android 2.2开始,Google服务框架 GoogleServicesFramework.apk 包自带的系统更新处理了android.settings.SYSTEM_UPDATE_SETTINGS这个intent。我们自己做的手机,当然不可能用Google自带的在线升级。为了不修改 GoogleServicesFramework.apk,在Settings的AndroidManifest.xml文件,把 SYSTEM_UPDATE_SETTINGS,修改为别的名字,比如 SYSTEM_UPGRADE_SETTINGS。 还需要同步修改这个文件:

Settings/res/xml/device_info_settings.xml
今天发神经病,花了一大早上的时候反编译GoogleServicesFramework里的update,看看别人如何设计的,就几个文件:
[deli@athena update]$ tree .
.
├── Download.java
├── StateWatcher.java
├── SystemUpdateActivity.java
├── SystemUpdateInstallDialog.java
├── SystemUpdateService.java
└── SystemUpdateVerifierTask.java

搞出600多行代码,才发现跟GoogleServicesFramework这个包里的其他代码非常缠绵,只好作罢。 大概思路也弄明白了,跟我们一样,也是用Downloads.ByUri 这个组件下载文件,
调用系统函数 RecoverySystem.installPackage(context, new File(filename)); 唯一的差别是没有网络连接的情况下,引导用户到设置的界面,比较人性化,很注重用户体验,我们直接跳出个对话框,没有网络连接,以后是要修改的。

默认的,installPackage 这个函数只支持文件放在 /data或/cahce 目录,但是,一般一个系统升级包有70M,一般机器不能保证有那么大的空间,我们只好把文件放在 SD card里,修改installPackage 函数,让它支持 sdcard 目录:

// from froyo, /sdcard ==> /mnt/sdcard
} else if (filename.startsWith("/mnt/sdcard/")) {
    filename = "SDCARD:" + filename.substring(12);

更新: 2011/7/23

一些网友遇到这样的 error:

FileNotFoundException: /cache/recovery/command (Permission denied)

记得在AndroidManifest.xml加上权限

<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.REBOOT" />

进阶:C2DM

使用 c2dm,给用户发push 通知消息,在状态栏提示有新版本可以更新啦。这部分的代码,可以参考大名鼎鼎的 CyanogenMod 的做法 CMUpdateNotify

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