Commit f54ad0d2 by zhangchengbo

feat:添加[黑名单]工具类与javaBean

parent a91b8262
package com.simplemobiletools.commons.models
import android.os.Parcelable
import android.telephony.PhoneNumberUtils
import androidx.annotation.Keep
import com.simplemobiletools.commons.extensions.normalizePhoneNumber
import kotlinx.parcelize.Parcelize
/**
* Used at displaying recent calls.
* For contacts with multiple numbers specify the number and type
*/
@Keep
@kotlinx.serialization.Serializable
@Parcelize
data class RecentCall(
val id: Int,
val phoneNumber: String,
val name: String,
val photoUri: String,
val startTS: Int,
val duration: Int,
val type: Int,
val neighbourIDs: MutableList<Int>,
val simID: Int,
val specificNumber: String,
val specificType: String,
val isUnknownNumber: Boolean,
var isShunFeng: Boolean,
var sfNumber: String,
var isExport: Boolean = false,//是否已经导出过该条记录
) : Parcelable {
fun doesContainPhoneNumber(text: String): Boolean {
val normalizedText = text.normalizePhoneNumber()
return PhoneNumberUtils.compare(phoneNumber.normalizePhoneNumber(), normalizedText) ||
phoneNumber.contains(text) ||
phoneNumber.normalizePhoneNumber().contains(normalizedText) ||
phoneNumber.contains(normalizedText)
}
}
package com.simplemobiletools.commons.models
import android.telecom.PhoneAccountHandle
import androidx.annotation.Keep
@Keep
data class SIMAccount(val id: Int, val handle: PhoneAccountHandle, val label: String, val phoneNumber: String)
package com.simplemobiletools.commons.utils;
import android.os.Build;
import android.util.Base64;
import androidx.annotation.RequiresApi;
import com.secspace.log.Log;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* AES 对称加密算法,加解密工具类
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class AESCommon {
private static final String TAG = AESCommon.class.getSimpleName() + " --> ";
/**
* 加密算法
*/
private static final String KEY_ALGORITHM = "AES";
/**
* AES 的 密钥长度,32 字节,范围:16 - 32 字节
*/
public static final int SECRET_KEY_LENGTH = 32;
/**
* 字符编码
*/
private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
/**
* 秘钥长度不足 16 个字节时,默认填充位数
*/
private static final String DEFAULT_VALUE = "0";
/**
* 加解密算法/工作模式/填充方式
*/
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
/**
* 加密密码,长度:16 或 32 个字符(随便定义)
*/
private static final String secretKey = "qweasd123";
/**
* AES 加密
*
* @param data 待加密内容
* @return 返回Base64转码后的加密数据
*/
public static String encrypt(String data) {
try {
//创建密码器
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//初始化为加密密码器
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(secretKey));
byte[] encryptByte = cipher.doFinal(data.getBytes(CHARSET_UTF8));
// 将加密以后的数据进行 Base64 编码
return base64Encode(encryptByte);
} catch (Exception e) {
handleException(e);
}
return null;
}
/**
* AES 解密
*
* @param base64Data 加密的密文 Base64 字符串
*/
public static String decrypt(String base64Data) {
try {
byte[] data = base64Decode(base64Data);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
//设置为解密模式
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(secretKey));
//执行解密操作
byte[] result = cipher.doFinal(data);
return new String(result, CHARSET_UTF8);
} catch (Exception e) {
handleException(e);
}
return null;
}
/**
* 使用密码获取 AES 秘钥
*/
public static SecretKeySpec getSecretKey(String secretKey) {
secretKey = toMakeKey(secretKey, SECRET_KEY_LENGTH, DEFAULT_VALUE);
return new SecretKeySpec(secretKey.getBytes(CHARSET_UTF8), KEY_ALGORITHM);
}
/**
* 如果 AES 的密钥小于 {@code length} 的长度,就对秘钥进行补位,保证秘钥安全。
*
* @param secretKey 密钥 key
* @param length 密钥应有的长度
* @param text 默认补的文本
* @return 密钥
*/
private static String toMakeKey(String secretKey, int length, String text) {
// 获取密钥长度
int strLen = secretKey.length();
// 判断长度是否小于应有的长度
if (strLen < length) {
// 补全位数
StringBuilder builder = new StringBuilder();
// 将key添加至builder中
builder.append(secretKey);
// 遍历添加默认文本
for (int i = 0; i < length - strLen; i++) {
builder.append(text);
}
// 赋值
secretKey = builder.toString();
}
return secretKey;
}
/**
* 将 Base64 字符串 解码成 字节数组
*/
public static byte[] base64Decode(String data) {
return Base64.decode(data, Base64.NO_WRAP);
}
/**
* 将 字节数组 转换成 Base64 编码
*/
public static String base64Encode(byte[] data) {
return Base64.encodeToString(data, Base64.NO_WRAP);
}
/**
* 处理异常
*/
private static void handleException(Exception e) {
e.printStackTrace();
Log.e(TAG, TAG + e);
}
/**
* 对文件进行AES加密
*
* @param sourceFile 待加密文件
* @param dir 加密后的文件存储路径
* @param toFileName 加密后的文件名称
* @param secretKey 密钥
* @return 加密后的文件
*/
public static File encryptFile(File sourceFile, String dir, String toFileName, String secretKey) {
try {
// 创建加密后的文件
File encryptFile = new File(dir, toFileName);
// 根据文件创建输出流
FileOutputStream outputStream = new FileOutputStream(encryptFile);
// 初始化 Cipher
Cipher cipher = initFileAESCipher(secretKey, Cipher.ENCRYPT_MODE);
// 以加密流写入文件
CipherInputStream cipherInputStream = new CipherInputStream(
new FileInputStream(sourceFile), cipher);
// 创建缓存字节数组
byte[] buffer = new byte[1024 * 2];
// 读取
int len;
// 读取加密并写入文件
while ((len = cipherInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
outputStream.flush();
}
// 关闭加密输入流
cipherInputStream.close();
closeStream(outputStream);
return encryptFile;
} catch (Exception e) {
handleException(e);
}
return null;
}
/**
* AES解密文件
*
* @param sourceFile 源加密文件
* @param dir 解密后的文件存储路径
* @param toFileName 解密后的文件名称
* @param secretKey 密钥
*/
public static File decryptFile(File sourceFile, String dir, String toFileName, String secretKey) {
try {
// 创建解密文件
File decryptFile = new File(dir, toFileName);
// 初始化Cipher
Cipher cipher = initFileAESCipher(secretKey, Cipher.DECRYPT_MODE);
// 根据源文件创建输入流
FileInputStream inputStream = new FileInputStream(sourceFile);
// 获取解密输出流
CipherOutputStream cipherOutputStream = new CipherOutputStream(
new FileOutputStream(decryptFile), cipher);
// 创建缓冲字节数组
byte[] buffer = new byte[1024 * 2];
int len;
// 读取解密并写入
while ((len = inputStream.read(buffer)) >= 0) {
cipherOutputStream.write(buffer, 0, len);
cipherOutputStream.flush();
}
// 关闭流
cipherOutputStream.close();
closeStream(inputStream);
return decryptFile;
} catch (IOException e) {
handleException(e);
}
return null;
}
/**
* 初始化 AES Cipher
*
* @param secretKey 密钥
* @param cipherMode 加密模式
* @return 密钥
*/
private static Cipher initFileAESCipher(String secretKey, int cipherMode) {
try {
// 创建密钥规格
SecretKeySpec secretKeySpec = getSecretKey(secretKey);
// 获取密钥
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 初始化
cipher.init(cipherMode, secretKeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
return cipher;
} catch (Exception e) {
handleException(e);
}
return null;
}
/**
* 关闭流
*
* @param closeable 实现Closeable接口
*/
private static void closeStream(Closeable closeable) {
try {
if (closeable != null) closeable.close();
} catch (Exception e) {
handleException(e);
}
}
}
package com.simplemobiletools.commons.utils
import java.lang.reflect.Field
object PhoneFromUtilCommon {
/**
* 获取调用者的包名
*
* @return
*/
// 反射的方式获取mReferrer
fun reflectGetReferrerA(): String {
try {
val activityClass = Class.forName("android.app.Activity");
val refererField = activityClass.getDeclaredField("mReferrer");
refererField.isAccessible = true
val referrer: String = refererField.get(this).toString()
return referrer
} catch (e: Exception) {
return "No referrer"
}
}
fun reflectGetReferrer(): String {
try {
val activityClass = Class.forName("android.app.Activity")
val refererField: Field = activityClass.getDeclaredField("mReferrer")
refererField.isAccessible = true
return refererField.get(this).toString()
} catch (e: ClassNotFoundException) {
e.printStackTrace()
return "No referrer"
} catch (e: IllegalAccessException) {
e.printStackTrace()
return "No referrer"
} catch (e: NoSuchFieldException) {
e.printStackTrace()
return "No referrer"
}
}
/**
* 是否是纯数字 正则
*/
fun isNumeric(str: String): Boolean {
return str.matches("\\d+".toRegex())
}
/**
* 判断字符串是否为纯中文
*
* @param str 输入的字符串
* @return 是否为纯中文
*/
fun isPureChinese(str: String?): Boolean {
if (str.isNullOrEmpty()) {
return false
}
// 定义中文字符的 Unicode 范围
val regex = "[\\u4E00-\\u9FA5|\\u3400-\\u4DBF|\\u20000-\\u2A6DF]+"
return str.matches(regex.toRegex())
}
fun containsChinese(str: String): Boolean {
for (i in 0 until str.length) {
val c = str[i]
if (c >= '\u4e00' && c <= '\u9fff' || c >= '\u3400' && c <= '\u4DBF') {
return true
}
}
return false
}
}
package com.simplemobiletools.commons.utils
/**
* 手机号码处理工具类
* Created by
*/
object PhoneUtilsCommon {
/**
* 电话号掩码规则
*/
fun phoneNumberFormat(number: String, phoneCallBack: (String) -> Unit/*, errorCallback: (String) -> Unit*/) {
if (number.isBlank() || number.length <= 6) return
var phoneResult = ""
val numberResult = number.replace(" ", "")//原始号码
when (numberResult.length) {
7 -> {
val phone = numberResult.substring(3, numberResult.length)
phoneResult = "${"***$phone"}"
phoneCallBack.invoke(phoneResult)
}
8 -> {
val phone = numberResult.substring(4, numberResult.length)
phoneResult = "${"****$phone"}"
phoneCallBack.invoke(phoneResult)
}
11 -> {
if (numberResult.substring(0, 1) == "1") {
phoneResult = numberResult.replace("(\\d{3})\\d{4}(\\d{4})".toRegex(), "$1****$2")
phoneCallBack.invoke(phoneResult)
} else {
val phone1 = numberResult.substring(0, 3)
val phone2 = numberResult.substring(7, numberResult.length)
phoneResult = "${"$phone1****$phone2"}"
phoneCallBack.invoke(phoneResult)
}
}
12 -> {
val phone1 = numberResult.substring(0, 4)
val phone2 = numberResult.substring(9, numberResult.length)
phoneResult = "${"$phone1****$phone2"}"
phoneCallBack.invoke(phoneResult)
}
14 -> {
if (numberResult.contains("+86")) {
val phoneNum = numberResult.substring(3, numberResult.length)
phoneResult = phoneNum.replace("(\\d{3})\\d{4}(\\d{4})".toRegex(), "$1****$2")
phoneCallBack.invoke(phoneResult)
}
}
else -> {
if (number.isNotBlank()) {
phoneCallBack.invoke(number)
}
}
}
// Log.e("shuju", "---phoneNumberFormat---原号码:${numberResult} 掩码后:$phoneResult //手机号长度:${numberResult.length}")
}
/**
* 手机号码脱敏转换
*/
fun phoneConvert(number: String): String {
if (number.isBlank() || number.length <= 6) return ""
var phoneResult = ""
val numberResult = number.replace(" ", "")//原始号码
if (numberResult.substring(0, 1) == "1") {
phoneResult = numberResult.replace("(\\d{3})\\d{4}(\\d{4})".toRegex(), "$1****$2")
} else {
val phone1 = numberResult.substring(0, 3)
val phone2 = numberResult.substring(7, numberResult.length)
phoneResult = "${"$phone1****$phone2"}"
}
return phoneResult
}
}
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