diff --git a/apkGen.pl b/apkGen.pl
index 2c15f882..abf66e4c 100644
--- a/apkGen.pl
+++ b/apkGen.pl
@@ -16,6 +16,7 @@ sub cmd($){
}
cmd "./gradlew --stop";
+cmd "rm -rf .gradle/caches/build-cache-*";
cmd "./gradlew clean";
cmd "./gradlew assembleNoFcmRelease";
cmd "./gradlew assembleFcmRelease";
diff --git a/app/src/fcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt b/app/src/fcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt
index 19c05d4b..0c21cc57 100644
--- a/app/src/fcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt
+++ b/app/src/fcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt
@@ -1,7 +1,12 @@
package jp.juggler.subwaytooter.push
+import android.content.Context
+import com.google.android.gms.common.ConnectionResult
+import com.google.android.gms.common.GoogleApiAvailability
import com.google.firebase.messaging.FirebaseMessaging
+import jp.juggler.util.log.LogCategory
import kotlinx.coroutines.tasks.await
+
/*
// ビルド要求
// com.google.firebase:firebase-messaging.20.3.0 以降
@@ -19,13 +24,50 @@ import kotlinx.coroutines.tasks.await
が出る場合はビルド設定を確認すること
*/
-@Suppress("unused")
-class FcmTokenLoader {
+object FcmTokenLoader {
+
+ private val log = LogCategory("FcmTokenLoader")
+
+ private fun connectionResultString(i: Int) = when (i) {
+ ConnectionResult.UNKNOWN -> "UNKNOWN"
+ ConnectionResult.SUCCESS -> "SUCCESS"
+ ConnectionResult.SERVICE_MISSING -> "SERVICE_MISSING"
+ ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED -> "SERVICE_VERSION_UPDATE_REQUIRED"
+ ConnectionResult.SERVICE_DISABLED -> "SERVICE_DISABLED"
+ ConnectionResult.SIGN_IN_REQUIRED -> "SIGN_IN_REQUIRED"
+ ConnectionResult.INVALID_ACCOUNT -> "INVALID_ACCOUNT"
+ ConnectionResult.RESOLUTION_REQUIRED -> "RESOLUTION_REQUIRED"
+ ConnectionResult.NETWORK_ERROR -> "NETWORK_ERROR"
+ ConnectionResult.INTERNAL_ERROR -> "INTERNAL_ERROR"
+ ConnectionResult.SERVICE_INVALID -> "SERVICE_INVALID"
+ ConnectionResult.DEVELOPER_ERROR -> "DEVELOPER_ERROR"
+ ConnectionResult.LICENSE_CHECK_FAILED -> "LICENSE_CHECK_FAILED"
+ ConnectionResult.CANCELED -> "CANCELED"
+ ConnectionResult.TIMEOUT -> "TIMEOUT"
+ ConnectionResult.INTERRUPTED -> "INTERRUPTED"
+ ConnectionResult.API_UNAVAILABLE -> "API_UNAVAILABLE"
+ ConnectionResult.SIGN_IN_FAILED -> "SIGN_IN_FAILED"
+ ConnectionResult.SERVICE_UPDATING -> "SERVICE_UPDATING"
+ ConnectionResult.SERVICE_MISSING_PERMISSION -> "SERVICE_MISSING_PERMISSION"
+ ConnectionResult.RESTRICTED_PROFILE -> "RESTRICTED_PROFILE"
+ ConnectionResult.RESOLUTION_ACTIVITY_NOT_FOUND -> "RESOLUTION_ACTIVITY_NOT_FOUND"
+ ConnectionResult.API_DISABLED -> "API_DISABLED"
+ ConnectionResult.API_DISABLED_FOR_CONNECTION -> "API_DISABLED_FOR_CONNECTION"
+ else -> "Unknown($i)"
+ }
+
+ fun isPlayServiceAvailavle(context: Context): Boolean {
+ val errorCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
+ if (errorCode == ConnectionResult.SUCCESS) return true
+ log.w("isPlayServiceAvailavle=${connectionResultString(errorCode)}")
+ return false
+ }
+
//
suspend fun getToken(): String? =
FirebaseMessaging.getInstance().token.await()
- suspend fun deleteToken(){
+ suspend fun deleteToken() {
FirebaseMessaging.getInstance().deleteToken().await()
}
}
diff --git a/app/src/fcm/java/jp/juggler/subwaytooter/push/MyFcmService.kt b/app/src/fcm/java/jp/juggler/subwaytooter/push/MyFcmService.kt
index 3a63edc8..d73cb963 100644
--- a/app/src/fcm/java/jp/juggler/subwaytooter/push/MyFcmService.kt
+++ b/app/src/fcm/java/jp/juggler/subwaytooter/push/MyFcmService.kt
@@ -2,16 +2,18 @@ package jp.juggler.subwaytooter.push
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
+import jp.juggler.subwaytooter.pref.PrefDevice
+import jp.juggler.subwaytooter.pref.prefDevice
import jp.juggler.util.log.LogCategory
+import jp.juggler.util.os.applicationContextSafe
import jp.juggler.util.os.checkAppForeground
-import kotlinx.coroutines.runBlocking
/**
* FCMのイベントを受け取るサービス。
* - IntentServiceの一種なのでワーカースレッドから呼ばれる。runBlockingして良し。
*/
class MyFcmService : FirebaseMessagingService() {
- companion object{
+ companion object {
private val log = LogCategory("MyFcmService")
}
@@ -21,7 +23,12 @@ class MyFcmService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
try {
checkAppForeground("MyFcmService.onNewToken")
- fcmHandler.onTokenChanged(token)
+ val context = applicationContextSafe
+ when (context.prefDevice.pushDistributor) {
+ null, "", PrefDevice.PUSH_DISTRIBUTOR_FCM -> {
+ PushWorker.enqueueRegisterEndpoint(context)
+ }
+ }
} catch (ex: Throwable) {
log.e(ex, "onNewToken failed.")
} finally {
@@ -37,9 +44,7 @@ class MyFcmService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
try {
checkAppForeground("MyFcmService.onMessageReceived")
- runBlocking {
- fcmHandler.onMessageReceived( remoteMessage.data)
- }
+ applicationContextSafe.pushRepo.handleFcmMessage(remoteMessage.data)
} catch (ex: Throwable) {
log.e(ex, "onMessageReceived failed.")
} finally {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9c2e69c5..964c1769 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -373,9 +373,6 @@
-
diff --git a/app/src/main/java/jp/juggler/subwaytooter/actmain/ActMainIntent.kt b/app/src/main/java/jp/juggler/subwaytooter/actmain/ActMainIntent.kt
index aa3b1df2..34f20b10 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/actmain/ActMainIntent.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/actmain/ActMainIntent.kt
@@ -23,6 +23,7 @@ import jp.juggler.subwaytooter.api.runApiTask2
import jp.juggler.subwaytooter.api.showApiError
import jp.juggler.subwaytooter.column.ColumnType
import jp.juggler.subwaytooter.column.startLoading
+import jp.juggler.subwaytooter.dialog.DlgConfirm.okDialog
import jp.juggler.subwaytooter.dialog.actionsDialog
import jp.juggler.subwaytooter.dialog.pickAccount
import jp.juggler.subwaytooter.dialog.runInProgress
@@ -356,7 +357,7 @@ fun ActMain.handleSharedIntent(intent: Intent) {
// アカウントを追加/更新したらappServerHashの取得をやりなおす
suspend fun ActMain.updatePushDistributer() {
when {
- fcmHandler.noFcm && prefDevice.pushDistributor.isNullOrEmpty() -> {
+ fcmHandler.noFcm(this) && prefDevice.pushDistributor.isNullOrEmpty() -> {
selectPushDistributor()
// 選択しなかった場合は購読の更新を行わない
}
@@ -384,52 +385,58 @@ fun AppCompatActivity.selectPushDistributor() {
else -> this
}
- actionsDialog(getString(R.string.select_push_delivery_service)) {
- if (fcmHandler.hasFcm) {
+ val upDistrobutors = UnifiedPush.getDistributors(
+ context,
+ features = ArrayList(listOf(UnifiedPush.FEATURE_BYTES_MESSAGE))
+ )
+ val hasFcm = fcmHandler.hasFcm(context)
+ if (upDistrobutors.isEmpty() && !hasFcm) {
+ okDialog(R.string.push_distributor_not_available)
+ } else {
+ actionsDialog(getString(R.string.select_push_delivery_service)) {
+ if (hasFcm) {
+ action(
+ getString(R.string.firebase_cloud_messaging)
+ .appendChecked(lastDistributor == PrefDevice.PUSH_DISTRIBUTOR_FCM)
+ ) {
+ runInProgress(cancellable = false) { reporter ->
+ withContext(AppDispatchers.DEFAULT) {
+ pushRepo.switchDistributor(
+ PrefDevice.PUSH_DISTRIBUTOR_FCM,
+ reporter = reporter
+ )
+ }
+ }
+ }
+ }
+ for (packageName in upDistrobutors) {
+ action(
+ packageName.appendChecked(lastDistributor == packageName)
+ ) {
+ runInProgress(cancellable = false) { reporter ->
+ withContext(AppDispatchers.DEFAULT) {
+ pushRepo.switchDistributor(
+ packageName,
+ reporter = reporter
+ )
+ }
+ }
+ }
+ }
action(
- getString(R.string.firebase_cloud_messaging)
- .appendChecked(lastDistributor == PrefDevice.PUSH_DISTRIBUTOR_FCM)
+ getString(R.string.none)
+ .appendChecked(lastDistributor == PrefDevice.PUSH_DISTRIBUTOR_NONE)
) {
runInProgress(cancellable = false) { reporter ->
withContext(AppDispatchers.DEFAULT) {
pushRepo.switchDistributor(
- PrefDevice.PUSH_DISTRIBUTOR_FCM,
+ PrefDevice.PUSH_DISTRIBUTOR_NONE,
reporter = reporter
)
}
}
}
}
- for (packageName in UnifiedPush.getDistributors(
- context,
- features = ArrayList(listOf(UnifiedPush.FEATURE_BYTES_MESSAGE))
- )) {
- action(
- packageName.appendChecked(lastDistributor == packageName)
- ) {
- runInProgress(cancellable = false) { reporter ->
- withContext(AppDispatchers.DEFAULT) {
- pushRepo.switchDistributor(
- packageName,
- reporter = reporter
- )
- }
- }
- }
- }
- action(
- getString(R.string.none)
- .appendChecked(lastDistributor == PrefDevice.PUSH_DISTRIBUTOR_NONE)
- ) {
- runInProgress(cancellable = false) { reporter ->
- withContext(AppDispatchers.DEFAULT) {
- pushRepo.switchDistributor(
- PrefDevice.PUSH_DISTRIBUTOR_NONE,
- reporter = reporter
- )
- }
- }
- }
}
}
}
diff --git a/app/src/main/java/jp/juggler/subwaytooter/actmain/SideMenuAdapter.kt b/app/src/main/java/jp/juggler/subwaytooter/actmain/SideMenuAdapter.kt
index f465425d..3ca33a0f 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/actmain/SideMenuAdapter.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/actmain/SideMenuAdapter.kt
@@ -588,11 +588,13 @@ class SideMenuAdapter(
}
private fun notificationActionRecommend(): Pair Unit>? = when {
+ // 通知権限がない場合の警告とアクション
actMain.prNotification.spec.listNotGranded(actMain).isNotEmpty() ->
Pair(R.string.notification_permission_not_granted) {
actMain.prNotification.openAppSetting(actMain)
}
- (actMain.prefDevice.pushDistributor.isNullOrEmpty() && actMain.fcmHandler.noFcm) ||
+ // プッシュ配送が選択されていない場合の警告とアクション
+ (actMain.prefDevice.pushDistributor.isNullOrEmpty() && fcmHandler.noFcm(actMain)) ||
actMain.prefDevice.pushDistributor == PUSH_DISTRIBUTOR_NONE ->
Pair(R.string.notification_push_distributor_disabled) {
actMain.selectPushDistributor()
diff --git a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgConfirm.kt b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgConfirm.kt
index 7c33213a..4199b74f 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgConfirm.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/dialog/DlgConfirm.kt
@@ -1,6 +1,8 @@
package jp.juggler.subwaytooter.dialog
import android.annotation.SuppressLint
+import android.text.method.LinkMovementMethod
+import android.text.util.Linkify
import android.view.View
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
@@ -121,4 +123,39 @@ object DlgConfirm {
}
}
}
+
+ suspend fun AppCompatActivity.okDialog(@StringRes messageId: Int, vararg args: Any?) =
+ okDialog(getString(messageId, *args))
+
+ suspend fun AppCompatActivity.okDialog(message: CharSequence, title: CharSequence? = null) {
+ suspendCancellableCoroutine { cont ->
+ try {
+ val views = DlgConfirmBinding.inflate(layoutInflater)
+
+ views.cbSkipNext.visibility = View.GONE
+
+ views.tvMessage.apply {
+ movementMethod = LinkMovementMethod.getInstance()
+ autoLinkMask = Linkify.WEB_URLS
+ text = message
+ }
+
+ val dialog = AlertDialog.Builder(this).apply {
+ setView(views.root)
+ setCancelable(true)
+ title?.let { setTitle(it) }
+ setPositiveButton(R.string.ok) { _, _ ->
+ if (cont.isActive) cont.resume(Unit)
+ }
+ }.create()
+ dialog.setOnDismissListener {
+ if (cont.isActive) cont.resumeWithException(CancellationException("dialog closed."))
+ }
+ dialog.show()
+ cont.invokeOnCancellation { dialog.dismissSafe() }
+ } catch (ex: Throwable) {
+ cont.resumeWithException(ex)
+ }
+ }
+ }
}
diff --git a/app/src/main/java/jp/juggler/subwaytooter/push/FcmHandler.kt b/app/src/main/java/jp/juggler/subwaytooter/push/FcmHandler.kt
index 0d796d68..b18420a6 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/push/FcmHandler.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/push/FcmHandler.kt
@@ -1,69 +1,36 @@
package jp.juggler.subwaytooter.push
import android.content.Context
-import androidx.startup.AppInitializer
-import androidx.startup.Initializer
-import jp.juggler.util.coroutine.AppDispatchers
-import jp.juggler.util.coroutine.EmptyScope
-import jp.juggler.util.log.LogCategory
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import jp.juggler.subwaytooter.BuildConfig
import jp.juggler.subwaytooter.pref.prefDevice
+import jp.juggler.util.coroutine.AppDispatchers
+import jp.juggler.util.data.notEmpty
+import jp.juggler.util.log.LogCategory
+import kotlinx.coroutines.withContext
-private val log = LogCategory("FcmHandler")
+val fcmHandler = FcmHandler
-@Suppress("MemberVisibilityCanBePrivate", "RedundantSuspendModifier")
-class FcmHandler(
- private val context: Context,
-) {
- companion object {
- val reNoFcm = """noFcm""".toRegex(RegexOption.IGNORE_CASE)
- }
+object FcmHandler {
+ private val log = LogCategory("FcmHandler")
- val fcmToken = MutableStateFlow(context.prefDevice.fcmToken)
+ fun hasFcm(context: Context): Boolean =
+ FcmTokenLoader.isPlayServiceAvailavle(context)
- val noFcm :Boolean
- get()= reNoFcm.containsMatchIn(BuildConfig.FLAVOR)
+ fun noFcm(context: Context): Boolean =
+ !hasFcm(context)
- val hasFcm get() = !noFcm
-
- fun onTokenChanged(token: String?) {
- context.prefDevice.fcmToken = token
- EmptyScope.launch(AppDispatchers.IO) { fcmToken.emit(token) }
- }
-
- suspend fun onMessageReceived(data: Map) {
- try {
- context.pushRepo.handleFcmMessage(data)
- } catch (ex: Throwable) {
- log.e(ex, "onMessage failed.")
- }
- }
-
- suspend fun deleteFcmToken() =
+ suspend fun deleteFcmToken(context: Context) =
withContext(AppDispatchers.IO) {
// 古いトークンを覚えておく
- context.prefDevice.fcmToken
- ?.takeIf { it.isNotEmpty() }
- ?.let { context.prefDevice.fcmTokenExpired = it }
- // FCMから削除する
- log.i("deleteFcmToken: start")
- FcmTokenLoader().deleteToken()
- log.i("deleteFcmToken: end")
- onTokenChanged(null)
- log.i("deleteFcmToken complete")
+ loadFcmToken()?.notEmpty()?.let {
+ context.prefDevice.fcmTokenExpired = it
+ }
+ // FCMにトークン変更を依頼する
+ FcmTokenLoader.deleteToken()
}
suspend fun loadFcmToken(): String? = try {
withContext(AppDispatchers.IO) {
- log.i("loadFcmToken start")
- val token = FcmTokenLoader().getToken()
- log.i("loadFcmToken onTokenChanged")
- onTokenChanged(token)
- log.i("loadFcmToken end")
- token
+ FcmTokenLoader.getToken()
}
} catch (ex: Throwable) {
// https://github.com/firebase/firebase-android-sdk/issues/4053
@@ -77,25 +44,3 @@ class FcmHandler(
null
}
}
-
-/**
- * AndroidManifest.xml で androidx.startup.InitializationProvider から参照される
- */
-@Suppress("unused")
-class FcmHandlerInitializer : Initializer {
- override fun dependencies(): List>> =
- emptyList()
-
- override fun create(context: Context): FcmHandler {
- val newHandler = FcmHandler(context.applicationContext)
- log.i("FcmHandlerInitializer hasFcm=${newHandler.hasFcm}, BuildConfig.FLAVOR=${BuildConfig.FLAVOR}")
- EmptyScope.launch{
- newHandler.loadFcmToken()
- }
- return newHandler
- }
-}
-
-val Context.fcmHandler: FcmHandler
- get() = AppInitializer.getInstance(this)
- .initializeComponent(FcmHandlerInitializer::class.java)
diff --git a/app/src/main/java/jp/juggler/subwaytooter/push/PushRepo.kt b/app/src/main/java/jp/juggler/subwaytooter/push/PushRepo.kt
index 63dfdd1a..dd22ac36 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/push/PushRepo.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/push/PushRepo.kt
@@ -141,21 +141,22 @@ class PushRepo(
UnifiedPush.unregisterApp(context)
// FCMトークンの削除。これでこの端末のこのアプリへの古いエンドポイント登録はgoneになり消えるはず
- fcmHandler.deleteFcmToken()
+ fcmHandler.deleteFcmToken(context)
when (pushDistributor) {
null, "" -> {
// 特に変更しない(アクセストークン更新時に呼ばれる
+ reporter.setMessage("enqueueRegisterEndpoint for ${pushDistributor}…")
enqueueRegisterEndpoint(context)
}
PrefDevice.PUSH_DISTRIBUTOR_NONE -> {
// 購読解除
- reporter.setMessage("SubscriptionUpdateService.launch")
+ reporter.setMessage("enqueueRegisterEndpoint for ${pushDistributor}…")
enqueueRegisterEndpoint(context)
}
PrefDevice.PUSH_DISTRIBUTOR_FCM -> {
// 特にイベントは来ないので、プッシュ購読をやりなおす
- reporter.setMessage("SubscriptionUpdateService.launch")
+ reporter.setMessage("enqueueRegisterEndpoint for ${pushDistributor}…")
enqueueRegisterEndpoint(context)
}
else -> {
@@ -196,7 +197,8 @@ class PushRepo(
* ワーカーからnewUpEndpoint()が呼ばれる
*/
suspend fun newUpEndpoint(upEndpoint: String) {
- refReporter?.get()?.setMessage("新しい UnifiedPush endpoint URL を取得しました")
+ refReporter?.get()
+ ?.setMessage(context.getString(R.string.unified_push_got_new_endpoint_url))
val upPackageName = UnifiedPush.getDistributor(context).notEmpty()
?: error("missing upPackageName")
@@ -223,6 +225,7 @@ class PushRepo(
suspend fun registerEndpoint(
keepAliveMode: Boolean,
) {
+ refReporter?.get()?.setMessage("registerEndpoint for ${prefDevice.pushDistributor}…")
subscriptionMutex.withLock {
log.i("registerEndpoint: keepAliveMode=$keepAliveMode")
@@ -230,7 +233,8 @@ class PushRepo(
try {
// 期限切れのUPエンドポイントがあればそれ経由の中継を解除する
prefDevice.fcmTokenExpired.notEmpty()?.let {
- refReporter?.get()?.setMessage("期限切れのFCMデバイストークンをアプリサーバから削除しています")
+ refReporter?.get()
+ ?.setMessage(context.getString(R.string.removing_old_fcm_token))
log.i("remove fcmTokenExpired")
apiAppServer.endpointRemove(fcmToken = it)
prefDevice.fcmTokenExpired = null
@@ -242,7 +246,8 @@ class PushRepo(
try {
// 期限切れのUPエンドポイントがあればそれ経由の中継を解除する
prefDevice.upEndpointExpired.notEmpty()?.let {
- refReporter?.get()?.setMessage("期限切れのUnifiedPushエンドポイントをアプリサーバから削除しています")
+ refReporter?.get()
+ ?.setMessage(context.getString(R.string.removing_old_unified_push_url))
log.i("remove upEndpointExpired")
apiAppServer.endpointRemove(upUrl = it)
prefDevice.upEndpointExpired = null
@@ -274,19 +279,23 @@ class PushRepo(
var willRemoveSubscription = false
- // アプリサーバにendpointを登録する
- refReporter?.get()?.setMessage("アプリサーバにプッシュサービスの情報を送信しています")
+ val hasFcm = fcmHandler.hasFcm(context)
- if (!fcmHandler.hasFcm && prefDevice.pushDistributor == PrefDevice.PUSH_DISTRIBUTOR_FCM) {
+
+ if (!hasFcm && prefDevice.pushDistributor == PrefDevice.PUSH_DISTRIBUTOR_FCM) {
log.w("fmc selected, but this is noFcm build. unset distributer.")
prefDevice.pushDistributor = null
}
+ // アプリサーバにendpointを登録する
+ refReporter?.get()
+ ?.setMessage(context.getString(R.string.sending_push_distributor_info_to_app_server))
+
val acctHashList = acctHashMap.keys.toList()
val json = when (prefDevice.pushDistributor) {
null, "" -> when {
- fcmHandler.hasFcm -> {
+ hasFcm -> {
log.i("registerEndpoint dist=FCM(default), acctHashList=${acctHashList.size}")
registerEndpointFcm(acctHashList)
}
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 59a81cd1..4860e3aa 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -1240,4 +1240,9 @@
通知のプッシュ配送サービスが選択されていません
通知のアクセント色
Pleroma機能
+ UnifiedPushの新しいendpoint URLを取得しました…
+ 期限切れのFCMデバイストークンをアプリサーバから削除しています…
+ 期限切れのUnifiedPushエンドポイントをアプリサーバから削除しています…
+ アプリサーバにプッシュサービスの情報を送信しています…
+ プッシュ配送サービスを利用できません。UnifiedPush対応のプッシュ配送アプリをインストールすることで、プッシュ通知を受け取ることができます。詳細 https://unifiedpush.org/
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2dab5926..45079142 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1256,4 +1256,9 @@
Notification push distributor not selected.
Notification accent color
Pleroma features
+ Got new UnifiedPush endpoint URL…
+ Removing expired FCM device token from app server…
+ Removing expired UnifiedPush endpoint URL from app server…
+ Sending push service information to app server…
+ Push distributor is not available. You can receive push notifications by installing a UnifiedPush compatible push delivery app. see https://unifiedpush.org/
diff --git a/app/src/noFcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt b/app/src/noFcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt
index c17bb68b..30ecae51 100644
--- a/app/src/noFcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt
+++ b/app/src/noFcm/java/jp/juggler/subwaytooter/push/FcmTokenLoader.kt
@@ -1,7 +1,10 @@
package jp.juggler.subwaytooter.push
-@Suppress("RedundantSuspendModifier")
-class FcmTokenLoader {
+import android.content.Context
+
+@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER")
+object FcmTokenLoader {
suspend fun getToken(): String? = null
suspend fun deleteToken() = Unit
+ fun isPlayServiceAvailavle(context: Context) = false
}