gpt4 book ai didi

android - Google Fit API 在内部测试中不起作用

转载 作者:行者123 更新时间:2023-12-04 23:59:28 25 4
gpt4 key购买 nike

我正在使用 Google Fit API 为 kotlin 应用程序获取健身数据。但 API 在 Google Play Developer Console 的内部测试中不起作用。

连接USB线直接安装APK会成功,所以我认为Google API设置(Sha1指纹等)是正确的。

API链接部分,the official github code按原样使用。你有关于我的错误的任何信息吗?


/**
* This enum is used to define actions that can be performed after a successful sign in to Fit.
* One of these values is passed to the Fit sign-in, and returned in a successful callback, allowing
* subsequent execution of the desired action.
*/
enum class FitActionRequestCode {
SUBSCRIBE,
READ_DATA
}

/**
* This sample demonstrates combining the Recording API and History API of the Google Fit platform
* to record steps, and display the daily current step count. It also demonstrates how to
* authenticate a user with Google Play Services.
*/
class MainActivity : AppCompatActivity() {
private val fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.addDataType(DataType.TYPE_STEP_COUNT_DELTA)
.build()

private val runningQOrLater =
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// This method sets up our custom logger, which will print all log messages to the device
// screen, as well as to adb logcat.
initializeLogging()

checkPermissionsAndRun(FitActionRequestCode.SUBSCRIBE)
}

private fun checkPermissionsAndRun(fitActionRequestCode: FitActionRequestCode) {
if (permissionApproved()) {
fitSignIn(fitActionRequestCode)
} else {
requestRuntimePermissions(fitActionRequestCode)
}
}

/**
* Checks that the user is signed in, and if so, executes the specified function. If the user is
* not signed in, initiates the sign in flow, specifying the post-sign in function to execute.
*
* @param requestCode The request code corresponding to the action to perform after sign in.
*/
private fun fitSignIn(requestCode: FitActionRequestCode) {
if (oAuthPermissionsApproved()) {
performActionForRequestCode(requestCode)
} else {
requestCode.let {
GoogleSignIn.requestPermissions(
this,
requestCode.ordinal,
getGoogleAccount(), fitnessOptions
)
}
}
}


/**
* Runs the desired method, based on the specified request code. The request code is typically
* passed to the Fit sign-in flow, and returned with the success callback. This allows the
* caller to specify which method, post-sign-in, should be called.
*
* @param requestCode The code corresponding to the action to perform.
*/
private fun performActionForRequestCode(requestCode: FitActionRequestCode) = when (requestCode) {
FitActionRequestCode.READ_DATA -> readData()
FitActionRequestCode.SUBSCRIBE -> subscribe()
}

var gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build()

private fun oAuthPermissionsApproved() = GoogleSignIn.hasPermissions(
getGoogleAccount(),
fitnessOptions
)

/**
* Gets a Google account for use in creating the Fitness client. This is achieved by either
* using the last signed-in account, or if necessary, prompting the user to sign in.
* `getAccountForExtension` is recommended over `getLastSignedInAccount` as the latter can
* return `null` if there has been no sign in before.
*/
private fun getGoogleAccount() = GoogleSignIn.getAccountForExtension(this, fitnessOptions)


/**
* Handles the callback from the OAuth sign in flow, executing the post sign in function
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)

when (resultCode) {
RESULT_OK -> {
val postSignInAction = FitActionRequestCode.values()[requestCode]
postSignInAction.let {
performActionForRequestCode(postSignInAction)
}
}
else -> oAuthErrorMsg(requestCode, resultCode)
}
}

private fun oAuthErrorMsg(requestCode: Int, resultCode: Int) {
val message = """
There was an error signing into Fit. Check the troubleshooting section of the README
for potential issues.
Request code was: $requestCode
Result code was: $resultCode
""".trimIndent()
Log.e(TAG, message)
}



/** Records step data by requesting a subscription to background step data. */
private fun subscribe() {
// To create a subscription, invoke the Recording API. As soon as the subscription is
// active, fitness data will start recording.
Fitness.getRecordingClient(this, getGoogleAccount())
.subscribe(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.i(TAG, "Successfully subscribed!")
} else {
Log.w(TAG, "There was a problem subscribing.", task.exception)
}
}
}

