Pages:  1 2 3 Market – lytsing's Blog

Tag: 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