pref: 优化一键签到

This commit is contained in:
HuanCheng65 2022-12-31 13:51:20 +08:00
parent 39a6470f4d
commit b2b85bfcda
No known key found for this signature in database
GPG Key ID: E9031EF91A805148
5 changed files with 307 additions and 48 deletions

View File

@ -27,6 +27,7 @@
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.miui.personalassistant.permission.FAVORITE" /> <uses-permission android:name="com.miui.personalassistant.permission.FAVORITE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<supports-screens <supports-screens
android:anyDensity="true" android:anyDensity="true"
@ -57,6 +58,13 @@
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">
<service
android:name=".services.OKSignService"
android:exported="true"
android:enabled="true"
android:permission="android.permission.BIND_JOB_SERVICE"
android:process=":oksign" />
<activity <activity
android:name=".activities.AppFontSizeActivity" android:name=".activities.AppFontSizeActivity"
android:configChanges="screenSize|screenLayout|orientation|smallestScreenSize|keyboardHidden" android:configChanges="screenSize|screenLayout|orientation|smallestScreenSize|keyboardHidden"
@ -77,6 +85,7 @@
android:configChanges="screenSize|screenLayout|orientation|smallestScreenSize|keyboardHidden" android:configChanges="screenSize|screenLayout|orientation|smallestScreenSize|keyboardHidden"
android:theme="@style/AppTheme.PhotoView" android:theme="@style/AppTheme.PhotoView"
android:windowSoftInputMode="adjustResize" /> android:windowSoftInputMode="adjustResize" />
<receiver <receiver
android:name=".receivers.BootCompleteSignReceiver" android:name=".receivers.BootCompleteSignReceiver"
android:enabled="true" android:enabled="true"
@ -150,11 +159,11 @@
</activity> </activity>
<activity-alias <activity-alias
android:name=".MainActivityIconOld" android:name=".MainActivityIconInvert"
android:enabled="false" android:enabled="false"
android:exported="true" android:exported="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher_new_invert"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_new_invert_round"
android:targetActivity=".MainActivityV2"> android:targetActivity=".MainActivityV2">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -167,11 +176,11 @@
android:resource="@xml/shortcut" /> android:resource="@xml/shortcut" />
</activity-alias> </activity-alias>
<activity-alias <activity-alias
android:name=".MainActivityIconInvert" android:name=".MainActivityIconOld"
android:enabled="false" android:enabled="false"
android:exported="true" android:exported="true"
android:icon="@mipmap/ic_launcher_new_invert" android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_new_invert_round" android:roundIcon="@mipmap/ic_launcher_round"
android:targetActivity=".MainActivityV2"> android:targetActivity=".MainActivityV2">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

View File

