在Android上实施Google Play应用程序无提示安装功能

时间:2012-09-05 12:21:08

标签: android

嗨专家/专家黑客,

我正在尝试在Android上实施Google Play应用程序静默安装功能(类似于appbrain fast web installer)。

到目前为止,我能够实现以下目标:

  1. 找出一种检索Google Play验证令牌的方法(从而授予我的应用程序与电话上的Google Play应用程序通话的权限)。我已经列出了我在下面使用的代码:

        Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : START");
        AccountManager accountManager = AccountManager.get(getApplicationContext());
        Account[] accArr = accountManager.getAccountsByType("com.google");
    
        for (Account acc : accArr) {
            Log.i(TAG, "For Account Name : " + acc.name + " - "+ "Account Type : " + acc.type);
            accountManager.getAuthToken(acc, "googleplay", null, this,new AccountManagerCallback<Bundle>() {
    
                        public void run(
                                AccountManagerFuture<Bundle> paramAccountManagerFuture) {
                            try {
                                Bundle localBundle = (Bundle) paramAccountManagerFuture.getResult();
                                String authToken = localBundle.get("authtoken") + "";
    
                                Log.i(TAG, "Got AuthToken : " + authToken);
    
                            } catch (Exception ex) {
                                StackTraceElement[] starray = ex.getStackTrace();
                                StringBuffer bf = new StringBuffer();
                                bf.append("Error : " + ex.getMessage()).append("\n");
                                for (StackTraceElement ste : starray) {
                                    bf.append(ste.toString()).append("\n");
                                }
                                Log.e(TAG, bf.toString());
                            }
    
                        }
    
                    }, null);
        }
        Log.i(TAG,"Getting the Google Play Auth Token Using Account Manager : END")
    
  2. 了解如何检索手机的Android-Id(我认为应该在将appInstall请求发送到Android手机上的GPlay服务器或Gplay /自动售货应用程序时使用此ID)

      Log.i(TAG, "Getting the Android ID Of the Phone : START");
    
        Uri localUri = Uri.parse("content://com.google.android.gsf.gservices");
        ContentResolver localContentResolver = getContentResolver();
        String[] arrayOfString = new String[1];
        arrayOfString[0] = "android_id";
        Cursor localCursor = localContentResolver.query(localUri, null,null, arrayOfString, null);
        Log.i(TAG, "Column Count : " + localCursor.getColumnCount());
        if ((localCursor != null) && (localCursor.moveToFirst())) {
            String androidId = Long.toHexString(Long.parseLong(localCursor.getString(1)));
            Log.i(TAG, "Received Android ID : " + androidId);
    
            Log.i(TAG,"Other Value in Column : " + localCursor.getString(0));
        }
    
        Log.i(TAG,"Getting the Android ID of the Phone : END");
    
  3. 找出要发送到手机上的Google Play服务器或Gplay /自动售货应用程序的协议缓冲请求,以启动静默应用程序下载&amp;安装过程。

    message InstallRequest {
    optional string appId = 1;
    }
    message RequestContext {
    required string authSubToken = 1;
    required bool isSecure = 2;
    required int32 version = 3;
    required string androidId = 4;
    optional string deviceAndSdkVersion = 5;
    optional string userLanguage = 6;
    optional string userCountry = 7;
    optional string operatorAlpha = 8;
    optional string simOperatorAlpha = 9;
    optional string operatorNumeric = 10;
    optional string simOperatorNumeric = 11;
    
    }
    message Request {
    optional RequestContext context = 1;
    repeated group RequestGroup = 2 {
    optional InstallRequest installRequest = 10;
    }
    }
    
  4. 4.我甚至使用了protobuf编译器并生成了用于操作上述协议缓冲区请求的java类,并用一些示例数据填充了上述协议缓冲区字段。请参阅以下代码:

        public void buildAndSendSilentInstallProtoBuffMessage(String gplayAuthToken, String deviceAndroidId){
    
        try{
        /*
         * The Root Request Object Assumed to be Holding the Silent Install Request
         */
        Request.Builder request = Request.newBuilder(); 
    
        //Populating the ReequestContext Object
        RequestContext.Builder context = RequestContext.newBuilder();
    
        context.setAndroidId(deviceAndroidId);
        context.setAuthSubToken(gplayAuthToken);
    
        context.setIsSecure(true);
        context.setVersion(1002);
        context.setDeviceAndSdkVersion("dream:4");
        context.setUserLanguage("en");
        context.setUserCountry("us");
        context.setOperatorAlpha("Android");
        context.setOperatorNumeric("310260");
        context.setSimOperatorNumeric("310260");
    
        //Building the Install Request
        InstallRequest.Builder installRequest = InstallRequest.newBuilder();
        installRequest.setAppId("-2564446724934482383");
    
        //Setting the Install Request to the Request Group
        RequestGroup.Builder requestGroup = RequestGroup.newBuilder();
        requestGroup.setInstallRequest(installRequest);
    
        //Setting the Request Context to the Main Request Object
        request.setContext(context);
    
        //Setting the Request Group to the Request Object
                request.addRequestGroup(requestGroup);
    

    GPlay令牌的示例数据和Android Id如下:

    1. Android_ID:
    2. 3a0f901831a0f402

      1. Google Play AuthToken:
      2. DQAAAMgAAACpOyPf6apRbb0i4qhTVaf0yYoikTAb4TYlHCRLrW 4mu5f14j-H35KGmO9TQKUDYCfj3-B-QIH5chfXT3bS02Uxljg7vYt4I-kgXLEJwPcynjugDcJ9fYPOh1c2FnOnywFXXxXw6hcqs5sVnJEt 5zW2ditoB5VeeXG9Zfodj9dXKobObi50-XnHoGfWi2b64Uf3EHGdQTsDCMzfZrE4mb22fr9LCW1oZG5tkzw S4KhPBHWMN2fO7w-1IZ4UK5LOI80vPBLjxBaavKAXHoVUHSNV

        1. 在Gplay应用程序静默安装期间,我还使用我的root galaxy nexus手机进行了一些嗅探,发现只有两个HTTP GET请求。
        2. 我尝试再现使用Shark for root捕获的那两个Http GET请求(使用我的root android安卓nexus手机),第一个请求只下载市场文件本身(我能够保存到手机的SD卡)但是它必须像任何未知的源应用程序一样安装)而第二个请求什么都不返回。

          捕获的两个获取请求如下所示:

          1. 获得请求:

            21 0.827240 192.168.135.102 173.194.36.4 HTTP 535 GET /market/download/Download?                                                                     packageName=com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld&versionCode=1&token=AOTCm0QRnH3rmypWtCGoAL_SU1BSt311wpyz-_LZTodkUSAlc-             f5SrdMiz5WDRDUKMMm6S3plBI9Jbh1tukT1jyCYXLgP4QhVvZvn5JLtZQ&downloadId=-165214892049282883 HTTP/1.1
            
             Which has the following http headers :
            
            Cookie: MarketDA=17214805622679635526\r\n
            Host: android.clients.google.com\r\n
            Connection: Keep-Alive\r\n
            User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)\r\n
            
          2. 获取请求两个:

            44    6.595093    192.168.135.102    222.165.163.15    HTTP    608    GET /market/GetBinary/com.gau.go.launcherex.theme.appwidget.gopowermaster.futureworld/1?expire=1346838270&ipbits=0&ip=0.0.0.0&cp=SnpybWlzSFk6OTYzMzg0MTE2NzA1ODEwOTYxMjE&sparams=expire,ipbits,ip,q:,cp&signature=2C0778C4635F6F8AE1DA8479FB08DCB9BC04C2E9.60202D8D4D2FDDA70609A3862A25852F0BAA2766&key=am2 HTTP/1.1
            
            Which has the following http headers :
            
            Cookie: MarketDA=17214805622679635526\r\n
            Host: o-o.preferred.slt-cmb2.v12.lscache4.c.android.clients.google.com\r\n
            Connection: Keep-Alive\r\n
            User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus  Build/JRO03C)\r\n
            
          3. 我一直在研究这个问题大约两个星期,但我仍然找不到以下内容:

            1. AppBrain快速Web安装程序是否使用协议缓冲区来调用手机或Gplay服务器上的Gplay(自动售货应用程序)?如果是,那么上述协议缓冲区请求格式是否正确??

            2. 如果上面的协议缓冲区请求格式正确,那么我应该向Phone或Gplay服务器中的哪个位置发送协议缓冲区请求以调用静默应用程序下载和安装过程?

            3. 我也有一个C2DM(现在的GCM)服务器和客户端设置围绕这个任务。任何人都可以指出我正确的方向或给我任何解决这个问题的线索吗?非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

