小编yoo*_*hok的帖子

如何在Android中测试应用内更新?

最近,谷歌在Google I / O 2019中引入了``应用内更新''。

所以我正在尝试使用它。

val appUpdateManager = AppUpdateManagerFactory.create(this)
val appUpdateInfo = appUpdateManager.appUpdateInfo
appUpdateInfo.addOnCompleteListener {
    val result = it.result
    if (result.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
            && result.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {

        info("should show update")
        appUpdateManager.startUpdateFlowForResult(
                        result,
                        AppUpdateType.FLEXIBLE,
                        this,
                        1)
    } else {
        info("This is already latest version: ${result.updateAvailability()}")
    }
}
Run Code Online (Sandbox Code Playgroud)

result.updateAvailability()总是如此UpdateAvailability.UPDATE_NOT_AVAILABLE

为此,我制作了一个带有先前版本代码的签名发行版APK。但这是行不通的。

根据开发人员主题演讲中的演示(16:40〜)

他正在用模拟器来做。看起来像调试模式。

我该怎么做?

android google-play in-app-update google-play-core

12
推荐指数
6
解决办法
1869
查看次数

如何获取未缓存在 android 线圈中的新图像?

我正在使用 Jetpack Compose 和 Coil ImageLoader 库开发一个 Android 应用程序。

它显示用户的个人资料图像。

我从 API 接收配置文件数据。GET: /users/{userId}

响应包含userIdprofileImgKey

对于用户头像,Backend提供了GET: /photo/{userId}API。

但问题是,如果某些用户更新他/她的个人资料图像,其他用户仍然看到以前的个人资料图像而不是新图像。

因为它是被Coil缓存的。

如果我关闭缓存选项,它可能会正常工作。但我不想这样做。我不想失去性能优势。

当用户更新其个人资料图像时,图像profileImgKey就会发生变化。所以我想用它作为缓存键。

但我不知道如何使用这个。

android android-jetpack-compose coil

7
推荐指数
1
解决办法
6370
查看次数

NestedScrollView 大小不适合 CollapsingToolbarLayout

我想在我的应用程序中应用 CollapsingToolbarLayout。

下面的 XML 工作正常。

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                    xmlns:ads="http://schemas.android.com/apk/res-auto"
                                    xmlns:app="http://schemas.android.com/apk/res-auto"
                                    xmlns:tools="http://schemas.android.com/tools"
                                    android:id="@+id/drawer_layout"
                                    android:layout_width="match_parent"
                                    android:layout_height="match_parent"
                                    tools:openDrawer="start">

<android.support.design.widget.CoordinatorLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.design.widget.TextInputLayout
                android:id="@+id/tilTitle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="24dp"
                android:layout_marginStart="56dp"
                android:layout_marginTop="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/Toolbar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

                <ViewSwitcher
                    android:id="@+id/switcherTitle"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:id="@+id/tvTitle"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:hint="@string/title"
                        android:textSize="36sp"/>

                    <EditText
                        android:id="@+id/etTitle"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:ems="10"
                        android:hint="@string/title"
                        android:inputType="textMultiLine"
                        android:textSize="36sp"/>
                </ViewSwitcher>
            </android.support.design.widget.TextInputLayout>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/Toolbar"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
            </android.support.v7.widget.Toolbar>
        </android.support.design.widget.CollapsingToolbarLayout>


    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <FrameLayout
            android:id="@+id/contentFrame"
            android:layout_width="match_parent" …
Run Code Online (Sandbox Code Playgroud)

android android-layout

5
推荐指数
1
解决办法
954
查看次数

Android:存储库模式创建对象的最佳解决方案是什么?

这个问题是关于OOP(类/接口)设计的。

我正在开发一个 android 库,而不是一个应用程序。该应用程序将使用该库。该库是按照Repository模式开发的。

1 个存储库和 2 个数据源(本地、远程)。

因为本地数据源使用“SharedPreference”,所以需要Context。

下面是我的存储库界面和实现。

interface MyRepository {

    fun create(String data)

    fun get(key: String): String
}

class MyRepositoryImpl(
        private val localDataSource: LocalDataSource,
        private val remoteDataSource: RemoteDataSource
): MyRepository {

    fun create(String data) {
        localDataSource.create(data);
        remoteDataSource.create(data);
    }

    fun get(key: String): String {
        // temp code
        return localDataSource.get(key)
    }

    companion object {

        private var instance: MyRepository? = null

        fun getInstance(context: Context): MyRepository {
            if (instance == null) {
                val localDataSource: LocalDataSource = LocalDataSourceImpl.getInstance(context)
                val remoteDataSource: RemoteDataSource = …
Run Code Online (Sandbox Code Playgroud)

oop singleton design-patterns repository-pattern kotlin

5
推荐指数
1
解决办法
5307
查看次数

如何使用 Vuetify 2.x 在表中的自定义默认行中使用 v-html?

我开始使用 Vuetify 2.x。

我有一个表格,一些列应该用 html 显示。

所以我使用了下面的代码:

        <v-data-table
          :headers="headers"
          :items="decorations"
          :items-per-page-options="[20]"
          class="elevation-1"
        >
          <template v-slot:items="props">
            <tr>
              <td class="text-sm-center">{{ props.item.name}}</td>
              <td><span v-html="props.item.desc"></span></td>
            </tr>
          </template>
        </v-data-table>
Run Code Online (Sandbox Code Playgroud)

但是从 Vuetify 2.0 开始,表已经改变了。

        <v-data-table
          :headers="headers"
          :items="decorations"
          :items-per-page-options="[20]"
          class="elevation-1"
        >
        </v-data-table>
Run Code Online (Sandbox Code Playgroud)

不再使用“模板”。所以我不知道如何在某些列中应用“v-html”。

javascript vue.js vue-component vuejs2 vuetify.js

5
推荐指数
1
解决办法
1993
查看次数

jetpack 撰写 LazyColumn 滚动不起作用

我正在使用 jetpack compose 开发一个 Android 聊天应用程序。

聊天消息使用 LazyColumn 显示。消息来自 WebSocket。

我想要开发的是:

  • 如果用户在新消息到来时看到最新消息,则 LazyColumn 应滚动到最新消息。
  • 如果当新消息到来时用户正在看到上一条消息(滚动到上方),则不应更改滚动位置。

为了做到这些,我发现listState.layoutInfo.visibleItemsInfo。如果listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == chatMessages.size - 1表示用户正在看到最新消息。(位于底部)

LazyColumn(
    state = listState
) {
    vm.scrollToBottom.value = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == chatMessages.size - 1
    Log.d("TEST", "[test] scrollToBottom: ${vm.scrollToBottom.value}")
    if (vm.scrollToBottom.value) {
        coroutineScope.launch {
            Log.d("TEST", "[test] scroll!")
            listState.animateScrollToItem(chatMessages.size)
        }
    }
    itemsIndexed(chatMessages) { _, chat ->
        when (chat.command) {
            Command.MESSAGE -> when (chat.userId) {
                myId -> MyChat(chat = chat)
                else -> OtherUserChat(chatMsg = chat)
            }
            Command.JOIN -> JoinLeaveMessage(
                chat …
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-compose

5
推荐指数
1
解决办法
3153
查看次数

Android - Firebase 身份验证失败

我正在开发一个简单的应用程序。我在以下文档中使用了 Firebase Auth。 https://firebase.google.com/docs/auth/android/firebaseui?authuser=0#top_of_page

在调试模式下,它工作正常。在发布模式下,我创建了一个Apk文件,然后直接安装,它也运行良好。

但是当我将它发布到 PlayStore 并下载它时,它失败了。

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == RC_SIGN_IN) {
        val response = IdpResponse.fromResultIntent(data)

        if (resultCode == Activity.RESULT_OK) {
            val user = FirebaseAuth.getInstance().currentUser
            info("onActivityResult - ${user!!.email}")
            mPresenter.isAlreadyExistUser(user!!.email!!)
        } else {
            error("signIn failed - ${response!!.error}")  <-- Only when I downloaded it from playstore, it failed...
            response!!.error!!.printStackTrace()
        }
    }
}

W/System.err: com.firebase.ui.auth.FirebaseUiException: Code: 12500, message: 12500: 
W/System.err:     at com.firebase.ui.auth.data.remote.GoogleSignInHandler.onActivityResult(GoogleSignInHandler.java:106)
W/System.err:     at com.firebase.ui.auth.ui.idp.SingleSignInActivity.onActivityResult(SingleSignInActivity.java:121)
Run Code Online (Sandbox Code Playgroud)

我试图找到错误代码 12500,但我找不到。发生了什么?!

我在 gradle 中执行了“signinReport”,并在 …

android firebase firebase-authentication

3
推荐指数
1
解决办法
1430
查看次数

改造如何在 url 中使用冒号?

我正在使用 Google Photo API 开发 Android 应用程序。

我正在尝试使用以下 API 将图像文件上传到 Google Photo Server。

https://developers.google.com/photos/library/reference/rest/v1/mediaItems/batchCreate

根据文档,我应该使用以下 URL 上传图像文件。

POST https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate
Run Code Online (Sandbox Code Playgroud)

所以我使用改造来编写代码。

@Headers("Content-type: application/json")
@POST("mediaItems:batchCreate") // The point is here
fun batchCreate(@Header("Authorization") authorization: String, @Body batchCreateRequest: BatchCreateRequest): Observable<BatchCreateResponse>
Run Code Online (Sandbox Code Playgroud)

当我运行它时,发生了 IllegalArgumentException。

java.lang.IllegalArgumentException:URL 格式错误。基础:https ://photoslibrary.googleapis.com/v1/,相对:mediaItems:batchCreate

我能做些什么来解决这个问题?

android rx-java retrofit google-photos

3
推荐指数
1
解决办法
545
查看次数

Android,当我使用应用内更新时发生InstallException

Google I/O 2019 新增应用内更新。

所以我尝试按照文档使用它:https ://developer.android.com/guide/app-bundle/in-app-updates

但它发送了一个 InstallException,如下所示:

com.google.android.play.core.tasks.RuntimeExecutionException: com.google.android.play.core.install.InstallException: Install Error: -6
    at com.google.android.play.core.tasks.k.getResult(Unknown Source:18)
    at com.eastriver.workingtimer.ui.MainActivity$onCreate$1.onComplete(MainActivity.kt:35)
Run Code Online (Sandbox Code Playgroud)

我的代码在这里:

val appUpdateManager = AppUpdateManagerFactory.create(this)
val appUpdateInfo = appUpdateManager.appUpdateInfo
appUpdateInfo.addOnCompleteListener {
    val result = it.result
    if (result.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
                    && result.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {

        info("should show update")
        appUpdateManager.startUpdateFlowForResult(
            result,
            AppUpdateType.FLEXIBLE,
            this,
            1)
    } else {
        info("This is already latest version!")
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道,它是今天才发布的。但有人知道这个吗?

android google-play in-app-update google-play-core

3
推荐指数
1
解决办法
3027
查看次数

RxJava,在订阅中清除一次性是否正确?

通常,我在“onStop/onDestroy”函数上调用“disposable.clear()”。

但是今天,我看到我的同事使用以下代码在 subscribe 函数中调用 clear 函数,例如:

val disposable: CompositeDisposable = CompositeDisposable()

...

disposable.add(
    MyObservable()
        .subscribeOn(ioScheduler)
        .observeOn(uiScheduler)
        .subscribe {

            // doSomething...

            disposable.clear // My question is here.
        }
)
Run Code Online (Sandbox Code Playgroud)

实际上,它看起来工作正常。但我不知道这段代码是否正确......

android kotlin rx-java

3
推荐指数
1
解决办法
4705
查看次数