@ -0,0 +1,235 @@
package com.huanchengfly.tieba.post.services
import android.Manifest
import android.app.IntentService
import android.app.PendingIntent
import android.content.Intent
import android.content.pm.PackageManager
import android.util.Log
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.ServiceCompat
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.LoginActivity
import com.huanchengfly.tieba.post.activities.MainActivity
import com.huanchengfly.tieba.post.api.models.SignResultBean
import com.huanchengfly.tieba.post.models.SignDataBean
import com.huanchengfly.tieba.post.pendingIntentFlagImmutable
import com.huanchengfly.tieba.post.ui.common.theme.utils.ThemeUtils
import com.huanchengfly.tieba.post.utils.AccountUtil
import com.huanchengfly.tieba.post.utils.ProgressListener
import com.huanchengfly.tieba.post.utils.SingleAccountSigner
import com.huanchengfly.tieba.post.utils.addFlag
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.CoroutineContext
class OKSignService : IntentService(TAG), CoroutineScope, ProgressListener {
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
private val notificationManager: NotificationManagerCompat by lazy {
NotificationManagerCompat.from(this)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.i(TAG, "onStartCommand")
if (intent?.action == ACTION_START_SIGN) {
startForeground(
1,
buildNotification(
getString(R.string.title_loading_data),
getString(R.string.text_please_wait)
).build()
)
}
return super.onStartCommand(intent, flags, startId)
}
override fun onHandleIntent(intent: Intent?) {
Log.i(TAG, "onHandleWork")
if (intent?.action == ACTION_START_SIGN) {
val loginInfo = AccountUtil.getLoginInfo()
if (loginInfo != null) {
runBlocking {
SingleAccountSigner(
this@OKSignService,
AccountUtil.getLoginInfo()!!
)
.apply {
setProgressListener(this@OKSignService)
}
.start()
}
} else {
updateNotification(
getString(R.string.title_oksign_fail),
getString(R.string.text_login_first),
Intent(this, LoginActivity::class.java)
)
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
}
} else {
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
}
}
private fun createNotificationChannel() {
notificationManager.createNotificationChannel(
NotificationChannelCompat.Builder(
NOTIFICATION_CHANNEL_ID,
NotificationManagerCompat.IMPORTANCE_LOW
)
.setName(getString(R.string.title_oksign))
.setLightsEnabled(false)
.setShowBadge(false)
.build()
)
}
private fun buildNotification(title: String, text: String?): NotificationCompat.Builder {
createNotificationChannel()
return NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setContentText(text)
.setContentTitle(title)
.setSubText(getString(R.string.title_oksign))
.setSmallIcon(R.drawable.ic_oksign)
.setAutoCancel(true)
.setStyle(NotificationCompat.BigTextStyle())
.setColor(ThemeUtils.getColorByAttr(this, R.attr.colorPrimary))
}
private fun updateNotification(title: String, text: String, intent: Intent) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
return
}
notificationManager.notify(
1,
buildNotification(title, text)
.setContentIntent(
PendingIntent.getActivity(
this,
0,
intent,
pendingIntentFlagImmutable()
)
)
.build()
)
}
private fun updateNotification(title: String, text: String?) {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
return
}
val notification = buildNotification(title, text)
.build()
notification.flags = notification.flags.addFlag(NotificationCompat.FLAG_ONGOING_EVENT)
notificationManager.notify(1, notification)
}
private fun clearNotification() {
notificationManager.cancel(1)
}
override fun onStart(total: Int) {
updateNotification(getString(R.string.title_start_sign), null)
if (total > 0) Toast.makeText(
this,
R.string.toast_oksign_start,
Toast.LENGTH_SHORT
).show()
}
override fun onDestroy() {
super.onDestroy()
coroutineContext.cancel()
}
override fun onProgressStart(signDataBean: SignDataBean, current: Int, total: Int) {
updateNotification(
getString(
R.string.title_signing_progress,
signDataBean.userName,
current,
total
),
getString(
R.string.title_forum_name,
signDataBean.forumName
)
)
}
override fun onProgressFinish(
signDataBean: SignDataBean,
signResultBean: SignResultBean,
current: Int,
total: Int
) {
updateNotification(
getString(
R.string.title_signing_progress,
signDataBean.userName,
current + 1,
total
),
if (signResultBean.userInfo?.signBonusPoint != null)
getString(
R.string.text_singing_progress_exp,
signDataBean.forumName,
signResultBean.userInfo.signBonusPoint
)
else
getString(R.string.text_singing_progress, signDataBean.forumName)
)
}
override fun onFinish(success: Boolean, signedCount: Int, total: Int) {
updateNotification(
getString(R.string.title_oksign_finish),
if (total > 0) getString(
R.string.text_oksign_done,
signedCount
) else getString(R.string.text_oksign_no_signable),
Intent(this, MainActivity::class.java)
)
sendBroadcast(Intent(ACTION_SIGN_SUCCESS_ALL))
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
}
override fun onFailure(current: Int, total: Int, errorCode: Int, errorMsg: String) {
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
updateNotification(getString(R.string.title_oksign_fail), errorMsg)
}
companion object {
// fun enqueueWork(context: Context, work: Intent) {
// enqueueWork(context, OKSignService::class.java, JOB_ID, work)
// }
//
// private const val JOB_ID = 233
const val TAG = "OKSignService"
const val NOTIFICATION_CHANNEL_ID = "1"
const val ACTION_SIGN_SUCCESS_ALL =
"com.huanchengfly.tieba.post.service.action.SIGN_SUCCESS_ALL"
const val ACTION_START_SIGN = "com.huanchengfly.tieba.post.service.action.ACTION_SIGN_START"
}
}

View File

