Tag Archives: Market

电子市场 Google 软件精选管理器

很多手拿Android手机的人不明白这个软件是干啥的,其实,就是Market Updater,我也不明白为什么中文会叫成这样。在Broncho的时候,反编译过这个MarketUpdater.apk,以后我也不干这坏事了,把成果贴出来吧: https://github.com/lytsing/MarketUpdater

就30多行代码,它干的事情很少,监听 “com.android.vending.UPDATE_MARKET”, intent把下载后的apk url传过来,调用静默安装apk的方法。

那么,谁发 “com.android.vending.UPDATE_MARKET” 这个intent action? 当然是电子市场了:

<receiver 
    android:name=".InitializeMarketAction$DownloadBroadcastReceiver"
    android:permission="android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"
    android:exported="true">
<receiver />

大致的InitializeMarketAction.java代码:

// From Vending.apk
package com.android.vending;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;

public class InitializeMarketAction {

    public class DownloadBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            final Uri contentUri = intent.getData();
            int status = DownloadManagerUtil.getStatus(context, contentUri);
            if (DownloadManagerUtil.isStatusAuthFailure(status)) {
                new Thread() {
                    public void run() {
                        VendingApplication.getVendingApplication().invalidateAuthTokenBlocking(
                                AuthService.ANDROID_SECURE);
                    }
                }.start();
                
            } else if (DownloadManagerUtil.isStatusSuccess(status)) {
                setBackgroundRunnable(new Runnable() {

                    @Override
                    public void run() {
                        ServiceLocator.getCacheManager().clear();
                        Context app = VendingApplication.getVendingApplication();
                        app.sendBroadcast(new Intent("com.android.vending.UPDATE_MARKET",
                                contentUri));
                    }
                    
                });
            }
            
        }
    }
}

那电子市场是如何自我更新的呢? 这个问题问得好。待续。。。

解决电子市场 3.13版本 “您的设备与此商品不兼容”的问题

Android market: Your device is not compatible with this item


用 apktool 1.4.1 反编译Vending.apk 3.1.3版本,遇到错误,无法插入调试信息再打包重新安装。搜索反编译后的文件查找信息:

您的设备与此商品不兼容。

smali/com/android/vending/R$string.smali:.field public static final availability_restriction_hardware:I = 0x7f080191

deli@deli-laptop:~/Desktop/a/Vending$ grep 0x7f080191 * -r
smali/com/google/android/finsky/activities/DetailsAvailabilityRestrictionViewBinder.smali: const v3, 0x7f080191

猜出大概代码:

public bind(View view, Document document, int iconWidth, int iconRightMargin, DfeToc toc) {

	TextView reason = view.findViewById(R.id.restriction_reason);
	int restriction = document.getAvailabilityRestriction();

	switch (restriction) {
	case 4:
		reason.setText(R.string.availability_restriction_hardware);
		break;
	}
}

public int getAvailabilityRestriction() {
	boolean hasAvailability = mFinskyDoc.hasAvailability();
	if (hasAvailability) {
		int restriction = mFinskyDoc.getAvailability().getRestriction();
		reutrn restriction;
	}

	return -1;
}

restriction的值是通过 setRestriction 设置,读取protobuf数据,也没弄清楚,因为无法插入调试信息。发现3.1.3版本比以前版本复杂多了。

最后发现

  deli@deli-laptop:~$ diff build.prop build.prop~
  31c31
  < ro.build.fingerprint=N708_800_600/broncho_N708/N708_800_600/:2.2/FRF91/user.N708_800_600.20110917.133140:user/test-keys
  ---
  > ro.build.fingerprint=N708/broncho_N708/N708_800_600/:2.2/FRF91/user.N708_800_600.20110917.133140:user/test-keys

ro.build.fingerprint=N708,N708这个是我们的项目名,临时修改编译脚本成N708_800_600,出现下划线,导致被google过滤掉了。搞第三方ROM的,注意了,别随意修改系统参数,除非你真的明白你在干啥东东。

Android Market 最新版本 2.3.6

亮点: 在设置多一下个选项,如图:

下载地址: http://lytsing.org/downloads/Vending-2.3.6-enable-paid.apk

如包名所示,我修改了几行代码,使它可以查看付费软件。

安装后,设置 – 应用程序 – 管理应用程序 – 全部 – 电子市场 – 清除缓存

适用范围:

Android 2.2,刷过 使用 test-key 签名的 第三方 rom ,比如大名鼎鼎的 CM.否则遇到下面的FC:

I/ActivityManager( 116): Process com.android.protips (pid 537) has died and restarted (pid 0).
E/DatabaseUtils( 364): Writing exception to parcel
E/DatabaseUtils( 364): java.lang.SecurityException: Permission Denial: writing com.google.android.gsf.settings.GoogleSettingsPrS
E/DatabaseUtils( 364): at android.content.ContentProvider
$Transport.enforceWritePermission(ContentProvider.java:325)
E/DatabaseUtils( 364): at android.content.ContentProvider $Transport.insert(ContentProvider.java:173)
E/DatabaseUtils( 364): at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:146)
E/DatabaseUtils( 364): at android.os.Binder.execTransact(Binder.java:288)
E/DatabaseUtils( 364): at dalvik.system.NativeStart.run(Native
Method)
W/dalvikvm( 353): threadid=33: thread exiting with uncaught exception (group=0x4001d7c8)
E/AndroidRuntime( 353): FATAL EXCEPTION: work-service-handler-thread
E/AndroidRuntime( 353): java.lang.SecurityException: Permission Denial: writing com.google.android.gsf.settings.GoogleSettingsPS
E/AndroidRuntime( 353): at android.os.Parcel.readException(Parcel.java:1247)
E/AndroidRuntime( 353): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:160)
E/AndroidRuntime( 353): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:114)

