使用 AuroraStore 代码,它如何获取“库”(已安装应用程序的历史记录),以及如何获取它们的安装时间?

Posted

技术标签:

【中文标题】使用 AuroraStore 代码,它如何获取“库”(已安装应用程序的历史记录),以及如何获取它们的安装时间?【英文标题】:Using AuroraStore code, how does it get the "library" (history of installed apps), and how to get the time they were installed? 【发布时间】:2021-06-30 19:28:37 【问题描述】:

背景

过去,我发现了一个名为“Purchased apps”的特殊应用程序,它以某种方式获取您购买的应用程序的列表。没有看到任何 API,我 asked how does it do it(遗憾的是仍然找不到明确的答案和 POC 来证明它)。

问题

时间过去了,我注意到实际上有一个名为“Aurora Store”(存储库here)的开源应用程序可以获取与 Play 商店一样多的信息。截图:

问题是,我在试图弄清楚如何正确使用其代码时遇到了问题,奇怪的是这些应用程序从不同的来源获取信息。

我尝试过的

因此,看到它可以让您登录 Google,然后获取“库”信息(已安装应用程序的历史记录),我决定试一试(Github 上的完整示例,here):

MainActivity.kt

class MainActivity : AppCompatActivity() 
    private lateinit var webView: WebView
    private val cookieManager = CookieManager.getInstance()

    @SuppressLint("SetjavascriptEnabled")
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        val cachedEmail = defaultSharedPreferences.getString("email", null)
        val cachedAasToken = defaultSharedPreferences.getString("aasToken", null)
        if (cachedEmail != null && cachedAasToken != null) 
            onGotAasToken(applicationContext, cachedEmail, cachedAasToken)
         else 
            webView = findViewById(R.id.webView)
            cookieManager.removeAllCookies(null)
            cookieManager.acceptThirdPartyCookies(webView)
            cookieManager.setAcceptThirdPartyCookies(webView, true)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
                webView.settings.safeBrowsingEnabled = false
            
            webView.webViewClient = object : WebViewClient() 
                override fun onPageFinished(view: WebView, url: String) 
                    val cookies = CookieManager.getInstance().getCookie(url)
                    val cookieMap: MutableMap<String, String> = AC2DMUtil.parseCookieString(cookies)
                    val oauthToken: String? = cookieMap[AUTH_TOKEN]
                    oauthToken?.let 
                        webView.evaluateJavascript("(function()  return document.getElementById('profileIdentifier').innerhtml; )();") 
                            val email = it.replace("\"".toRegex(), "")
                            Log.d("AppLog", "got email?$email.isNotBlank() got oauthToken?$oauthToken.isNotBlank()")
                            buildAuthData(applicationContext, email, oauthToken)
                        
                     ?: Log.d("AppLog", "could not get oauthToken")
                
            
            webView.settings.apply 
                allowContentAccess = true
                databaseEnabled = true
                domStorageEnabled = true
                javaScriptEnabled = true
                cacheMode = WebSettings.LOAD_DEFAULT
            
            webView.loadUrl(EMBEDDED_SETUP_URL)
        
    

    companion object 
        const val EMBEDDED_SETUP_URL =
                "https://accounts.google.com/EmbeddedSetup/identifier?flowName=EmbeddedSetupandroid"
        const val AUTH_TOKEN = "oauth_token"

        private fun buildAuthData(context: Context, email: String, oauthToken: String?) 
            thread 
                try 
                    val aC2DMResponse: Map<String, String> =
                            AC2DMTask().getAC2DMResponse(email, oauthToken)
                    val aasToken = aC2DMResponse["Token"]!!
                    PreferenceManager.getDefaultSharedPreferences(context)
                            .edit().putString("email", email).putString("aasToken", aasToken).apply()
                    onGotAasToken(context, email, aasToken)
                 catch (e: Exception) 
                    e.printStackTrace()
                
            
        

        private fun onGotAasToken(context: Context, email: String, aasToken: String) 
            thread 
                val properties = NativeDeviceInfoProvider(context).getNativeDeviceProperties()
                val authData = AuthHelper.build(email, aasToken, properties)
                val purchaseHelper = PurchaseHelper(authData).using(HttpClient.getPreferredClient())
                var offset = 0
                Log.d("AppLog", "list of purchase history:")
                while (true) 
                    val purchaseHistory = purchaseHelper.getPurchaseHistory(offset)
                    if (purchaseHistory.isNullOrEmpty())
                        break
                    val size = purchaseHistory.size
                    offset += size
                    purchaseHistory.forEach 
                        Log.d("AppLog", "$it.packageName $it.displayName")
                    
                
                Log.d("AppLog", "done")
            
        
    

