feat: dev-5.1 分支基线(v1.3.35 发版后代码 + 5.1 声道改造文档)
- 以 main(ccc65af) 为基线提交当前工作区代码
- 新增 5.1 声道改造文档两份
- .gitignore 补充 .vscode/、.screenshots/
This commit is contained in:
0
libcore/.gitignore
vendored
Executable file → Normal file
0
libcore/.gitignore
vendored
Executable file → Normal file
0
libcore/build.gradle
Executable file → Normal file
0
libcore/build.gradle
Executable file → Normal file
0
libcore/consumer-rules.pro
Executable file → Normal file
0
libcore/consumer-rules.pro
Executable file → Normal file
0
libcore/proguard-rules.pro
vendored
Executable file → Normal file
0
libcore/proguard-rules.pro
vendored
Executable file → Normal file
0
libcore/src/androidTest/java/com/pukka/libcore/ExampleInstrumentedTest.java
Executable file → Normal file
0
libcore/src/androidTest/java/com/pukka/libcore/ExampleInstrumentedTest.java
Executable file → Normal file
0
libcore/src/main/AndroidManifest.xml
Executable file → Normal file
0
libcore/src/main/AndroidManifest.xml
Executable file → Normal file
10
libcore/src/main/java/com/pukka/libcore/base/BaseConst.java
Executable file → Normal file
10
libcore/src/main/java/com/pukka/libcore/base/BaseConst.java
Executable file → Normal file
@@ -14,14 +14,14 @@ public class BaseConst {
|
||||
|
||||
public static final String header = "huashitv";
|
||||
|
||||
//渠道code
|
||||
public static String agentVendorCode = "1100101010208919998410060";
|
||||
//渠道code(橘视厅5.1环绕声业务渠道,与 ChannelManger.initChannel 保持一致)
|
||||
public static String agentVendorCode = "1100101010200492358120169";
|
||||
//业务组合code
|
||||
public static String serviceComboCode = "1100121010208920760580061";
|
||||
public static String serviceComboCode = "1100121044377892530980001";
|
||||
//业务分组code
|
||||
public static String serviceGroupCode = "1100122010208920968780062";
|
||||
public static String serviceGroupCode = "1100122010201752209710182";
|
||||
//业务线参数
|
||||
public static String businessLine = "4100450011967708592750001";
|
||||
public static String businessLine = "4100450044057893707260002";
|
||||
|
||||
|
||||
public static String getMemberCode(String token){
|
||||
|
||||
0
libcore/src/main/java/com/pukka/libcore/base/BaseUrl.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/BaseUrl.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/BuildConfig.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/BuildConfig.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/DifferenceApi.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/DifferenceApi.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/DifferenceUrl.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/base/DifferenceUrl.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/boxShared/BoxSharedParameters.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/boxShared/BoxSharedParameters.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/boxShared/BoxSharedParamsUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/boxShared/BoxSharedParamsUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/boxShared/IpUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/boxShared/IpUtils.java
Executable file → Normal file
264
libcore/src/main/java/com/pukka/libcore/boxShared/MacUtils.java
Executable file → Normal file
264
libcore/src/main/java/com/pukka/libcore/boxShared/MacUtils.java
Executable file → Normal file
@@ -1,27 +1,13 @@
|
||||
package com.pukka.libcore.boxShared;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
import com.pukka.libcore.utils.SharedPreferenceUtils;
|
||||
import com.pukka.libcore.utils.StringUtil;
|
||||
import com.pukka.libcore.utils.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@@ -31,226 +17,70 @@ import java.util.Locale;
|
||||
*/
|
||||
public class MacUtils {
|
||||
/**
|
||||
* 获取mac地址(适配所有Android版本)
|
||||
* 获取 mac 地址(适配所有 Android 版本)
|
||||
* 优先取 ETH_MAC 缓存,再读设备;都拿不到就如实返回空字符串,
|
||||
* 不再伪造(伪造 MAC 在服务端设备库里匹配不到,行为更糟)。
|
||||
*
|
||||
* @param context 上下文
|
||||
* @return mac地址
|
||||
* @return mac地址;拿不到时返回 ""
|
||||
*/
|
||||
public static String getMac(Context context) {
|
||||
// String mac = getMacAddressIP();
|
||||
// if (TextUtils.isEmpty(mac)) {
|
||||
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
// mac = getMacDefault(context);
|
||||
// } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
// mac = getMacAddress();
|
||||
// } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
// mac = getMacFromHardware();
|
||||
// }
|
||||
// }
|
||||
// if (TextUtils.isEmpty(mac)){
|
||||
String mac = SharedPreferenceUtils.getString("ETH_MAC","");
|
||||
LogUtils.d("从APK缓存中获取有线mac="+mac);
|
||||
if(StringUtils.isEmpty(mac)) {
|
||||
//安柠获取mac的方法
|
||||
// 1) 优先从缓存取(有线 MAC 第一次成功读取后会写到这里)
|
||||
String mac = SharedPreferenceUtils.getString("ETH_MAC", "");
|
||||
LogUtils.d("从APK缓存中获取有线mac=" + mac);
|
||||
if (StringUtils.isEmpty(mac)) {
|
||||
// 2) 缓存未命中,按多路策略读设备
|
||||
mac = StringUtil.getLocalMac();
|
||||
LogUtils.d("从设备中获取mac="+mac);
|
||||
}
|
||||
if(StringUtils.isEmpty(mac)) {
|
||||
//自己生成mac的方法
|
||||
mac = MacUtils2.getMAC(context);
|
||||
LogUtils.d("从设备中自生成mac="+mac);
|
||||
LogUtils.d("从设备中获取mac=" + mac);
|
||||
}
|
||||
return mac;
|
||||
//}
|
||||
//return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* 读 /sys/class/net/wlan0/address,走 shell cat 以绕过 SELinux 对 Java 直读 sysfs 的拒绝。
|
||||
* 循环读满直到 EOF,避免单次 read(buffer) 不保证读满的坑。
|
||||
*
|
||||
* @return wlan0 MAC;读不到返回 ""
|
||||
*/
|
||||
public static String getWlan0Mac() {
|
||||
String mac = "";
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address");
|
||||
InputStream is = p.getInputStream();
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader bf = new BufferedReader(isr);
|
||||
String line = "";
|
||||
if ((line = bf.readLine()) != null) {
|
||||
mac = line;
|
||||
}
|
||||
bf.close();
|
||||
isr.close();
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return mac.toUpperCase();
|
||||
// 复用 StringUtil.readSysFsMac,仅末尾大小写归一化与本方法旧行为一致
|
||||
return StringUtil.readSysFsMac("/sys/class/net/wlan0/address").toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Android 6.0 之前(不包括6.0)获取mac地址
|
||||
* 必须的权限 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
|
||||
* 统一封装:拿不到有线 MAC 时以 WifiMAC 为主(两者相同),避免下游出现"伪 mac"。
|
||||
* 返回 String[2] = {mac, wifiMac}:
|
||||
* <ul>
|
||||
* <li>有线拿到了:mac = 有线MAC,wifiMac = wlan0MAC(两者可能不同——双网卡设备)</li>
|
||||
* <li>有线没拿到、wifi 拿到了:mac = wlan0MAC,wifiMac = wlan0MAC(两者完全一致)</li>
|
||||
* <li>都拿不到:两者均为 ""</li>
|
||||
* </ul>
|
||||
* 当两者真值相同(wifi-only 设备)但大小写不同时,统一成大写——便于后端按字符串比对 MAC。
|
||||
* 双网卡设备上两者来自不同接口(有线 ≠ 无线),保留各自原值不强制统一。
|
||||
*
|
||||
* @param context * @return
|
||||
* @param context 上下文
|
||||
* @return 长度固定为 2 的数组:[mac, wifiMac]
|
||||
*/
|
||||
private static String getMacDefault(Context context) {
|
||||
String mac = "";
|
||||
if (context == null) {
|
||||
return mac;
|
||||
public static String[] getDeviceMacPair(Context context) {
|
||||
// 独立取两条路径,避免继承 getMac() 内部任何兜底行为
|
||||
String ethMac = getMac(context);
|
||||
String wifiMac = getWlan0Mac();
|
||||
// 拿不到有线时以 wifi 为主(两者相同)
|
||||
if (TextUtils.isEmpty(ethMac) && !TextUtils.isEmpty(wifiMac)) {
|
||||
ethMac = wifiMac;
|
||||
}
|
||||
WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
|
||||
WifiInfo info = null;
|
||||
try {
|
||||
info = wifi.getConnectionInfo();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// 拿不到 wifi 时以有线为主(双向兜底,保持两者一致)
|
||||
if (TextUtils.isEmpty(wifiMac) && !TextUtils.isEmpty(ethMac)) {
|
||||
wifiMac = ethMac;
|
||||
}
|
||||
|
||||
if (info == null) {
|
||||
return null;
|
||||
// 两者都非空且真值相同(wifi-only 设备的常见场景),统一大小写
|
||||
// 双网卡设备上两者来源不同,equalsIgnoreCase 不命中,保留各自原值
|
||||
if (!TextUtils.isEmpty(ethMac) && !TextUtils.isEmpty(wifiMac)
|
||||
&& ethMac.equalsIgnoreCase(wifiMac)) {
|
||||
String canonical = ethMac.toUpperCase(Locale.ENGLISH);
|
||||
ethMac = canonical;
|
||||
wifiMac = canonical;
|
||||
}
|
||||
mac = info.getMacAddress();
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
mac = mac.toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Android 6.0-Android 7.0 获取mac地址
|
||||
*/
|
||||
private static String getMacAddress() {
|
||||
String macSerial = null;
|
||||
String str = "";
|
||||
|
||||
try {
|
||||
Process pp = Runtime.getRuntime().exec("cat /sys/class/net/wlan0/address");
|
||||
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
|
||||
LineNumberReader input = new LineNumberReader(ir);
|
||||
|
||||
while (null != str) {
|
||||
str = input.readLine();
|
||||
if (str != null) {
|
||||
macSerial = str.trim();//去空格
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// 赋予默认值
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return macSerial;
|
||||
}
|
||||
|
||||
/**
|
||||
* Android 7.0之后获取Mac地址
|
||||
* 遍历循环所有的网络接口,找到接口是 wlan0
|
||||
* 必须的权限 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static String getMacFromHardware() {
|
||||
Enumeration<NetworkInterface> interfaces = null;
|
||||
try {
|
||||
interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String hardWareAddress = null;
|
||||
NetworkInterface iF = null;
|
||||
if (interfaces == null) {
|
||||
return null;
|
||||
}
|
||||
while (interfaces.hasMoreElements()) {
|
||||
iF = interfaces.nextElement();
|
||||
try {
|
||||
hardWareAddress = bytesToString(iF.getHardwareAddress());
|
||||
if (hardWareAddress != null) {
|
||||
break;
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return hardWareAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Android 6.0 之前(不包括6.0)
|
||||
* 获取有线网络mac
|
||||
*
|
||||
* @return 有线网络mac
|
||||
*/
|
||||
private static String getMacAddressIP() {
|
||||
String strMacAddr = null;
|
||||
try {
|
||||
InetAddress ip = getLocalInetAddress();
|
||||
byte[] b = NetworkInterface.getByInetAddress(ip)
|
||||
.getHardwareAddress();
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
if(b != null) {
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
if (i != 0) {
|
||||
buffer.append(':');
|
||||
}
|
||||
String str = Integer.toHexString(b[i] & 0xFF);
|
||||
buffer.append(str.length() == 1 ? 0 + str : str);
|
||||
}
|
||||
}
|
||||
strMacAddr = buffer.toString().toUpperCase();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return strMacAddr;
|
||||
}
|
||||
|
||||
/***
|
||||
* byte转为String
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
private static String bytesToString(byte[] bytes) {
|
||||
if (bytes == null || bytes.length == 0) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
buf.append(String.format("%02X:", b));
|
||||
}
|
||||
if (buf.length() > 0) {
|
||||
buf.deleteCharAt(buf.length() - 1);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本地IP
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static InetAddress getLocalInetAddress() {
|
||||
InetAddress ip = null;
|
||||
try {
|
||||
//列举
|
||||
Enumeration en_netInterface = NetworkInterface.getNetworkInterfaces();
|
||||
while (en_netInterface.hasMoreElements()) {//是否还有元素
|
||||
NetworkInterface ni = (NetworkInterface) en_netInterface.nextElement();//得到下一个元素
|
||||
Enumeration en_ip = ni.getInetAddresses();//得到一个ip地址的列举
|
||||
while (en_ip.hasMoreElements()) {
|
||||
ip = (InetAddress) en_ip.nextElement();
|
||||
if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
|
||||
break;
|
||||
} else {
|
||||
ip = null;
|
||||
}
|
||||
}
|
||||
if (ip != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return ip;
|
||||
return new String[]{ethMac, wifiMac};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
package com.pukka.libcore.boxShared;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.pukka.libcore.utils.LogUtils;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
public class MacUtils2 {
|
||||
|
||||
public static String getMAC(Context context) {
|
||||
// 获取基础信息
|
||||
String baseInfo = getBaseDeviceInfo(context);
|
||||
// 生成MAC格式字符串
|
||||
String macAddress = generateMacFromHash(baseInfo);
|
||||
LogUtils.i("MacUtils", "return Mac:" + macAddress);
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
public static String getBaseDeviceInfo(Context context) {
|
||||
// 获取设备基本信息
|
||||
String androidId = "";
|
||||
androidId = Settings.Secure.getString(
|
||||
context.getContentResolver(),
|
||||
Settings.Secure.ANDROID_ID
|
||||
);
|
||||
LogUtils.i("MacUtils", "androidId:" + androidId);
|
||||
String deviceInfo = Build.BRAND
|
||||
+ Build.DEVICE
|
||||
+ Build.MANUFACTURER
|
||||
+ Build.MODEL;
|
||||
LogUtils.i("MacUtils", "BRAND:" + Build.BRAND);
|
||||
LogUtils.i("MacUtils", "DEVICE:" + Build.DEVICE);
|
||||
LogUtils.i("MacUtils", "MANUFACTURER:" + Build.MANUFACTURER);
|
||||
LogUtils.i("MacUtils", "MODEL:" + Build.MODEL);
|
||||
return androidId + deviceInfo;
|
||||
}
|
||||
|
||||
public static String getModel() {
|
||||
LogUtils.i("getModel", Build.BRAND + " " + Build.MODEL);
|
||||
return Build.BRAND + " " + Build.MODEL;
|
||||
}
|
||||
|
||||
private static String generateMacFromHash(String input) {
|
||||
LogUtils.i("MacUtils", "generateMacFromHash:" + input);
|
||||
try {
|
||||
// 生成MD5
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
byte[] hash = md.digest(input.getBytes());
|
||||
|
||||
// 取前6个字节构造MAC
|
||||
StringBuilder mac = new StringBuilder();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (i > 0) mac.append(":");
|
||||
mac.append(String.format("%02X", hash[i] & 0xFF));
|
||||
}
|
||||
|
||||
// 确保第一个字节是偶数(本地管理的MAC地址)
|
||||
char firstChar = mac.charAt(0);
|
||||
if ((Character.digit(firstChar, 16) & 0x1) != 0) {
|
||||
mac.setCharAt(0, (char) (firstChar - 1));
|
||||
}
|
||||
|
||||
return mac.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return "02:00:00:00:00:00"; // 默认值
|
||||
}
|
||||
}
|
||||
}
|
||||
0
libcore/src/main/java/com/pukka/libcore/cipher/AesUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/cipher/AesUtils.java
Executable file → Normal file
6
libcore/src/main/java/com/pukka/libcore/cipher/HMacShaUtils.java
Executable file → Normal file
6
libcore/src/main/java/com/pukka/libcore/cipher/HMacShaUtils.java
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
package com.pukka.libcore.cipher;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class HMacShaUtils {
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA256_ALGORITHM);
|
||||
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
|
||||
mac.init(signingKey);
|
||||
return mac.doFinal(data.getBytes(Charset.forName("UTF-8")));
|
||||
return mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
@@ -51,7 +51,7 @@ public class HMacShaUtils {
|
||||
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
|
||||
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
|
||||
mac.init(signingKey);
|
||||
return mac.doFinal(data.getBytes(Charset.forName("UTF-8")));
|
||||
return mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
4
libcore/src/main/java/com/pukka/libcore/cipher/Md5Utils.java
Executable file → Normal file
4
libcore/src/main/java/com/pukka/libcore/cipher/Md5Utils.java
Executable file → Normal file
@@ -2,7 +2,7 @@ package com.pukka.libcore.cipher;
|
||||
|
||||
import com.pukka.libcore.utils.ByteConversionUtils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,7 @@ public class Md5Utils {
|
||||
public static String encrypt(String message) {
|
||||
String md5str = "";
|
||||
try {
|
||||
md5str = encrypt(message.getBytes(Charset.forName("UTF-8")));
|
||||
md5str = encrypt(message.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
0
libcore/src/main/java/com/pukka/libcore/fresco/BaseSimpleDraweeView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/BaseSimpleDraweeView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/FrescoInit.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/FrescoInit.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/IPkSimpleDraweeView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/IPkSimpleDraweeView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/PkControllerListener.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/PkControllerListener.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/PkSimpleDraweeListener.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/PkSimpleDraweeListener.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/PkSimpleDraweeView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/PkSimpleDraweeView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/Tls12SocketFactory.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/Tls12SocketFactory.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/TrustAllManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/fresco/TrustAllManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/DefaultObserver.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/DefaultObserver.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/ExceptionReason.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/ExceptionReason.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/OkHttpClientUtil.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/OkHttpClientUtil.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/PkApiService.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/PkApiService.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/RetrofitApi.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/RetrofitApi.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/lowplatform/AndroidPlatform9.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/lowplatform/AndroidPlatform9.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/lowplatform/LowPlatformUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/lowplatform/LowPlatformUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/lowplatform/OptionalMethod.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/retrofit/lowplatform/OptionalMethod.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/ConcurrentDispatchQueue.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/ConcurrentDispatchQueue.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/DispatchQueue.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/DispatchQueue.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/DispatchQueueType.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/DispatchQueueType.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/GuardedRunnable.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/GuardedRunnable.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/SerialDispatchQueue.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/SerialDispatchQueue.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/Timer.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/threading/Timer.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppContext.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppContext.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppLifecycleObserver.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppLifecycleObserver.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/AppUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/Base64Decoder.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/Base64Decoder.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/Base64Util.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/Base64Util.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ByteConversionUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ByteConversionUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ContextUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ContextUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/DateUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/DateUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/GreyingManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/GreyingManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/JsonUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/JsonUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ListUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ListUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/LogUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/LogUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/MD5Utils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/MD5Utils.java
Executable file → Normal file
53
libcore/src/main/java/com/pukka/libcore/utils/MacAddressUtil.java
Executable file → Normal file
53
libcore/src/main/java/com/pukka/libcore/utils/MacAddressUtil.java
Executable file → Normal file
@@ -113,17 +113,62 @@ public class MacAddressUtil {
|
||||
if (interfaces == null) {
|
||||
return null;
|
||||
}
|
||||
// 优先取 eth0,再退回 wlan0。原实现是"遍历到第一个有 MAC 就 break",
|
||||
// 但 Linux 设备上 dummy0/ifb0/tunl0/gre* 等虚拟接口都有内核分配的本地随机 MAC,
|
||||
// 会被错误命中。改为过滤虚拟接口并按 eth0 > wlan0 优先级返回。
|
||||
String ethMac = null;
|
||||
String wlanMac = null;
|
||||
while (interfaces.hasMoreElements()) {
|
||||
iF = interfaces.nextElement();
|
||||
String name = iF.getName();
|
||||
String lower = name == null ? "" : name.toLowerCase();
|
||||
try {
|
||||
hardWareAddress = bytesToString(iF.getHardwareAddress());
|
||||
if (hardWareAddress != null)
|
||||
break;
|
||||
// 跳过回环
|
||||
if (iF.isLoopback()) continue;
|
||||
// 跳过 DOWN 状态
|
||||
if (!iF.isUp()) continue;
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
// 跳过明显的虚拟接口(dummy/ifb/隧道/p2p)
|
||||
if (isVirtualNetworkInterface(lower)) continue;
|
||||
try {
|
||||
hardWareAddress = bytesToString(iF.getHardwareAddress());
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
if (hardWareAddress == null) continue;
|
||||
// 跳过 Android 7.0+ 默认占位 MAC
|
||||
if ("02:00:00:00:00:00".equals(hardWareAddress)) continue;
|
||||
if ("eth0".equals(lower)) {
|
||||
ethMac = hardWareAddress;
|
||||
} else if ("wlan0".equals(lower)) {
|
||||
wlanMac = hardWareAddress;
|
||||
}
|
||||
}
|
||||
return hardWareAddress;
|
||||
return ethMac != null ? ethMac : wlanMac;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为虚拟网络接口(不应作为设备主 MAC 返回)。
|
||||
* 覆盖常见 Linux 虚拟接口:dummy/ifb/tunl/gre/gretap/erspan/ip_vti/ip6_vti/sit/ip6tnl/ip6gre/p2p。
|
||||
*/
|
||||
private static boolean isVirtualNetworkInterface(String lowerName) {
|
||||
return lowerName.startsWith("dummy")
|
||||
|| lowerName.startsWith("ifb")
|
||||
|| lowerName.startsWith("tunl")
|
||||
|| lowerName.startsWith("gre") // 包括 gre0 / gretap0 / ip6gre0
|
||||
|| lowerName.startsWith("gretap")
|
||||
|| lowerName.startsWith("erspan")
|
||||
|| lowerName.startsWith("ip_vti")
|
||||
|| lowerName.startsWith("ip6_vti")
|
||||
|| lowerName.startsWith("sit")
|
||||
|| lowerName.startsWith("ip6tnl")
|
||||
|| lowerName.startsWith("ip6gre")
|
||||
|| lowerName.startsWith("p2p")
|
||||
|| lowerName.equals("lo");
|
||||
}
|
||||
|
||||
private static String bytesToString(byte[] bytes) {
|
||||
|
||||
0
libcore/src/main/java/com/pukka/libcore/utils/PackageUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/PackageUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ProcessUtil.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ProcessUtil.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ScreenUtil.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/ScreenUtil.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/SharedPreferenceUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/SharedPreferenceUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/SpSaveModel.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/SpSaveModel.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/SpTimeUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/SpTimeUtils.java
Executable file → Normal file
81
libcore/src/main/java/com/pukka/libcore/utils/StringUtil.java
Executable file → Normal file
81
libcore/src/main/java/com/pukka/libcore/utils/StringUtil.java
Executable file → Normal file
@@ -2,6 +2,9 @@ package com.pukka.libcore.utils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Locale;
|
||||
|
||||
public class StringUtil {
|
||||
@@ -10,8 +13,11 @@ public class StringUtil {
|
||||
public static String getLocalMac() {
|
||||
String mac = "";
|
||||
|
||||
mac= MacAddressUtil.getMacAddressFromFile("/sys/class/net/eth0/address");
|
||||
LogUtils.d("有线(eth0)mac:"+mac);
|
||||
// 第 1 层:sysfs 直读 eth0。走 shell `cat` 而非 FileInputStream,绕过 SELinux 对
|
||||
// Java 进程直读 /sys/class/net/*/address 的拒绝(这是导致 wifi-only / 严格 SELinux
|
||||
// 设备上"7 层全空"的根因)。
|
||||
mac = readSysFsMac("/sys/class/net/eth0/address");
|
||||
LogUtils.d("有线(eth0)mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
//本地存有线mac
|
||||
if (!StringUtils.isEmpty(mac)) {
|
||||
@@ -20,43 +26,88 @@ public class StringUtil {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
mac= MacAddressUtil.getLocalMacAddress();
|
||||
LogUtils.d("有线(LocalMac)mac:"+mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
mac= MacAddressUtil.getMacAddressFromFile("/sys/class/net/wlan0/address");
|
||||
LogUtils.d("无线mac:"+mac);
|
||||
// 第 2 层:NetworkInterface 枚举 eth0 -> wlan0 硬件地址(API 路径)
|
||||
mac = MacAddressUtil.getLocalMacAddress();
|
||||
LogUtils.d("有线(LocalMac)mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac) && !TextUtils.equals("02:00:00:00:00:00", mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
// 第 3 层:sysfs 直读 wlan0。同样走 shell `cat`。
|
||||
mac = readSysFsMac("/sys/class/net/wlan0/address");
|
||||
LogUtils.d("无线mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
// 第 4 层:InetAddress 反查(API 路径)
|
||||
mac = MacAddressUtil.getMacAddress();
|
||||
LogUtils.d("通过InetAddress mac:"+mac);
|
||||
LogUtils.d("通过InetAddress mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
// 第 5 层:ifconfig eth0(shell 路径)
|
||||
mac = MacAddressUtil.getLocalMac("ifconfig eth0");
|
||||
LogUtils.d("通过ifconfig eth0 mac:"+mac);
|
||||
LogUtils.d("通过ifconfig eth0 mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
// 第 6 层:ifconfig wlan0(shell 路径)
|
||||
mac = MacAddressUtil.getLocalMac("ifconfig wlan0");
|
||||
LogUtils.d("通过ifconfig wlan0 mac:"+mac);
|
||||
LogUtils.d("通过ifconfig wlan0 mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
|
||||
// 第 7 层:NetworkInterface 遍历硬件地址(API 路径)
|
||||
mac = MacAddressUtil.getMachineHardwareAddress();
|
||||
LogUtils.d("通过MachineHardwareAddress mac:"+mac);
|
||||
LogUtils.d("通过MachineHardwareAddress mac:" + mac);
|
||||
if (!TextUtils.isEmpty(mac)) {
|
||||
return mac.toLowerCase(Locale.getDefault());
|
||||
}
|
||||
// 如果所有方法都失败,返回空字符串
|
||||
// 如果所有方法都失败,返回空字符串(不再伪造;MacUtils2 已删除)
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 走 shell `cat <path>` 读 sysfs 网络节点。
|
||||
* 走 shell 而非 FileInputStream 的原因:
|
||||
* SELinux 策略下 untrusted_app / system_app 直读 sysfs class net 下各 address 常被 MAC 拒绝,
|
||||
* 而 Runtime.exec("cat ...") 启动的进程 label 是 init_shell,能绕过该限制。
|
||||
* 同时循环 read 直到 EOF,避免单次 read(buffer) 不保证读满的坑。
|
||||
*
|
||||
* @return 读到的内容;读不到返回 ""
|
||||
*/
|
||||
public static String readSysFsMac(String path) {
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec("cat " + path);
|
||||
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
String line;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (sb.length() > 0) sb.append('\n');
|
||||
sb.append(line);
|
||||
}
|
||||
try {
|
||||
process.waitFor();
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
} catch (IOException e) {
|
||||
LogUtils.d("readSysFsMac 读取 " + path + " 失败: " + e.getMessage());
|
||||
return "";
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
0
libcore/src/main/java/com/pukka/libcore/utils/StringUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/utils/StringUtils.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/viewmodel/BaseVM.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/viewmodel/BaseVM.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/AlwaysMarqueeTextView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/AlwaysMarqueeTextView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/BrowserWebView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/BrowserWebView.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/ContentRecyclerViewTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/ContentRecyclerViewTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/HorizontalLinearLayoutManagerTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/HorizontalLinearLayoutManagerTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/HorizontalRecyclerViewTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/HorizontalRecyclerViewTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/TVLinearLayoutManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/TVLinearLayoutManager.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/VerticalGridLayoutManagerTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/VerticalGridLayoutManagerTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/VerticalLinearLayoutManagerTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/VerticalLinearLayoutManagerTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/VerticalRecyclerViewTv.java
Executable file → Normal file
0
libcore/src/main/java/com/pukka/libcore/widget/VerticalRecyclerViewTv.java
Executable file → Normal file
0
libcore/src/test/java/com/pukka/libcore/ExampleUnitTest.java
Executable file → Normal file
0
libcore/src/test/java/com/pukka/libcore/ExampleUnitTest.java
Executable file → Normal file
Reference in New Issue
Block a user