最近,谷歌在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。但这是行不通的。
他正在用模拟器来做。看起来像调试模式。
我该怎么做?
我正在使用 Jetpack Compose 和 Coil ImageLoader 库开发一个 Android 应用程序。
它显示用户的个人资料图像。
我从 API 接收配置文件数据。GET: /users/{userId}
响应包含userId和profileImgKey。
对于用户头像,Backend提供了GET: /photo/{userId}API。
但问题是,如果某些用户更新他/她的个人资料图像,其他用户仍然看到以前的个人资料图像而不是新图像。
因为它是被Coil缓存的。
如果我关闭缓存选项,它可能会正常工作。但我不想这样做。我不想失去性能优势。
当用户更新其个人资料图像时,图像profileImgKey就会发生变化。所以我想用它作为缓存键。
但我不知道如何使用这个。
我想在我的应用程序中应用 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) 这个问题是关于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) 我开始使用 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”。
我正在使用 jetpack compose 开发一个 Android 聊天应用程序。
聊天消息使用 LazyColumn 显示。消息来自 WebSocket。
我想要开发的是:
为了做到这些,我发现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) 我正在开发一个简单的应用程序。我在以下文档中使用了 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”,并在 …
我正在使用 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
我能做些什么来解决这个问题?
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)
我知道,它是今天才发布的。但有人知道这个吗?
通常,我在“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 ×8
google-play ×2
kotlin ×2
rx-java ×2
coil ×1
firebase ×1
javascript ×1
oop ×1
retrofit ×1
singleton ×1
vue.js ×1
vuejs2 ×1
vuetify.js ×1