依存関係の更新に伴う変更。WorkManagerのサービスがmanifestにforegroundServiceTypeを持たない問題の対応。

This commit is contained in:
tateisu 2023-06-30 00:24:17 +09:00
parent e9f9b11e7b
commit 8ceb21a48a
13 changed files with 121 additions and 56 deletions

View File

@ -5,6 +5,7 @@
<application tools:ignore="MissingApplicationIcon">
<service
android:name="jp.juggler.subwaytooter.push.MyFcmService"
android:foregroundServiceType="dataSync"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />

View File

@ -10,7 +10,6 @@ import jp.juggler.util.*
import jp.juggler.util.data.digestSHA256Hex
import jp.juggler.util.log.LogCategory
import jp.juggler.util.log.showToast
import okhttp3.internal.toHexString
import java.io.File
import java.io.FileOutputStream
import java.util.*
@ -48,7 +47,7 @@ class ActCallback : AppCompatActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
log.d("onCreate flags=0x${intent.flags.toHexString()}")
log.d("onCreate flags=0x${intent.flags.toString(radix = 16)}")
super.onCreate(savedInstanceState)
var intent: Intent? = intent

View File

@ -2,6 +2,7 @@ package jp.juggler.subwaytooter
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Typeface
@ -21,14 +22,66 @@ import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import io.github.inflationx.viewpump.ViewPumpContextWrapper
import jp.juggler.subwaytooter.action.accessTokenPrompt
import jp.juggler.subwaytooter.action.timeline
import jp.juggler.subwaytooter.actmain.*
import jp.juggler.subwaytooter.actmain.ActMainPhoneViews
import jp.juggler.subwaytooter.actmain.ActMainTabletViews
import jp.juggler.subwaytooter.actmain.ColumnStripLinearLayout
import jp.juggler.subwaytooter.actmain.SideMenuAdapter
import jp.juggler.subwaytooter.actmain.afterNotificationGranted
import jp.juggler.subwaytooter.actmain.closePopup
import jp.juggler.subwaytooter.actmain.defaultInsertPosition
import jp.juggler.subwaytooter.actmain.handleIntentUri
import jp.juggler.subwaytooter.actmain.handleSharedIntent
import jp.juggler.subwaytooter.actmain.importAppData
import jp.juggler.subwaytooter.actmain.initPhoneTablet
import jp.juggler.subwaytooter.actmain.initUIQuickPost
import jp.juggler.subwaytooter.actmain.isOrderChanged
import jp.juggler.subwaytooter.actmain.justifyWindowContentPortrait
import jp.juggler.subwaytooter.actmain.launchDialogs
import jp.juggler.subwaytooter.actmain.onBackPressedImpl
import jp.juggler.subwaytooter.actmain.onClickImpl
import jp.juggler.subwaytooter.actmain.onCompleteActPost
import jp.juggler.subwaytooter.actmain.onMyClickableSpanClickedImpl
import jp.juggler.subwaytooter.actmain.phoneTab
import jp.juggler.subwaytooter.actmain.refreshAfterPost
import jp.juggler.subwaytooter.actmain.reloadAccountSetting
import jp.juggler.subwaytooter.actmain.reloadBoostAlpha
import jp.juggler.subwaytooter.actmain.reloadColors
import jp.juggler.subwaytooter.actmain.reloadFonts
import jp.juggler.subwaytooter.actmain.reloadIconSize
import jp.juggler.subwaytooter.actmain.reloadMediaHeight
import jp.juggler.subwaytooter.actmain.reloadRoundRatio
import jp.juggler.subwaytooter.actmain.reloadTextSize
import jp.juggler.subwaytooter.actmain.reloadTimeZone
import jp.juggler.subwaytooter.actmain.resizeColumnWidth
import jp.juggler.subwaytooter.actmain.scrollColumnStrip
import jp.juggler.subwaytooter.actmain.scrollToColumn
import jp.juggler.subwaytooter.actmain.scrollToLastColumn
import jp.juggler.subwaytooter.actmain.searchFromActivityResult
import jp.juggler.subwaytooter.actmain.setColumnsOrder
import jp.juggler.subwaytooter.actmain.showFooterColor
import jp.juggler.subwaytooter.actmain.showQuickPostVisibility
import jp.juggler.subwaytooter.actmain.tabOnly
import jp.juggler.subwaytooter.actmain.updateColumnStrip
import jp.juggler.subwaytooter.actmain.updateColumnStripSelection
import jp.juggler.subwaytooter.actpost.CompletionHelper
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.api.entity.EntityId
import jp.juggler.subwaytooter.api.entity.TootVisibility
import jp.juggler.subwaytooter.column.*
import jp.juggler.subwaytooter.column.Column
import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.subwaytooter.column.fireColumnColor
import jp.juggler.subwaytooter.column.fireRelativeTime
import jp.juggler.subwaytooter.column.fireShowColumnHeader
import jp.juggler.subwaytooter.column.fireShowContent
import jp.juggler.subwaytooter.column.onActivityStart
import jp.juggler.subwaytooter.column.onLanguageFilterChanged
import jp.juggler.subwaytooter.column.removeColumnViewHolderByActivity
import jp.juggler.subwaytooter.column.saveScrollPosition
import jp.juggler.subwaytooter.column.startLoading
import jp.juggler.subwaytooter.column.viewHolder
import jp.juggler.subwaytooter.dialog.DlgQuickTootMenu
import jp.juggler.subwaytooter.itemviewholder.StatusButtonsPopup
import jp.juggler.subwaytooter.notification.checkNotificationImmediateAll
@ -58,12 +111,12 @@ import jp.juggler.util.string
import jp.juggler.util.ui.ActivityResultHandler
import jp.juggler.util.ui.attrColor
import jp.juggler.util.ui.isNotOk
import jp.juggler.util.ui.viewPumpFonts
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import okhttp3.internal.toHexString
import java.lang.ref.WeakReference
import java.util.*
import java.util.LinkedList
class ActMain : AppCompatActivity(),
View.OnClickListener,
@ -685,6 +738,7 @@ class ActMain : AppCompatActivity(),
btnToot.performClick()
true
}
else -> false
}
}
@ -756,10 +810,18 @@ class ActMain : AppCompatActivity(),
window.setBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.window_background))
val color = attrColor(R.attr.colorWindowBackground)
log.i("Build MANUFACTURER=${Build.MANUFACTURER}, BRAND=${Build.BRAND}, MODEL=${Build.MODEL}, bgColor=${color.toHexString()}")
log.i(
"Build MANUFACTURER=${Build.MANUFACTURER}, BRAND=${Build.BRAND}, MODEL=${Build.MODEL}, bgColor=${
color.toString(radix = 16)
}"
)
if (Build.MANUFACTURER?.contains("samsung", ignoreCase = true) == true) {
// 余計なオーバードローを一回追加する
window.decorView.rootView.setBackgroundColor(color)
}
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase, viewPumpFonts))
}
}