它似乎得到了它需要的令牌(和电子邮件),但遗憾的是它似乎得到了 2 个应用程序,仅此而已,然后当我尝试获取下一个应用程序时,我得到了相同的 2 个应用程序,多了两次,意思是:

list of purchase history:
dev.southpaw.dungeon Dungeon Live Wallpaper
com.crydata.mylivewallpaper Hex AMOLED Neon Live Wallpaper 2021
dev.southpaw.dungeon Dungeon Live Wallpaper
com.crydata.mylivewallpaper Hex AMOLED Neon Live Wallpaper 2021
dev.southpaw.dungeon Dungeon Live Wallpaper
com.crydata.mylivewallpaper Hex AMOLED Neon Live Wallpaper 2021

在它最后一次尝试获取下一个应用程序块时,它会崩溃并出现以下异常:

FATAL EXCEPTION: Thread-4
    Process: com.lb.getplaystoreinstalledappshistory, PID: 6149
    Server(code=400, reason=Bad Request)
        at com.aurora.gplayapi.helpers.AppDetailsHelper.getAppByPackageName(AppDetailsHelper.kt:115)
        at com.aurora.gplayapi.helpers.PurchaseHelper.getPurchaseHistory(PurchaseHelper.kt:63)
        at com.lb.getplaystoreinstalledappshistory.MainActivity$Companion$onGotAasToken$1.invoke(MainActivity.kt:96)
        at com.lb.getplaystoreinstalledappshistory.MainActivity$Companion$onGotAasToken$1.invoke(MainActivity.kt:68)
        at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

问题

    我尝试获取应用程序列表的方式有什么问题?我怎样才能把它按安装时间排序? 有什么方法可以获取它们的安装时间(或任何有关它的线索)?不知何故,“Purchased apps”应用程序得到了时间。当然,它仅适用于购买的应用程序,但仍然... “Purchased apps”应用甚至可以更好地登录,因为它不需要用户名和密码。相反,它提供了一个对话框来选择帐户。假设我做对了,是否可以使用相同的登录对话框获取相同的信息?

【问题讨论】:

【参考方案1】:

不确定此信息是否对远程有用,但不妨提一下...

我不小心从 2015 年开始反编译了他们存档的 APK,当时他们没有最小化他们的代码,至少当时他们使用的是 JSoup HTML 解析器蜘蛛。可能它们仍然存在,这可能是 Google 不允许的,而且极易维护。

【讨论】:

这是解析本身(这也很重要),但是如何获取登录阶段,然后这里的“html”参数?您是否为此尝试过 POC? 我在哪里可以得到你反编译的这个未最小化的 APK?我想看看它,也许从中学到一些东西。 @user14678216 也许来自这里:apkpure.com/purchased-apps-reinstall-your-paid-apps-games/…

以上是关于使用 AuroraStore 代码,它如何获取“库”(已安装应用程序的历史记录),以及如何获取它们的安装时间?的主要内容,如果未能解决你的问题,请参考以下文章

当 iOS 应用程序链接到静态库时,如何获取丢弃的符号列表?

在 Scala 中使用 Slick 库获取自动增量值

将 subversion 存储库编号获取到代码中

如何在c中获取屏幕截图[关闭]

如何获取设计库,以便它可以像PHP库一样进行修改

如何使用网络库从函数外部获取更新值