可能会出现的问题:
(一)下载软件,一直卡在“Download paused”/“下载暂停”。

解决方法:
1. 把SDCARD卸载。
2. 删除 “/mnt/secure/asec/smdl2tmp1.asec” 或者 sd卡上的空目录 “.android_secure”.

Android Market 架构设计解析

1. 没有源代码。
2. 通过反编译工具(apktool/dex2jar),察看网络数据包工具(tcpdump/wireshark)研究,不能保证100%的正确,但整体的思路还是能看出来的。国内也有很多第三方电子市场,但形像神不像。

Android Market Overview : Client & Server

大致的代码目录(android 1.5版本, 后续版本比较复杂):

Vending
|-- AndroidManifest
|-- res
|   |-- drawable
|   |-- drawable-finger
|   |-- layout
|   |-- menu
|   |-- values
|   `-- xml
`-- src
    `-- com
        |-- android
        |   `-- vending
        |       |-- SuggestionsProvider.java
        |       |-- ...
        |       |-- VendingNotificationManager.java
        |       |-- adapters
        |       |   |-- AggregatedAdapter.java
        |       |   `-- SectionAdapter.java
        |       |-- api
        |       |   |-- ApiException.java
        |       |   |-- ...
        |       |   `-- UninstallReasonService.java
        |       |-- cache
        |       |   |-- CacheManager.java
        |       |   |-- CacheManagerImpl.java
        |       |   `-- Cacheable.java
        |       |-- controller
        |       |   |-- ActivityAccessor.java
        |       |   |-- ...
        |       |   `-- ResultsController.java
        |       |-- licensing
        |       |   |-- ILicenseResultListener.aidl
        |       |   |-- ILicensingService.aidl
        |       |   `-- LicensingService.java
        |       |-- model
        |       |   |-- Address.java
        |       |   |-- ...
        |       |   `-- UninstallReasonResponseProto.java
        |       `-- util
        |           |-- Base64.java
        |           |-- ...
        |           `-- Util.java
        `-- google
            `-- android
                |-- googleapps
                |-- googlelogin
                `-- providers

代码文件命名规则

每个Activity,以Activity为后缀,比如AssetCategoryBrowserActivity.java
api目录中,继承BaseService的类,以Service为后缀,比如AssetService.java
model目录中,提供Protobuf TAG的类,以Proto为后缀,比如UninstallReasonResponseProto.java

用到的设计模式

MVC, COR(Chain Of Responsibility), Observer(Notification机制), State ,Singleton,Abstact Factory等,看Android的源代码,这些都很常见。除此之外,对于Server/Client 网络系统,Service Locator, Request-Response,lazyload等设计方法也用到。

数据交换格式protobuf

Protocol Buffers in Android 稍有提到过,protobuf传输的是二进制,比Json、XML有速度上的优势和使用的方便,服务器端可以用C/C++,Java,python等实现。

API

http://code.google.com/p/android-market-api/
Android Market 的开源 API 项目,非官方提供的,基于Google Protocol Buffers 协议实现。

Cache 机制
Cache 可以保存在内存,也可以写入disk上。

/data/data/com.android.vending/cache # ls
AVMC_UAR{-5434199881535588028_}_____0_10_rei___
AVMC_UAR{8501175443043592143_}_____0_10_rei___
AVMC_UAR{}APPLICATION__APP_WALLPAPER_POPULAR_ALL_0_10____
AVMC_UAR{}APPLICATION__APP_WALLPAPER_POPULAR_ALL_10_10____
AVMC_UAR{}_____0_10__rvh__
AVMC_UCR-5434199881535588028_0_3_self_
AVMC_UCR8501175443043592143_0_3_self_
AVMC_UGIR_-2863385711196347958
AVMC_UGIR_-4594342797900232749
AVMC_UGIR_-5005302620309917353
AVMC_UGIR_-543419988153558802
......

AVMC_UGIR_-543419988153558802的格式是这样的:
“AVMC_” + “U”/”S” + “GIR_” + assetId

其他类似。

具体实现,可以参考libaddressinput 里的 Cache.java

本地数据库

/data/data/com.android.vending/databases/assets.db

把它 pull 出来,用 sqlite3 工具可以看到数据表。这个主要用来保存下载过的apk信息。

PUSH 通知

有软件更新时,就用push推送消息,com/google/android/server/checkin/CheckinService 收到消息后,给market发送一个 “com.android.vending.UPDATES_AVAILABLE” intent。push机制,android froyo之前,用的是XMPP协议,之后是c2dm。

支付系统

Google checkout, 没有用过。

还有很多很多细节的东西,不一一详述。总之,做这么一个平台,需要考虑的东西太多了,不是一个人可以搞出来的。

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

Pages: 1 2 3 Next