@ -2,8 +2,19 @@ package com.huanchengfly.tieba.post.utils
import android.content.Context import android.content.Context
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.* import androidx.datastore.preferences.core.Preferences
import com.huanchengfly.tieba.post.* import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import com.huanchengfly.tieba.post.dataStore
import com.huanchengfly.tieba.post.getBoolean
import com.huanchengfly.tieba.post.getFloat
import com.huanchengfly.tieba.post.getInt
import com.huanchengfly.tieba.post.getLong
import com.huanchengfly.tieba.post.getString
import com.huanchengfly.tieba.post.utils.ThemeUtil.TRANSLUCENT_THEME_LIGHT import com.huanchengfly.tieba.post.utils.ThemeUtil.TRANSLUCENT_THEME_LIGHT
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -21,6 +32,11 @@ open class AppPreferencesUtils(context: Context) {
var userLikeLastRequestUnix by DataStoreDelegates.long(defaultValue = 0L) var userLikeLastRequestUnix by DataStoreDelegates.long(defaultValue = 0L)
var appIcon by DataStoreDelegates.string(
defaultValue = Icons.DEFAULT_ICON,
key = AppIconUtil.PREF_KEY_APP_ICON
)
var autoSign by DataStoreDelegates.boolean(defaultValue = false, key = "auto_sign") var autoSign by DataStoreDelegates.boolean(defaultValue = false, key = "auto_sign")
var autoSignTime by DataStoreDelegates.string( var autoSignTime by DataStoreDelegates.string(

View File

@ -1,6 +1,7 @@
package com.huanchengfly.tieba.post.utils package com.huanchengfly.tieba.post.utils
import android.content.Context import android.content.Context
import android.util.Log
import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.models.MSignBean import com.huanchengfly.tieba.post.api.models.MSignBean
import com.huanchengfly.tieba.post.api.models.SignResultBean import com.huanchengfly.tieba.post.api.models.SignResultBean
@ -118,6 +119,7 @@ class SingleAccountSigner(
signData.clear() signData.clear()
var userName: String by Delegates.notNull() var userName: String by Delegates.notNull()
var tbs: String by Delegates.notNull() var tbs: String by Delegates.notNull()
Log.i(TAG, "start")
AccountUtil.fetchAccountFlow(account) AccountUtil.fetchAccountFlow(account)
.flatMapConcat { account -> .flatMapConcat { account ->
userName = account.name userName = account.name

View File

@ -2,33 +2,35 @@ package com.huanchengfly.tieba.post.utils
import android.app.AlarmManager import android.app.AlarmManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.* import android.content.ClipData
import android.content.ClipDescription
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.os.Build import android.os.Build
import android.os.PersistableBundle import android.os.PersistableBundle
import androidx.work.ExistingWorkPolicy import androidx.core.content.ContextCompat
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import com.huanchengfly.tieba.post.R import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.WebViewActivity import com.huanchengfly.tieba.post.activities.WebViewActivity
import com.huanchengfly.tieba.post.api.TiebaApi import com.huanchengfly.tieba.post.api.TiebaApi
import com.huanchengfly.tieba.post.api.models.CheckReportBean import com.huanchengfly.tieba.post.api.models.CheckReportBean
import com.huanchengfly.tieba.post.components.dialogs.LoadingDialog import com.huanchengfly.tieba.post.components.dialogs.LoadingDialog
import com.huanchengfly.tieba.post.components.workers.OKSignWork
import com.huanchengfly.tieba.post.pendingIntentFlagImmutable import com.huanchengfly.tieba.post.pendingIntentFlagImmutable
import com.huanchengfly.tieba.post.receivers.AutoSignAlarm import com.huanchengfly.tieba.post.receivers.AutoSignAlarm
import com.huanchengfly.tieba.post.services.OKSignService
import com.huanchengfly.tieba.post.toastShort import com.huanchengfly.tieba.post.toastShort
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
import java.util.* import java.util.Calendar
object TiebaUtil { object TiebaUtil {
private fun ClipData.setIsSensitive(isSensitive: Boolean): ClipData { private fun ClipData.setIsSensitive(isSensitive: Boolean): ClipData = apply {
description.extras = PersistableBundle().apply { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, isSensitive) description.extras = PersistableBundle().apply {
putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, isSensitive)
}
} }
return this
} }
@JvmStatic @JvmStatic
@ -80,36 +82,31 @@ object TiebaUtil {
@JvmStatic @JvmStatic
fun startSign(context: Context) { fun startSign(context: Context) {
context.appPreferences.signDay = Calendar.getInstance()[Calendar.DAY_OF_MONTH] context.appPreferences.signDay = Calendar.getInstance()[Calendar.DAY_OF_MONTH]
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // OKSignService.enqueueWork(
// try { // context,
// context.startForegroundService( // Intent()
// Intent() // .setClassName(
// .setClassName( // context.packageName,
// context.packageName, // "${context.packageName}.services.OKSignService"
// "${context.packageName}.services.OKSignService"
// )
// .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// .setAction(OKSignService.ACTION_START_SIGN)
// ) // )
// } catch (e: IllegalStateException) { // .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// e.printStackTrace() // .setAction(OKSignService.ACTION_START_SIGN)
// } // )
// } else { ContextCompat.startForegroundService(
// context.startService( context,
// Intent() Intent()
// .setClassName( .setClassName(
// context.packageName, context.packageName,
// "${context.packageName}.services.OKSignService" "${context.packageName}.services.OKSignService"
// ) )
// .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// .setAction(OKSignService.ACTION_START_SIGN) .setAction(OKSignService.ACTION_START_SIGN)
// ) )
// } // val okSignWork = OneTimeWorkRequestBuilder<OKSignWork>()
val okSignWork = OneTimeWorkRequestBuilder<OKSignWork>() // .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) // .build()
.build() // WorkManager.getInstance(context)
WorkManager.getInstance(context) // .enqueueUniqueWork("OKSign", ExistingWorkPolicy.KEEP, okSignWork)
.enqueueUniqueWork("OKSign", ExistingWorkPolicy.KEEP, okSignWork)
} }
@JvmStatic @JvmStatic