Commit 61ba7a3a authored by wanglei's avatar wanglei

提交代码

parent 43a22ec3
......@@ -73,8 +73,9 @@
</intent-filter>
</activity>
<activity android:name=".ui.page.webview.PrivacyWebActivity"
android:screenOrientation="portrait"/>
<activity
android:name=".ui.page.webview.PrivacyWebActivity"
android:screenOrientation="portrait" />
<activity
android:name=".ui.page.bigfileclean.BigFileCleanActivity"
android:exported="true"
......@@ -288,12 +289,6 @@
android:resource="@xml/file_paths" />
</provider>
<service
android:name=".common.notification.AppService"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="phoneCall|mediaPlayback|dataSync|mediaProjection|connectedDevice|location"
tools:ignore="ExportedService" />
<service
android:name=".ui.start.FlashlightService"
android:exported="true"
......@@ -308,6 +303,28 @@
</intent-filter>
</service>
<receiver
android:name=".notification.broadcast.CloseNotificationReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.example.app.CLOSE_NOTIFICATION" />
</intent-filter>
</receiver>
<!-- android:foregroundServiceType="phoneCall|mediaPlayback|dataSync|mediaProjection|connectedDevice|location"-->
<service
android:name=".notification.service.NotificationService"
android:process=":clean_notification" />
<provider
android:name=".notification.provider.MyContentProvider"
android:authorities="com.zxhyis.toolss"
android:exported="true"
android:grantUriPermissions="true"
tools:ignore="ExportedContentProvider">
<!--suppress AndroidElementNotAllowed -->
<grant-uri-permission android:pathPattern=".*" />
</provider>
</application>
......
......@@ -7,6 +7,9 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Process
import androidx.work.Configuration
import androidx.work.WorkManager
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.DeviceUtils
......@@ -26,10 +29,11 @@ import com.zxhyis.toolss.ad.GravitySensorManager
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.ad.queryDataStoreBlock
import com.zxhyis.toolss.ad.saveDataStoreBlock
import com.zxhyis.toolss.common.notification.ActionBroadcast.Companion.initBroadcast
import com.zxhyis.toolss.common.notification.NotificationBroadcast
import com.zxhyis.toolss.common.notification.NotificationHelper
import com.zxhyis.toolss.common.notification.PackageBroadcast.Companion.newInitBroadcast
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.broadcast.ActionBroadcast.Companion.initBroadcast
import com.zxhyis.toolss.notification.broadcast.NotificationBroadcast
import com.zxhyis.toolss.notification.broadcast.PackageBroadcast.Companion.newInitBroadcast
import com.zxhyis.toolss.notification.provider.MyContentProviderUtils
import com.zxhyis.toolss.ui.page.SplashActivity
import com.zxhyis.toolss.ui.receiver.BatteryReceiver
import kotlinx.coroutines.Dispatchers
......@@ -38,6 +42,7 @@ import kotlinx.coroutines.launch
class FileApp : Application() {
private val TAG = "FileApp"
private lateinit var gravitySensorManager: GravitySensorManager
private var times = 0
......@@ -57,13 +62,7 @@ class FileApp : Application() {
super.onCreate()
fContext = this
initApplication()
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// startForegroundService(Intent(this, AppService::class.java))
// } else {
// startService(Intent(this, AppService::class.java))
// }
initNotificationWork()
}
@SuppressLint("UnspecifiedRegisterReceiverFlag")
......@@ -86,9 +85,7 @@ class FileApp : Application() {
EventHelper.event("al_start")
initEvenParams()
eventParams?.let {
NotificationHelper.pushCircleOrderTimber(it)
}
registerReceiver(BatteryReceiver(), IntentFilter().apply {
addAction("android.intent.action.BATTERY_CHANGED")
})
......@@ -107,50 +104,65 @@ class FileApp : Application() {
}
}
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
private var count = 0
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
}
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
private var count = 0
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {
override fun onActivityStarted(activity: Activity) {
// Log.e("onActivityStarted", "activity=$activity")
count++
if (count == 1 && !AppUtils.isAppForeground()) {
val topActivity = ActivityUtils.getTopActivity()
if (ConfigHelper.noLoadingActivities.all {
!topActivity.localClassName.contains(
it, true
)
}) {
if (AdmobUtils.isOpenAdLoaded()) {
AdmobUtils.showAppOpenAd(activity)
} else {
topActivity.startActivity(
Intent(
topActivity,
SplashActivity::class.java
).apply {
putExtra("isHotLaunch", true)
})
count++
if (count == 1 && !AppUtils.isAppForeground()) {
val topActivity = ActivityUtils.getTopActivity()
if (ConfigHelper.noLoadingActivities.all {
!topActivity.localClassName.contains(
it, true
)
}) {
if (AdmobUtils.isOpenAdLoaded()) {
AdmobUtils.showAppOpenAd(activity)
} else {
topActivity.startActivity(
Intent(
topActivity,
SplashActivity::class.java
).apply {
putExtra("isHotLaunch", true)
})
}
}
}
}
}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {
MyContentProviderUtils.setMyIntValue(this@FileApp, MyContentProviderUtils.RESUMED_VALUE)
}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {
MyContentProviderUtils.setMyIntValue(this@FileApp, MyContentProviderUtils.PAUSED_VALUE)
}
override fun onActivityStopped(activity: Activity) {
count--
}
override fun onActivityStopped(activity: Activity) {
count--
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
})
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
}
override fun onActivityDestroyed(activity: Activity) {}
})
private fun initNotificationWork() {
if (ConfigHelper.ifAgreePrivacy) {
if (Process.myPid() == ComUtils.getProcessNotificationPid(this)) {
WorkManager.initialize(this, Configuration.Builder().build())
LogEx.logDebug(TAG, "NotificationService initialize:" + Process.myPid())
return
}
}
LogEx.logDebug(TAG, "startService:" + Process.myPid())
}
......
......@@ -223,4 +223,13 @@ object ComUtils {
return false
}
fun getProcessNotificationPid(context: Context): Int {
val manager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val processes = manager.runningAppProcesses
val notificationProcess = processes.find { it.processName == context.packageName + ":clean_notification" }
val notificationPid = notificationProcess?.pid
return notificationPid ?: 0
}
}
\ No newline at end of file
package com.zxhyis.toolss.ad
import android.text.TextUtils
import com.blankj.utilcode.util.AppUtils
import android.os.Process
import com.zxhyis.toolss.FileApp
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.ad.bean.PushCfg
import com.zxhyis.toolss.common.notification.JinChengCheck
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.provider.MyContentProviderUtils
/**
* 推送的配置类,定义了是否推送的判断条件
*/
object PushManager {
object PushStrategy {
private val TAG = "PushManager"
private val TAG = "PushStrategy"
/**
* 新用户是否显示
*/
fun newUserPush(newUserAvoidTime: Int): Boolean {
fun newUserPush(newUserAvoidTime: Int, pid: Int = 0): Boolean {
val firstLaunchTime = FileApp.fContext.queryDataStoreBlock(FIRST_LAUNCH_TIME_KEY, 0L)
val haveFirstLaunchTime = (System.currentTimeMillis() - firstLaunchTime) / 1000
LogEx.logDebug(TAG, "haveFirstLaunchTime=$haveFirstLaunchTime newUserAvoidTime=$newUserAvoidTime")
LogEx.logDebug(TAG, "pid=$pid haveFirstLaunchTime=$haveFirstLaunchTime newUserAvoidTime=$newUserAvoidTime")
val flag = haveFirstLaunchTime > newUserAvoidTime
return flag
}
......@@ -32,9 +31,10 @@ object PushManager {
* @param interval 秒,目前默认自然和渠道用户都配的 60s
*/
fun canPushNextTime(interval: Int): Boolean {
val pid = Process.myPid()
val lastPushTime = FileApp.fContext.queryDataStoreBlock(ALL_LAST_PUSH_TIME, 0)
val haveInterval = (System.currentTimeMillis() - lastPushTime) / 1000
LogEx.logDebug(TAG, "haveInterval=$haveInterval interval=$interval")
LogEx.logDebug(TAG, "pid=$pid haveInterval=$haveInterval interval=$interval")
return haveInterval > interval
}
......@@ -76,20 +76,15 @@ object PushManager {
}
//是否在前台推送
if (AppUtils.isAppForeground()) {
val isResumed = MyContentProviderUtils.getMyIntValue(FileApp.fContext) == MyContentProviderUtils.RESUMED_VALUE
LogEx.logDebug(TAG, "isResumed=$isResumed")
if (isResumed) {
LogEx.logDebug(TAG, "================================app在前台拦截===============================")
EventHelper.event("pushCircleOrder_isPush", "app在前台拦截", eventParams = eventParams)
return false
}
//进程是否是活的
if (!TextUtils.isEmpty(JinChengCheck.getAliveProcessName(FileApp.fContext))) {
LogEx.logDebug(TAG, "================================app当前进程未拉起拦截===============================")
EventHelper.event("pushCircleOrder_isPush", "app当前进程未拉起拦截", eventParams = eventParams)
return false
}
val pid = Process.myPid()
LogEx.logDebug(TAG, "pid=$pid 可以发送通知了。。。")
return true
}
......@@ -97,11 +92,12 @@ object PushManager {
* 当前类型通知推送间隔是否大于配置间隔
*/
private fun actionTypeCanPsh(actionId: Int): Boolean {
val pid = Process.myPid()
val pushCfg: PushCfg? = ComUtils.getPushTypeData(actionId.toString())
val pushInterval = pushCfg?.push_interval ?: 0
val lastTypePushTime = FileApp.fContext.queryDataStoreBlock(createByActionId(actionId), 0L)
val actionInterval = (System.currentTimeMillis() - lastTypePushTime) / 1000
LogEx.logDebug(TAG, "actionId=$actionId actionInterval=$actionInterval pushInterval=$pushInterval")
LogEx.logDebug(TAG, "pid=$pid actionId=$actionId actionInterval=$actionInterval pushInterval=$pushInterval")
return actionInterval > pushInterval
}
......
package com.zxhyis.toolss.common.notification
import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.zxhyis.toolss.common.notification.OpenNotificationsUtil.createNotification
class AppService : Service() {
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
val notification = createNotification(this, 0)
startForeground(OpenNotificationsUtil.OPEN_SERVICE_NOTIFICATION_ID, notification) //显示常驻通知
}
}
\ No newline at end of file
package com.zxhyis.toolss.common.notification
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import androidx.core.app.NotificationManagerCompat
import com.blankj.utilcode.util.SPUtils
import com.zxhyis.toolss.ad.EventHelper
import com.zxhyis.toolss.ad.bean.PushCfg
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.logic.startActivity
import com.zxhyis.toolss.ui.page.BatteryInfoActivity
import com.zxhyis.toolss.ui.page.NetWorkActivity
import com.zxhyis.toolss.ui.page.PrepareScanActivity
import com.zxhyis.toolss.ui.page.RepeaterdPhotoActivity
import com.zxhyis.toolss.ui.page.SpeakerCleanerActivity
import com.zxhyis.toolss.ui.page.VirusActivity
import com.zxhyis.toolss.ui.page.appmanager.AppManager2Activity
import com.zxhyis.toolss.ui.page.bigfileclean.BigFileCleanActivity
import com.zxhyis.toolss.ui.page.notifaction.NotificationCleanActivity
import com.zxhyis.toolss.ui.page.notifaction.NotificationGuestActivity
import com.zxhyis.toolss.ui.page.photocompress.photo.StartCompressionPhotoActivity
import com.zxhyis.toolss.ui.page.recentusage.RecentAppActivity
import com.zxhyis.toolss.ui.page.speed.BatteryOptimizerActivity
import com.zxhyis.toolss.ui.page.speed.SpeedActivity
/**
* 响应通知RemoteViews的点击事件
*/
class NotificationBroadcast : BroadcastReceiver() {
private val TAG = "NotificationBroadcast"
override fun onReceive(context: Context, intent: Intent?) {
val action = intent?.action
LogEx.logDebug(TAG, "onReceive action=$action")
val cancel = intent?.extras?.getString("cancel")
if (cancel != null) {
cancelNotification(context)
}
val actionId = intent?.extras?.getInt("actionId")
LogEx.logDebug(TAG, "onReceive actionId=$actionId")
when (actionId) {
PushCfg.ID_JUNK_CLEAN_PUSH -> {
context.startActivity<PrepareScanActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_VIRUS_PUSH -> {
context.startActivity<VirusActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_BIGFILE_PUSH -> {
context.startActivity<BigFileCleanActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_PHOTO_COMPRESS -> {
context.startActivity<StartCompressionPhotoActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_APP_MANAGER -> {
context.startActivity<AppManager2Activity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_NETWORK_TRAFFIC -> {
context.startActivity<NetWorkActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_CLEAN_NOTIFICATION -> {
if (SPUtils.getInstance().getBoolean("notification_guest", false)) {
context.startActivity<NotificationCleanActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
} else {
context.startActivity<NotificationGuestActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
}
cancelNotification(context)
}
PushCfg.ID_RECENT_USE_APP -> {
context.startActivity<RecentAppActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_SIMILAR_IMAGE -> {
context.startActivity<RepeaterdPhotoActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_CLEAN_SPEAKER -> {
context.startActivity<SpeakerCleanerActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_BATTERY_OPTIMIZATION -> {
context.startActivity<BatteryOptimizerActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
//================================被动广播=========================================
PushCfg.ID_INSTALL_PACKAGE_PUSH -> {
context.startActivity<VirusActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_UNINSTALL_PACKAGE_PUSH -> {
context.startActivity<PrepareScanActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_CHARGE -> {
context.startActivity<BatteryInfoActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_LOW_BATTERY_PUSH -> {
context.startActivity<BatteryInfoActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
PushCfg.ID_PHONE_ACCELERATE -> {
context.startActivity<SpeedActivity>(flag = FLAG_ACTIVITY_NEW_TASK)
cancelNotification(context)
}
}
if (actionId != null) {
EventHelper.event("NotificationBroadcast action_click actionId=$actionId")
}
}
companion object {
const val action = "com.file.notification.NotificationBroadcast"
fun cancelNotification(context: Context) {
val id = NotificationHelper.notificationId
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.cancel(id)
}
}
}
\ No newline at end of file
package com.zxhyis.toolss.common.notification
import com.zxhyis.toolss.FileApp
import com.zxhyis.toolss.ad.EventHelper
import com.zxhyis.toolss.ad.PushManager
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.ad.bean.PushCfg
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_LOW_RAM_PUSH
import com.zxhyis.toolss.ad.createByActionId
import com.zxhyis.toolss.ad.queryDataStoreBlock
import com.zxhyis.toolss.common.notification.NotificationHelper.postActionNotification
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.logic.RamMemoryEx
import java.util.TimerTask
import kotlin.time.Duration.Companion.minutes
import kotlin.time.DurationUnit
/**
* 循环推送任务
*/
class NotificationTimerTask(val eventParams: EventParams?) : TimerTask() {
private val TAG = "NotificationTimerTask"
override fun run() {
oneShotNotification()
}
fun oneShotNotification(noLimit: Boolean = false) {
//是否推送手机加速
// val flag = isPostPhoneAccelerate()
// if (flag) {
// return
// }
val id = NotificationHelper.getPresentPushId()
val isPush = PushManager.isPush(id, eventParams = eventParams)
val log = "isPush=$isPush " + "id=${id} "
EventHelper.event("pushCircleOrder_isPush", log, eventParams = eventParams)
LogEx.logDebug(TAG, log)
if (isPush || noLimit) {
var extra: Int? = null
if (id == PushCfg.ID_PHONE_ACCELERATE) {
extra = RamMemoryEx.getMemoryUsage(FileApp.fContext).toInt()
}
FileApp.fContext.postActionNotification(id, eventParams, extra)
}
}
private fun isPostPhoneAccelerate(): Boolean {
val extra = RamMemoryEx.getMemoryUsage(FileApp.fContext)
var log: String = ""
if (extra < 60) {
log = "isPostPhoneAccelerate ram<60 ram=$extra"
EventHelper.event("pushCircleOrder_isPush ", log, eventParams = eventParams)
return false
}
val memoryPushTime = FileApp.fContext.queryDataStoreBlock(createByActionId(PushCfg.ID_PHONE_ACCELERATE), 0)
val interval = System.currentTimeMillis() - memoryPushTime
val flag = interval > 20.minutes.toLong(DurationUnit.MILLISECONDS)
if (!flag) {
log = "isPostPhoneAccelerate interval < 20minus interval=$interval"
EventHelper.event("pushCircleOrder_isPush ", log, eventParams = eventParams)
return false
}
val isPush = PushManager.isPush(PushCfg.ID_PHONE_ACCELERATE)
if (!isPush) {
return false
}
FileApp.fContext.postActionNotification(PushCfg.ID_PHONE_ACCELERATE, eventParams, extra.toInt())
return true
}
}
\ No newline at end of file
......@@ -6,9 +6,9 @@ import com.zxhyis.toolss.BuildConfig
object LogEx {
val isOpen = true
val filterTAG = arrayOf(
"ActionBroadcast",
"com.zxhyis.toolss.notification.broadcast.ActionBroadcast",
// "NotificationTimerTask",
// "NotificationHelper",
// "com.zxhyis.toolss.notification.NotificationHelper",
// "NotificationEx",
// "TimeUtils",
// "LaunchesFragment"
......
package com.zxhyis.toolss.common.notification
package com.zxhyis.toolss.notification
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo
import android.content.Context
object JinChengCheck {
fun getAliveProcessName(context: Context): String? {
......@@ -26,9 +24,9 @@ object JinChengCheck {
return null
}
fun isProcessAlive(context: Context, processName: String): Boolean {
fun isProcessAlive(context: Context, processName: String): Boolean {
val activityManager: ActivityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val runningAppProcesses: List<RunningAppProcessInfo> = activityManager.getRunningAppProcesses() ?: return false
val runningAppProcesses: List<RunningAppProcessInfo> = activityManager.runningAppProcesses ?: return false
for (processInfo in runningAppProcesses) {
if (processInfo.processName.equals(processName)) {
return true
......@@ -37,7 +35,7 @@ object JinChengCheck {
return false
}
fun isCurrentProcess(context: Context, processName: String): Boolean {
fun isCurrentProcess(context: Context, processName: String): Boolean {
return processName == context.packageName
}
}
\ No newline at end of file
package com.zxhyis.toolss.common.notification
package com.zxhyis.toolss.notification
import android.annotation.SuppressLint
import android.app.Notification
......@@ -10,13 +10,13 @@ import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
import android.graphics.drawable.AnimationDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Process
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.datastore.preferences.core.stringPreferencesKey
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
......@@ -28,7 +28,6 @@ import com.zxhyis.toolss.ad.EventHelper
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_APP_MANAGER
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_BATTERY_OPTIMIZATION
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_BATTERY_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_BIGFILE_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_CHARGE
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_CLEAN_NOTIFICATION
......@@ -36,7 +35,6 @@ import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_CLEAN_SPEAKER
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_INSTALL_PACKAGE_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_JUNK_CLEAN_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_LOW_BATTERY_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_LOW_RAM_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_NETWORK_TRAFFIC
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_PHONE_ACCELERATE
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_PHOTO_COMPRESS
......@@ -48,15 +46,10 @@ import com.zxhyis.toolss.ad.createByActionId
import com.zxhyis.toolss.ad.queryDataStoreBlock
import com.zxhyis.toolss.ad.saveDataStoreBlock
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.broadcast.NotificationBroadcast
import com.zxhyis.toolss.ui.page.SplashActivity
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import okhttp3.internal.notify
import java.util.Timer
import kotlin.random.Random
/**
* 推送的帮助类,定义了推送逻辑
* 动态申请 <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
......@@ -64,10 +57,10 @@ import kotlin.random.Random
object NotificationHelper {
private const val CHANNEL_ID = "clean master notification"
private const val CHANNEL_NAME = "clean master channel"
private val TAG = "NotificationHelper"
val notificationId = 12086
private const val CHANNEL_ID = "super notification"
private const val CHANNEL_NAME = "super master channel"
private val TAG = "com.zxhyis.toolss.notification.NotificationHelper"
val notificationId = 11086
/**
......@@ -88,17 +81,6 @@ object NotificationHelper {
ID_PHONE_ACCELERATE,//被动推送加入主动推送列表
)
/**
* 轮训推送任务
*/
fun pushCircleOrderTimber(eventParams: EventParams) {
val pushManagement = ComUtils.getPushConfig()
val interval = pushManagement.loop_interval
LogEx.logDebug(TAG, "pushManagement=$pushManagement loop_interval=$interval")
val timer = Timer()
timer.schedule(NotificationTimerTask(eventParams), 0L, interval * 1000L)
}
/**
* 过滤可推送actionId
*/
......@@ -117,6 +99,7 @@ object NotificationHelper {
* 获取当前的推送id
*/
fun getPresentPushId(): Int {
val pid = Process.myPid()
val pushCircleOrder = ComUtils.getPushConfig().push_circle_order
LogEx.logDebug(TAG, "push_circle_order=$pushCircleOrder")
val tempList = arrayListOf<Int>()
......@@ -148,7 +131,7 @@ object NotificationHelper {
val usedJson = Gson().toJson(tempList)
FileApp.fContext.saveDataStoreBlock(stringPreferencesKey("push_circle_order"), usedJson)
LogEx.logDebug(TAG, "i=$i tempList=$tempList pushCircleOrder=$pushCircleOrder")
LogEx.logDebug(TAG, "pid=$pid i=$i tempList=$tempList pushCircleOrder=$pushCircleOrder")
return i
}
......@@ -285,6 +268,12 @@ object NotificationHelper {
intent.putExtra("desc", desc)
val customKey = "type"
intent.putExtra(customKey, actionId)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val bundle = Bundle()
bundle.putInt(customKey, actionId)
intent.putExtras(bundle)
val uri = Uri.parse("cleanapp://com.super.master/com.zxhyis.smartf.ui.page.SplashActivity?type=$actionId")
intent.data = uri
//按钮事件
......
package com.zxhyis.toolss.common.notification
package com.zxhyis.toolss.notification.broadcast
import android.app.ActivityManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build
import android.util.Log
import com.zxhyis.toolss.FileApp
import com.zxhyis.toolss.ad.ComUtils
import com.zxhyis.toolss.ad.PushManager
import com.zxhyis.toolss.ad.bean.PushCfg
import com.zxhyis.toolss.ad.PushStrategy
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_CHARGE
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_LOW_BATTERY_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_LOW_RAM_PUSH
import com.zxhyis.toolss.ad.createByActionId
import com.zxhyis.toolss.ad.queryDataStoreBlock
import com.zxhyis.toolss.ad.saveDataStoreBlock
import com.zxhyis.toolss.common.notification.NotificationHelper.postActionNotification
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.NotificationHelper.postActionNotification
import com.zxhyis.toolss.notification.NotificationUtils
import com.zxhyis.toolss.ui.receiver.BatteryReceiver
import kotlin.time.Duration.Companion.minutes
import kotlin.time.DurationUnit
......@@ -32,7 +27,7 @@ class ActionBroadcast : BroadcastReceiver() {
private var isLock = false
companion object {
private val TAG = "ActionBroadcast"
private val TAG = "com.zxhyis.toolss.notification.broadcast.ActionBroadcast"
fun Context.initBroadcast() {
LogEx.logDebug(TAG, "initBroadcast")
val filter = IntentFilter()
......@@ -72,7 +67,7 @@ class ActionBroadcast : BroadcastReceiver() {
Log.d("glc", "解锁")
if (mIsScreenOn && !isLock) {
// 展示主动推送
NotificationTimerTask(null).oneShotNotification()
NotificationUtils.sendTimerPush(null)
}
}
......@@ -86,21 +81,24 @@ class ActionBroadcast : BroadcastReceiver() {
}
Intent.ACTION_BATTERY_CHANGED -> {//电量改变
val level = BatteryReceiver.level
LogEx.logDebug(TAG, "电量改变 level=$level", isMust = true)
if (level < 50) {
val lastPushTime = FileApp.fContext.queryDataStoreBlock(createByActionId(ID_LOW_BATTERY_PUSH), 0)
val flag2 = (System.currentTimeMillis() - lastPushTime) > 20.minutes.toLong(DurationUnit.MILLISECONDS)
val isPushCfg = PushManager.isPush(ID_LOW_BATTERY_PUSH)
if (flag2 && isPushCfg) {
FileApp.fContext.postActionNotification(ID_LOW_BATTERY_PUSH, extra = level)
}
}
// lowBattery()
}
}
}
fun lowBattery() {
val level = BatteryReceiver.level
LogEx.logDebug(TAG, "电量改变 level=$level", isMust = true)
if (level < 50) {
val lastPushTime = FileApp.fContext.queryDataStoreBlock(createByActionId(ID_LOW_BATTERY_PUSH), 0)
val flag2 = (System.currentTimeMillis() - lastPushTime) > 20.minutes.toLong(DurationUnit.MILLISECONDS)
val isPushCfg = PushStrategy.isPush(ID_LOW_BATTERY_PUSH)
if (flag2 && isPushCfg) {
FileApp.fContext.postActionNotification(ID_LOW_BATTERY_PUSH, extra = level)
}
}
}
}
\ No newline at end of file
package com.zxhyis.toolss.notification.broadcast
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.NotificationUtils
class CloseNotificationReceiver : BroadcastReceiver() {
private val TAG = "com.zxhyis.toolss.notification.broadcast.CloseNotificationReceiver"
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
val notificationId = it.getIntExtra("notificationId", -1)
if (notificationId != -1 && it.action != "DELETE_NOTIFICATION") {
val notificationManager = context?.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
notificationManager?.cancel(NotificationUtils.NOTIFICATION_TAG, notificationId)
}
LogEx.logDebug(TAG, "onReceive")
}
}
}
package com.zxhyis.toolss.notification.broadcast
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationManagerCompat
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.NotificationHelper
/**
* 响应通知RemoteViews的点击事件
*/
class NotificationBroadcast : BroadcastReceiver() {
private val TAG = "NotificationBroadcast"
override fun onReceive(context: Context, intent: Intent?) {
val cancel = intent?.extras?.getString("cancel")
LogEx.logDebug(TAG, "onReceive cancel=$cancel")
if (cancel != null) {
cancelNotification(context)
}
}
companion object {
const val action = "com.super.master.notification.broadcast.NotificationBroadcast"
fun cancelNotification(context: Context) {
val id = NotificationHelper.notificationId
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.cancel(id)
}
}
}
\ No newline at end of file
package com.zxhyis.toolss.common.notification
package com.zxhyis.toolss.notification.broadcast
import android.app.ActivityManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Build
import com.zxhyis.toolss.FileApp
import com.zxhyis.toolss.ad.ComUtils
import com.zxhyis.toolss.ad.PushManager
import com.zxhyis.toolss.ad.bean.PushCfg
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_INSTALL_PACKAGE_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_LOW_BATTERY_PUSH
import com.zxhyis.toolss.ad.bean.PushCfg.Companion.ID_UNINSTALL_PACKAGE_PUSH
import com.zxhyis.toolss.common.notification.NotificationHelper.postActionNotification
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.NotificationHelper.postActionNotification
/**
* 只监听安装卸载
......@@ -23,7 +17,7 @@ import com.zxhyis.toolss.logic.LogEx
class PackageBroadcast : BroadcastReceiver() {
companion object {
private val TAG = "PackageBroadcast"
private val TAG = "com.zxhyis.toolss.notification.broadcast.PackageBroadcast"
fun Context.newInitBroadcast() {
// LogEx.logDebug(TAG, "initBroadcast")
val filter = IntentFilter()
......
package com.zxhyis.toolss.notification.broadcast
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class TimerControlReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (ACTION_START_TIMER == action && !isTimerRunning) {
// 启动定时器
// startTimer(intent,context)
} else if (ACTION_STOP_TIMER == action && isTimerRunning) {
// 停止定时器
stopTimer(context)
}
}
private fun stopTimer(context: Context) {
isTimerRunning = false
}
companion object {
private const val ACTION_START_TIMER = "com.zxhyis.toolss.timercontrol.START_TIMER"
private const val ACTION_STOP_TIMER = "com.zxhyis.toolss.timercontrol.STOP_TIMER"
private var isTimerRunning = false
}
}
\ No newline at end of file
package com.zxhyis.toolss.notification.provider
import android.content.ContentProvider
import android.content.ContentValues
import android.content.UriMatcher
import android.database.Cursor
import android.database.MatrixCursor
import android.net.Uri
class MyContentProvider : ContentProvider() {
private var myIntValue = 0
override fun onCreate(): Boolean {
return true
}
override fun query(
uri: Uri,
projection: Array<String>?,
selection: String?,
selectionArgs: Array<String>?,
sortOrder: String?
): Cursor {
var cursor: Cursor? = null
cursor = when (uriMatcher.match(uri)) {
1 -> {
val matrixCursor = MatrixCursor(arrayOf("myIntValue"))
matrixCursor.addRow(arrayOf<Any>(myIntValue))
matrixCursor
}
else -> throw IllegalArgumentException("Unsupported URI: $uri")
}
return cursor
}
override fun getType(uri: Uri): String? {
return null
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
return null
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
return 0
}
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int {
myIntValue = when (uriMatcher.match(uri)) {
1 -> values!!.getAsInteger("myIntValue")
else -> throw IllegalArgumentException("Unsupported URI: $uri")
}
return 1
}
companion object {
// 定义 UriMatcher
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
init {
uriMatcher.addURI("com.zxhyis.toolss", "myIntValue", 1)
}
}
}
package com.zxhyis.toolss.notification.provider
import android.content.ContentValues
import android.content.Context
import android.net.Uri
object MyContentProviderUtils {
private val CONTENT_URI = Uri.parse("content://com.zxhyis.toolss/myIntValue")
const val RESUMED_VALUE = 1
const val PAUSED_VALUE = 2
fun getMyIntValue(context: Context): Int {
var myIntValue = 0
val contentResolver = context.contentResolver
val cursor = contentResolver.query(CONTENT_URI, null, null, null, null)
if (cursor != null && cursor.moveToFirst()) {
myIntValue = cursor.getInt(0)
cursor.close()
}
return myIntValue
}
fun setMyIntValue(context: Context, myIntValue: Int) {
val contentResolver = context.contentResolver
val values = ContentValues()
values.put("myIntValue", myIntValue)
contentResolver.update(CONTENT_URI, values, null, null)
}
}
package com.zxhyis.toolss.notification.service
import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.IBinder
import android.os.Process
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.DeviceUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.ScreenUtils
import com.zxhyis.toolss.ad.ComUtils
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.notification.NotificationUtils
import com.zxhyis.toolss.notification.broadcast.ActionBroadcast
import com.zxhyis.toolss.notification.task.PeriodicTaskScheduler
class NotificationService : Service() {
private val TAG = "NotificationService"
companion object {
var isRunning = false
}
private var eventParams: EventParams? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
LogEx.logDebug(TAG, "onStartCommand")
if (isRunning) {
LogEx.logDebug(TAG, "Service is running" + Process.myPid())
return START_NOT_STICKY
}
isRunning = true
LogEx.logDebug(TAG, "Service is start " + Process.myPid())
initEvenParams()
if (eventParams != null) {
startTimer()
}
initBroadcast()
val notification = NotificationUtils.createPermanentNotification(applicationContext)
startForeground(1, notification)
return START_STICKY
}
private fun startTimer() {
LogEx.logDebug(TAG, "========================startTimer======================")
val pushManagement = ComUtils.getPushConfig()
PeriodicTaskScheduler.instance?.setPushParams(pushManagement)
?.setEventParam(eventParams)?.start(applicationContext)
}
fun Context.initBroadcast() {
LogEx.logDebug(TAG, "initBroadcast")
val filter = IntentFilter()
filter.addAction(Intent.ACTION_SCREEN_OFF)
filter.addAction(Intent.ACTION_SCREEN_ON)
filter.addAction(Intent.ACTION_USER_PRESENT)
filter.addAction(Intent.ACTION_POWER_CONNECTED)
filter.addAction(Intent.ACTION_POWER_DISCONNECTED)
filter.addAction(Intent.ACTION_BATTERY_CHANGED)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(ActionBroadcast(), filter, Context.RECEIVER_EXPORTED)
} else {
registerReceiver(ActionBroadcast(), filter)
}
}
private fun initEvenParams() {
eventParams = EventParams(
ScreenUtils.getScreenHeight(),
ScreenUtils.getScreenWidth(),
DeviceUtils.getModel(),
NetworkUtils.getNetworkType(),
AppUtils.getAppVersionName(),
DeviceUtils.getAndroidID()
)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onDestroy() {
LogEx.logDebug(TAG, "service is onDestroy")
super.onDestroy()
}
}
\ No newline at end of file
package com.zxhyis.toolss.notification.task
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.notification.NotificationUtils
class NotificationTask(private val eventParams: EventParams?) : Runnable {
private val TAG = "task.NotificationTask"
override fun run() {
NotificationUtils.sendTimerPush(eventParams)
}
}
\ No newline at end of file
package com.zxhyis.toolss.notification.task
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.zxhyis.toolss.FileApp
import com.zxhyis.toolss.logic.LogEx
class NotificationWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
private val TAG = "NotificationWorker"
override fun doWork(): Result {
if (PeriodicTaskScheduler.instance?.isRunning == false) {
LogEx.logDebug(TAG, "doWork start")
PeriodicTaskScheduler.instance?.start(FileApp.fContext)
}
return Result.success()
}
}
\ No newline at end of file
package com.zxhyis.toolss.notification.task
import android.content.Context
import androidx.work.BackoffPolicy
import androidx.work.Data
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.google.gson.Gson
import com.zxhyis.toolss.ad.bean.EventParams
import com.zxhyis.toolss.ad.bean.PushManagement
import com.zxhyis.toolss.logic.LogEx
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit
class PeriodicTaskScheduler private constructor() {
private val TAG = "PeriodicTaskScheduler"
private val scheduler: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
private var pushManagement: PushManagement? = null
private var eventParams: EventParams? = null
var isRunning = false
fun start(context: Context) {
startTimer()
startPeriodicTask(context)
}
fun setPushParams(pushManagement: PushManagement): PeriodicTaskScheduler {
this.pushManagement = pushManagement
// TIMER_INTERVAL_MINUTES = pushManagement.loop_interval
return this
}
fun setEventParam(eventParams: EventParams?): PeriodicTaskScheduler {
this.eventParams = eventParams
return this
}
/**
* 轮训通知
*/
private fun startTimer() {
LogEx.logDebug(TAG, "startTimer is isRunning=$isRunning")
if (isRunning) {
return
}
scheduler.scheduleAtFixedRate(NotificationTask(eventParams), 0, TIMER_INTERVAL_MINUTES.toLong(), TimeUnit.SECONDS)
isRunning = true
}
/**
* 周期性启动轮训 PeriodicWorkRequest
*/
private fun startPeriodicTask(context: Context) {
val isWorkRunning = isNotificationWorkerRunning(context)
LogEx.logDebug(TAG, "startPeriodicTask isWorkRunning=$isWorkRunning")
if (isWorkRunning) {
LogEx.logDebug(TAG, "startPeriodicTask is Running")
return
}
val inputData = Data.Builder()
.putString("param", Gson().toJson(eventParams))
.build()
val periodicWorkRequest: PeriodicWorkRequest =
PeriodicWorkRequest.Builder(NotificationWorker::class.java, CHECK_INTERVAL_MINUTES, TimeUnit.MINUTES)
.setBackoffCriteria(BackoffPolicy.LINEAR, PeriodicWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)
.addTag(WORKER_TAG)
.setInputData(inputData)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(WORKER_TAG, ExistingPeriodicWorkPolicy.REPLACE, periodicWorkRequest)
}
fun stop() {
scheduler.shutdown()
isRunning = false
}
companion object {
var instance: PeriodicTaskScheduler? = null
get() {
if (field == null) {
synchronized(PeriodicTaskScheduler::class.java) {
if (field == null) {
field = PeriodicTaskScheduler()
}
}
}
return field
}
private set
private const val WORKER_TAG = "Notification_super_timer"
private const val CHECK_INTERVAL_MINUTES = 15L
private var TIMER_INTERVAL_MINUTES = 30
private fun isNotificationWorkerRunning(context: Context): Boolean {
val workManager = WorkManager.getInstance(context)
try {
val workInfos = workManager.getWorkInfosByTag(WORKER_TAG).get()
for (workInfo in workInfos) {
if (workInfo.state == WorkInfo.State.RUNNING || workInfo.state == WorkInfo.State.ENQUEUED) {
return true
}
}
} catch (e: ExecutionException) {
e.printStackTrace()
} catch (e: InterruptedException) {
e.printStackTrace()
}
return false
}
}
}
......@@ -23,12 +23,12 @@ import com.zxhyis.toolss.ad.ConfigHelper
import com.zxhyis.toolss.ad.EventHelper
import com.zxhyis.toolss.ad.bean.PushCfg
import com.zxhyis.toolss.base.TopActivity
import com.zxhyis.toolss.common.notification.AppService
import com.zxhyis.toolss.common.notification.NotificationBroadcast
import com.zxhyis.toolss.databinding.ActivityLayoutSplashBinding
import com.zxhyis.toolss.logic.LogEx
import com.zxhyis.toolss.logic.setOnClick
import com.zxhyis.toolss.logic.startActivity
import com.zxhyis.toolss.notification.broadcast.NotificationBroadcast
import com.zxhyis.toolss.notification.service.NotificationService
import com.zxhyis.toolss.ui.home.MainActivity
import com.zxhyis.toolss.ui.page.appmanager.AppManager2Activity
import com.zxhyis.toolss.ui.page.bigfileclean.BigFileCleanActivity
......@@ -142,12 +142,14 @@ class SplashActivity : TopActivity<ActivityLayoutSplashBinding>() {
startActivity(intent)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
startForegroundService(Intent(this, AppService::class.java))
} else {
startService(Intent(this, AppService::class.java))
if (ConfigHelper.ifAgreePrivacy) {
val intent = Intent(this, NotificationService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
}
}
private fun loadAd() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment