Commit 1af1a0f7 authored by mengcuiguang's avatar mengcuiguang

代码优化

parent 0b340486
/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.content.pm;
/**
* API for package data change related callbacks from the Package Manager.
* Some usage scenarios include deletion of cache directory, generate
* statistics related to code, data, cache usage(TODO)
* {@hide}
*/
oneway interface IPackageDataObserver {
void onRemoveCompleted(in String packageName, boolean succeeded);
}
/*
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.content.pm;
import android.content.pm.PackageStats;
/**
* API for package data change related callbacks from the Package Manager.
* Some usage scenarios include deletion of cache directory, generate
* statistics related to code, data, cache usage(TODO)
* {@hide}
*/
oneway interface IPackageStatsObserver {
void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
}
/* //device/java/android/android/view/WindowManager.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.content.pm;
parcelable PackageStats;
......@@ -16,7 +16,7 @@ object Constant {
* 获取 TAG NAME
*/
const val TAG_NAME = "SUN"
const val MINTS_APP_NAME = "智慧清理专家"
const val MINTS_APP_NAME = "乐看短剧"
const val MINTS_PKG_NAME = "com.mints.wisdomclean"
/**
......@@ -37,13 +37,6 @@ object Constant {
var MEMBERS_URL = "https://mints-web.mints-id.com/agreements/wisdomclean/gmxy.html"//会员付费服务协议
// 扫描类型 type 1 -> 一键清理 5 -> 全部清理
const val SCAN_TYPE = "SCAN_TYPE"
const val CARRIER_SPEED_TEST = "SPEED_TEST" // 网络测速
const val CARRIER_BOOST = "BOOST" // 一键加速
const val CARRIER_CLEAN = "CLEAN" // 一键清理
const val CARRIER_SAVE_POWER = "SAVE_POWER" // 超强省电
// ******************
object BeenHolder {
......
package com.mints.wisdomclean.common
enum class PhotoConstant(val value: String) {
BODY_SEG("BODY_SEG"), //
TO_YOUNG_STYLE("CHANGE_AGE"), // 年龄变化
OLD_REPAIR_STYLE("IMAGE_CLARITY"), // 图像清晰度增强
IMAGE_COLOR("IMAGE_COLOR"), // 黑白图片上色
PHOTO_SCORE("PHOTO_SCORE") // 拍照评分
}
\ No newline at end of file
package com.mints.wisdomclean.common
enum class ScanConstant(val value: String) {
// 本地判断证件照,非服务端使用
id_photo("证件照")// 证件照
}
\ No newline at end of file
package com.mints.wisdomclean.common
enum class TransConstant(val value: String) {
translation("translation"),
zh("中文"), //中文
en("英文"), //英文
jp("日语"), //日语
kor("韩语"), //韩语
pt("葡萄牙语"), //葡萄牙语
fra("法语"), //法语
de("德语"), //德语
it("意大利语"), //意大利语
spa("西班牙语"), //西班牙语
ru("俄语"), //俄语
}
\ No newline at end of file
package com.mints.wisdomclean.manager
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.database.ContentObserver
import android.net.Uri
import android.provider.MediaStore
import androidx.core.content.ContextCompat
import com.mints.wisdomclean.R
import com.mints.wisdomclean.mvp.model.Folder
import com.mints.wisdomclean.mvp.model.Image
import com.mints.wisdomclean.utils.ImageUtil
import com.mints.wisdomclean.utils.UriUtils
import java.io.File
import java.util.*
object AlbumCleanModel {
/**
* 缓存图片
*/
private var cacheImageList: ArrayList<Folder>? = null
private var isNeedCache = false
private var observer: PhotoContentObserver? = null
/**
* 预加载图片
*
* @param context
*/
fun preloadAndRegisterContentObserver(context: Context) {
isNeedCache = true
if (observer == null) {
observer = PhotoContentObserver(context.applicationContext)
context.applicationContext.contentResolver.registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, observer!!
)
}
preload(context)
}
private fun preload(context: Context) {
val hasWriteExternalPermission =
ContextCompat.checkSelfPermission(
context,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
if (hasWriteExternalPermission == PackageManager.PERMISSION_GRANTED) {
//有权限,加载图片。
loadImageForSDCard(context, true, null)
}
}
/**
* 清空缓存
*/
fun clearCache(context: Context) {
isNeedCache = false
if (observer != null) {
context.applicationContext.contentResolver.unregisterContentObserver(observer!!)
observer = null
}
Thread(Runnable {
synchronized(AlbumCleanModel::class.java) {
if (cacheImageList != null) {
cacheImageList!!.clear()
cacheImageList = null
}
}
}).start()
}
/**
* 从SDCard加载图片
*
* @param context
* @param callback
*/
fun loadImageForSDCard(
context: Context,
callback: DataCallback?
) {
loadImageForSDCard(context, false, callback)
}
/**
* 从SDCard加载图片
*
* @param context
* @param isPreload 是否是预加载
* @param callback
*/
private fun loadImageForSDCard(
context: Context,
isPreload: Boolean,
callback: DataCallback?
) {
//由于扫描图片是耗时的操作,所以要在子线程处理。
Thread(Runnable {
synchronized(AlbumCleanModel::class.java) {
val imageCacheDir: String = ImageUtil.getImageCacheDir(context)
var folders: ArrayList<Folder>? = null
if (cacheImageList == null || isPreload) {
val imageList: ArrayList<Image> = loadImage(context)
imageList.sortWith(Comparator { image, t1 ->
when {
image.time > t1.time -> {
1
}
image.time < t1.time -> {
-1
}
else -> {
0
}
}
})
val images: ArrayList<Image> = arrayListOf()
for (image in imageList) {
// 过滤不存在或未下载完成的图片
val exists =
"downloading" != getExtensionName(image.path) && checkImgExists(
image.path
)
//过滤剪切保存的图片;
val isCutImage: Boolean =
ImageUtil.isCutImage(imageCacheDir, image.path)
if (!isCutImage && exists) {
images.add(image)
}
}
images.reverse()
folders = splitFolder(context, images)
if (isNeedCache) {
cacheImageList = folders
}
} else {
folders = cacheImageList
}
callback?.onSuccess(folders)
}
}).start()
}
/**
* 从SDCard加载图片
*
* @param context
* @return
*/
@SuppressLint("Range")
@Synchronized
private fun loadImage(context: Context): ArrayList<Image> {
//扫描图片
val mImageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val mContentResolver = context.contentResolver
val mCursor = mContentResolver.query(
mImageUri, arrayOf(
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.MIME_TYPE,
MediaStore.Images.Media.SIZE
),
MediaStore.MediaColumns.SIZE + ">0",
null,
MediaStore.Images.Media.DATE_ADDED + " DESC"
)
val images: ArrayList<Image> = arrayListOf()
//读取扫描到的图片
if (mCursor != null) {
while (mCursor.moveToNext()) {
// 获取图片的路径
val id =
mCursor.getLong(mCursor.getColumnIndex(MediaStore.Images.Media._ID))
val path = mCursor.getString(
mCursor.getColumnIndex(MediaStore.Images.Media.DATA)
)
//获取图片名称
var name = mCursor.getString(
mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
)
if (name == null) {
name = "" + System.currentTimeMillis()
}
//获取图片时间
var time = mCursor.getLong(
mCursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED)
)
if (time.toString().length < 13) {
time *= 1000
}
//获取图片类型
val mimeType = mCursor.getString(
mCursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE)
)
//获取图片uri
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon()
.appendPath(id.toString()).build()
//获取图片size
var size = mCursor.getLong(
mCursor.getColumnIndex(MediaStore.Images.Media.SIZE)
)
images.add(Image(path, time, name, mimeType, uri, size))
}
mCursor.close()
}
return images
}
/**
* 检查图片是否存在。ContentResolver查询处理的数据有可能文件路径并不存在。
*
* @param filePath
* @return
*/
private fun checkImgExists(filePath: String): Boolean {
return File(filePath).exists()
}
private fun getPathForAndroidQ(
context: Context,
id: Long
): String? {
return UriUtils.getPathForUri(
context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon()
.appendPath(id.toString()).build()
)
}
/**
* 把图片按文件夹拆分,第一个文件夹保存所有的图片
*
* @param images
* @return
*/
private fun splitFolder(
context: Context,
images: ArrayList<Image>
): ArrayList<Folder> {
val folders: ArrayList<Folder> = ArrayList<Folder>()
folders.add(Folder(context.getString(R.string.selector_all_image), images))
if (images != null && images.isNotEmpty()) {
val size = images.size
for (i in 0 until size) {
val path: String = images[i]!!.path
val name = getFolderName(path)
if (name.isNotEmpty()) {
val folder: Folder = getFolder(name, folders)
folder.addImage(images[i])
}
}
}
return folders
}
/**
* Java文件操作 获取文件扩展名
*/
fun getExtensionName(filename: String?): String {
if (filename != null && filename.isNotEmpty()) {
val dot = filename.lastIndexOf('.')
if (dot > -1 && dot < filename.length - 1) {
return filename.substring(dot + 1)
}
}
return ""
}
/**
* 根据图片路径,获取图片文件夹名称
*
* @param path
* @return
*/
private fun getFolderName(path: String): String {
if (path.isNotEmpty()) {
val strings =
path.split(File.separator.toRegex()).toTypedArray()
if (strings.size >= 2) {
return strings[strings.size - 2]
}
}
return ""
}
private fun getFolder(
name: String,
folders: MutableList<Folder>
): Folder {
if (folders.isNotEmpty()) {
val size = folders.size
for (i in 0 until size) {
val folder: Folder = folders[i]
if (name == folder.name) {
return folder
}
}
}
val newFolder = Folder(name)
folders.add(newFolder)
return newFolder
}
interface DataCallback {
fun onSuccess(folders: ArrayList<Folder>?)
}
private class PhotoContentObserver(private val context: Context) :
ContentObserver(null) {
override fun onChange(
selfChange: Boolean,
uri: Uri?
) {
super.onChange(selfChange, uri)
preload(context)
}
}
}
\ No newline at end of file
//package com.mints.wisdomclean.manager
//
//import android.app.Application
//import com.bytedance.applog.AppLog
//import com.bytedance.applog.InitConfig
//import com.bytedance.applog.util.UriConstants
//import com.bytedance.hume.readapk.HumeSDK
//import com.mints.wisdomclean.BuildConfig
//import com.mints.wisdomclean.MintsApplication
//import com.mints.wisdomclean.utils.MateUtils
//
///**
// * 穿山甲增长参谋
// */
//object AppLogManager {
//
// // ***这个id是增长参谋的appid,不是gormore的appid
// private const val APP_LOG_ID=""
//
// fun init(application: Application) {
//// val config = InitConfig(APP_LOG_ID, MateUtils.getAppMetaData(MintsApplication.getContext(), "CHANNEL_NAME") + HumeSDK.getChannel(MintsApplication.getContext()))
//// //上报地址
//// config.setUriConfig(UriConstants.DEFAULT)
//// // 加密开关,SDK 5.5.1 及以上版本支持,false 为关闭加密,上线前建议设置为 true
//// AppLog.setEncryptAndCompress(true)
//// config.isLogEnable = true
//// config.setAutoStart(true)
//// config.isAutoTrackEnabled = true
//// AppLog.init(application, config)
// }
//}
\ No newline at end of file
package com.mints.wisdomclean.manager
import com.mints.wisdomclean.utils.AppPreferencesManager
/**
* wifi本地数据管理
*
* 孟崔广
*/
object CleanDataManager {
private val sp by lazy { AppPreferencesManager.get() }
// 上次加速操作时间
const val FAKE_BOOST_TIME = "FAKE_BOOST_TIME"
// 上次降温操作时间
const val FAKE_COOL_TIME = "FAKE_COOL_TIME"
// 上次清理操作时间
const val FAKE_CLEAN_TIME = "FAKE_CLEAN_TIME"
// 上次省电操作时间
const val FAKE_SAVE_BATTERY_TIME = "FAKE_SAVE_BATTERY_TIME"
fun getFakeBoostTime() = sp.getLong(FAKE_BOOST_TIME, 0L)
fun setFakeBoostTime(value: Long) {
sp.put(FAKE_BOOST_TIME, value)
}
fun getFakeCleanTime() = sp.getLong(FAKE_CLEAN_TIME, 0L)
fun setFakeCleanTime(value: Long) {
sp.put(FAKE_CLEAN_TIME, value)
}
fun getFakeSaveBatteryTime() = sp.getLong(FAKE_SAVE_BATTERY_TIME, 0L)
fun setFakeSaveBatteryTime(value: Long) {
sp.put(FAKE_SAVE_BATTERY_TIME, value)
}
fun getFakeCoolTime() = sp.getLong(FAKE_COOL_TIME, 0L)
fun setFakeCoolTime(value: Long) {
sp.put(FAKE_COOL_TIME, value)
}
}
\ No newline at end of file
package com.mints.wisdomclean.manager
import android.os.Environment
import java.io.File
import java.util.*
object FileScanModel {
private val mEligibleFiles: ArrayList<String> by lazy { arrayListOf<String>() }
private val mBigFiles: ArrayList<String> by lazy { arrayListOf<String>() }
/**
* Java文件操作 根据文件后缀获取全部文件
*/
fun getSuffixFiles(callback: DataCallback, vararg suffixs: String) {
mEligibleFiles.clear()
Thread {
val sdDir = Environment.getExternalStorageDirectory()
val listFiles = sdDir.listFiles()
getSuffixFile(listFiles, *suffixs)
callback.onSuccess(mEligibleFiles)
}.start()
}
/**
* Java文件操作 根据文件后缀获取全部文件
*/
fun getSuffixFilesFormDir(dir: String, vararg suffixs: String): ArrayList<String> {
mEligibleFiles.clear()
val sdDir = File(dir)
val listFiles = sdDir.listFiles()
getSuffixFile(listFiles, *suffixs)
return mEligibleFiles
}
private fun getSuffixFile(files: Array<File>, vararg suffixs: String) {
files.let {
for (file in files) {
if (file.isDirectory) {
getSuffixFile(file.listFiles(), *suffixs)
} else {
val fileName = file.name
suffixs.forEach {
if (fileName.endsWith(".$it")) {
mEligibleFiles.add(file.absolutePath)
}
}
}
}
}
}
/**
* Java文件操作 根据文件大小获取文件
*/
fun getBigFiles(callback: DataCallback) {
mBigFiles.clear()
Thread {
val sdDir = Environment.getExternalStorageDirectory()
val listFiles = sdDir.listFiles()
getBigFile(listFiles)
callback.onSuccess(mBigFiles)
}.start()
}
private fun getBigFile(files: Array<File>) {
files.let {
for (file in files) {
if (file.isDirectory) {
getBigFile(file.listFiles())
} else {
// 大于10MB即视为大文件
if (file.length() > 1024 * 1024 * 10) {
mBigFiles.add(file.absolutePath)
}
}
}
}
}
interface DataCallback {
fun onSuccess(filePaths: ArrayList<String>?)
}
}
\ No newline at end of file
package com.mints.wisdomclean.ui.activitys
import android.Manifest
import android.app.Dialog
import android.os.Bundle
import android.os.Handler
......@@ -9,24 +8,24 @@ import android.text.TextPaint
import android.text.TextUtils
import android.text.style.ClickableSpan
import android.view.View
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.daimajia.androidanimations.library.Techniques
import com.daimajia.androidanimations.library.YoYo
import com.mints.library.utils.nodoubleclick.AntiShake
import com.mints.wisdomclean.R
import com.mints.wisdomclean.common.Constant
import com.mints.wisdomclean.common.ScanConstant
import com.mints.wisdomclean.manager.ActivityPageManager
import com.mints.wisdomclean.manager.UserManager
import com.mints.wisdomclean.mvp.presenters.LoginPresenter
import com.mints.wisdomclean.mvp.views.LoginView
import com.mints.wisdomclean.ui.activitys.base.BaseActivity
import com.mints.wisdomclean.ui.widgets.CustomDialogAsApple
import com.mints.wisdomclean.ui.widgets.DialogListener
import com.mints.wisdomclean.utils.*
import com.mints.library.utils.nodoubleclick.AntiShake
import com.mints.wisdomclean.manager.ActivityPageManager
import com.mints.wisdomclean.utils.BackInputUtil
import com.mints.wisdomclean.utils.LogUtil
import com.mints.wisdomclean.utils.SpanUtils
import com.mints.wisdomclean.utils.ToastUtil
import kotlinx.android.synthetic.main.activity_mobile_login.*
import kotlinx.android.synthetic.main.activity_settings.*
import kotlinx.android.synthetic.main.header_layout.*
......
......@@ -60,7 +60,7 @@ class SettingsActivity : BaseActivity(), View.OnClickListener {
item_back.setOnClickListener(this)
item_phone.setOnClickListener(this)
item_invitedCode.findViewById<TextView>(R.id.tv_title).text = "智慧清理专家ID"
item_invitedCode.findViewById<TextView>(R.id.tv_title).text = "乐看短剧ID"
val invitedCode = ContextCompat.getDrawable(this, R.mipmap.icon_settings_invite)
invitedCode?.setBounds(0, 0, 56, 56)
item_invitedCode.findViewById<TextView>(R.id.tv_title)
......
package com.mints.wisdomclean.utils
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.media.MediaPlayer
import com.mints.wisdomclean.R
import com.mints.wisdomclean.mvp.model.FileBean
import java.io.File
object ApkUtils {
/**
* 根据apk存储路径获取apk信息
*/
fun getApkInfo(
context: Context, apkPath: String
): FileBean {
var apkIcon: Drawable = context.getDrawable(R.mipmap.ic_launcher_main)!!
var apkLabel = ""
val pm: PackageManager = context.packageManager
val info = pm.getPackageArchiveInfo(
apkPath,
PackageManager.GET_ACTIVITIES
)
if (info != null) {
val appInfo = info.applicationInfo
appInfo.sourceDir = apkPath
appInfo.publicSourceDir = apkPath
try {
apkIcon = appInfo.loadIcon(pm)
apkLabel = appInfo.loadLabel(pm).toString()
} catch (e: OutOfMemoryError) {
LogUtil.e(e)
}
}
val apkFile = File(apkPath)
val size = apkFile.length()
val modifiedTime = FormatUtils.formatTime(apkFile.lastModified())
return FileBean(apkIcon, apkPath, modifiedTime, apkLabel, size)
}
/**
* 获取压缩包信息
*/
fun getZipInfo(
filePath: String
): FileBean {
val file = File(filePath)
val name = file.name
val modifiedTime = FormatUtils.formatTime(file.lastModified())
val size = file.length()
return FileBean("", filePath, modifiedTime, name, size)
}
/**
* 获取大文件信息
*/
fun getBigFileInfo(context: Context, filePath: String): FileBean {
val file = File(filePath)
val name = file.name
var modifiedTime: String
val extensionName = FileUtils.getExtensionName(name)
val size = file.length()
val image: String
when (extensionName) {
"apk" -> {
return getApkInfo(context, filePath)
}
"mp3" -> {
val mediaPlayer = MediaPlayer()
mediaPlayer.setDataSource(filePath)
mediaPlayer.prepare()
modifiedTime = FormatUtils.formatDuration(mediaPlayer.duration.toLong())
image = filePath
}
"mp4" -> {
val mediaPlayer = MediaPlayer()
mediaPlayer.setDataSource(filePath)
mediaPlayer.prepare()
modifiedTime = FormatUtils.formatDuration(mediaPlayer.duration.toLong())
image = filePath
}
"txt" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = filePath
}
"jpeg" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = filePath
}
"jpg" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = filePath
}
"png" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = filePath
}
"gif" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = filePath
}
"zip" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = ""
}
"rar" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = ""
}
"7z" -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = ""
}
else -> {
modifiedTime = FormatUtils.formatTime(file.lastModified())
image = ""
}
}
return FileBean(image, filePath, modifiedTime, name, size)
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.os.Build;
import com.mints.wisdomclean.MintsApplication;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
No comments
No comments
* des :
*/
public class AppManagerUtils {
private final static long oneMonth = 1000L * 60L * 60L * 24L * 30L ;
private final static long threeMonth = 1000L * 60L * 60L * 24L * 30L * 3L;
private final static long sixMonth = 1000L * 60L * 60L * 24L * 30L * 6L;
public static List<String> getOverOneMonth(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<String> result = new ArrayList<>();
UsageStatsManager usm = (UsageStatsManager) activity.getSystemService(Context.USAGE_STATS_SERVICE);
Calendar calendar = Calendar.getInstance();
//endTime当前系统时间
long endTime = calendar.getTimeInMillis();
//一个月前的时间
calendar.add(Calendar.YEAR, -2);
long startTimeOneMonth = calendar.getTimeInMillis();
List<UsageStats> list = usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, startTimeOneMonth, endTime);
for (UsageStats usageStats : list) {
long lastTime = usageStats.getLastTimeUsed();//获取最后一次运行的时间
if(lastTime<0) continue;
long interval = System.currentTimeMillis() - lastTime;
if (interval <= threeMonth&&interval>oneMonth){
result.add(usageStats.getPackageName());
}
}
return result;
} else {
return new ArrayList<>();
}
}
public static List<String> getOverThreeMonth(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<String> result = new ArrayList<>();
UsageStatsManager usm = (UsageStatsManager) activity.getSystemService(Context.USAGE_STATS_SERVICE);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
calendar.add(Calendar.YEAR, -2);
long startTimeThreeMonth = calendar.getTimeInMillis();
List<UsageStats> list = usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, startTimeThreeMonth, endTime);
for (UsageStats usageStats : list) {
long lastTime = usageStats.getLastTimeUsed();//获取最后一次运行的时间
if(lastTime<0) continue;
long interval = endTime - lastTime;
if (interval <= sixMonth&&interval>threeMonth){
result.add(usageStats.getPackageName());
}
}
return result;
} else {
return new ArrayList<>();
}
}
public static List<String> getOverSixMonth(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
List<String> result = new ArrayList<>();
UsageStatsManager usm = (UsageStatsManager) activity.getSystemService(Context.USAGE_STATS_SERVICE);
Calendar calendar = Calendar.getInstance();
long endTime = calendar.getTimeInMillis();
//6个月前的时间
calendar.add(Calendar.YEAR, -2);
long startTimeSixMonth = calendar.getTimeInMillis();
List<UsageStats> list = usm.queryUsageStats(UsageStatsManager.INTERVAL_YEARLY, startTimeSixMonth, endTime);
for (UsageStats usageStats : list) {
long lastTime = usageStats.getLastTimeUsed();//获取最后一次运行的时间
if(lastTime<0) continue;
long interval = endTime - lastTime;
if (interval > sixMonth){
result.add(usageStats.getPackageName());
}
}
return result;
} else {
return new ArrayList<>();
}
}
public static boolean isHaveAccess() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
long ts = System.currentTimeMillis();
@SuppressLint("WrongConstant") UsageStatsManager usageStatsManager = (UsageStatsManager) MintsApplication.getContext()
.getSystemService("usagestats");
List<UsageStats> queryUsageStats = usageStatsManager.queryUsageStats(
UsageStatsManager.INTERVAL_BEST, 0, ts);
if (queryUsageStats == null || queryUsageStats.isEmpty()) {
return false;
}
return true;
} else {
return false;
}
}
}
package com.mints.wisdomclean.utils;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.core.app.NotificationManagerCompat;
import com.mints.wisdomclean.BuildConfig;
import com.mints.wisdomclean.MintsApplication;
import com.mints.wisdomclean.common.Constant;
import com.mints.wisdomclean.manager.UserManager;
import com.mints.wisdomclean.utils.rxutil.CommonRxTask;
import com.mints.wisdomclean.utils.rxutil.RxjavaUtil;
import java.util.List;
public class AppPackageUsageUtils {
/**
* 判断当前设备中是否有"有权查看使用情况的应用程序"这个选项
*
* @param context
* @return
*/
public static boolean isNoOption(Context context) {
PackageManager packageManager = context
.getPackageManager();
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
/**
* 判断这个选项的打开状态
*
* @param context
* @return
*/
public static boolean isNoSwitch(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), context.getPackageName());
return mode == AppOpsManager.MODE_ALLOWED;
}
return false;
}
/**
* 判断当前app在手机中是否开启了允许消息推送 true-打开了消息通知
*
* @param context
* @return
*/
public static boolean isNotificationEnabled(Context context) {
boolean isOpened = false;
try {
isOpened = NotificationManagerCompat.from(context).areNotificationsEnabled();
} catch (Exception e) {
e.printStackTrace();
isOpened = false;
}
return isOpened;
}
/**
* 打开手机消息设置页面
*
* @param context
*/
public static void gotoSet(Context context) {
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= 26) {
// android 8.0引导
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
} else if (Build.VERSION.SDK_INT >= 21) {
// android 5.0-7.0
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", context.getPackageName());
intent.putExtra("app_uid", context.getApplicationInfo().uid);
} else {
// 其他
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", context.getPackageName(), null));
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 跳转短信界面
*
* @param context
*/
public static void gotoMessage(Context context, String number) {
try {
String mobile = "";
if (!TextUtils.isEmpty(UserManager.getInstance().getMobile())) {
mobile = UserManager.getInstance().getMobile();
}
String msg = "您的好友" + mobile + ",要添加你为【智慧清理专家】的好友,立即下载查看吧" + BuildConfig.MainIp + "share/shareFriend.html?channel=" + CommonUtils.getAppMetaData(MintsApplication.getContext(), "CHANNEL_NAME");
Intent sendIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("smsto:" + number));
sendIntent.putExtra("sms_body", msg);
context.startActivity(sendIntent);
} catch (Exception e) {
ToastUtil.show(context, "请使用微信分享");
}
}
private static void readyGo(Context context, Class<?> clazz, Bundle bundle) {
Intent intent = new Intent(context, clazz);
if (null != bundle) {
intent.putExtras(bundle);
}
context.startActivity(intent);
}
}
package com.mints.wisdomclean.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.RemoteException;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import com.mints.wisdomclean.common.Constant;
import com.mints.wisdomclean.mvp.model.AppBean;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* No comments
*/
public class CategoryUtils {
public static final int APP_RUNNING_FOREGROUND = 1;
public static final int APP_RUNNING_BACKGROUND = 2;
public static final int APP_NOT_LAUNCH = 3;
public static String getMimeTypeFromPath(String filePath) {
File file = new File(filePath);
String suffix = getSuffix(file);
if (suffix == null) {
return "file/*";
}
String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(suffix);
if (!TextUtils.isEmpty(type)) {
return type;
}
return "file/*";
}
//返回"/"之后的string
public static String getSuffixOfLastLine(String filePath) {
File file = new File(filePath);
if (!file.exists() || file.isDirectory()) {
return null;
}
if (TextUtils.isEmpty(filePath) || filePath.endsWith("/")) {
return null;
}
int lastIndexOf = filePath.lastIndexOf("/");
if (lastIndexOf != -1) {
return filePath.substring(lastIndexOf + 1);
} else {
return null;
}
}
//返回后缀 without "."
private static String getSuffix(File file) {
if (file == null || !file.exists() || file.isDirectory()) {
return null;
}
String fileName = file.getName();
if (fileName.equals("") || fileName.endsWith(".")) {
return null;
}
int index = fileName.lastIndexOf(".");
if (index != -1) {
return fileName.substring(index + 1).toLowerCase(Locale.US);
} else {
return null;
}
}
/**
* 获得App应用的大小
*
* @param context
* @param pkgName
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public static AppBean getPkgSize(final Context context, final String pkgName, final AppBean appBean) throws NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
// getPackageSizeInfo是PackageManager中的一个private方法,所以需要通过反射的机制来调用
Method method = PackageManager.class.getMethod("getPackageSizeInfo",
String.class, IPackageStatsObserver.class);
// 调用 getPackageSizeInfo 方法,需要两个参数:1、需要检测的应用包名;2、回调
method.invoke(context.getPackageManager(), pkgName,
new IPackageStatsObserver.Stub() {
@Override
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) throws RemoteException {
if (succeeded) {
appBean.setCacheSize(Formatter.formatFileSize(context, pStats.cacheSize));//缓存大小
appBean.setDataSize(Formatter.formatFileSize(context, pStats.dataSize));//数据大小
appBean.setCodeSize(Formatter.formatFileSize(context, pStats.codeSize));//程序大小
}
}
});
return appBean;
}
/**
* 获取apk包的信息:版本号,名称,图标等
*
* @param absPath apk包的绝对路径
* @param context
*/
public static AppBean apkInfo(Context context, String absPath, String size) {
File f = new File(absPath);
if (!f.exists() || f.isDirectory()) {
return null;
}
AppBean appBean = new AppBean();
PackageManager pm = context.getPackageManager();
PackageInfo pkgInfo = pm.getPackageArchiveInfo(absPath, PackageManager.GET_ACTIVITIES);
if (pkgInfo != null) {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
/* 必须加这两句,不然下面icon获取是default icon而不是应用包的icon */
appInfo.sourceDir = absPath;
appInfo.publicSourceDir = absPath;
String fileName = getSuffixOfLastLine(absPath);
String appName = pm.getApplicationLabel(appInfo).toString();// 得到应用名
String packageName = appInfo.packageName; // 得到包名
String versionName = pkgInfo.versionName; // 得到版本信息
int versionCode = pkgInfo.versionCode;
/* icon1和icon2其实是一样的 */
Drawable icon1 = pm.getApplicationIcon(appInfo);// 得到图标信息
Drawable icon2 = appInfo.loadIcon(pm);
boolean apkInstalled = isApkInstalled(context, packageName);
String desc = String.format("%s %s %s", appName, "(Version " + versionName + ")", size);
//0,已安装,安装包和已安装版本一致; 1,表示安装包版本高; -1,表示安装包版本低; -2,apk未安装;
int apkStats = Constant.APK_UNINSTALL;
if (apkInstalled) {
apkStats = Constant.APK_VERSION_EQUAL;
List<AppBean> installedApps = Constant.INSTANCE.getInstalledApps();
for (AppBean bean : installedApps) {
String beanPackageName = bean.getPackageName();
if (TextUtils.equals(packageName, beanPackageName)) {
String beanVersionName = bean.getVersionName();
int beanVersionCode = bean.getVersionCode();
// apkStats = compareVersion(versionName, beanVersionName);
apkStats = compareVersion(versionCode, beanVersionCode);
}
}
}
appBean.setPath(absPath);
appBean.setFileName(fileName);
appBean.setName(appName);
appBean.setPackageName(packageName);
appBean.setVersionName(versionName);
appBean.setVersionCode(versionCode);
appBean.setDesc(desc);
appBean.setCodeSize(size);
appBean.setApkStats(apkStats);
} else {
return null;
}
return appBean;
}
public static boolean isApkInstalled(Context context, String packageName) {
try {
context.getPackageManager().getApplicationInfo(packageName, 0);
return true;
} catch (PackageManager.NameNotFoundException localNameNotFoundException) {
return false;
}
}
//注意uri在 7.0 有限制
/*public static void installAPK(Context context, String apkPath) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri fileUri = FileOperationUtil.getFileUri(context, new File(apkPath));
intent.setDataAndType(fileUri,
"application/vnd.android.package-archive");
context.startActivity(intent);
}*/
//卸载应用,通过系统广播监听是否卸载成功
public static void uninstallApp(Context context, String packageName) {
Uri uri = Uri.parse("package:" + packageName);
Intent intent = new Intent(Intent.ACTION_DELETE, uri);
context.startActivity(intent);
}
public static void openAPK(Context context, String packageName) {
PackageManager packageManager = context.getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(packageName);
if (intent == null) {
Toast.makeText(context, "Launch failed", Toast.LENGTH_SHORT).show();
return;
}
context.startActivity(intent);
}
public static int compareVersion(int apkVersion, int packageVersion) {
if (apkVersion == packageVersion) {
return Constant.APK_VERSION_EQUAL;
} else if (apkVersion > packageVersion) {
return Constant.APK_VERSION_HIGHER;
} else {
return Constant.APK_VERSION_LOWER;
}
}
// public static void toStorage(Activity context, int operate, List<FileItem> fileItems) {
// ArrayList<String> paths = new ArrayList<>();
// for (FileItem fileItem : fileItems) {
// String path = fileItem.getPath();
// paths.add(path);
// }
// // 路强
// // StorageActivity.actionStart(context, operate, paths);
// }
}
package com.mints.wisdomclean.utils;
import android.view.View;
/**
* No comments
*/
public class ClickProxy implements View.OnClickListener {
private View.OnClickListener origin;
private long lastclick = 0;
private long timems = 500; //ms
private IAgain mIAgain;
public ClickProxy(View.OnClickListener origin, long timems, IAgain again) {
this.origin = origin;
this.mIAgain = again;
this.timems = timems;
}
public ClickProxy(View.OnClickListener origin) {
this.origin = origin;
}
@Override
public void onClick(View v) {
if (System.currentTimeMillis() - lastclick >= timems) {
origin.onClick(v);
lastclick = System.currentTimeMillis();
} else {
if (mIAgain != null) mIAgain.onAgain();
}
}
public interface IAgain {
void onAgain();//重复点击
}
}
package com.mints.wisdomclean.utils
import android.text.TextUtils
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
object CopyFileUtil {
interface CopyListener {
fun onSuccess()
fun onFailure()
}
fun copyMultipleFiles(files: List<File>, destDirPath: String, listener: CopyListener?) {
Thread {
val destDir = File(destDirPath)
if (!destDir.exists()) {
destDir.mkdirs()
}
var successCount = 0
files.forEach { file ->
val destFile = File(destDir, file.name)
try {
FileInputStream(file).use { input ->
FileOutputStream(destFile).use { output ->
input.copyTo(output)
}
}
successCount++
} catch (ex: Exception) {
ex.printStackTrace()
}
}
if (successCount == files.size) {
listener?.onSuccess()
} else {
listener?.onFailure()
}
}.start()
}
fun startDelete(path: String) {
if (TextUtils.isEmpty(path)) {
return
}
val file = File(path)
if (!file.exists()) {
return
}
file.delete()
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;
import com.mints.wisdomclean.R;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class DeleteFilesAsyncTask extends AsyncTask<String, Integer, String> {
private final String TAG = getClass().getName();
private ArrayList<File> listFile;
private Context mContext;
private LoadingDialog progressDialog;
private OnRestoreListener onRestoreListener;
TextView tvNumber;
int count = 0;
public DeleteFilesAsyncTask(Context context, ArrayList<File> mList, OnRestoreListener mOnRestoreListener) {
this.mContext = context;
this.listFile = mList;
this.onRestoreListener = mOnRestoreListener;
}
protected void onPreExecute() {
super.onPreExecute();
this.progressDialog = new LoadingDialog(this.mContext);
this.progressDialog.setCancelable(false);
this.progressDialog.show();
}
protected String doInBackground(String... strAr) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int strArr = 0; strArr < this.listFile.size(); strArr++) {
if ( this.listFile.get(strArr).exists()) {
boolean flag = isOnExtSdCard(this.listFile.get(strArr), mContext);
if (Build.VERSION.SDK_INT < 21 || !isOnExtSdCard(this.listFile.get(strArr), mContext)) {
try {
this.listFile.get(strArr).delete();
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
getDocumentFile( this.listFile.get(strArr), false, mContext).delete();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
count = strArr+1;
publishProgress(count);
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String str) {
super.onPostExecute(str);
try{
if (this.progressDialog != null&&progressDialog.isShowing()) {
this.progressDialog.cancel();
this.progressDialog = null;
}
}catch (Exception e){
}
if (null != onRestoreListener) {
onRestoreListener.onComplete();
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
tvNumber = (TextView)progressDialog.findViewById(R.id.tvNumber);
try {
}catch (Exception e){
tvNumber.setText(String.format("删除 ... %d 文件", values[0]));
}
}
public interface OnRestoreListener {
void onComplete();
}
@Nullable
private DocumentFile getDocumentFile( File file, boolean isDirectory, Context context) {
String sdUri = PreferenceManager.getDefaultSharedPreferences(context).getString("sdCardUri", "");
Log.i(TAG, "getDocumentFile: " + sdUri);
String baseFolder = getExtSdCardFolder(file, context);
boolean originalDirectory = false;
if (baseFolder == null) {
return null;
}
String relativePath = null;
try {
String fullPath = file.getCanonicalPath();
if (baseFolder.equals(fullPath)) {
originalDirectory = true;
} else {
relativePath = fullPath.substring(baseFolder.length() + 1);
}
} catch (IOException e) {
return null;
} catch (Exception e2) {
originalDirectory = true;
}
Uri treeUri = null;
if (!(sdUri == null || sdUri.equals(""))) {
treeUri = Uri.parse(sdUri);
}
if (treeUri == null) {
return null;
}
DocumentFile document = DocumentFile.fromTreeUri(context, treeUri);
if (originalDirectory) {
return document;
}
String[] parts = relativePath.split("\\/");
for (int i = 0; i < parts.length; i++) {
DocumentFile nextDocument = document.findFile(parts[i]);
if (nextDocument == null) {
if (i < parts.length - 1 || isDirectory) {
nextDocument = document.createDirectory(parts[i]);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
Log.i(TAG, "getDocumentFile: " + fileExtension);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
if (mimeType == null || TextUtils.isEmpty(mimeType)) {
nextDocument = document.createFile(mimeType, parts[i]);
} else {
nextDocument = document.createFile(mimeType, parts[i]);
}
}
}
document = nextDocument;
}
return document;
}
@TargetApi(19)
private static String getExtSdCardFolder(File file, Context context) {
String[] extSdPaths = getExtSdCardPaths(context);
int i = 0;
while (i < extSdPaths.length) {
try {
if (file.getCanonicalPath().startsWith(extSdPaths[i])) {
return extSdPaths[i];
}
i++;
} catch (IOException e) {
return null;
}
}
return null;
}
@TargetApi(19)
private static String[] getExtSdCardPaths(Context context) {
List<String> paths = new ArrayList();
for (File file : context.getExternalFilesDirs("external")) {
if (!(file == null || file.equals(context.getExternalFilesDir("external")))) {
int index = file.getAbsolutePath().lastIndexOf("/Android/data");
if (index < 0) {
Log.w("log", "Unexpected external file dir: " + file.getAbsolutePath());
} else {
String path = file.getAbsolutePath().substring(0, index);
try {
path = new File(path).getCanonicalPath();
} catch (IOException e) {
}
paths.add(path);
}
}
}
if (paths.isEmpty()) {
paths.add("/storage/sdcard1");
}
return (String[]) paths.toArray(new String[0]);
}
@TargetApi(19)
public static boolean isOnExtSdCard(File file, Context c) {
return getExtSdCardFolder(file, c) != null;
}
public String getType(Context c,File file){
ContentResolver cR = c.getContentResolver();
return cR.getType(Uri.fromFile(file));
}
}
package com.mints.wisdomclean.utils;
import android.os.Build;
import com.mints.wisdomclean.MintsApplication;
import java.util.UUID;
public class DevicesUtil {
/**
* 获取唯一标识idfa
*
* @return
*/
/**
* 获取Oaid
*
* @return oaid或错误码
*/
public static String getOaid() {
String idfa = "";
// if (MintsApplication.isSupportOaid()) {
// idfa = MintsApplication.getOaid();
// }
return idfa;
}
/**
* Pseudo-Unique ID, 这个在任何Android手机中都有效
* 有一些特殊的情况,一些如平板电脑的设置没有通话功能,或者你不愿加入READ_PHONE_STATE许可。而你仍然想获得唯
* 一序列号之类的东西。这时你可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出
* 来的ID不是唯一的(因为如果两个手机应用了同样的硬件以及Rom 镜像)。但应当明白的是,出现类似情况的可能性基
* 本可以忽略。大多数的Build成员都是字符串形式的,我们只取他们的长度信息。我们取到13个数字,并在前面加上“35
* ”。这样这个ID看起来就和15位IMEI一样了。
*
* @return PesudoUniqueID
*/
public static String getPesudoUniqueID() {
String m_szDevIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length() % 10 +
Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 +
Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 +
Build.HOST.length() % 10 +
Build.ID.length() % 10 +
Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 +
Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 +
Build.TYPE.length() % 10 +
Build.USER.length() % 10; //13 digits
m_szDevIDShort = MD5.GetMD5Code(m_szDevIDShort);
return m_szDevIDShort;
}
/**
* uuid
*
* @return
*/
public static String getUUID() {
String serial = null;
String m_szDevIDShort = "35" +
Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
Build.USER.length() % 10; //13 位
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
serial = android.os.Build.getSerial();
} else {
serial = Build.SERIAL;
}
//API>=9 使用serial号
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
} catch (Exception exception) {
//serial需要一个初始化
serial = "serial"; // 随便一个初始化
}
//使用硬件信息拼凑出来的15位号码
return new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
}
}
package com.mints.wisdomclean.utils
import java.text.DateFormat
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.roundToLong
object FormatUtils {
//定义GB的计算常量
private const val GB = 1024 * 1024 * 1024
//定义MB的计算常量
private const val MB = 1024 * 1024
//定义KB的计算常量
private const val KB = 1024
fun formatFileSize(bytes: Long): String {
if (bytes <= 0) return ""
//格式化小数
val format = DecimalFormat("###.0")
return when {
bytes / GB >= 1 -> {
format.format(bytes.toDouble() / GB) + "GB"
}
bytes / MB >= 1 -> {
format.format(bytes.toDouble() / MB) + "MB"
}
bytes / KB >= 1 -> {
format.format(bytes.toDouble() / KB) + "KB"
}
else -> {
bytes.toString() + "B"
}
}
}
fun formatDuration(duration: Long): String {
if (duration <= 0) return ""
var time: String? = ""
val minute: Long = duration / 60000
val seconds: Long = duration % 60000
val second = (seconds.toFloat() / 1000).roundToLong()
if (minute < 10) {
time += "0"
}
time += "$minute:"
if (second < 10) {
time += "0"
}
time += second
return time!!
}
fun formatTime(time: Long): String {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return formatter.format(time)
}
fun msDateFormat(ms: Long): String? { //日期
if (ms <= 0) {
return ""
}
val simpleDateFormat = DateFormat.getDateTimeInstance()
return simpleDateFormat.format(Date(ms))
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import java.text.SimpleDateFormat;
import java.util.Date;
public class GetPathFromUri {
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
if ("5D68-9217".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
public static String getVideoFileName() {
Date date = new Date(System.currentTimeMillis());// 获取当前的系统的时间
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyyMMddHHmmss");
return "android_" + dateFormat.format(date) + (int) ((Math.random() * 9 + 1) * 10000) + ".mp4";
}
}
package com.mints.wisdomclean.utils;
public class GpsUtil {
private static final double R = 6371;// 地球半径千米
//计算纬度半径差
private static double dlat(double dis) {
double dlat = dis / R;
return dlat * 180 / Math.PI;
}
//计算经度半径差
private static double dlng(double latitude, double dis) {
double dlng = 2 * Math.asin(Math.sin(dis / (2 * R)) / Math.cos(latitude * Math.PI / 180));
return dlng * 180 / Math.PI;// 角度转为弧度
}
/**
* 计算该GPS半径在radius(默认50米)的区域的范围(矩形范围)
* @param lat 纬度
* @param lng 经度
* @param radius 半径
* @return
*/
private static GpsRange getGpsRange(double lat, double lng, double radius) {
if (radius <= 0)
radius = 0.05;
double longitude = lng;// 经度
double dlng = dlng(lat, radius);//经度半径差
double latitude = lat;// 纬度
double dlat = dlat(radius);//纬度半径差
GpsRange gpsRange = new GpsRange();
gpsRange.lat_low = latitude - dlat;//左纬度
gpsRange.lat_high = latitude + dlat;//右纬度
gpsRange.lng_low = longitude - dlng;//上经度
gpsRange.lng_high = longitude + dlng;//下经度
return gpsRange;
}
static class GpsRange{
public double lat_low,lat_high;//左纬度,右纬度
public double lng_low,lng_high;//上经度,下经度
}
/**
* 验证2个Gps坐标是否在一定范围内(半径)交叉
* @param longitude1 经度1
* @param latitude1 纬度1
* @param longitude2 经度2
* @param latitude2 纬度2
* @param radius
* @return
*/
private static boolean checkCross(double longitude1, double latitude1,double longitude2, double latitude2, double radius){
if (longitude1 <= 0 || latitude1 <=0 || longitude2<=0 || latitude2 <=0)
throw new RuntimeException("经纬度错误");
GpsRange gpsRange = getGpsRange(latitude1, longitude1, radius);
System.out.println("经纬度:("+longitude2+"|"+latitude2+")"+gpsRange.lng_low +"--"+ gpsRange.lng_high +"--"+gpsRange.lat_low+ "--"+gpsRange.lat_high);
if (longitude2 >= gpsRange.lng_low && longitude2 <= gpsRange.lng_high && latitude2 >= gpsRange.lat_low && latitude2 <= gpsRange.lat_high)
return true;
return false;
}
/**
*
* @param longitude1
* @param latitude1
* @param longitude2
* @param latitude2
* @param radius
* @return true-范围内
*/
public static boolean checkCrossM(double longitude1, double latitude1,double longitude2, double latitude2, double radius){
return checkCross(longitude1,latitude1,longitude2,latitude2,radius/1000);
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils;
import android.animation.TypeEvaluator;
import android.graphics.Color;
public class HsvEvaluator implements TypeEvaluator<Integer> {
float[] startHsv = new float[3];
float[] endHsv = new float[3];
float[] outHsv = new float[3];
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
// 把 ARGB 转换成 HSV
Color.colorToHSV(startValue, startHsv);
Color.colorToHSV(endValue, endHsv);
// 计算当前动画完成度(fraction)所对应的颜色值
if (endHsv[0] - startHsv[0] > 180) {
endHsv[0] -= 360;
} else if (endHsv[0] - startHsv[0] < -180) {
endHsv[0] += 360;
}
outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction;
if (outHsv[0] > 360) {
outHsv[0] -= 360;
} else if (outHsv[0] < 0) {
outHsv[0] += 360;
}
outHsv[1] = startHsv[1] + (endHsv[1] - startHsv[1]) * fraction;
outHsv[2] = startHsv[2] + (endHsv[2] - startHsv[2]) * fraction;
// 计算当前动画完成度(fraction)所对应的透明度
int alpha = startValue >> 24 + (int) ((endValue >> 24 - startValue >> 24) * fraction);
// 把 HSV 转换回 ARGB 返回
return Color.HSVToColor(alpha, outHsv);
}
}
package com.mints.wisdomclean.utils
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.core.content.FileProvider
import java.io.File
object IntentUtils {
val isAndroidN = VersionUtils.isAndroidN()
fun openFile(context: Context, filePath: String?): Intent? {
val file = File(filePath)
if (!file.exists()) return null
/* 取得扩展名 */
val end: String =
file.name.substring(file.name.lastIndexOf(".") + 1, file.name.length)
.toLowerCase()
/* 依扩展名的类型决定MimeType */return if (end == "m4a" || end == "mp3" || end == "mid" || end == "xmf" || end == "ogg" || end == "wav") {
getAudioFileIntent(context, filePath)
} else if (end == "3gp" || end == "mp4") {
getAudioFileIntent(context, filePath)
} else if (end == "jpg" || end == "gif" || end == "png" || end == "jpeg" || end == "bmp") {
getImageFileIntent(context, filePath)
} else if (end == "apk") {
getApkFileIntent(context, filePath)
} else if (end == "ppt") {
getPptFileIntent(context, filePath)
} else if (end == "xls") {
getExcelFileIntent(context, filePath)
} else if (end == "doc") {
getWordFileIntent(context, filePath)
} else if (end == "pdf") {
getPdfFileIntent(context, filePath)
} else if (end == "chm") {
getChmFileIntent(context, filePath)
} else if (end == "txt") {
getTextFileIntent(filePath, false)
} else {
getAllIntent(context, filePath)
}
}
//Android获取一个用于打开APK文件的intent
fun getAllIntent(context: Context, param: String?): Intent? {
val intent = Intent()
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.action = Intent.ACTION_VIEW
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "*/*")
return intent
}
//Android获取一个用于打开APK文件的intent
fun getApkFileIntent(context: Context, param: String?): Intent? {
val intent = Intent()
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.action = Intent.ACTION_VIEW
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/vnd.android.package-archive")
return intent
}
//Android获取一个用于打开APK文件的intent
fun getZipFileIntent(context: Context, param: String?): Intent? {
val intent = Intent()
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.action = Intent.ACTION_VIEW
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/x-gzip")
return intent
}
//Android获取一个用于打开VIDEO文件的intent
fun getVideoFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("oneshot", 0)
intent.putExtra("configchange", 0)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "video/*")
return intent
}
//Android获取一个用于打开AUDIO文件的intent
fun getAudioFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.putExtra("oneshot", 0)
intent.putExtra("configchange", 0)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "audio/*")
return intent
}
//Android获取一个用于打开Html文件的intent
fun getHtmlFileIntent(param: String?): Intent? {
val uri: Uri = Uri.parse(param).buildUpon().encodedAuthority("com.android.htmlfileprovider")
.scheme("content").encodedPath(param).build()
val intent = Intent("android.intent.action.VIEW")
intent.setDataAndType(uri, "text/html")
return intent
}
//Android获取一个用于打开图片文件的intent
fun getImageFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "image/*")
return intent
}
//Android获取一个用于打开PPT文件的intent
fun getPptFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/vnd.ms-powerpoint")
return intent
}
//Android获取一个用于打开Excel文件的intent
fun getExcelFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/vnd.ms-excel")
return intent
}
//Android获取一个用于打开Word文件的intent
fun getWordFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/msword")
return intent
}
//Android获取一个用于打开CHM文件的intent
fun getChmFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/x-chm")
return intent
}
//Android获取一个用于打开文本文件的intent
fun getTextFileIntent(param: String?, paramBoolean: Boolean): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (paramBoolean) {
val uri1: Uri = Uri.parse(param)
intent.setDataAndType(uri1, "text/plain")
} else {
val uri2: Uri = Uri.fromFile(File(param))
intent.setDataAndType(uri2, "text/plain")
}
return intent
}
//Android获取一个用于打开PDF文件的intent
fun getPdfFileIntent(context: Context, param: String?): Intent? {
val intent = Intent("android.intent.action.VIEW")
intent.addCategory("android.intent.category.DEFAULT")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
var uri: Uri?
uri = if (isAndroidN) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
File(param)
)
} else {
Uri.fromFile(File(param))
}
intent.setDataAndType(uri, "application/pdf")
return intent
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils;
import android.app.Dialog;
import android.content.Context;
import com.mints.wisdomclean.R;
public class LoadingDialog extends Dialog {
private Context mContext;
public LoadingDialog(Context activity) {
super(activity, com.google.android.ads.mediationtestsuite.R.style.Theme_AppCompat_DayNight_Dialog);
this.mContext = activity;
requestWindowFeature(1);
setCancelable(false);
setCanceledOnTouchOutside(false);
setContentView(R.layout.layout_loading_dialog_dupicate);
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils
import android.content.Context
import android.net.TrafficStats
/**
* 获取网速
*/
object NetSpeed {
const val SPEED_INTERVAL: Long = 500 //获取网速速度 1秒
const val SPEED_MSG_WHAT = 101
private var lastTotalRxBytes: Long = 0
private var lastRxTimeStamp: Long = 0
private var lastTotalTxBytes: Long = 0
private var lastTxTimeStamp: Long = 0
/**
* 获取下行实时网速
*/
fun getRxNetSpeed(context: Context): Float {
val nowTotalRxBytes = getTotalRxBytes(context.applicationInfo.uid)
val nowTimeStamp = System.currentTimeMillis()
val speed =
(nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastRxTimeStamp) //毫秒转换
lastRxTimeStamp = nowTimeStamp
lastTotalRxBytes = nowTotalRxBytes
return speed.toFloat() // 单位kb
}
/**
* 获取上行实时网速
*/
fun getTxNetSpeed(context: Context): Float {
val nowTotalTxBytes = getTotalTxBytes(context.applicationInfo.uid)
val nowTimeStamp = System.currentTimeMillis()
val speed =
(nowTotalTxBytes - lastTotalTxBytes) * 1000 / (nowTimeStamp - lastTxTimeStamp) //毫秒转换
lastTxTimeStamp = nowTimeStamp
lastTotalTxBytes = nowTotalTxBytes
return speed.toFloat()
}
/**
* 下行实际用到的流量
*/
fun getTotalRxBytes(uid: Int): Long {
return if (TrafficStats.getUidRxBytes(uid) == TrafficStats.UNSUPPORTED.toLong()) 0 else TrafficStats.getTotalRxBytes() / 1024 //转为KB
}
/**
* 上行实际用到的流量
*/
fun getTotalTxBytes(uid: Int): Long {
return if (TrafficStats.getUidRxBytes(uid) == TrafficStats.UNSUPPORTED.toLong()) 0 else TrafficStats.getTotalTxBytes() / 1024 //转为KB
}
private var lastTestDownloadBytes: Long = 0
private var lastTestTimeStamp: Long = 0
/**
* 重置数据
*/
fun resetTestProperty() {
lastTestDownloadBytes = 0L
lastTestTimeStamp = 0L
lastTotalTxBytes = 0L
lastTxTimeStamp = 0L
lastTotalRxBytes = 0L
lastRxTimeStamp = 0L
}
/**
* 获取下载网速
*/
fun getDownloadNetSpeed(currentDownloadBytes: Long): Float {
if (currentDownloadBytes <= 0L) return 0f
val nowTimeStamp = System.currentTimeMillis()
if (nowTimeStamp - lastTestTimeStamp < 100) return 0f
val speed = (currentDownloadBytes
- lastTestDownloadBytes) * 1000 / (nowTimeStamp - lastTestTimeStamp) //毫秒转换
lastTestTimeStamp = nowTimeStamp
lastTestDownloadBytes = currentDownloadBytes
return String.format(
"%.2f",
speed / (1024.00)
).toFloat() // 转换成Kb
}
/**
* 获取下载网速
* @param speed 单位kb
*/
fun getShowStr(speed: Float): String {
if (speed > 1024f) {
return "${
String.format("%.2f", speed / 1024)
}Mb/s"
}
return "${
String.format("%.2f", speed)
}Kb/s"
}
}
\ No newline at end of file
package com.mints.wisdomclean.utils;
import android.widget.TextView;
import java.util.LinkedList;
import java.util.Random;
/**
* 描述:
* 作者:孟崔广
* 时间:2021/7/7 15:20
*/
public class NumAnimUtil {
//每秒刷新多少次
private static final int COUNTPERS = 10;
/**
* 进度100 时间2秒
* @param textV
*/
public static void startAnim(TextView textV) {
startAnim(textV, 100, 2000);
}
/**
* 进度随意 时间2秒
* @param textV
*/
public static void startAnim(TextView textV, float num) {
startAnim(textV, num, 2000);
}
/**
* 进度随意 时间随意
* @param textV
*/
public static void startAnim(TextView textV, float num, long time) {
if (num == 0) {
textV.setText(NumAnimUtil.NumberFormat(num, 2));
return;
}
Float[] nums = splitnum(num, (int) ((time / 1000f) * COUNTPERS));
Counter counter = new Counter(textV, nums, time);
textV.removeCallbacks(counter);
textV.post(counter);
}
private static Float[] splitnum(float num, int count) {
Random random = new Random();
float numtemp = num;
float sum = 0;
LinkedList<Float> nums = new LinkedList<Float>();
nums.add(0f);
while (true) {
float nextFloat = NumAnimUtil.NumberFormatFloat(
(random.nextFloat() * num * 2f) / (float) count,
2);
System.out.println("next:" + nextFloat);
if (numtemp - nextFloat >= 0) {
sum = NumAnimUtil.NumberFormatFloat(sum + nextFloat, 2);
nums.add(sum);
numtemp -= nextFloat;
} else {
nums.add(num);
return nums.toArray(new Float[0]);
}
}
}
static class Counter implements Runnable {
private final TextView view;
private Float[] nums;
private long pertime;
private int i = 0;
Counter(TextView view, Float[] nums, long time) {
this.view = view;
this.nums = nums;
this.pertime = time / nums.length;
}
@Override
public void run() {
if (i > nums.length - 1) {
view.removeCallbacks(Counter.this);
return;
}
view.setText("正在安全检测中("+NumAnimUtil.NumberFormat(nums[i++], 2)+"%)");
view.removeCallbacks(Counter.this);
view.postDelayed(Counter.this, pertime);
}
}
public static String NumberFormat(float f, int m) {
return String.format("%." + 0 + "f", f);
// return String.format("%" + f);
}
public static float NumberFormatFloat(float f, int m) {
String strfloat = NumberFormat(f, m);
return Float.parseFloat(strfloat);
}
}
package com.mints.wisdomclean.utils;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.Uri;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AlertDialog;
import java.util.ArrayList;
import java.util.List;
/**
* Desction:授权工具类
* Author:pengjianbo
* Date:2017/1/15 AM2:39
*/
public class PermissionUtils {
public static final int CODE_PERMISSIONS = 123;
public interface PermissionGrant {
/**
* 处理结果
*
* @param requestCode 请求码
* @param permissions 本次授权权限列表
* @param grantResults 本次授权结果,0:授权成功 -1:拒绝授权
* @param requestPermissions 请求所有权限
*/
void onPermissionGranted(final int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults, String[] requestPermissions);
}
private static void showMessageOKCancel(final Activity context, String message, DialogInterface.OnClickListener okListener, DialogInterface.OnClickListener cancelListener) {
new AlertDialog.Builder(context)
.setMessage(message)
.setPositiveButton("是", okListener)
.setNegativeButton("否", cancelListener)
.create()
.show();
}
/**
* 跳转到系统设置界面去开启权限
*
* @param activity
* @param message
*/
private static void openSettingActivity(final Activity activity, String message) {
showMessageOKCancel(activity, message, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivity(intent);
}
}, null);
}
/////////////////////////////////执行授权/////////////////////////////////////
/**
* 一次申请多个权限
*
* @param activity
* @param grant
*/
public static void requestMultiPermissions(final Activity activity, final String[] requestPermissions, final PermissionGrant grant) {
//获取没有授权的权限
final List<String> permissionsList = getNoGrantedPermission(activity, requestPermissions, false);
//获取上次被拒权限列表
final List<String> shouldRationalePermissionsList = getNoGrantedPermission(activity, requestPermissions, true);
if (permissionsList == null || shouldRationalePermissionsList == null) {
return;
}
final int[] grantResults = new int[requestPermissions.length];
if (permissionsList.size() > 0) {//去授权
ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]), CODE_PERMISSIONS);
} else if (shouldRationalePermissionsList.size() > 0) {
showMessageOKCancel(activity, "应用缺少权限,是否重新去授权?",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(activity, shouldRationalePermissionsList.toArray(new String[shouldRationalePermissionsList.size()]),
CODE_PERMISSIONS);
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
grant.onPermissionGranted(CODE_PERMISSIONS, requestPermissions, grantResults, requestPermissions);
}
});
} else {
grant.onPermissionGranted(CODE_PERMISSIONS, requestPermissions, grantResults, requestPermissions);
}
}
private static ArrayList<String> getNoGrantedPermission(Activity activity, String[] requestPermissions, boolean isShouldRationale) {
ArrayList<String> permissions = new ArrayList<>();
for (int i = 0; i < requestPermissions.length; i++) {
String requestPermission = requestPermissions[i];
int checkSelfPermission = -1;
try {
checkSelfPermission = ActivityCompat.checkSelfPermission(activity, requestPermission);
} catch (RuntimeException e) {
return null;
}
if (checkSelfPermission != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, requestPermission)) {
if (isShouldRationale) {
permissions.add(requestPermission);
}
} else {
if (!isShouldRationale) {
permissions.add(requestPermission);
}
}
}
}
return permissions;
}
/////////////////////////////////处理授权结果/////////////////////////////////////
/**
* 处理授权
*
* @param requestCode Need consistent with requestPermission
* @param permissions
* @param grantResults
*/
public static void requestPermissionsResult(final int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults, String[] requestPermissions, PermissionUtils.PermissionGrant permissionGrant) {
if (requestCode == CODE_PERMISSIONS) {
permissionGrant.onPermissionGranted(requestCode, permissions, grantResults, requestPermissions);
return;
}
}
/**
* 判断是否打开网络定位
*
* @param context 用于获取LocationManager
* @return true/false
*/
public static boolean isOpenGps(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
//这里只判断了是否开启网络定位
//还有GPS定位 LocationManager.GPS_PROVIDER
return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} else {
return false;
}
}
}
package com.mints.wisdomclean.utils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
/**
* author: 李文烙
* date: 2017/11/7
* desc:ping工具类
*/
public class PingNet {
private static final String TAG = "PingNet";
/**
* @param pingNetEntity 检测网络实体类
* @return 检测后的数据
*/
public static PingNetEntity ping(PingNetEntity pingNetEntity) {
String line = null;
Process process = null;
BufferedReader successReader = null;
//ping -c 次数 -w 超时时间(s) ip
String command = "ping -c " + pingNetEntity.getPingCount() + " -w " + pingNetEntity.getPingWtime() + " " + pingNetEntity.getIp();
try {
process = Runtime.getRuntime().exec(command);
if (process == null) {
Log.e(TAG, "ping fail:process is null.");
append(pingNetEntity.getResultBuffer(), "ping fail:process is null.");
pingNetEntity.setPingTime(null);
pingNetEntity.setResult(false);
return pingNetEntity;
}
successReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int count = 0;
BigDecimal sum = new BigDecimal(0);
while ((line = successReader.readLine()) != null) {
Log.i(TAG, line);
append(pingNetEntity.getResultBuffer(), line);
BigDecimal time = getTime(line);
if (time != null) {
sum = sum.add(time);
count++;
}
}
//时间取平均值,四舍五入保留两位小数
if (count > 0)
pingNetEntity.setPingTime((sum.divide(new BigDecimal(count), 0, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString() + " ms"));
else
pingNetEntity.setPingTime("0 ms");
int status = process.waitFor();
if (status == 0) {
Log.i(TAG, "exec cmd success:" + command);
append(pingNetEntity.getResultBuffer(), "exec cmd success:" + command);
pingNetEntity.setResult(true);
} else {
Log.e(TAG, "exec cmd fail.");
append(pingNetEntity.getResultBuffer(), "exec cmd fail.");
pingNetEntity.setPingTime(null);
pingNetEntity.setResult(false);
}
Log.i(TAG, "exec finished.");
append(pingNetEntity.getResultBuffer(), "exec finished.");
} catch (IOException e) {
Log.e(TAG, String.valueOf(e));
} catch (InterruptedException e) {
Log.e(TAG, String.valueOf(e));
} finally {
Log.i(TAG, "ping exit.");
if (process != null) {
process.destroy();
}
if (successReader != null) {
try {
successReader.close();
} catch (IOException e) {
Log.e(TAG, String.valueOf(e));
}
}
}
Log.i(TAG, pingNetEntity.getResultBuffer().toString());
return pingNetEntity;
}
private static void append(StringBuffer stringBuffer, String text) {
if (stringBuffer != null) {
stringBuffer.append(text + "\n");
}
}
/**
* 获取ping接口耗时
*
* @param line
* @return BigDecimal避免float、double精准度问题
*/
private static BigDecimal getTime(String line) {
String[] lines = line.split("\n");
String time = null;
for (String l : lines) {
if (!l.contains("time="))
continue;
int index = l.indexOf("time=");
time = l.substring(index + "time=".length());
index = time.indexOf("ms");
time = time.substring(0, index);
Log.e(TAG, time);
}
return time == null ? null : new BigDecimal(time.trim());
}
// private static String getTime(String line) {
// String[] lines = line.split("\n");
// String time = null;
// for (String l : lines) {
// if (!l.contains("time="))
// continue;
// int index = l.indexOf("time=");
// time = l.substring(index + "time=".length());
// Log.i(TAG, time);
// }
// return time;
// }
public static class PingNetEntity {
/*
TODO:进行ping操作的ip
*/
private String ip;
/*
TODO:进行ping操作的次数
*/
private int pingCount;
/*
TODO:ping操作超时时间
*/
private int pingWtime;
/*
TODO:存储ping操作后得到的数据
*/
private StringBuffer resultBuffer;
/*
TODO:ping ip花费的时间
*/
private String pingTime;
/*
TODO:进行ping操作后的结果
*/
private boolean result;
public PingNetEntity(String ip, int pingCount, int pingWtime, StringBuffer resultBuffer) {
this.ip = ip;
this.pingWtime = pingWtime;
this.pingCount = pingCount;
this.resultBuffer = resultBuffer;
}
public String getPingTime() {
return pingTime;
}
public void setPingTime(String pingTime) {
this.pingTime = pingTime;
}
public StringBuffer getResultBuffer() {
return resultBuffer;
}
public void setResultBuffer(StringBuffer resultBuffer) {
this.resultBuffer = resultBuffer;
}
public int getPingCount() {
return pingCount;
}
public void setPingCount(int pingCount) {
this.pingCount = pingCount;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public boolean isResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
public int getPingWtime() {
return pingWtime;
}
public void setPingWtime(int pingWtime) {
this.pingWtime = pingWtime;
}
}
}
package com.mints.wisdomclean.utils;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
public class SignUtils {
private static final String ALGORITHM = "RSA";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
private static final String DEFAULT_CHARSET = "UTF-8";
private static String getAlgorithms(boolean rsa2) {
return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;
}
public static String sign(String content, String privateKey, boolean rsa2) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance(getAlgorithms(rsa2));
signature.initSign(priKey);
signature.update(content.getBytes(DEFAULT_CHARSET));
byte[] signed = signature.sign();
return Base64.encode(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.mints.wisdomclean.utils;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import java.io.File;
/**
* @Author teach-梁任彦
* @Description
* @Date 2019-09-11
*/
public class UriUtils {
@SuppressLint("NewApi")
public static String getPathForUri(Context context,Uri uri){
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
if (VersionUtils.INSTANCE.isAndroidQ()) {
return context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" + split[1];
} else {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} catch (IllegalArgumentException ex) {
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
* 判断是否是Google相册的图片,类似于content://com.google.android.apps.photos.content/...
**/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* 判断是否是Google相册的图片,类似于content://com.google.android.apps.photos.contentprovider/0/1/mediakey:/local%3A821abd2f-9f8c-4931-bbe9-a975d1f5fabc/ORIGINAL/NONE/1075342619
**/
public static boolean isGooglePlayPhotosUri(Uri uri) {
return "com.google.android.apps.photos.contentprovider".equals(uri.getAuthority());
}
/**
* 图片路径转uri
* @param context
* @param path
* @return
*/
public static Uri getImageContentUri(Context context, String path) {
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID }, MediaStore.Images.Media.DATA + "=? ",
new String[] { path }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (new File(path).exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, path);
return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
}
package com.mints.wisdomclean.utils;
import android.util.Log;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
public class WeChatClearUtils {
// 微信包名称
//com.tencent.mm
private static final String TAG = "WeChatClearUtils";
// 图片
public static final String Pictures = "/sdcard/Pictures/WeiXin";
// 外部 缓冲数据
public static final String MicroMsg = "/sdcard/tencent/MicroMsg";
// 内部 缓冲数据
public static final String ANDROID_DATA_MicroMsg = "/sdcard/Android/data/com.tencent.mm/MicroMsg";
// 缓冲路径
public static final String CACHE = "/sdcard/Android/data/com.tencent.mm/cache";
// 微信接收文件的目录
public static final String DOWNLOAD = "/sdcard/Android/data/com.tencent.mm/MicroMsg/Download";
public static final String attachment = "attachment";
// 头像
public static final String avatar = "avatar";
public static final String bizcache = "bizcache";
public static final String bizimg = "bizimg";
public static final String brandicon = "brandicon";
public static final String draft = "draft";
//emoji
public static final String emoji = "emoji";
public static final String favoffline = "favoffline";
public static final String favorite = "favorite";
public static final String image = "image";
public static final String image2 = "image2";
public static final String mailapp = "mailapp";
public static final String music = "music";
public static final String oneday = "oneday";
public static final String openapi = "openapi";
public static final String openapi_cache = "openapi_cache";
public static final String openim = "openim";
public static final String _package = "package";
public static final String patmsg = "patmsg";
public static final String recbiz = "recbiz";
public static final String record = "record";
public static final String scanner = "scanner";
public static final String video = "video";
public static final String voice = "voice";
public static final String voice2 = "voice2";
public static final String voiceremind = "voiceremind";
public static final String webcanvascache = "webcanvascache";
public static final String wenote = "wenote";
public static final String JPG = ".jpg";
public static final String PNG = ".png";
public static final String JPEG = ".jpeg";
public static final String WEBP = ".webp";
public static final String MP3 = ".mp3";
public static final String MP4 = ".mp4";
public static final String PDF = ".pdf";
/**
* 去除List<String>中重复元素
*
* @param data
* @return
*/
public static List<String> removeDuplicateElements(List<String> data) {
HashSet ckear = new HashSet(data);
data.clear();
data.addAll(ckear);
return data;
}
/**
* 去除没有后缀的文件
*/
public static List<String> removeFilesWithoutSuffix(List<String> datas) {
List<String> result = new ArrayList<>();
for (String it : datas) {
File file = new File(it);
if (file.getName().lastIndexOf(".") != -1) {
result.add(it);
}
}
return result;
}
/**
* 获取文件创建时间
*
* @param file
* @return
*/
public static long getFileLastModifiedTime(File file) {
long time = file.lastModified();
return time;
}
/**
* 遍历所有的文件
*
* @param result
* @param path
*/
public static void search(List<String> result, String path) {
File file = new File(path);
if (file.exists()) {
File[] files = file.listFiles();
if (files == null || files.length == 0) {
return;
}
for (File it : files) {
if (it.isHidden()) {
continue;
}
if (it.isDirectory()) {
search(result, it.getPath());
}
result.add(it.getPath());
}
} else {
Log.e(TAG, "search: " + path + "not exists ");
}
}
/**
* 根据文件类型 遍历文件
*
* @param result
* @param path
* @param fileType
*/
public static void search(List<String> result, String path, String fileType) {
File file = new File(path);
if (file.exists()) {
File[] files = file.listFiles();
if (files == null || files.length == 0) {
return;
}
for (File it : files) {
if (it.isHidden()) {
continue;
}
if (it.isDirectory()) {
search(result, it.getPath(), fileType);
}
if (it.getPath().endsWith(fileType)) {
result.add(it.getPath());
}
}
} else {
Log.e(TAG, "search: " + path + "not exists ");
}
}
/**
* 微信 根据文件类型获取 文件列表
*
* @param fileType 文件类型, 传入后缀名称 eg:.png ,jpeg
* @return
*/
public static List<String> fileTypeToFiles(String fileType) {
List<String> result = new ArrayList<>();
search(result, Pictures, fileType);
search(result, MicroMsg, fileType);
return removeDuplicateElements(result);
}
/**
* 获取微信内 jpg 图片
*
* @return
*/
public static List<String> jpgs() {
List<String> result = new ArrayList<>();
search(result, Pictures, JPG);
search(result, MicroMsg, JPG);
return removeDuplicateElements(result);
}
/**
* 获取微信 png 图片
*
* @return
*/
public static List<String> pngs() {
List<String> result = new ArrayList<>();
search(result, Pictures, PNG);
search(result, MicroMsg, PNG);
return removeDuplicateElements(result);
}
/**
* 获取微信mp3文件
*
* @return
*/
public static List<String> mp3s() {
List<String> result = new ArrayList<>();
search(result, Pictures, MP3);
search(result, MicroMsg, MP3);
return removeDuplicateElements(result);
}
/**
* 获取微信 mp4 文件
*
* @return
*/
public static List<String> mp4s() {
List<String> result = new ArrayList<>();
search(result, Pictures, MP4);
search(result, MicroMsg, MP4);
return removeDuplicateElements(result);
}
/**
* 获取微信所有的图片
*
* @return
*/
public static List<String> images() {
List<String> result = new ArrayList<>();
search(result, Pictures, PNG);
search(result, MicroMsg, PNG);
search(result, Pictures, JPEG);
search(result, MicroMsg, JPEG);
search(result, Pictures, JPG);
search(result, MicroMsg, JPG);
search(result, Pictures, WEBP);
search(result, MicroMsg, WEBP);
return removeDuplicateElements(result);
}
/**
* 获取微信接收文件
*/
public static List<String> receiveFiles() {
List<String> result = new ArrayList<>();
search(result, DOWNLOAD);
return removeFilesWithoutSuffix(removeDuplicateElements(result));
}
/**
* 获取emoji缓冲数据
*
* @return
*/
public static List<String> emojis() {
List<String> result = new ArrayList<>();
List<String> accounts = accounts();
for (String it : accounts) {
String path = ANDROID_DATA_MicroMsg + "/" + it + "/" + emoji;
search(result, path);
}
return removeDuplicateElements(result);
}
/**
* /sdcard/Android/data/com.tencent.mm/MicroMsg/be37a7363309141066efd4f524ef1234
* <p>
* 获取 /sdcard/Android/data/com.tencent.mm/cache/ 路径下的 md5 用户标识
*
* @return
*/
private static List<String> accounts() {
List<String> result = new ArrayList<>();
File file = new File(ANDROID_DATA_MicroMsg);
if (file.exists()) {
File[] files = file.listFiles();
if (files == null || files.length == 0) {
return result;
}
for (File it : files) {
String fileName = it.getName();
if (fileName.length() == 32) {
result.add(fileName);
}
}
}
return result;
}
/**
* 获取微信语音聊天
*
* @return
*/
public static List<String> voice2() {
List<String> result = new ArrayList<>();
List<String> accounts = accounts();
for (String it : accounts) {
String path = ANDROID_DATA_MicroMsg + "/" + it + "/" + voice2;
search(result, path);
}
return removeDuplicateElements(result);
}
}
package com.mints.wisdomclean.utils;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.lang.ref.WeakReference;
public class WeakHandler extends Handler {
public interface IHandler {
void handleMsg(Message msg);
}
private final WeakReference<IHandler> mRef;
public WeakHandler(IHandler handler) {
mRef = new WeakReference<>(handler);
}
public WeakHandler(Looper looper, IHandler handler) {
super(looper);
mRef = new WeakReference<>(handler);
}
@SuppressWarnings("unused")
@Override
public void handleMessage(Message msg) {
IHandler handler = mRef.get();
if (handler != null && msg != null)
handler.handleMsg(msg);
}
}
\ No newline at end of file
......@@ -19,7 +19,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:text="智慧清理专家自动续费协议"
android:text="乐看短剧自动续费协议"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"></TextView>
......
......@@ -37,7 +37,7 @@
android:layout_marginTop="20dp"
android:layout_marginRight="26dp"
android:layout_marginBottom="30dp"
android:text="智慧清理专家将读取、写入(包括保存、下载、备份、上传、清理/删除、修改、扫描、检测)照片、媒体内容和文件,用于垃圾清理及加速、安全检测、文件风险扫描、本地照片、媒体内容和文件上传和备份,软件管理、下载安装、视频压缩。(使用场景以您实际触发为准)"
android:text="乐看短剧将读取、写入(包括保存、下载、备份、上传、清理/删除、修改、扫描、检测)照片、媒体内容和文件,用于垃圾清理及加速、安全检测、文件风险扫描、本地照片、媒体内容和文件上传和备份,软件管理、下载安装、视频压缩。(使用场景以您实际触发为准)"
android:textSize="14sp" />
<TextView
......
......@@ -17,7 +17,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:text="欢迎使用智慧清理专家"
android:text="欢迎使用乐看短剧"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
......@@ -38,7 +38,7 @@
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:text="欢迎使用智慧清理专家,我们非常重视对您的个人信息保护,在您使用智慧清理专家服务之前,请您认真阅读《用户注册协议》及《隐私政策》"
android:text="欢迎使用乐看短剧,我们非常重视对您的个人信息保护,在您使用乐看短剧服务之前,请您认真阅读《用户注册协议》及《隐私政策》"
android:textColor="@color/black"
android:textSize="14sp" />
......
......@@ -38,7 +38,7 @@
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginRight="16dp"
android:text="我们依据最新的法律,向您说明智慧清理专家软件的隐私政策,特向您推送本提示。请您阅读并充分理解相关条款。"
android:text="我们依据最新的法律,向您说明乐看短剧软件的隐私政策,特向您推送本提示。请您阅读并充分理解相关条款。"
android:textColor="@color/black"
android:textSize="14sp" />
......
<resources>
<string name="app_name">智慧清理专家</string>
<string name="app_name">乐看短剧</string>
<string name="netfail">网络异常,请检查网络</string>
<string name="notifyTitle">提示</string>
<string name="setting">设置</string>
......@@ -25,21 +25,21 @@
<string name="selector_all_image">全部图片</string>
<string name="str_agreement_vip">尊敬的智慧清理专家用户:\n
鉴于本协议是智慧清理专家用户(下称“用户”或“您”)(下称 “本公司”或“我们”)关于使用智慧清理专家产品提供的自动续费委托扣款服务(下称“本服务”)所订立的协议。您使用本服务前,已经注册成为智慧清理专家的用户,且已同意为使用智慧清理专家及本服务的相关用户协议及其它平台规则。\n
<string name="str_agreement_vip">尊敬的乐看短剧用户:\n
鉴于本协议是乐看短剧用户(下称“用户”或“您”)(下称 “本公司”或“我们”)关于使用乐看短剧产品提供的自动续费委托扣款服务(下称“本服务”)所订立的协议。您使用本服务前,已经注册成为乐看短剧的用户,且已同意为使用乐看短剧及本服务的相关用户协议及其它平台规则。\n
本协议描述我们与用户之间关于本服务的使用及相关方面的权利义务。本协议构成用户使用我们所提供的本服务之先决条件,除非用户接受本协议条款,否则用户无法使用本服务,用户选择使用本服务的行为将视为同意接受本协议当中的各项条款约束。\n
本协议未约定的内容,以用户在使用智慧清理专家时同意的相关用户协议及其它平台规则为准。 【注意】如您未满18周岁,请在监护人陪同下仔细阅读并充分理解本协议,并征得监护人的同意后使用本产品及相关服务。\n
本协议未约定的内容,以用户在使用乐看短剧时同意的相关用户协议及其它平台规则为准。 【注意】如您未满18周岁,请在监护人陪同下仔细阅读并充分理解本协议,并征得监护人的同意后使用本产品及相关服务。\n
本公司有权根据需要不定时地制定、修改本协议或各类规则,经修订的协议、规则一经公布,立即自动生效。对新协议、规则生效之后注册的用户发生法律效力,对于协议、规则生效之前注册的用户,若用户在新规则生效后继续使用本产品提供的各项服务,则表明用户已充分阅读并认可和同意遵守新的协议或规则。\n
若用户拒绝接受新的协议和规则,用户有权放弃或终止继续使用本产品提供的各项服务,但该用户应承担在本产品已经进行的交易下所应承担的任何法律责任,且应遵循该用户发生交易时有效的协议或规则内容。\n
您点击同意、接受或下一步,或您购买/开通自动续费会员服务的行为均视为您已阅读、理解并同意签署本协议。\n\n
一、连续包月服务条款确认及接纳\n
本公司提供的连续包月服务涉及到的相关知识产权均归本公司所有,受中华人民共和国法律及国际公约的依法保护。本服务协议项下的条款效力范围及于本公司的一切网络服务,用户在完成注册程序并开始使用智慧清理专家所提供的自动续费服务时,均应当受本服务协议下的各项条款约束。\n
本公司提供的连续包月服务涉及到的相关知识产权均归本公司所有,受中华人民共和国法律及国际公约的依法保护。本服务协议项下的条款效力范围及于本公司的一切网络服务,用户在完成注册程序并开始使用乐看短剧所提供的自动续费服务时,均应当受本服务协议下的各项条款约束。\n
一旦本协议发生修改,本公司将通过系统提示和/或信息推送和/或后台公告等形式发布,请您务必仔细阅读。如您对本协议的修改有任何问题,可以停止使用本服务并咨询客服,但需要提醒您的是,更新后的本协议自更新版本发布之日起生效。\n\n
二、自动续费服务相关说明\n
2.1 本服务是基于用户对自动续费需求,在用户已开通本服务的前提下,为避免用户因疏忽或其他原因导致未能及时续费造成损失而推出的服务。用户开通该服务后,即授权本公司可在会员自动续费期限到期前48小时和到期后,委托支付渠道(如支付宝、微信等)代扣下一个计费周期的费用,部分由运营商或支付渠道根据实际情况自行决定扣费周期的以实际扣费时间为准,如手机话费渠道、ios渠道等。选择自动续费的用户,即同意支付渠道在不验证账户密码、支付密码、短信校验码等信息的情况下从账户中扣划下一个计费周期的费用。一旦扣款成功,本公司将开通下一个计费周期的服务,并同时相应延长服务期限。该服务实现的前提是用户已将其智慧清理专家用户账号与上述账户绑定,且可成功从其上述账户中扣款。计费周期:如月度、季度、年度等(具体以智慧清理专家订购页面提供的为准),会员可自行选择。\n
2.1 本服务是基于用户对自动续费需求,在用户已开通本服务的前提下,为避免用户因疏忽或其他原因导致未能及时续费造成损失而推出的服务。用户开通该服务后,即授权本公司可在会员自动续费期限到期前48小时和到期后,委托支付渠道(如支付宝、微信等)代扣下一个计费周期的费用,部分由运营商或支付渠道根据实际情况自行决定扣费周期的以实际扣费时间为准,如手机话费渠道、ios渠道等。选择自动续费的用户,即同意支付渠道在不验证账户密码、支付密码、短信校验码等信息的情况下从账户中扣划下一个计费周期的费用。一旦扣款成功,本公司将开通下一个计费周期的服务,并同时相应延长服务期限。该服务实现的前提是用户已将其乐看短剧用户账号与上述账户绑定,且可成功从其上述账户中扣款。计费周期:如月度、季度、年度等(具体以乐看短剧订购页面提供的为准),会员可自行选择。\n
2.2 自动续费具体指基于2.1的前提下,本公司通过上述账户收取用户下一计费周期费用的扣费方式。用户需保证本公司可以从上述账户扣款成功,如因账户可扣款余额不足等其他用户自身原因导致的续费失败,应由用户自行承担责任。\n
2.3 自动续费服务所涉及或可能衍生的相关一切知识产权权利均由本公司依法所有,用户不得因使用自动续费服务而自动获得其任一或全部权利。\n
2.4 本公司将根据自身产品和服务的调整以及中华人民共和国有关法律、法规的变化,不断地完善服务质量并依此修改服务条款。本公司有权就服务协议随时更新,并在智慧清理专家产品相应服务页面进行显著、及时的提示。\n
2.4 本公司将根据自身产品和服务的调整以及中华人民共和国有关法律、法规的变化,不断地完善服务质量并依此修改服务条款。本公司有权就服务协议随时更新,并在乐看短剧产品相应服务页面进行显著、及时的提示。\n
2.5 本公司建议用户,定期关注本服务协议的条款。当用户认为本服务协议之任一或全部条款的调整不可接受时,请及时终止对本公司所提供之相关服务。\n\n
三、自动续费服务协议有效期限及终止\n
3.1 本协议自用户选择接受并使用本服务后生效。除非本公司或用户主动明确地取消了自动续费,否则用户获得的自动续费服务视为持续有效、不受次数限制。\n
......@@ -48,7 +48,7 @@
四、自动续费服务双方的权利和义务\n
4.1 本公司扣除的下一计费周期费用,并同时延长对应服务有效期。\n
4.2 如在扣费过程出现问题,本公司应与用户密切配合查明原因,各自承担己方过错造成的损失;若因双方各自存在不均等过错造成损失,应由双方按过错程度承担对应程度的责任;双方共负责任的,由双方均摊责任。\n
4.3 本公司可根据自身业务开展或技术升级等情况变更或修改本协议的有关服务内容、规则及条款。本公司在做出上述变更或修改前,在智慧清理专家产品相应服务页面进行显著、及时的提示。\n
4.3 本公司可根据自身业务开展或技术升级等情况变更或修改本协议的有关服务内容、规则及条款。本公司在做出上述变更或修改前,在乐看短剧产品相应服务页面进行显著、及时的提示。\n
4.4 本服务由用户自主选择是否取消,若用户未取消服务,则视为用户同意本公司继续按照一定规则进行续费扣款(长期有效、不受次数限制)。一旦完成扣款,本公司将为用户开通下一个计费周期服务。\n
4.5 对于所选择的支付渠道,用户有义务定期关注并确保该支付方式的账户下有充足的余额用于满足自动续费服务的应用。如因前述原因(包括但不限于余额不足)而导致无法完成自动续费服务,则本公司有权在不再作另行通知的前提下,暂停用户通过自动续费服务所接入的相关服务。\n\n
五、退费\n
......
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