您能否将 link 传递给更新可用性检查器以检查应用内更新功能是否正常运行?
Can you pass a link to the update availability checker to check if the in-app update function is working well?
我正在尝试在我刚刚在 Android Studio 上创建的用于测试的新应用程序上实施应用程序内更新。该应用程序只是一个“hello world”,但我实现了应用程序内更新检查器,正如它在这两页中所说的那样:
https://developer.android.com/guide/playcore/in-app-updates#kotlin
https://johncodeos.com/how-to-implement-in-app-updates-in-android-using-kotlin/
我们使用 Google 工作游戏(或“私人访问”游戏商店的实际名称)上传我们的业务应用程序,这些应用程序仅供员工在商店中使用。但即便如此,这个应用程序有一个link,与普通应用程序相同(https://play.google.com/store/apps/details?id=country.company.appname.something)
我想我了解它是如何工作的(或多或少),但在上传应用程序之前我想直接检查另一个应用程序 link 它是否有效。
我的问题是我是否可以使用我们其中一个应用程序的 link 之一(当然,在具有访问权限且已经配置的 phone 上)来检查更新可用性检查器工作,或者如果我只能在我正在做的新应用程序上使用它,因此我需要上传它并使用这个“测试”应用程序完成所有过程
我把代码放在这里,你可以看看。一些 snackbars 只是为了跟踪代码的流程。
UpdateInApp.kt class:
package com.example.demoinappupdates
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.InstallState
import com.google.android.play.core.install.InstallStateUpdatedListener
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.InstallStatus
import com.google.android.play.core.install.model.UpdateAvailability
class UpdateInApp(activity: Activity) : InstallStateUpdatedListener {
private var appUpdateManager: AppUpdateManager
private val MY_REQUEST_CODE = 500
private var parentActivity: Activity = activity
private var currentType = AppUpdateType.FLEXIBLE
init {
appUpdateManager = AppUpdateManagerFactory.create(parentActivity)
appUpdateManager.appUpdateInfo.addOnSuccessListener { info ->
// Check if update is available
Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"Aquí, en el init, entra",
Snackbar.LENGTH_INDEFINITE).show()
if (info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) { // UPDATE IS AVAILABLE
if (info.updatePriority() == 5) { // Priority: 5 (Immediate update flow)
if (info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
startUpdate(info, AppUpdateType.IMMEDIATE)
}
} else if (info.updatePriority() == 4) { // Priority: 4
val clientVersionStalenessDays = info.clientVersionStalenessDays()
if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 5 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// Trigger IMMEDIATE flow
startUpdate(info, AppUpdateType.IMMEDIATE)
} else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 3 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
}
} else if (info.updatePriority() == 3) { // Priority: 3
val clientVersionStalenessDays = info.clientVersionStalenessDays()
if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 30 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// Trigger IMMEDIATE flow
startUpdate(info, AppUpdateType.IMMEDIATE)
} else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 15 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
}
} else if (info.updatePriority() == 2) { // Priority: 2
val clientVersionStalenessDays = info.clientVersionStalenessDays()
if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 90 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// Trigger IMMEDIATE flow
startUpdate(info, AppUpdateType.IMMEDIATE)
} else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 30 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
}
} else if (info.updatePriority() == 1) { // Priority: 1
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
} else { // Priority: 0
// Do not show in-app update
}
} else {
// UPDATE IS NOT AVAILABLE
/* Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"El Snakcbar de prueba",
Snackbar.LENGTH_INDEFINITE).show() */
}
}
appUpdateManager.registerListener(this)
}
private fun startUpdate(info: AppUpdateInfo, type: Int) {
appUpdateManager.startUpdateFlowForResult(info, type, parentActivity, MY_REQUEST_CODE)
currentType = type
/* Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"startupdate entra",
Snackbar.LENGTH_INDEFINITE).show() */
}
fun onResume() {
Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"El Snakcbar de onresume",
Snackbar.LENGTH_INDEFINITE).setAction("ejej"){}.show()
appUpdateManager.appUpdateInfo.addOnSuccessListener { info ->
if (currentType == AppUpdateType.FLEXIBLE) {
// If the update is downloaded but not installed, notify the user to complete the update.
if (info.installStatus() == InstallStatus.DOWNLOADED)
flexibleUpdateDownloadCompleted()
} else if (currentType == AppUpdateType.IMMEDIATE) {
// for AppUpdateType.IMMEDIATE only, already executing updater
if (info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
startUpdate(info, AppUpdateType.IMMEDIATE)
}
}
}
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == MY_REQUEST_CODE) {
if (resultCode != AppCompatActivity.RESULT_OK) {
// If the update is cancelled or fails, you can request to start the update again.
Log.e("ERROR", "Update flow failed! Result code: $resultCode")
}
}
}
private fun flexibleUpdateDownloadCompleted() {
Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"An update has just been downloaded.",
Snackbar.LENGTH_INDEFINITE
).apply {
setAction("RESTART") { appUpdateManager.completeUpdate() }
setActionTextColor(Color.WHITE)
show()
}
}
fun onDestroy() {
appUpdateManager.unregisterListener(this)
}
override fun onStateUpdate(state: InstallState) {
if (state.installStatus() == InstallStatus.DOWNLOADED) {
flexibleUpdateDownloadCompleted()
}
}
}
MainActivity.kt class
package com.example.demoinappupdates
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
class MainActivity : AppCompatActivity() {
private lateinit var inAppUpdate: UpdateInApp
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
inAppUpdate = UpdateInApp(this)
/* Snackbar.make(
this.findViewById(R.id.activity_main_layout),
"El Snakcbar de prueba",
Snackbar.LENGTH_INDEFINITE).show()*/
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
inAppUpdate.onActivityResult(requestCode,resultCode, data)
}
override fun onResume() {
super.onResume()
inAppUpdate.onResume()
}
override fun onDestroy() {
super.onDestroy()
inAppUpdate.onDestroy()
}
}
我认为这是不可能的,因为我正在尝试做的事情只能通过更改 Bundle ID 来完成,这会导致一些兼容性问题,因为不止一个应用共享同一个应用。
郑重声明,当我提到 Bundle ID 时,我指的是 build.gradle 文件中的 applicationId
。
我正在尝试在我刚刚在 Android Studio 上创建的用于测试的新应用程序上实施应用程序内更新。该应用程序只是一个“hello world”,但我实现了应用程序内更新检查器,正如它在这两页中所说的那样:
https://developer.android.com/guide/playcore/in-app-updates#kotlin
https://johncodeos.com/how-to-implement-in-app-updates-in-android-using-kotlin/
我们使用 Google 工作游戏(或“私人访问”游戏商店的实际名称)上传我们的业务应用程序,这些应用程序仅供员工在商店中使用。但即便如此,这个应用程序有一个link,与普通应用程序相同(https://play.google.com/store/apps/details?id=country.company.appname.something)
我想我了解它是如何工作的(或多或少),但在上传应用程序之前我想直接检查另一个应用程序 link 它是否有效。
我的问题是我是否可以使用我们其中一个应用程序的 link 之一(当然,在具有访问权限且已经配置的 phone 上)来检查更新可用性检查器工作,或者如果我只能在我正在做的新应用程序上使用它,因此我需要上传它并使用这个“测试”应用程序完成所有过程
我把代码放在这里,你可以看看。一些 snackbars 只是为了跟踪代码的流程。
UpdateInApp.kt class:
package com.example.demoinappupdates
import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import com.google.android.play.core.appupdate.AppUpdateInfo
import com.google.android.play.core.appupdate.AppUpdateManager
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
import com.google.android.play.core.install.InstallState
import com.google.android.play.core.install.InstallStateUpdatedListener
import com.google.android.play.core.install.model.AppUpdateType
import com.google.android.play.core.install.model.InstallStatus
import com.google.android.play.core.install.model.UpdateAvailability
class UpdateInApp(activity: Activity) : InstallStateUpdatedListener {
private var appUpdateManager: AppUpdateManager
private val MY_REQUEST_CODE = 500
private var parentActivity: Activity = activity
private var currentType = AppUpdateType.FLEXIBLE
init {
appUpdateManager = AppUpdateManagerFactory.create(parentActivity)
appUpdateManager.appUpdateInfo.addOnSuccessListener { info ->
// Check if update is available
Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"Aquí, en el init, entra",
Snackbar.LENGTH_INDEFINITE).show()
if (info.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE) { // UPDATE IS AVAILABLE
if (info.updatePriority() == 5) { // Priority: 5 (Immediate update flow)
if (info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
startUpdate(info, AppUpdateType.IMMEDIATE)
}
} else if (info.updatePriority() == 4) { // Priority: 4
val clientVersionStalenessDays = info.clientVersionStalenessDays()
if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 5 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// Trigger IMMEDIATE flow
startUpdate(info, AppUpdateType.IMMEDIATE)
} else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 3 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
}
} else if (info.updatePriority() == 3) { // Priority: 3
val clientVersionStalenessDays = info.clientVersionStalenessDays()
if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 30 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// Trigger IMMEDIATE flow
startUpdate(info, AppUpdateType.IMMEDIATE)
} else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 15 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
}
} else if (info.updatePriority() == 2) { // Priority: 2
val clientVersionStalenessDays = info.clientVersionStalenessDays()
if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 90 && info.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) {
// Trigger IMMEDIATE flow
startUpdate(info, AppUpdateType.IMMEDIATE)
} else if (clientVersionStalenessDays != null && clientVersionStalenessDays >= 30 && info.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
}
} else if (info.updatePriority() == 1) { // Priority: 1
// Trigger FLEXIBLE flow
startUpdate(info, AppUpdateType.FLEXIBLE)
} else { // Priority: 0
// Do not show in-app update
}
} else {
// UPDATE IS NOT AVAILABLE
/* Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"El Snakcbar de prueba",
Snackbar.LENGTH_INDEFINITE).show() */
}
}
appUpdateManager.registerListener(this)
}
private fun startUpdate(info: AppUpdateInfo, type: Int) {
appUpdateManager.startUpdateFlowForResult(info, type, parentActivity, MY_REQUEST_CODE)
currentType = type
/* Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"startupdate entra",
Snackbar.LENGTH_INDEFINITE).show() */
}
fun onResume() {
Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"El Snakcbar de onresume",
Snackbar.LENGTH_INDEFINITE).setAction("ejej"){}.show()
appUpdateManager.appUpdateInfo.addOnSuccessListener { info ->
if (currentType == AppUpdateType.FLEXIBLE) {
// If the update is downloaded but not installed, notify the user to complete the update.
if (info.installStatus() == InstallStatus.DOWNLOADED)
flexibleUpdateDownloadCompleted()
} else if (currentType == AppUpdateType.IMMEDIATE) {
// for AppUpdateType.IMMEDIATE only, already executing updater
if (info.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) {
startUpdate(info, AppUpdateType.IMMEDIATE)
}
}
}
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == MY_REQUEST_CODE) {
if (resultCode != AppCompatActivity.RESULT_OK) {
// If the update is cancelled or fails, you can request to start the update again.
Log.e("ERROR", "Update flow failed! Result code: $resultCode")
}
}
}
private fun flexibleUpdateDownloadCompleted() {
Snackbar.make(
parentActivity.findViewById(R.id.activity_main_layout),
"An update has just been downloaded.",
Snackbar.LENGTH_INDEFINITE
).apply {
setAction("RESTART") { appUpdateManager.completeUpdate() }
setActionTextColor(Color.WHITE)
show()
}
}
fun onDestroy() {
appUpdateManager.unregisterListener(this)
}
override fun onStateUpdate(state: InstallState) {
if (state.installStatus() == InstallStatus.DOWNLOADED) {
flexibleUpdateDownloadCompleted()
}
}
}
MainActivity.kt class
package com.example.demoinappupdates
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
class MainActivity : AppCompatActivity() {
private lateinit var inAppUpdate: UpdateInApp
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
inAppUpdate = UpdateInApp(this)
/* Snackbar.make(
this.findViewById(R.id.activity_main_layout),
"El Snakcbar de prueba",
Snackbar.LENGTH_INDEFINITE).show()*/
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
inAppUpdate.onActivityResult(requestCode,resultCode, data)
}
override fun onResume() {
super.onResume()
inAppUpdate.onResume()
}
override fun onDestroy() {
super.onDestroy()
inAppUpdate.onDestroy()
}
}
我认为这是不可能的,因为我正在尝试做的事情只能通过更改 Bundle ID 来完成,这会导致一些兼容性问题,因为不止一个应用共享同一个应用。
郑重声明,当我提到 Bundle ID 时,我指的是 build.gradle 文件中的 applicationId
。