Commit 2c0cd27f authored by wanglei's avatar wanglei

Merge remote-tracking branch 'origin/master'

parents 4ca82a26 c3135d6b
......@@ -92,13 +92,13 @@ dependencies {
//广告
implementation("com.google.android.gms:play-services-ads:23.1.0")
implementation 'com.google.ads.mediation:applovin:12.4.3.0'
implementation 'com.google.ads.mediation:applovin:13.0.1.0'
implementation 'com.google.ads.mediation:facebook:6.17.0.0'
implementation 'com.google.ads.mediation:mintegral:16.7.21.0'
implementation 'com.google.ads.mediation:pangle:5.9.0.4.0'
//max
implementation 'com.applovin:applovin-sdk:+'
// implementation 'com.applovin:applovin-sdk:+'
// implementation 'com.applovin.mediation:google-adapter:+'
// implementation 'com.applovin.mediation:facebook-adapter:+'
// implementation 'com.applovin.mediation:mintegral-adapter:+'
......@@ -115,9 +115,14 @@ dependencies {
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-crashlytics-ktx'
implementation 'com.google.firebase:firebase-analytics:21.6.2'
implementation("com.google.firebase:firebase-messaging-directboot")
//google 内购订阅
def billing_version = "7.0.0"
implementation "com.android.billingclient:billing:$billing_version"
//work
implementation("androidx.work:work-runtime-ktx:2.7.1") // 请使用最新版本
}
\ No newline at end of file
......@@ -250,12 +250,19 @@
android:name="com.google.android.gms.ads.flag.NATIVE_AD_DEBUGGER_ENABLED"
android:value="false" />
<!-- 常驻通知栏 -->
<!-- <service-->
<!-- android:name=".service.StayNotificationService"-->
<!-- android:foregroundServiceType="dataSync" />-->
<service
android:name=".service.StayNotificationService"
android:foregroundServiceType="dataSync" />
android:name=".service.StayJobService"
android:exported="false"
android:foregroundServiceType="dataSync"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:directBootAware="true"
android:name=".fcm.MessagingService"
android:exported="true">
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
......
......@@ -16,8 +16,10 @@ import com.base.filerecoveryrecyclebin.help.BlackUtils
import com.base.filerecoveryrecyclebin.help.ConfigHelper
import com.base.filerecoveryrecyclebin.utils.ActivityManagerUtils
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.base.filerecoveryrecyclebin.utils.InstallHelps
import com.base.filerecoveryrecyclebin.help.InstallHelps
import com.base.filerecoveryrecyclebin.service.StayJobService.Companion.startJob
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.base.filerecoveryrecyclebin.work.schedulePeriodicWork
import com.facebook.FacebookSdk
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import kotlinx.coroutines.Dispatchers
......@@ -59,7 +61,7 @@ class MyApplication : BaseApplication() {
fun initApp(isStartClick: Boolean = false) {
if (!isStartClick) {
Log.e("MXL", "initApp: ", )
Log.e("MXL", "initApp: ")
@Suppress("DEPRECATION")
FacebookSdk.sdkInitialize(applicationContext)
// FacebookSdk.setIsDebugEnabled(true)
......@@ -72,6 +74,8 @@ class MyApplication : BaseApplication() {
InstallHelps.init()
BlackUtils.requestBlack()
initLifeListener()
schedulePeriodicWork(this)
startJob()
}
if (ifAgreePrivacy) {
......
package com.base.filerecoveryrecyclebin.activity
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.view.View
import android.widget.Toast
import androidx.activity.addCallback
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.base.filerecoveryrecyclebin.activity.repeat.RepeatActivity
import com.base.filerecoveryrecyclebin.activity.repeat.RepeatActivity.Companion.similarPhotoDeleted
import com.base.filerecoveryrecyclebin.activity.screenshot.ScreenShotActivity.Companion.screenPhotoDeleted
import com.base.filerecoveryrecyclebin.ads.admob.AdmobBannerUtils
import com.base.filerecoveryrecyclebin.bean.MediaBean
import com.base.filerecoveryrecyclebin.databinding.ActivityMainBinding
......@@ -33,8 +32,10 @@ import com.base.filerecoveryrecyclebin.view.PermissionDialog.showPermissionBotto
import com.base.filerecoveryrecyclebin.view.RateStarPop.showRateStarPopDialog
import com.facebook.appevents.AppEventsLogger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.last
import kotlinx.coroutines.launch
import java.io.File
import java.util.Locale
......@@ -118,8 +119,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
logger.logEvent("home")
AppPreferences.getInstance().put("fb_home", 1)
}
}
private fun initStayServiceObserver() {
......@@ -186,22 +185,35 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
}
private var initPhotoSizeFirst = true
private fun initPhotoSize() = lifecycleScope.launch(Dispatchers.IO) {
LogEx.logDebug(TAG, "initPhotoSize")
val list = arrayListOf<MediaBean>()
getImageMedia(list)
val screenSize =
list.filter { it.path.lowercase(Locale.ENGLISH).contains("screenshot") }.map { File(it.path) }.sumOf { it.length() }
val similar = calculateSimilar(list).flatMap { it.value }.map { File(it.path) }.sumOf { it.length() }
var screenSize = 0L
if (screenPhotoDeleted || initPhotoSizeFirst) {
screenSize =
list.filter { it.path.lowercase(Locale.ENGLISH).contains("screenshot") }.map { File(it.path) }.sumOf { it.length() }
screenPhotoDeleted = false
delay(1500)
photoSizeFlow.emit(Pair(screenSize, 0L))
}
var similar = 0L
if (similarPhotoDeleted || initPhotoSizeFirst) {
val similarPhoto = calculateSimilar(list)
RepeatActivity.readySimilarList = similarPhoto
similar = similarPhoto.flatMap { it.value }.map { File(it.path) }.sumOf { it.length() }
similarPhotoDeleted = false
delay(1500)
photoSizeFlow.emit(Pair(screenSize, similar))
}
LogEx.logDebug(TAG, "screenSize=$screenSize")
initPhotoSizeFirst = false
delay(1500)
photoSizeFlow.emit(Pair(screenSize, similar))
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.Color
import androidx.activity.OnBackPressedCallback
import androidx.core.view.updatePadding
import com.base.filerecoveryrecyclebin.activity.appmanager.AppManagerAnimationActivity
import com.base.filerecoveryrecyclebin.activity.appprocess.AppProcessAnimationActivity
import com.base.filerecoveryrecyclebin.activity.battery.BatteryInfoAnimationActivity
import com.base.filerecoveryrecyclebin.activity.junkclean.ScanJunkActivity
......@@ -15,6 +16,8 @@ import com.base.filerecoveryrecyclebin.activity.screenshot.ScreenShotAnimationAc
import com.base.filerecoveryrecyclebin.activity.whatsapp.WhatsAppCleanerAnimationActivity
import com.base.filerecoveryrecyclebin.adapter.AppFunctionAdapter
import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper
import com.base.filerecoveryrecyclebin.bean.ConstObject
import com.base.filerecoveryrecyclebin.bean.ConstObject.APP_MANAGER
import com.base.filerecoveryrecyclebin.bean.ConstObject.APP_PROCESS
import com.base.filerecoveryrecyclebin.bean.ConstObject.BATTERY_INFO
import com.base.filerecoveryrecyclebin.bean.ConstObject.JUNK_CLEANER
......@@ -53,13 +56,6 @@ class ResultActivity : BaseActivity<ActivityLayoutResultBinding>() {
startActivity(Intent(this, ScanJunkActivity::class.java))
}
REPEAT_PHOTOS -> {
startActivity(Intent(this, RepeatAnimationActivity::class.java))
}
SCREENSHOT_CLEANER -> {
startActivity(Intent(this, ScreenShotAnimationActivity::class.java))
}
RECOVERY_PHOTOS -> {
startActivity(Intent(this, FileScanResultActivity::class.java).apply {
......@@ -79,6 +75,15 @@ class ResultActivity : BaseActivity<ActivityLayoutResultBinding>() {
})
}
REPEAT_PHOTOS -> {
startActivity(Intent(this, RepeatAnimationActivity::class.java))
}
SCREENSHOT_CLEANER -> {
startActivity(Intent(this, ScreenShotAnimationActivity::class.java))
}
WHATSAPP_CLEANER -> {
startActivity(Intent(this, WhatsAppCleanerAnimationActivity::class.java))
}
......@@ -87,6 +92,10 @@ class ResultActivity : BaseActivity<ActivityLayoutResultBinding>() {
startActivity(Intent(this, AppProcessAnimationActivity::class.java))
}
APP_MANAGER -> {
startActivity(Intent(this, AppManagerAnimationActivity::class.java))
}
LARGE_FILE -> {
startActivity(Intent(this, LargeFileAnimationActivity::class.java))
}
......
......@@ -11,6 +11,8 @@ import com.base.filerecoveryrecyclebin.fcm.FCMManager.subscribeToTopic
import com.base.filerecoveryrecyclebin.fcm.FCMManager.unsubscribeFromTopic
import com.base.filerecoveryrecyclebin.help.BaseActivity
import com.base.filerecoveryrecyclebin.help.ConfigHelper
import com.base.filerecoveryrecyclebin.service.StayJobService
import com.base.filerecoveryrecyclebin.service.StayJobService.Companion.startJob
import com.base.filerecoveryrecyclebin.service.StayNotificationService
import com.base.filerecoveryrecyclebin.service.StayNotificationService.Companion.startStayNotification
import com.base.filerecoveryrecyclebin.utils.BarUtils
......@@ -41,10 +43,12 @@ class SettingActivity : BaseActivity<ActivitySettingBinding>() {
binding.switchStayNotification.setOnCheckedChangeListener { buttonView, isChecked ->
stayNotification = isChecked
if (isChecked) {
startStayNotification()
startJob()
// startStayNotification()
} else {
val serviceIntent = Intent(this, StayNotificationService::class.java)
stopService(serviceIntent)
StayJobService.isCancel = true
// val serviceIntent = Intent(this, StayNotificationService::class.java)
// stopService(serviceIntent)
}
}
binding.switchFcmNotification.setOnCheckedChangeListener { buttonView, isChecked ->
......
......@@ -14,7 +14,6 @@ import com.base.filerecoveryrecyclebin.databinding.ActivityBatteryBinding
import com.base.filerecoveryrecyclebin.help.BaseActivity
import com.base.filerecoveryrecyclebin.receiver.BatteryReceiver
import com.base.filerecoveryrecyclebin.utils.BarUtils
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.base.filerecoveryrecyclebin.view.DialogViews.showExitFunctionDialog
import kotlin.math.abs
......
......@@ -63,7 +63,7 @@ class BatteryInfoAnimationActivity : BaseActivity<ActivityBatteryInfoAnimationBi
binding.lottieCompleted.playAnimation()
binding.tv.text = "Completed!"
delay(1000)
AdmobMaxHelper.admobMaxShowOpenAd(this@BatteryInfoAnimationActivity, showBeforeAction = {}) {
AdmobMaxHelper.admobMaxShowInterstitialAd(this@BatteryInfoAnimationActivity) {
binding.lottie.clearAnimation()
startActivity(Intent(this@BatteryInfoAnimationActivity, BatteryActivity::class.java))
finish()
......
......@@ -4,19 +4,14 @@ import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.util.Log
import android.view.View
import androidx.activity.addCallback
import androidx.annotation.RequiresApi
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.activity.ResultActivity
import com.base.filerecoveryrecyclebin.activity.recovery.FileRecoveredActivity
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinFileEx.findRecycleBinFile
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinFileEx.findRecycleBinJsonFile
import com.base.filerecoveryrecyclebin.bean.ConstObject
import com.base.filerecoveryrecyclebin.bean.ConstObject.RECYCLE_BIN
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean.Companion.mAudioStr
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean.Companion.mDocumentStr
......@@ -27,6 +22,7 @@ import com.base.filerecoveryrecyclebin.help.BaseActivity
import com.base.filerecoveryrecyclebin.help.KotlinExt.toFormatSize
import com.base.filerecoveryrecyclebin.help.KotlinExt.toFormatTime
import com.base.filerecoveryrecyclebin.help.VideoPlayerUtil
import com.base.filerecoveryrecyclebin.service.BackUpUtils
import com.base.filerecoveryrecyclebin.service.BackUpUtils.recoveryFile
import com.base.filerecoveryrecyclebin.utils.BarUtils
import com.base.filerecoveryrecyclebin.utils.LogEx
......@@ -85,7 +81,7 @@ class RecycleBinDetailActivity : BaseActivity<ActivityRecycleBinDetailBinding>()
}
Glide.with(this).load(bean.backupPath).centerCrop().into(binding.iv)
binding.tvName.text = bean.path
binding.tvPath.text = bean.path
binding.tvSize.text = bean.size.toFormatSize()
binding.tvTime.text = "Delete time:${bean.deleteTime.toFormatTime()}"
}
......@@ -106,7 +102,7 @@ class RecycleBinDetailActivity : BaseActivity<ActivityRecycleBinDetailBinding>()
runCatching {
binFile.copyTo(file, true)
binFile.delete()
recoveryFile(bean.name)
recoveryFile(bean.namePath)
}
}
startActivity(Intent(this, FileRecoveredActivity::class.java).apply {
......@@ -132,20 +128,17 @@ class RecycleBinDetailActivity : BaseActivity<ActivityRecycleBinDetailBinding>()
binding.ivBofang.setOnClickListener {
recycleBinBean?.let { bean ->
val file = File(bean.path)
val binFile = findRecycleBinFile(file.name)
VideoPlayerUtil.playVideo(this, binFile?.absolutePath)
VideoPlayerUtil.playVideo(this, bean.backupPath)
}
}
binding.flDelete.setOnClickListener {
recycleBinBean?.let { bean ->
val file = File(bean.path)
val binFile = findRecycleBinFile(file.name)
val binJsonFile = findRecycleBinJsonFile(file.name)
binFile?.delete()
binJsonFile?.delete()
BackUpUtils.deleteFileSp(bean.namePath)
val file = File(bean.backupPath)
if (file.exists()) {
file.delete()
}
}
finish()
}
......
......@@ -27,6 +27,7 @@ import com.base.filerecoveryrecyclebin.view.DialogViews.showGerPermission
import com.base.filerecoveryrecyclebin.view.DialogViews.showTittleDescExitDialog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import java.io.File
class RepeatActivity : BaseActivity<ActivityRepeatBinding>() {
......@@ -74,9 +75,6 @@ class RepeatActivity : BaseActivity<ActivityRepeatBinding>() {
})
}
// val s = opencvCompareSimilar("/storage/emulated/0/DCIM/1.jpg","/storage/emulated/0/DCIM/22.jpg")
// LogEx.logDebug(TAG,"s=$s")
// Toast.makeText(this, s.toString(), Toast.LENGTH_SHORT).show()
}
override fun initListener() {
......@@ -121,6 +119,7 @@ class RepeatActivity : BaseActivity<ActivityRepeatBinding>() {
private fun cleanFile() {
similarPhotoDeleted = true
lifecycleScope.launch(Dispatchers.IO) {
val cleanList = mediaAdapter.getSelectData().second
cleanList.forEach {
......@@ -147,20 +146,24 @@ class RepeatActivity : BaseActivity<ActivityRepeatBinding>() {
val list = arrayListOf<MediaBean>()
getImageMedia(list)
LogEx.logDebug(TAG, "list=${list.size}")
val similarList = calculateSimilar(list)
// similarList.forEach { t, u ->
// LogEx.logDebug(TAG, "t=$t u=$u")
// }
// val hashMap = HashMap<String, ArrayList<MediaBean>>()
// list.forEach {
// val time = it.time.toFormatTime()
// if (hashMap[time] == null) {
// hashMap[time] = arrayListOf()
// }
// hashMap[time]?.add(it)
// }
val beanList = similarList.map { map ->
list.reversed()
val result = if (readySimilarList == null) {
val similarList = HashMap<String, ArrayList<MediaBean>>()
val startTime = System.currentTimeMillis()
val endTime = withTimeout(15 * 1000) {
calculateSimilar(list, similarList)
System.currentTimeMillis()
}
val spendTime = endTime - startTime
LogEx.logDebug(TAG, "spendTime=$spendTime startTime=$startTime endTime=$endTime")
similarList
} else {
readySimilarList ?: hashMapOf()
}
val beanList = result.map { map ->
val time = File(map.key).lastModified().toFormatTime()
MediaTimeBean(time = time, beans = map.value)
}
......@@ -175,7 +178,11 @@ class RepeatActivity : BaseActivity<ActivityRepeatBinding>() {
binding.llEmpty.isVisible = beanList.isEmpty()
}
}
}
companion object {
var readySimilarList: HashMap<String, ArrayList<MediaBean>>? = null
var similarPhotoDeleted: Boolean = false
}
}
\ No newline at end of file
......@@ -22,9 +22,12 @@ import com.base.filerecoveryrecyclebin.utils.BarUtils
import com.base.filerecoveryrecyclebin.view.DialogViews.showDeletePermanentlyDialog
import com.base.filerecoveryrecyclebin.view.DialogViews.showExitFunctionDialog
import com.base.filerecoveryrecyclebin.view.DialogViews.showGerPermission
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
......@@ -32,6 +35,7 @@ import kotlin.collections.HashSet
class ScreenShotActivity : BaseActivity<ActivityScreenShotBinding>() {
private val TAG = "ScreenShotActivity"
private lateinit var screenShotAdapter: ScreenShotAdapter
override val binding: ActivityScreenShotBinding by lazy {
......@@ -66,7 +70,6 @@ class ScreenShotActivity : BaseActivity<ActivityScreenShotBinding>() {
@SuppressLint("SetTextI18n")
private fun setCleanUpUi(size: Int) {
if (size > 0) {
binding.tvClean.isEnabled = true
......@@ -79,7 +82,9 @@ class ScreenShotActivity : BaseActivity<ActivityScreenShotBinding>() {
}
private fun initData() = lifecycleScope.launch(Dispatchers.IO) {
val list = getScreenshotBean()
launch(Dispatchers.Main) {
screenShotAdapter.setData(list)
val size = list.sumOf { it.screenPhotoBean.sumOf { ss -> ss.file.length() } }
......@@ -135,6 +140,7 @@ class ScreenShotActivity : BaseActivity<ActivityScreenShotBinding>() {
@SuppressLint("SetTextI18n")
private fun cleanFile() {
screenPhotoDeleted = true
val files = screenShotAdapter.getSelectData()
lifecycleScope.launch(Dispatchers.IO) {
async {
......@@ -156,28 +162,42 @@ class ScreenShotActivity : BaseActivity<ActivityScreenShotBinding>() {
}
}
private fun getScreenshotBean(): ArrayList<ScreenshotBean> {
private fun CoroutineScope.getScreenshotBean(myBeans: ArrayList<ScreenshotBean>? = null): ArrayList<ScreenshotBean> {
val beans = myBeans ?: arrayListOf<ScreenshotBean>()
val dcim = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
val screenFiles = FileHelp.getDirFiles(dcim)
val hash = HashMap<String, HashSet<File>>()
val formatter = SimpleDateFormat("yyyy/MM", Locale.getDefault())
screenFiles.forEach { file ->
val time = formatter.format(file.lastModified())
if (hash[time] == null) {
hash[time] = HashSet()
runCatching {
screenFiles.forEach { file ->
val time = formatter.format(file.lastModified())
if (hash[time] == null) {
hash[time] = HashSet()
}
val set = hash[time]
set?.add(file)
if (!isActive) throw Exception("out Time")
}
val set = hash[time]
set?.add(file)
}
val beans = arrayListOf<ScreenshotBean>()
hash.forEach { (t, u) ->
val arrayList = arrayListOf<ScreenPhotoBean>()
val mapList = u.map { file -> ScreenPhotoBean(file) }
arrayList.addAll(mapList)
beans.add(ScreenshotBean(t, arrayList))
runCatching {
hash.forEach { (t, u) ->
val arrayList = arrayListOf<ScreenPhotoBean>()
val mapList = u.map { file -> ScreenPhotoBean(file) }
arrayList.addAll(mapList)
beans.add(ScreenshotBean(t, arrayList))
if (!isActive) throw Exception("out Time")
}
}
return beans
}
companion object {
var screenPhotoDeleted: Boolean = false
}
}
\ No newline at end of file
......@@ -64,7 +64,6 @@ class Splash2Activity : BaseActivity<ActivitySplashBinding>(),
mTaskManager = TaskManager(binding, this)
if (ifAgreePrivacy) {
onAgreePrivacy()
// EventUtils.event("app_start")
} else {
PrivacyManager(binding, this, this)
}
......@@ -81,18 +80,11 @@ class Splash2Activity : BaseActivity<ActivitySplashBinding>(),
override fun onAgreePrivacy() {
EventUtils.event("app_start")
if (jumpType == 0) {
startStayNotification()
// startStayNotification()
}
AdmobMaxHelper.preloadAd(this)
mTaskManager?.startProgress()
loadAd()
// if (!ConfigHelper.ifGuest) {
// mTaskManager?.pauseProgress()
// onProgressMax()
// return
// } else {
// loadAd()
// }
}
......@@ -103,9 +95,6 @@ class Splash2Activity : BaseActivity<ActivitySplashBinding>(),
}
private fun loadAd() {
// AdmobMaxHelper.admobMaxShowOpenAd(this){
//
// }
AdmobMaxHelper.admobMaxShowOpenAd(this, {
mTaskManager?.pauseProgress()
}, {
......
......@@ -89,6 +89,7 @@ object StartUtils {
if (!isHotLaunch) {
if (!isGuide) {
context.startActivity(Intent(context, GuideActivity::class.java))
isGuide = true
} else {
context.startActivity(Intent(context, MainActivity::class.java))
}
......
......@@ -32,7 +32,6 @@ class AppFunctionAdapter(val click: (name: String) -> Unit) :
Fun(RECOVERY_PHOTOS, R.mipmap.photos_ss),
Fun(RECOVERY_VIDEOS, R.mipmap.videos_ss),
Fun(RECOVERY_DOCUMENTS, R.mipmap.documents_ss),
Fun(PRIVACY_SPACE, R.mipmap.space),
Fun(REPEAT_PHOTOS, R.mipmap.repeatedphotos),
Fun(SCREENSHOT_CLEANER, R.mipmap.screenshots),
Fun(WHATSAPP_CLEANER, R.mipmap.h_whatsapp),
......
......@@ -2,15 +2,11 @@ package com.base.filerecoveryrecyclebin.adapter
import android.annotation.SuppressLint
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinFileEx.findRecycleBinFile
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean.Companion.mAudioStr
import com.base.filerecoveryrecyclebin.bean.RecycleBinBean.Companion.mDocumentStr
......@@ -26,7 +22,6 @@ import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import java.io.File
class RecycleBinAdapter(val click: (bean: RecycleBinBean) -> Unit) : RecyclerView.Adapter<RecycleBinAdapter.RBAV>() {
......@@ -86,7 +81,7 @@ class RecycleBinAdapter(val click: (bean: RecycleBinBean) -> Unit) : RecyclerVie
binding.iv.setImageResource(R.mipmap.h_documents)
}
binding.tvName.text = bean.name
binding.tvName.text = bean.namePath
binding.tvTime.text = "delete time:" + bean.deleteTime.toFormatTime()
binding.tvSize.text = bean.size.toFormatSize()
binding.root.setOnClickListener {
......
package com.base.filerecoveryrecyclebin.ads
//object AdmobCommonUtils {
//
// private var lastAd: Any? = null
// private var maxMultiClick = AppPreferences.getInstance().getString("maxMultiClick", "10").toInt()
// private var multiClick = 0
// fun isMultiClick(currentAd: Any?) {
// if (currentAd == null) {
// return
// }
// if (lastAd == currentAd) {
// multiClick++
// if (multiClick >= maxMultiClick) {
// AdDisplayUtils.getInstance()
// .setAdClickCount(AdDisplayUtils.getInstance().maxAdClickCount)
// ActivityManagerUtils.getInstance().finishAllActivity()
// return
// }
// } else {
// multiClick = 0
// }
//
// lastAd = currentAd
//
// }
//}
\ No newline at end of file
......@@ -112,6 +112,18 @@ public class AdDisplayUtils {
obj2.put("shouldDisplayAd", shouldDisplayAd);
obj2.put("shouldIncrementClickCount", shouldIncrementClickCount);
obj2.put("adDisplayCount", adDisplayCount);
obj2.put("maxAdDisplayCount", maxAdDisplayCount);
obj2.put("adClickCount", adClickCount);
obj2.put("maxAdClickCount", maxAdClickCount);
obj2.put("adRequestFailCount", adRequestFailCount);
obj2.put("adRequestCount", maxAdRequestFailCount);
obj2.put("adRequestCount", adRequestCount);
obj2.put("maxAdRequestCount", maxAdRequestCount);
obj2.put("ad_unit", ad_unit);
EventUtils.INSTANCE.event("ad_show_error", null, obj2, false);
} catch (JSONException ignored) {
......
......@@ -3,15 +3,9 @@ package com.base.filerecoveryrecyclebin.ads
import android.app.Activity
import android.util.Log
import android.view.ViewGroup
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.ads.admob.AdmobInterstitialUtils
import com.base.filerecoveryrecyclebin.ads.admob.AdmobNativeUtils
import com.base.filerecoveryrecyclebin.ads.admob.AdmobOpenUtils
import com.base.filerecoveryrecyclebin.ads.max.AdMaxInit
import com.base.filerecoveryrecyclebin.ads.max.AdMaxInit.initAdMax
import com.base.filerecoveryrecyclebin.ads.max.AdMaxInterstitialUtils
import com.base.filerecoveryrecyclebin.ads.max.AdMaxNativeUtils
import com.base.filerecoveryrecyclebin.ads.max.AdMaxOpenUtils
import com.base.filerecoveryrecyclebin.help.BaseApplication
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.base.filerecoveryrecyclebin.utils.EventUtils
......@@ -51,7 +45,7 @@ object AdmobMaxHelper {
if (isBlack) {
return
}
if (getSpAdmobTrueMaxFalse()) {
if (true) {
if (!isAdInit.get()) {
LogEx.logDebug(TAG, "init sp Admob")
MobileAds.initialize(BaseApplication.context) { initializationStatus ->
......@@ -59,20 +53,21 @@ object AdmobMaxHelper {
}
}
} else {
if (!isAdInit.get()) {
LogEx.logDebug(TAG, "init sp AdMax")
BaseApplication.context.initAdMax()
}
// if (!isAdInit.get()) {
// LogEx.logDebug(TAG, "init sp AdMax")
// BaseApplication.context.initAdMax()
// }
}
}
//End end
fun isOpenAdLoaded(): Boolean {
return if (getSpAdmobTrueMaxFalse()) {
AdmobOpenUtils.isOpenAdLoaded()
} else {
AdMaxOpenUtils.isOpenAdLoaded()
}
// if (getSpAdmobTrueMaxFalse()) {
//
// } else {
// AdMaxOpenUtils.isOpenAdLoaded()
// }
return AdmobOpenUtils.isOpenAdLoaded()
}
//展示广告关闭时赋值
......@@ -96,14 +91,14 @@ object AdmobMaxHelper {
return
}
if (getSpAdmobTrueMaxFalse()) {
if (true) {
AdmobInterstitialUtils.showInterstitialAd(activity) {
onHidden?.invoke()
}
} else {
AdMaxInterstitialUtils.showInterstitialAd(activity) {
onHidden?.invoke()
}
// AdMaxInterstitialUtils.showInterstitialAd(activity) {
// onHidden?.invoke()
// }
}
}
......@@ -116,14 +111,14 @@ object AdmobMaxHelper {
onHidden?.invoke()
return
}
if (getSpAdmobTrueMaxFalse()) {
if (true) {
AdmobOpenUtils.showAppOpenAd(activity, showBefore = showBeforeAction) {
onHidden?.invoke()
}
} else {
AdMaxOpenUtils.showAppOpenAd(activity, loadCallBack = showBeforeAction) {
onHidden?.invoke()
}
// AdMaxOpenUtils.showAppOpenAd(activity, loadCallBack = showBeforeAction) {
// onHidden?.invoke()
// }
}
}
......@@ -131,20 +126,20 @@ object AdmobMaxHelper {
if (isBlack) {
return
}
if (getSpAdmobTrueMaxFalse()) {
if (true) {
AdmobNativeUtils.showNativeAd(activity, parent)
} else {
var layout = R.layout.layout_max_native_small
if (where == 0) {
layout = R.layout.layout_max_native_small_f8f8f8
}
if (where == 1) {
layout = R.layout.layout_max_native_big
}
if (where == 2) {
layout = R.layout.layout_max_native_big_2
}
AdMaxNativeUtils.showNativeAd(activity, parent, layout)
// var layout = R.layout.layout_max_native_small
// if (where == 0) {
// layout = R.layout.layout_max_native_small_f8f8f8
// }
// if (where == 1) {
// layout = R.layout.layout_max_native_big
// }
// if (where == 2) {
// layout = R.layout.layout_max_native_big_2
// }
// AdMaxNativeUtils.showNativeAd(activity, parent, layout)
}
}
......@@ -153,19 +148,19 @@ object AdmobMaxHelper {
return
}
if (getSpAdmobTrueMaxFalse()) {
AdmobOpenUtils.loadAppOpenAd()
if (true) {
// AdmobOpenUtils.loadAppOpenAd()
AdmobInterstitialUtils.loadInterstitialAd(activity)
} else {
if (isAdInit.get()) {
AdMaxOpenUtils.loadAppOpenAd(activity)
AdMaxInterstitialUtils.loadInterstitialAd(activity)
// AdMaxOpenUtils.loadAppOpenAd(activity)
// AdMaxInterstitialUtils.loadInterstitialAd(activity)
} else {
AdMaxInit.maxInitAction = {
Log.d(TAG, "max init suc")
// AdMaxInit.maxInitAction = {
Log.d(TAG, "max init suc")
// AdMaxOpenUtils.loadAppOpenAd(activity)
// AdMaxInterstitialUtils.loadInterstitialAd(activity)
}
// }
}
}
}
......
package com.base.filerecoveryrecyclebin.ads.admob
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils
import com.base.filerecoveryrecyclebin.utils.ActivityManagerUtils
import com.base.filerecoveryrecyclebin.utils.AppPreferences
object AdmobCommonUtils {
private var lastAd: Any? = null
private var maxMultiClick = AppPreferences.getInstance().getString("maxMultiClick", "10").toInt()
private var multiClick = 0
fun isMultiClick(currentAd: Any?) {
if (currentAd == null) {
return
}
if (lastAd == currentAd) {
multiClick++
if (multiClick >= maxMultiClick) {
AdDisplayUtils.getInstance()
.setAdClickCount(AdDisplayUtils.getInstance().maxAdClickCount)
ActivityManagerUtils.getInstance().finishAllActivity()
return
}
} else {
multiClick = 0
}
lastAd = currentAd
}
}
\ No newline at end of file
package com.base.filerecoveryrecyclebin.ads.admob
import android.annotation.SuppressLint
import android.app.Activity
import android.app.Dialog
import android.os.CountDownTimer
import android.widget.Toast
import com.base.filerecoveryrecyclebin.BuildConfig
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils
import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper.lastShowedOnHiddenTime
import com.base.filerecoveryrecyclebin.ads.admob.AdmobCommonUtils.isMultiClick
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.clickAd
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.pullAd
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.showAd
import com.base.filerecoveryrecyclebin.help.BaseApplication
import com.base.filerecoveryrecyclebin.help.ConfigHelper
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.base.filerecoveryrecyclebin.utils.EventUtils
import com.base.filerecoveryrecyclebin.view.CustomDialog
import com.google.android.gms.ads.AdError
......@@ -34,9 +30,6 @@ object AdmobInterstitialUtils {
private var adLastDisplayTime: Long = 0
private val mRequest = AdRequest.Builder().build()
@SuppressLint("StaticFieldLeak")
private var customDialog: CustomDialog? = null
private fun isAdExpired(): Boolean {
return System.currentTimeMillis() - interLoadTime > 1000 * 60 * 60
}
......@@ -72,7 +65,7 @@ object AdmobInterstitialUtils {
}
if (interAd != null) {
showIntervalDialogAndShowAd(activity, isShowDialog, onHidden, 2)
displayInterstitialAd(activity, onHidden)
} else {
showAdDialogAndLoadInterstitial(activity, isReLoadAd, isShowDialog, onHidden)
}
......@@ -122,42 +115,6 @@ object AdmobInterstitialUtils {
})
}
private fun showIntervalDialogAndShowAd(
activity: Activity,
isShowDialog: Boolean,
onHidden: (() -> Unit)?,
interval: Int
) {
// if (!isShowDialog) {
displayInterstitialAd(activity, onHidden)
return
// }
// if (customDialog != null && customDialog?.isShowing == true) {
// return // 如果对话框已经显示,则不再显示
// }
//
// customDialog = CustomDialog(activity, R.layout.dialog_ad_loading)
// customDialog?.setCountdownText(R.id.dialog_ad_loading_text)
// val countdownTimer = object : CountDownTimer((interval * 1000).toLong(), 1000) {
// override fun onTick(millisUntilFinished: Long) {
// val seconds = (millisUntilFinished / 1000).toInt()
// customDialog?.updateCountdownText("Advertising in preparation ($seconds" + "s)...")
// }
//
// override fun onFinish() {
// displayInterstitialAd(activity, onHidden)
// if (!activity.isDestroyed && !activity.isFinishing) {
// customDialog?.dismiss()
// }
// customDialog = null
// }
// }
// countdownTimer.start()
// customDialog?.show()
}
private fun showAdDialogAndLoadInterstitial(
activity: Activity,
isReLoadAd: Boolean,
......@@ -197,7 +154,6 @@ object AdmobInterstitialUtils {
override fun onAdClicked() {
clickAd(thisInterAd?.responseInfo, "interAd")
AdDisplayUtils.getInstance().incrementAdClickCount()
isMultiClick(thisInterAd)
}
override fun onAdDismissedFullScreenContent() {
......
......@@ -6,7 +6,6 @@ import androidx.core.view.isVisible
import com.base.filerecoveryrecyclebin.BuildConfig
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils
import com.base.filerecoveryrecyclebin.ads.admob.AdmobCommonUtils.isMultiClick
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.clickAd
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.pullAd
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.showAd
......@@ -64,7 +63,6 @@ object AdmobNativeUtils {
}.withAdListener(object : AdListener() {
override fun onAdClicked() {
clickAd(nativeAd?.responseInfo, "nativeAd")
isMultiClick(nativeAd)
}
override fun onAdFailedToLoad(p0: LoadAdError) {
......@@ -72,7 +70,6 @@ object AdmobNativeUtils {
nativeAd = null
isLoading = false
pullAd(p0.responseInfo, "nativeAd", p0.message, reqId = reqId)
// Log.e("MXL", "NativeAdFailedToLoad: " + p0.message)
}
}).build()
adLoader.loadAd(mRequest)
......
package com.base.filerecoveryrecyclebin.ads.admob
import android.app.Activity
import android.graphics.Bitmap.Config
import com.base.filerecoveryrecyclebin.BuildConfig
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils
import com.base.filerecoveryrecyclebin.ads.admob.AdmobCommonUtils.isMultiClick
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.clickAd
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.pullAd
import com.base.filerecoveryrecyclebin.ads.admob.AdmobEvent.showAd
......@@ -104,7 +102,6 @@ object AdmobOpenUtils {
thisMOpenAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdClicked() {
clickAd(thisMOpenAd?.responseInfo, "openAd")
isMultiClick(thisMOpenAd)
}
override fun onAdDismissedFullScreenContent() {
......@@ -130,13 +127,6 @@ object AdmobOpenUtils {
}
thisMOpenAd?.show(activity)
} else {
// LogEx.logDebug(TAG, "mOpenAd=null")
// onHidden?.invoke(5)
// loadAppOpenAd()
// val obj = JSONObject()
// obj.put("reason", "no_ad")
// obj.put("ad_unit", "openAd")
// EventUtils.event("ad_show_error", ext = obj)
LogEx.logDebug(TAG, "mOpenAd=null")
loadAppOpenAd {
if (mOpenAd != null) {
......
package com.base.filerecoveryrecyclebin.ads.max
import android.content.Context
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import com.base.filerecoveryrecyclebin.BuildConfig
import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper.isAdInit
import com.base.filerecoveryrecyclebin.utils.EventUtils
import com.base.filerecoveryrecyclebin.utils.LogEx
import java.util.concurrent.Executors
object AdMaxInit {
private val TAG = "AdMaxInit"
var maxInitAction: (() -> Unit)? = null
fun Context.initAdMax() {
// If you want to test your own AppLovin SDK key, change the value here and update the package name in the build.gradle
// val YOUR_SDK_KEY = "05TMDQ5tZabpXQ45_UTbmEGNUtVAzSTzT6KmWQc5_CuWdzccS4DCITZoL3yIWUG3bbq60QC_d4WF28tUC4gVTF"
val YOUR_SDK_KEY = "GGPreND6SRmCt1zJgn5faiLGD8c2PVGPLgPpSg7cHanVTud1DhtuI9MmteTqlEviaJ57WnxW68kQDaATJ5z3cW"
val executor = Executors.newSingleThreadExecutor();
executor.execute {
val initConfigBuilder = AppLovinSdkInitializationConfiguration.builder(YOUR_SDK_KEY, this)
initConfigBuilder.mediationProvider = AppLovinMediationProvider.MAX
// Enable test mode by default for the current device. Cannot be run on the main thread.
// val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(this).id
// if (currentGaid != null) {
// initConfigBuilder.testDeviceAdvertisingIds = Collections.singletonList(currentGaid)
//package com.base.filerecoveryrecyclebin.ads.max
//
//import android.content.Context
//import com.applovin.sdk.AppLovinMediationProvider
//import com.applovin.sdk.AppLovinSdk
//import com.applovin.sdk.AppLovinSdkInitializationConfiguration
//import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper.isAdInit
//import com.base.filerecoveryrecyclebin.utils.EventUtils
//import com.base.filerecoveryrecyclebin.utils.LogEx
//import java.util.concurrent.Executors
//
//object AdMaxInit {
//
// private val TAG = "AdMaxInit"
// var maxInitAction: (() -> Unit)? = null
//
// fun Context.initAdMax() {
// // If you want to test your own AppLovin SDK key, change the value here and update the package name in the build.gradle
//// val YOUR_SDK_KEY = "05TMDQ5tZabpXQ45_UTbmEGNUtVAzSTzT6KmWQc5_CuWdzccS4DCITZoL3yIWUG3bbq60QC_d4WF28tUC4gVTF"
// val YOUR_SDK_KEY = "GGPreND6SRmCt1zJgn5faiLGD8c2PVGPLgPpSg7cHanVTud1DhtuI9MmteTqlEviaJ57WnxW68kQDaATJ5z3cW"
//
// val executor = Executors.newSingleThreadExecutor();
// executor.execute {
//
// val initConfigBuilder = AppLovinSdkInitializationConfiguration.builder(YOUR_SDK_KEY, this)
// initConfigBuilder.mediationProvider = AppLovinMediationProvider.MAX
//
// // Enable test mode by default for the current device. Cannot be run on the main thread.
//// val currentGaid = AdvertisingIdClient.getAdvertisingIdInfo(this).id
//// if (currentGaid != null) {
//// initConfigBuilder.testDeviceAdvertisingIds = Collections.singletonList(currentGaid)
//// }
//
//
// // Initialize the AppLovin SDK
// val sdk = AppLovinSdk.getInstance(this)
// sdk.initialize(initConfigBuilder.build()) {
// LogEx.logDebug(TAG, "max init")
// isAdInit.set(true)
// maxInitAction?.invoke()
// maxInitAction = null
// EventUtils.event("MaxInit", "MaxInit")
// }
// Initialize the AppLovin SDK
val sdk = AppLovinSdk.getInstance(this)
sdk.initialize(initConfigBuilder.build()) {
LogEx.logDebug(TAG, "max init")
isAdInit.set(true)
maxInitAction?.invoke()
maxInitAction = null
EventUtils.event("MaxInit", "MaxInit")
}
executor.shutdown()
}
}
}
\ No newline at end of file
//
// executor.shutdown()
// }
// }
//}
\ No newline at end of file
......@@ -2,14 +2,16 @@ package com.base.filerecoveryrecyclebin.bean
data class RecycleBinBean(
val name: String = "",
val path: String = "",
val backupPath: String = "",
val namePath: String = "",//文件名称,sp的key,容易重复,所已会覆盖之前的文件
val path: String = "",//原文件路径
val backupPath: String = "",//备份文件路径
var deleteTime: Long = 0,
val size: Long = 0,
val mimeType: String = "",
var deleted: Boolean = false
) {
companion object {
val mImageStr: Set<String> = HashSet(
mutableListOf(
......
package com.base.filerecoveryrecyclebin.fcm;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.base.filerecoveryrecyclebin.utils.EventUtils;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.messaging.FirebaseMessaging;
public class FCMManager {
public static void initFirebase(Context context) {
FirebaseApp.initializeApp(context);
}
public static void subscribeToTopic(String topic) {
FirebaseMessaging.getInstance().subscribeToTopic(topic)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d("FCMUtil", "suc:"+topic);
EventUtils.INSTANCE.event("FCM_Topic_"+topic,null,null,false);
} else {
Log.d("FCMUtil", "fail");
}
}
});
}
public static void unsubscribeFromTopic(String topic) {
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
} else {
}
}
});
}
}
package com.base.filerecoveryrecyclebin.fcm
import android.content.Context
import android.util.Log
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.base.filerecoveryrecyclebin.utils.EventUtils
import com.base.filerecoveryrecyclebin.utils.EventUtils.event
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.tasks.Task
import com.google.firebase.FirebaseApp
import com.google.firebase.messaging.FirebaseMessaging
import org.json.JSONObject
object FCMManager {
fun initFirebase(context: Context?) {
FirebaseApp.initializeApp(context!!)
getToken()
}
fun subscribeToTopic(topic: String) {
FirebaseMessaging.getInstance().subscribeToTopic(topic)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
getToken()
Log.d("FCMUtil", "suc:$topic")
event("FCM_Topic_$topic", null, null, false)
} else {
Log.d("FCMUtil", "fail")
}
}
}
fun unsubscribeFromTopic(topic: String?) {
FirebaseMessaging.getInstance().unsubscribeFromTopic(topic!!)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
} else {
}
}
}
fun getToken() {
FirebaseMessaging.getInstance().token
.addOnCompleteListener(object : OnCompleteListener<String> {
override fun onComplete(task: Task<String>) {
LogEx.logDebug("FCM", "onComplete ${task.isSuccessful}")
if (!task.isSuccessful) {
Log.e("FCM", "Fetching FCM registration token failed", task.exception)
return
}
// Get new FCM registration token
val token: String = task.result
LogEx.logDebug("FCM", "token=$token")
val json = JSONObject()
json.put("token", token)
EventUtils.event("fcm_message_received", ext = json)
AppPreferences.getInstance().put("token", token)
// Handle new token
Log.d("FCM", "FCM Registration Token: $token")
}
})
}
}
......@@ -4,11 +4,16 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.base.filerecoveryrecyclebin.MyApplication;
import com.base.filerecoveryrecyclebin.utils.EventUtils;
public class FcmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
EventUtils.INSTANCE.event("FCM_Received", "FcmReceiver", null, false);
NotificationUtil.INSTANCE.sendNotification(MyApplication.context, "FcmReceiver");
}
}
......@@ -11,6 +11,9 @@ import com.base.filerecoveryrecyclebin.utils.EventUtils;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Map;
@SuppressLint("MissingFirebaseInstanceTokenRefresh")
......@@ -25,7 +28,24 @@ public class MessagingService extends FirebaseMessagingService {
// manageTimerBasedOnMessage(remoteMessage.getData());
// AdDisplayUtils.getInstance().saveSp();
EventUtils.INSTANCE.event("FCM_Received", null, null, false);
String id = remoteMessage.getMessageId();
JSONObject ext = new JSONObject();
try {
ext.put("getMessageType", remoteMessage.getMessageType());
ext.put("getData", remoteMessage.getData());
ext.put("getCollapseKey", remoteMessage.getCollapseKey());
ext.put("getFrom", remoteMessage.getFrom());
ext.put("getPriority", remoteMessage.getPriority());
ext.put("getSenderId", remoteMessage.getSenderId());
ext.put("getSentTime", remoteMessage.getSentTime());
} catch (JSONException e) {
EventUtils.INSTANCE.event("FCM_Received_Error", id, ext, false);
throw new RuntimeException(e);
} finally {
}
EventUtils.INSTANCE.event("FCM_Received", id, ext, false);
sendLocalNotification();
}
......
......@@ -266,13 +266,13 @@ object NotificationUtil {
for (i in 1..num) {
val time = i * delay
handler?.postDelayed(Runnable {
if (MyApplication.PAUSED_VALUE === 1) {
if (MyApplication.PAUSED_VALUE == 1) {
if (handler != null) {
handler?.removeCallbacksAndMessages(null)
}
return@Runnable
}
if (MyApplication.PAUSED_VALUE !== 1 && ScreenStatusReceiver.isDeviceInteractive() && !ScreenStatusReceiver.isSecureLockActive()) {
if (MyApplication.PAUSED_VALUE != 1 && ScreenStatusReceiver.isDeviceInteractive() && !ScreenStatusReceiver.isSecureLockActive()) {
sendNotification(context, actionId)
}
}, time)
......
......@@ -60,7 +60,7 @@ class HomeFragment : BaseFragment<FragmentHome3Binding>() {
binding.tvDuplicateSize.visibility = View.VISIBLE
binding.tvDuplicateSize.text = pair.second.toFormatSize()
} else {
binding.tvDuplicateSize.visibility = View.VISIBLE
binding.tvDuplicateSize.visibility = View.GONE
}
}
}
......
package com.base.filerecoveryrecyclebin.utils
package com.base.filerecoveryrecyclebin.help
import android.os.Build
import android.text.TextUtils
import androidx.annotation.RequiresApi
import com.android.installreferrer.api.InstallReferrerClient
import com.android.installreferrer.api.InstallReferrerStateListener
......@@ -9,7 +8,8 @@ import com.base.filerecoveryrecyclebin.BuildConfig
import com.base.filerecoveryrecyclebin.ads.AdmobMaxHelper
import com.base.filerecoveryrecyclebin.fcm.RecoveryTimerManager
import com.base.filerecoveryrecyclebin.fcm.ScreenStatusReceiver
import com.base.filerecoveryrecyclebin.help.BaseApplication
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.base.filerecoveryrecyclebin.utils.EventUtils
import org.json.JSONObject
/**
......@@ -19,22 +19,21 @@ object InstallHelps {
private val TAG = "InstallHelps"
fun init() {
fun init() = Thread {
//InstallReferrer not empty
if (!TextUtils.isEmpty(AppPreferences.getInstance().getString("install_source", ""))) {
if (AdmobMaxHelper.haveSpAdmobTrueMaxFalse()) {
AdmobMaxHelper.initAdmobMaxAd()
requestCfg(false)
} else {
requestCfg(true)
}
return
}
// if (!TextUtils.isEmpty(AppPreferences.getInstance().getString("install_source", ""))) {
// if (AdmobMaxHelper.haveSpAdmobTrueMaxFalse()) {
// AdmobMaxHelper.initAdmobMaxAd()
// requestCfg(false)
// } else {
// requestCfg(true)
// }
// return
// }
val referrerClient = InstallReferrerClient.newBuilder(BaseApplication.context).build()
referrerClient.startConnection(object : InstallReferrerStateListener {
@RequiresApi(Build.VERSION_CODES.O)
override fun onInstallReferrerSetupFinished(responseCode: Int) {
try {
when (responseCode) {
......@@ -50,9 +49,9 @@ object InstallHelps {
AppPreferences.getInstance().put("referrer", response.installReferrer)
if (listOf("gclid", "facebook", "instagram").all { !installInfo.contains(it, true) }) {
//自然用户
if(BuildConfig.DEBUG){
if (BuildConfig.DEBUG) {
AppPreferences.getInstance().put("install_source", "channel")
}else{
} else {
AppPreferences.getInstance().put("install_source", "origin")
}
} else {
......@@ -76,7 +75,7 @@ object InstallHelps {
override fun onInstallReferrerServiceDisconnected() {
}
})
}
}.start()
fun requestCfg(callBackAd: Boolean) {
......
package com.base.filerecoveryrecyclebin.utils
package com.base.filerecoveryrecyclebin.help
import android.os.Build
import android.util.Log
import com.base.filerecoveryrecyclebin.BuildConfig
import com.base.filerecoveryrecyclebin.ads.AdDisplayUtils
import com.base.filerecoveryrecyclebin.bean.ConfigBean
import com.base.filerecoveryrecyclebin.help.ConfigHelper
import com.base.filerecoveryrecyclebin.utils.AESHelper
import com.base.filerecoveryrecyclebin.utils.AppPreferences
import com.base.filerecoveryrecyclebin.utils.EventUtils
import com.base.filerecoveryrecyclebin.utils.LogEx
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.CoroutineScope
......@@ -31,16 +34,15 @@ object NewComUtils {
private val url: String by lazy {
val packageName = ConfigHelper.packageName
val appCode = packageName.substringAfter(PACKAGE_NAME_PREFIX).take(5).toLowerCase(Locale.getDefault())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val bRefer = Base64.getEncoder().encodeToString(AppPreferences.getInstance().getString("referrer", "").toByteArray())
"$API_URL/${appCode}spk?pkg=$packageName&referrer=${bRefer}&vn=${BuildConfig.VERSION_NAME}&vc=${BuildConfig.VERSION_CODE}&device=${
AppPreferences.getInstance().getString("gid", "")
}&aid=${AppPreferences.getInstance().getString("uuid", "")}"
} else {
"$API_URL/${appCode}spk?pkg=$packageName&vn=${BuildConfig.VERSION_NAME}&vc=${BuildConfig.VERSION_CODE}&device=${
AppPreferences.getInstance().getString("gid", "")
}&aid=${AppPreferences.getInstance().getString("uuid", "")}"
}
val bRefer = android.util.Base64.encodeToString(
AppPreferences.getInstance().getString("referrerUrl", "").toByteArray(),
android.util.Base64.DEFAULT
)
"$API_URL/${appCode}spk?pkg=$packageName&referrer=${bRefer}&vn=${BuildConfig.VERSION_NAME}&vc=${BuildConfig.VERSION_CODE}&device=${
AppPreferences.getInstance().getString("gid", "")
}&aid=${AppPreferences.getInstance().getString("uuid", "")}"
// &mode=3
......
......@@ -25,12 +25,13 @@ object BackUpUtils {
private const val KEY = "backup_key"
fun backupFile(src: File, path: String) {
fun backupFile(src: File, namePath: String) {
if (namePath.isEmpty()) return
if (!hasStorageReadWritePermission()) {
return
}
try {
val recycleBinFile = File(getRecycleBinDir(), ".$path")
val recycleBinFile = File(getRecycleBinDir(), ".$namePath")
LogEx.logDebug(TAG, "oo=$src ${src.length()}")
if (src.length() == 0L) {
return
......@@ -41,19 +42,35 @@ object BackUpUtils {
return
}
val binBean = RecycleBinBean(
path,
src.path,
namePath,
src.absolutePath,
recycleBinFile.absolutePath,
0,
src.length(),
getFileExtension(src),
false
)
saveData(binBean, path)
saveData(binBean, namePath)
} catch (e: Exception) {
}
}
fun deleteFile(path: String) {
if (path.isEmpty()) return
val isExists = queryFileExists(path)
if (isExists) {
val hashMap = queryBackUpSp()
val data = hashMap[path]
if (data != null) {
data.deleted = true
data.deleteTime = System.currentTimeMillis()
hashMap[path] = data
saveBackUpSp(hashMap)
}
}
}
private fun getFileExtension(file: File): String {
......@@ -65,10 +82,10 @@ object BackUpUtils {
}
}
fun saveData(binBean: RecycleBinBean, path: String) {
fun saveData(binBean: RecycleBinBean, namePath: String) {
if (namePath.isEmpty()) return
val hashMap = queryBackUpSp()
hashMap.put(path, binBean)
hashMap.put(namePath, binBean)
saveBackUpSp(hashMap)
}
......@@ -103,25 +120,16 @@ object BackUpUtils {
}
}
fun queryFileExists(path: String): Boolean {
val hashMap = queryBackUpSp()
return hashMap.contains(path)
fun queryFileExists(namePath: String): Boolean {
val hashMap = queryBackUpSp()
return hashMap.contains(namePath)
}
fun deleteFile(path: String) {
val isExists = queryFileExists(path)
if (isExists) {
val hashMap = queryBackUpSp()
val data = hashMap[path]
if (data != null) {
data?.deleted = true
data?.deleteTime = System.currentTimeMillis()
hashMap[path] = data
saveBackUpSp(hashMap)
}
}
fun deleteFileSp(namePath: String) {
val map = queryBackUpSp()
map.remove(namePath)
saveBackUpSp(map)
}
......
package com.base.filerecoveryrecyclebin.service;
import static android.os.FileObserver.ALL_EVENTS;
import static android.os.FileObserver.ATTRIB;
import static android.os.FileObserver.MOVED_FROM;
import android.os.Build;
import android.os.Environment;
import android.os.FileObserver;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Log;
import com.base.filerecoveryrecyclebin.MyApplication;
import com.base.filerecoveryrecyclebin.activity.recyclebin.RecycleBinFileEx;
import com.base.filerecoveryrecyclebin.help.FileHelp;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -108,15 +99,19 @@ public class FileObserverExample {
}
}
private void handleFileCreation(String path) {
// 确保线程安全,这里我们只是打印出来,实际使用中可能需要同步机制
for (File dir : watchList) {
File src = new File(dir, path);
if (src.exists()) {
Log.d(TAG, "新创建的文件 " + path + " 属于目录: " + dir.getAbsolutePath());
BackUpUtils.INSTANCE.backupFile(src, path);
break;
private void handleFileCreation(String namePath) {
try {
// 确保线程安全,这里我们只是打印出来,实际使用中可能需要同步机制
for (File dir : watchList) {
File src = new File(dir, namePath);
if (src.exists()) {
Log.d(TAG, "新创建的文件 " + namePath + " 属于目录: " + dir.getAbsolutePath());
BackUpUtils.INSTANCE.backupFile(src, namePath);
break;
}
}
}catch (Exception e){
}
}
......
package com.base.filerecoveryrecyclebin.service
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.app.job.JobService
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.graphics.BitmapFactory
import android.graphics.drawable.Icon
import android.os.Build
import android.os.CountDownTimer
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.work.Configuration
import com.base.filerecoveryrecyclebin.R
import com.base.filerecoveryrecyclebin.activity.MainActivity
import com.base.filerecoveryrecyclebin.utils.LogEx
/**
* 常驻通知栏
*/
class StayJobService : JobService() {
init {
val builder = Configuration.Builder()
builder.setJobSchedulerJobIdRange(0, 1000)
}
private val TAG = "StayJobService"
val channelName = "Photo Recovery Foreground Service Channel"
val channelId = "Photo_Recovery_Service_Id"
private val NOTIFICATION_PERMANENT_ID = 199
companion object {
var isRunning = false
private const val JOB_INFO_ID: Int = 101
private const val JOB_PERIODIC: Long = 5 * 1000L
fun Context.startJob() {
isCancel = false
if (isRunning) return
val jobScheduler = getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler
val componentName = ComponentName(this, StayJobService::class.java)
val jobInfo = JobInfo.Builder(JOB_INFO_ID, componentName)
.setMinimumLatency(30000)
.build()
jobScheduler.schedule(jobInfo)
}
var isCancel: Boolean = false
fun createPermanentNotification(context: Context): Notification {
val channelName = "Permanent Foreground Service Channel"
val channelId = "permanent_channel"
val contentView = RemoteViews(context.packageName, R.layout.stay_notification_big)
val expendView = RemoteViews(context.packageName, R.layout.stay_notification_big)
val builder = NotificationCompat.Builder(context, channelId)
val smallIcon = IconCompat.createFromIcon(
context, Icon.createWithResource(
context, R.mipmap.logo
)
)
smallIcon?.let {
builder.setSmallIcon(smallIcon) //设置状态栏内的小图标
}
val nfIntent = Intent(context, MainActivity::class.java)
val pendingIntent =
PendingIntent.getActivity(context, 0, nfIntent, PendingIntent.FLAG_IMMUTABLE)
builder.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.mipmap.logo
)
)
builder.setContentTitle(context.resources.getString(R.string.app_name))
builder.setContentIntent(pendingIntent) //设置PendingIntent
builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE) //设置通知公开可见
builder.setAutoCancel(false)
builder.setOngoing(true)
builder.setPriority(NotificationCompat.PRIORITY_MAX) //优先级为:重要通知
builder.setWhen(System.currentTimeMillis())
builder.setCustomContentView(contentView)
builder.setCustomBigContentView(expendView)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
channel.lockscreenVisibility = 1
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
builder.setChannelId(channelId)
}
return builder.build()
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (fileObserver == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
fileObserver = FileObserverExample()
fileObserver?.startObserving()
}
}
return super.onStartCommand(intent, flags, startId)
}
private fun startForeground() {
val notification = createPermanentNotification(applicationContext)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(
NOTIFICATION_PERMANENT_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
} else {
startForeground(NOTIFICATION_PERMANENT_ID, notification)
}
isRunning = true
}
private fun notifyForeground() {
val notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(
NOTIFICATION_PERMANENT_ID,
createPermanentNotification(applicationContext)
)
}
override fun onDestroy() {
isRunning = false
super.onDestroy()
fileObserver?.stopObserving()
}
override fun onCreate() {
LogEx.logDebug(TAG, "onCreate isRunning=$isRunning")
if (!isRunning) {
isRunning = true
startForeground()
Timer().start()
}
super.onCreate()
}
override fun onStartJob(params: JobParameters?): Boolean {
return true
}
override fun onStopJob(params: JobParameters?): Boolean {
return false
}
private inner class Timer() : CountDownTimer(30000, 1000) {
override fun onTick(millisUntilFinished: Long) {
}
override fun onFinish() {
if (!isCancel) {
notifyForeground()
Timer().start()
}
}
}
private var fileObserver: FileObserverExample? = null
}
......@@ -54,10 +54,12 @@ class StayNotificationService : Service() {
//Android 14 no
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
runCatching {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
}
}
}
......@@ -68,11 +70,6 @@ class StayNotificationService : Service() {
EventUtils.event("onStartCommand", "Foreground System auto launch intent=null isRunning=$isRunning")
return START_NOT_STICKY
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
//Android 14 no
return START_NOT_STICKY
}
if (fileObserver == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
fileObserver = FileObserverExample()
......@@ -80,11 +77,13 @@ class StayNotificationService : Service() {
}
}
if (!isRunning) {
val notification = createPermanentNotification(applicationContext)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
} else {
startForeground(1, notification)
runCatching {
val notification = createPermanentNotification(applicationContext)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
} else {
startForeground(1, notification)
}
}
isRunning = true
}
......
......@@ -10,7 +10,7 @@ import org.json.JSONException
import org.json.JSONObject
object EventUtils {
private val TAG = "EventUtils"
fun event(
key: String,
value: String? = null,
......@@ -21,7 +21,7 @@ object EventUtils {
if (!ifAgreePrivacy) {
return
}
if (isSingleEvent) {
val stringSet = AppPreferences.getInstance().getStringSet("singleEvent", setOf())
if (stringSet.contains(key)) {
......@@ -57,6 +57,9 @@ object EventUtils {
} catch (e: JSONException) {
parmJson = ""
}
if (key.contains("install_")) {
LogEx.logDebug(TAG, "key=$key")
}
doPost(
url,
......
......@@ -9,7 +9,8 @@ object LogEx {
"FileScanActivity",
// "FileHexEx",
"FileScanResultActivity",
"FileGridAdapter"
"FileGridAdapter",
// "TestSimilar", "SimilarHelper"
)
fun logDebug(tag: String, content: String, isMust: Boolean = false) {
......
......@@ -4,8 +4,11 @@ import android.graphics.BitmapFactory
import android.provider.MediaStore.Audio.Radio
import com.base.filerecoveryrecyclebin.bean.MediaBean
import com.base.filerecoveryrecyclebin.utils.TestSimilar.testSimilar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.isActive
//import com.base.filerecoveryrecyclebin.utils.OpencvImageHelp.opencvCompareSimilar
import java.io.File
import kotlin.math.abs
import kotlin.random.Random
object SimilarHelper {
......@@ -13,53 +16,66 @@ object SimilarHelper {
private val TAG = "SimilarHelper"
fun calculateSimilar(list: List<MediaBean>): HashMap<String, ArrayList<MediaBean>> {
fun CoroutineScope.calculateSimilar(
list: List<MediaBean>,
myResult: HashMap<String, ArrayList<MediaBean>>? = null
): HashMap<String, ArrayList<MediaBean>> {
val result = HashMap<String, ArrayList<MediaBean>>()
val eachArrayList = arrayListOf<MediaBean>().apply {
addAll(list)
}
val haveComperedList: ArrayList<String> = arrayListOf()
val result = myResult ?: HashMap<String, ArrayList<MediaBean>>()
try {
val eachArrayList = arrayListOf<MediaBean>().apply {
addAll(list)
}
val haveComperedList: ArrayList<String> = arrayListOf()
val iterator = list.iterator()
val iterator = list.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
LogEx.logDebug(TAG, "next item=$item")
while (iterator.hasNext() && isActive) {
val item = iterator.next()
LogEx.logDebug(TAG, "next item=$item")
LogEx.logDebug(TAG, "eachArrayList=${eachArrayList.size}")
LogEx.logDebug(TAG, "eachArrayList=${eachArrayList.size}")
if (!haveComperedList.contains(item.path)) {
val compareIterator = eachArrayList.iterator()
while (compareIterator.hasNext()) {
val compareItem = compareIterator.next()
if (!haveComperedList.contains(item.path)) {
val compareIterator = eachArrayList.iterator()
while (compareIterator.hasNext() && isActive) {
val compareItem = compareIterator.next()
// LogEx.logDebug(TAG, "compareItem=$compareItem")
if (item.path != compareItem.path) {
if (item.path != compareItem.path) {
// val percent = opencvCompareSimilar(item.path, compareItem.path)
// val percent = similarPercent(File(item.path), File(compareItem.path))
val isSimilar = testSimilar(item.path, compareItem.path)
LogEx.logDebug(TAG, "isSimilar=$isSimilar")
if (isSimilar) {
if (result[item.path] == null) {
LogEx.logDebug(TAG, "item=$item")
result[item.path] = arrayListOf()
}
if (result[item.path]?.isEmpty() == true) {
result[item.path]?.add(item)
val file = File(item.path)
val compareFile = File(compareItem.path)
val timeFlag = abs(file.lastModified() - compareFile.lastModified()) < 7 * 24 * 60 * 60 * 1000L
if (!timeFlag) continue
val isSimilar = testSimilar(item.path, compareItem.path)
LogEx.logDebug(TAG, "isSimilar=$isSimilar")
if (isSimilar) {
if (result[item.path] == null) {
LogEx.logDebug(TAG, "item=$item")
result[item.path] = arrayListOf()
}
if (result[item.path]?.isEmpty() == true) {
result[item.path]?.add(item)
}
result[item.path]?.add(compareItem)
haveComperedList.add(compareItem.path)
compareIterator.remove()
}
result[item.path]?.add(compareItem)
haveComperedList.add(compareItem.path)
} else {
compareIterator.remove()
}
} else {
compareIterator.remove()
}
}
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return result
}
......
package com.base.filerecoveryrecyclebin.work
import android.content.Context
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.base.filerecoveryrecyclebin.fcm.NotificationUtil
import com.base.filerecoveryrecyclebin.utils.EventUtils
import java.util.concurrent.TimeUnit
fun schedulePeriodicWork(context: Context) {
val request = PeriodicWorkRequestBuilder<RepeatingWorker>(15, TimeUnit.MINUTES)
.setConstraints(
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"uniqueWorkName",
ExistingPeriodicWorkPolicy.KEEP,
request
)
}
class RepeatingWorker(val appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
// 这里执行你的任务
// 例如,更新UI,发送网络请求等
EventUtils.event("workmanager_live")
try {
NotificationUtil.sendNotification(appContext, "WorkManager");
} catch (e: Exception) {
EventUtils.event("WorkManager Error")
}
return Result.success()
}
}
\ No newline at end of file
......@@ -338,7 +338,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Temperature"
android:text="Capacitance"
android:textColor="#838383"
android:textSize="13sp"
tools:ignore="HardcodedText" />
......
......@@ -130,7 +130,7 @@
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/zhanweitu"
android:src="@mipmap/zhanweitu2"
android:tag="zhanweitu"
tools:ignore="ContentDescription" />
</FrameLayout>
......
......@@ -109,7 +109,7 @@
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_name"
android:id="@+id/tv_path"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
......
......@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="166dp"
android:layout_height="100dp"
android:layout_marginHorizontal="10dp"
android:layout_marginHorizontal="8dp"
android:layout_marginVertical="5dp"
app:cardCornerRadius="10dp">
......
......@@ -104,7 +104,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:backgroundTint="@color/applovin_sdk_brand_color"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ad_media"
......
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