/**
* Reads the current daily step total, computed from midnight of the current day on the device's
* current timezone.
*/
private fun readData() {
Fitness.getHistoryClient(this, getGoogleAccount())
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener { dataSet ->
val total = when {
dataSet.isEmpty -> 0
else -> dataSet.dataPoints.first().getValue(Field.FIELD_STEPS).asInt()
}
Log.i(TAG, "Total steps: $total")
}
.addOnFailureListener { e ->
Log.w(TAG, "There was a problem getting the step count.", e)
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the main; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == R.id.action_read_data) {
fitSignIn(FitActionRequestCode.READ_DATA)
return true
}
return super.onOptionsItemSelected(item)
}

/** Initializes a custom log class that outputs both to in-app targets and logcat. */
private fun initializeLogging() {
// Wraps Android's native log framework.
val logWrapper = LogWrapper()
// Using Log, front-end to the logging chain, emulates android.util.log method signatures.
Log.setLogNode(logWrapper)
// Filter strips out everything except the message text.
val msgFilter = MessageOnlyLogFilter()
logWrapper.next = msgFilter
// On screen logging via a customized TextView.
val logView = findViewById<View>(R.id.sample_logview) as LogView
TextViewCompat.setTextAppearance(logView, R.style.Log)
logView.setBackgroundColor(Color.WHITE)
msgFilter.next = logView
Log.i(TAG, "Ready")
}

private fun permissionApproved(): Boolean {
val approved = if (runningQOrLater) {
PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACTIVITY_RECOGNITION
)
} else {
true
}
return approved
}

private fun requestRuntimePermissions(requestCode: FitActionRequestCode) {
val shouldProvideRationale =
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACTIVITY_RECOGNITION
)

// Provide an additional rationale to the user. This would happen if the user denied the
// request previously, but didn't check the "Don't ask again" checkbox.
requestCode.let {
if (shouldProvideRationale) {
Log.i(TAG, "Displaying permission rationale to provide additional context.")
Snackbar.make(
findViewById(R.id.main_activity_view),
R.string.permission_rationale,
Snackbar.LENGTH_INDEFINITE
)
.setAction(R.string.ok) {
// Request permission
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACTIVITY_RECOGNITION),
requestCode.ordinal
)
}
.show()
} else {
Log.i(TAG, "Requesting permission")
// Request permission. It's possible this can be auto answered if device policy
// sets the permission in a given state or the user denied the permission
// previously and checked "Never ask again".
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACTIVITY_RECOGNITION),
requestCode.ordinal
)
}
}
}

override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>,
grantResults: IntArray
) {
when {
grantResults.isEmpty() -> {
// If user interaction was interrupted, the permission request
// is cancelled and you receive empty arrays.
Log.i(TAG, "User interaction was cancelled.")
}
grantResults[0] == PackageManager.PERMISSION_GRANTED -> {
// Permission was granted.
val fitActionRequestCode = FitActionRequestCode.values()[requestCode]
fitActionRequestCode.let {
fitSignIn(fitActionRequestCode)
}
}
else -> {
// Permission denied.

// In this Activity we've chosen to notify the user that they
// have rejected a core permission for the app since it makes the Activity useless.
// We're communicating this message in a Snackbar since this is a sample app, but
// core permissions would typically be best requested during a welcome-screen flow.

// Additionally, it is important to remember that a permission might have been
// rejected without asking the user for permission (device policy or "Never ask
// again" prompts). Therefore, a user interface affordance is typically implemented
// when permissions are denied. Otherwise, your app could appear unresponsive to
// touches or interactions which have required permissions.

}
}
}
}```


[1]: /image/UpQLO.png

最佳答案

我们遇到了完全相同的问题,但似乎没有任何记录。即使这个问题已经提出 1 年多了,我仍然认为能得到它的回答是件好事。

当您上传 APK 进行内部测试时,它不会使用您的证书进行签名,而是使用 Google 颁发的证书进行签名。因此,为健身 API 配置的 SHA1 指纹不匹配。

要解决这个问题,您要做的是转到开发人员控制台> 内部测试> 版本详细信息> 下载并从那里下载 apk。获得 apk 后,使用

直接从中获取 sha-1 指纹
keytool -printcert -jarfile fileName.apk 

这将打印证书的详细信息,包括 SHA-1 指纹。为健身 oauth 证书配置该指纹,它将起作用!

进入测试版/生产版时记得将其更改为正确的指纹

很高兴为此提供特写

关于android - Google Fit API 在内部测试中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66330616/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com