View File

@ -144,6 +144,7 @@ class App1 : Application() {
return when {
userAgentCustom.isNotEmpty() && !reNotAllowedInUserAgent.matcher(userAgentCustom)
.find() -> userAgentCustom
else -> userAgentDefault
}
}
@ -233,8 +234,6 @@ class App1 : Application() {
1 /* 1 means first position */
)
initializeFont()
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
@ -468,7 +467,7 @@ class App1 : Application() {
}
return try {
response.body?.bytes()
response.body.bytes()
} catch (ex: Throwable) {
log.e(ex, "getHttp content error. $url")
null
@ -489,6 +488,7 @@ class App1 : Application() {
accessInfo.putMisskeyApiToken().toPostRequestBuilder()
.url(url)
.cacheControl(CACHE_CONTROL)
else ->
Request.Builder()
.url(url)
@ -513,7 +513,7 @@ class App1 : Application() {
}
return try {
response.body?.string()
response.body.string()
} catch (ex: Throwable) {
log.e(ex, "getHttp content error. $url")
null

View File

@ -121,7 +121,7 @@ private suspend fun Response.readString(): String? {
return try {
// XXX: 進捗表示
withContext(AppDispatchers.IO) {
val bodyString = response.body?.string()
val bodyString = response.body.string()
if (bodyString.isNullOrEmpty()) {
if (response.code in 200 until 300) {
// Misskey の /api/notes/favorites/create は 204(no content)を返す。ボディはカラになる。
@ -150,7 +150,7 @@ private suspend fun Response.readString(): String? {
}
}
} finally {
response.body?.closeQuietly()
response.body.closeQuietly()
}
}

View File

@ -48,7 +48,7 @@ class TootApiClient(
fun simplifyErrorHtml(
response: Response,
caption: String = "?",
bodyString: String = response.body?.string() ?: "",
bodyString: String = response.body.string(),
jsonErrorParser: (json: JsonObject) -> String? = DEFAULT_JSON_ERROR_PARSER,
) = TootApiResult(
response = response,
@ -186,7 +186,7 @@ class TootApiClient(
)
)
val bodyString = response.body?.string()
val bodyString = response.body.string()
if (isApiCancelled()) return null
// Misskey の /api/notes/favorites/create は 204(no content)を返す。ボディはカラになる。
@ -210,7 +210,7 @@ class TootApiClient(
bodyString
}
} finally {
response.body?.closeQuietly()
response.body.closeQuietly()
}
}
@ -235,7 +235,7 @@ class TootApiClient(
)
)
val bodyBytes = response.body?.bytes()
val bodyBytes = response.body.bytes()
if (isApiCancelled()) return null
if (!response.isSuccessful || bodyBytes?.isEmpty() != false) {
@ -323,7 +323,7 @@ class TootApiClient(
val response = result.response!! // nullにならないはず
// HTMLならタグを除去する
val ct = response.body?.contentType()
val ct = response.body.contentType()
if (ct?.subtype == "html") {
val decoded = DecodeOptions().decodeHTML(bodyString).toString()
.replace("""[\s ]+""".toRegex(), " ")

View File

@ -52,7 +52,7 @@ abstract class ResponseWithBase {
// HTMLならタグの除去を試みる
try {
val ct = response.body?.contentType()
val ct = response.body.contentType()
if (ct?.subtype == "html") {
val decoded = DecodeOptions().decodeHTML(body).toString()
return TootApiResult.reWhiteSpace.matcher(decoded).replaceAll(" ").trim()
@ -144,7 +144,7 @@ class ResponseBeforeRead(
)
)
withContext(AppDispatchers.IO) {
val bodyString = response.body?.string()
val bodyString = response.body.string()
if (bodyString.isNullOrEmpty()) {
if (response.code in 200 until 300) {
// Misskey の /api/notes/favorites/create は 204(no content)を返す。ボディはカラになる。
@ -173,7 +173,7 @@ class ResponseBeforeRead(
}
}
} finally {
response.body?.closeQuietly()
response.body.closeQuietly()
}
}
@ -214,7 +214,7 @@ class ResponseBeforeRead(
ProgressResponseBody.bytes(response, callback)
else ->
response.body?.bytes() ?: error("missing response body.")
response.body.bytes()
}
}
} catch (ex: Throwable) {
@ -231,7 +231,7 @@ class ResponseBeforeRead(
}
}
} finally {
response.body?.closeQuietly()
response.body.closeQuietly()
}
}

View File

@ -130,7 +130,7 @@ open class TootApiResult(
}
// HTMLならタグの除去を試みる
val ct = response.body?.contentType()
val ct = response.body.contentType()
if (ct?.subtype == "html") {
val decoded = DecodeOptions().decodeHTML(sv).toString()
return reWhiteSpace.matcher(decoded).replaceAll(" ").trim()
@ -154,7 +154,7 @@ open class TootApiResult(
sb.append(simplifyErrorHtml(bodyString, jsonErrorParser))
} else {
try {
val string = response.body?.string()
val string = response.body.string()
if (string != null) {
sb.append(simplifyErrorHtml(string, jsonErrorParser))
}

View File

@ -62,6 +62,6 @@ class ApiPushAppServer(
.url("$appServerPrefix/l/$largeObjectId")
.build()
.await(okHttp)
.body?.bytes()
.body.bytes()
}
}

View File

@ -213,11 +213,20 @@ enum class NotificationChannels(
setWhen(System.currentTimeMillis())
setOngoing(true)
}
return ForegroundInfo(
nc.notificationId,
builder.build(),
nc.foregroundServiceType,
)
return if (Build.VERSION.SDK_INT >= 34) {
ForegroundInfo(
nc.notificationId,
builder.build(),
nc.foregroundServiceType,
)
} else {
// WorkManagerのサービスにforegroundServiceTypeが定義されてないので、
// foregroundServiceTypeを渡すと怒られる
ForegroundInfo(
nc.notificationId,
builder.build(),
)
}
}
fun cancel(context: Context, tag: String? = null) {

View File

@ -23,12 +23,8 @@ class ProgressResponseBody private constructor(
fun makeInterceptor(): Interceptor = Interceptor { chain ->
val originalResponse = chain.proceed(chain.request())
val originalBody = originalResponse.body
?: error("makeInterceptor: originalResponse.body() returns null.")
originalResponse.newBuilder()
.body(ProgressResponseBody(originalBody))
.body(ProgressResponseBody(originalResponse.body))
.build()
}
@ -37,8 +33,7 @@ class ProgressResponseBody private constructor(
response: Response,
callback: suspend (bytesRead: Long, bytesTotal: Long) -> Unit,
): ByteArray {
val body = response.body ?: error("response.body() is null.")
return bytes(body, callback)
return bytes(response.body, callback)
}
@Suppress("MemberVisibilityCanPrivate")
@ -47,9 +42,7 @@ class ProgressResponseBody private constructor(
body: ResponseBody,
callback: suspend (bytesRead: Long, bytesTotal: Long) -> Unit,
): ByteArray {
if (body is ProgressResponseBody) {
body.callback = callback
}
(body as? ProgressResponseBody)?.callback = callback
return body.bytes()
}
}
@ -143,7 +136,7 @@ class ProgressResponseBody private constructor(
get() = originalSource.buffer
@Deprecated("use val buffer.", replaceWith = ReplaceWith("buffer"))
@Suppress("DEPRECATION", "OverridingDeprecatedMember")
@Suppress("OverridingDeprecatedMember")
override fun buffer() = buffer
override fun peek(): BufferedSource = originalSource.peek()

View File

@ -6,20 +6,18 @@ import io.github.inflationx.calligraphy3.CalligraphyInterceptor
import io.github.inflationx.calligraphy3.CalligraphyTypefaceSpan
import io.github.inflationx.viewpump.ViewPump
fun initializeFont() {
ViewPump.init(
ViewPump.builder()
.addInterceptor(
CalligraphyInterceptor(
CalligraphyConfig.Builder()
// AGP8で参照するRクラスが分割されてエラーになる。
// 指定する必要もないと思う…
// .setFontAttrId(R.attr.fontPath)
.build()
)
val viewPumpFonts by lazy {
ViewPump.builder()
.addInterceptor(
CalligraphyInterceptor(
CalligraphyConfig.Builder()
// AGP8で参照するRクラスが分割されてエラーになる。
// 指定する必要もないと思う…
// .setFontAttrId(R.attr.fontPath)
.build()
)
.build()
)
)
.build()
}
fun fontSpan(tf: Typeface): Any = CalligraphyTypefaceSpan(tf)

View File

@ -17,8 +17,11 @@ buildscript {
ext.detektVersion = '1.23.0'
ext.emoji2Version = "1.3.0"
ext.exoplayerVersion = '2.18.7'
ext.glideVersion = "4.15.1"
// webpDecoder 2.3.4.14.2 glideを上げられない
ext.glideVersion = "4.14.2"
ext.webpDecoderVersion = "2.3.$glideVersion"
ext.javaSourceCompatibility = JavaVersion.VERSION_1_8
ext.javaTargetCompatibility = JavaVersion.VERSION_1_8
ext.junitVersion = "4.13.2"