只有Google Play才能在Google Experience设备上进行静音安装。更一般地说,只有预装在硬件上的商店才能实现这一点,因为他们需要使用操作系统的签名密钥。

这是出于安全原因。用户需要能够接受新安装的权限。操作系统无法验证非官方商店是否已正确完成此操作。

第三方应用程序必须使用PackageManager安装新应用程序,这些应用程序将代表您显示权限并需要明确的用户批准。

试图规避这一点可能属于Google Play DDA的“禁止操作”条款,这会使您的开发者帐户面临暂停的风险。不要这样做。

答案 1 :(得分:1)

O.S.有几个动作。不会允许任何人,但它是可信任的应用程序。

使用平台密钥签名的应用程序受O.S.信任,因此这些应用程序可以使用手机执行更多操作,例如静默安装。我倾向于看到平台签名的应用程序比具有root功能更强大,因为它允许您更轻松地访问意图和android API。

您无需嗅探Google Play从HTTP服务器发送/接收的消息......您需要使用平台密钥对应用程序进行签名。问题是每个运营商/制造商/手机/版本都可能有不同的平台密钥...因此,要实现这一点,您需要为每个特定设备构建多个版本的应用程序......

有些运营商使用相同的密钥为同一制造商的所有手机签名,但其他运营商会为每部手机使用不同的密钥。

您必须付出巨大努力并与运营商协商以允许此功能,或依赖ROOT用户。或者只是发布使用测试密钥签名的应用程序(android SDK附带的应用程序),它将适用于所有拥有测试密钥的自定义rom的用户。