嗨,专家/专家黑客,
我正在尝试在android上实现Google Play应用程序静默安装功能(类似于appbrain快速网络安装程序)。
到目前为止,我能够实现以下目标:
-
找到一种检索Google Play Auth Token的方法(从而允许我的应用程序在手机上与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")
-
了解如何检索手机的Android Id(我认为这个Id应该在向GPlay服务器或Android手机上的GPlay/自动售货应用程序发送appInstall请求时使用)
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");
-
找出要发送到Google Play服务器或手机上的Gplay/自动售货应用程序的协议缓冲区请求以启动静默应用程序下载&安装过程。
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.我甚至使用了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的示例数据如下:
- Android_ID:
3aof901831a0f402
- Google Play AuthToken:
DQAAAMgAAACpOyPf6apRbb0i4qhTVaf0yYoikTAb4TYlHCRLrW 4mu5f14j-H35KGmO9QKUDYCfj3-b-QIH5chfXT3bS02Uxljg7vYt4I-kgXLEJwPcJjj9cJ9fYPOh1c2FonnywFXXxXw6cqs5sVnJEt 5zW2ditoB5VeeX9Zfodj9dXKobObi50-XnHoGfWi2b64Uf3EHGdQTsDCMzfZrE4mb22fr9LCW1oZG5tkzw S4Kh PBHWMN2fO7w-1IZ4UK5LOI80vPBLjxBaavKAXHoVUHSNV
- 在Gplay应用程序静默安装期间,我还使用我的根galaxy nexus手机进行了一些嗅探,只发现了两个HTTP GET请求
我尝试复制使用Shark for root捕获的两个Http GET请求(使用我的root android galaxy nexus手机),第一个请求只下载了市场文件本身(我可以将其保存到手机的SD卡中。但之后它必须像任何未知来源的应用程序一样安装),而第二个请求什么都不返回。
捕获的两个get请求如下所示:
获取请求一:
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=17214805622679635526rn Host: android.clients.google.comrn Connection: Keep-Alivern User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)rn
获取请求二:
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=17214805622679635526rn Host: o-o.preferred.slt-cmb2.v12.lscache4.c.android.clients.google.comrn Connection: Keep-Alivern User-Agent: AndroidDownloadManager/4.1.1 (Linux; U; Android 4.1.1; Galaxy Nexus Build/JRO03C)rn
我已经研究了大约两周了,但我仍然找不到以下内容:
AppBrain快速Web安装程序是否使用协议缓冲区来调用手机或Gplay服务器上的Gplay(自动售货应用程序)?。如果是,上述协议缓冲区请求格式是否正确??。
如果Above Protocol Buffer Request格式正确,那么我应该将协议缓冲区请求发送到电话或Gplay服务器中的何处,以调用静默应用程序下载和安装过程?。
我也有一个C2DM(现在的GCM)服务器和客户端设置围绕这个任务。有人能给我指明正确的方向吗?或者给我任何解决这个问题的线索吗?。非常感谢您的帮助。
只有Google Play才能在Google Experience设备上进行静默安装。一般来说,只有预装在硬件上的商店才能实现这一点,因为它们需要使用操作系统的签名密钥。
这是出于安全考虑。用户需要能够接受新安装的权限。操作系统无法验证非官方商店是否正确地做到了这一点。
第三方应用程序必须使用PackageManager安装新应用程序,这将代表您显示权限,并需要明确的用户批准。
试图绕过这一点可能属于Google Play DDA的"禁止行为"条款,这将使您的开发者帐户面临被暂停的风险。不要这样做。
有几个操作是O.S.不允许任何人执行的,但它是受信任的应用程序。
使用平台密钥签名的应用程序受到O.S.的信任,因此这些应用程序可以在手机上做更多的事情,比如静默安装。我倾向于看到一个平台级应用程序比拥有根功能更强大,因为它让你更容易访问意图和android API。
你不需要探查Google Play从HTTP服务器发送/接收的消息。。。您需要使用平台密钥对应用程序进行签名。问题是,每个运营商/制造商/手机/版本可能都有不同的平台密钥。。。因此,要实现这一点,您需要为每个特定设备构建多个版本的应用程序。。。
一些运营商使用相同的密钥为同一制造商的所有手机签名,但另一些运营商则为每部手机使用不同的密钥。
您将不得不付出巨大的努力,并与运营商协商,以允许此功能,或者依赖ROOT用户。或者只需发布用测试密钥签名的应用程序(android SDK附带的应用程序),它将适用于所有拥有带有测试密钥的自定义rom的用户。