2022-10-20 14:22:04 +08:00
|
|
|
|
package chaoran.business.utils;
|
|
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint;
|
2022-11-01 11:28:44 +08:00
|
|
|
|
import android.app.Activity;
|
2022-10-31 11:51:27 +08:00
|
|
|
|
import android.content.Context;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import android.content.Intent;
|
2024-12-09 15:14:20 +08:00
|
|
|
|
import android.content.SharedPreferences;
|
2022-11-01 11:28:44 +08:00
|
|
|
|
import android.content.pm.ActivityInfo;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
|
|
import android.net.Uri;
|
2024-12-11 14:15:57 +08:00
|
|
|
|
import android.net.wifi.WifiInfo;
|
|
|
|
|
|
import android.net.wifi.WifiManager;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
import android.os.Build;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import android.os.Environment;
|
2024-12-11 14:15:57 +08:00
|
|
|
|
import android.provider.Settings;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import android.provider.MediaStore;
|
|
|
|
|
|
import android.util.Base64;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
import android.util.Log;
|
2022-11-02 09:32:52 +08:00
|
|
|
|
import android.view.Surface;
|
2022-11-01 11:28:44 +08:00
|
|
|
|
import android.view.View;
|
2022-11-02 09:32:52 +08:00
|
|
|
|
import android.view.WindowManager;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
import android.webkit.JavascriptInterface;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import android.webkit.WebView;
|
|
|
|
|
|
|
|
|
|
|
|
import androidx.core.app.ActivityCompat;
|
|
|
|
|
|
import androidx.core.content.ContextCompat;
|
|
|
|
|
|
import androidx.core.content.FileProvider;
|
|
|
|
|
|
|
|
|
|
|
|
import org.json.JSONObject;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
|
import java.text.SimpleDateFormat;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
import java.net.Inet4Address;
|
|
|
|
|
|
import java.net.InetAddress;
|
|
|
|
|
|
import java.net.NetworkInterface;
|
|
|
|
|
|
import java.net.SocketException;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import java.util.Date;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
import java.util.Enumeration;
|
2026-03-10 14:39:39 +08:00
|
|
|
|
import java.util.Locale;
|
2025-04-18 09:57:07 +08:00
|
|
|
|
import java.util.Random;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
|
2023-04-20 10:40:28 +08:00
|
|
|
|
import chaoran.business.BuildConfig;
|
2022-11-01 11:28:44 +08:00
|
|
|
|
|
2022-10-20 14:22:04 +08:00
|
|
|
|
public class LocalAddressUtil {
|
2022-10-31 11:51:27 +08:00
|
|
|
|
|
2024-12-09 15:14:20 +08:00
|
|
|
|
public final static String SSO_KEY = "!~CROP@CRTECH@PDA~!";
|
|
|
|
|
|
|
2022-10-31 11:51:27 +08:00
|
|
|
|
private Context context;
|
|
|
|
|
|
|
2022-11-01 11:28:44 +08:00
|
|
|
|
private Activity activity;
|
|
|
|
|
|
|
|
|
|
|
|
private View view;
|
|
|
|
|
|
|
2022-10-31 11:51:27 +08:00
|
|
|
|
private int[] heights;
|
|
|
|
|
|
|
2026-03-10 14:39:39 +08:00
|
|
|
|
private static final String TAG = "LocalAddressUtil";
|
|
|
|
|
|
private static final int REQUEST_CODE_NATIVE_CAMERA = 31002;
|
|
|
|
|
|
private static final int REQUEST_CODE_PERMISSION_CAMERA = 31001;
|
|
|
|
|
|
private static final String DEFAULT_CAMERA_CALLBACK = "onNativeCameraResult";
|
|
|
|
|
|
|
|
|
|
|
|
// Base64 settings for camera callback
|
|
|
|
|
|
private static final int CAMERA_IMAGE_MAX_DIMENSION = 1280;
|
|
|
|
|
|
private static final int CAMERA_IMAGE_JPEG_QUALITY = 80;
|
|
|
|
|
|
private static final String CAMERA_DATA_URL_PREFIX = "data:image/jpeg;base64,";
|
|
|
|
|
|
|
|
|
|
|
|
private Uri nativeCameraPhotoUri;
|
|
|
|
|
|
private String pendingCameraCallback = null;
|
|
|
|
|
|
|
2022-11-01 11:28:44 +08:00
|
|
|
|
public LocalAddressUtil(Context context, Activity activity, View view) {
|
2022-10-31 11:51:27 +08:00
|
|
|
|
this.context = context;
|
2022-11-01 11:28:44 +08:00
|
|
|
|
this.activity = activity;
|
|
|
|
|
|
this.view = view;
|
2022-10-31 11:51:27 +08:00
|
|
|
|
this.heights = StatusBarUtil.getStatusBarHeight(context);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-10 14:39:39 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 直接调用原生相机(默认回调:window.onNativeCameraResult(base64OrDataUrl, error))
|
|
|
|
|
|
*/
|
|
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public void openNativeCamera() {
|
|
|
|
|
|
openNativeCamera(DEFAULT_CAMERA_CALLBACK);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 直接调用原生相机(自定义回调函数名:window[callback](base64OrDataUrl, error))
|
|
|
|
|
|
* @param callback JS 回调函数名(不需要传 window. 前缀)
|
|
|
|
|
|
*/
|
|
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public void openNativeCamera(String callback) {
|
|
|
|
|
|
this.pendingCameraCallback = (callback == null || callback.trim().isEmpty())
|
|
|
|
|
|
? DEFAULT_CAMERA_CALLBACK
|
|
|
|
|
|
: callback.trim();
|
|
|
|
|
|
|
|
|
|
|
|
if (!checkCameraPermission()) {
|
|
|
|
|
|
ActivityCompat.requestPermissions(activity,
|
|
|
|
|
|
new String[]{android.Manifest.permission.CAMERA},
|
|
|
|
|
|
REQUEST_CODE_PERMISSION_CAMERA);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Intent cameraIntent = createNativeCameraIntent();
|
|
|
|
|
|
if (cameraIntent == null) {
|
|
|
|
|
|
dispatchCameraResultToJs(null, "create_intent_failed");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
activity.startActivityForResult(cameraIntent, REQUEST_CODE_NATIVE_CAMERA);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
Log.e(TAG, "启动相机失败", e);
|
|
|
|
|
|
dispatchCameraResultToJs(null, "start_failed");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 由宿主 Activity 转发调用
|
|
|
|
|
|
*/
|
|
|
|
|
|
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
|
|
|
|
if (requestCode != REQUEST_CODE_NATIVE_CAMERA) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
|
|
|
|
String dataUrl = buildCameraPhotoDataUrl(nativeCameraPhotoUri);
|
|
|
|
|
|
if (dataUrl == null || dataUrl.trim().isEmpty()) {
|
|
|
|
|
|
dispatchCameraResultToJs(null, "encode_failed");
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dispatchCameraResultToJs(dataUrl, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dispatchCameraResultToJs(null, "cancelled");
|
|
|
|
|
|
}
|
|
|
|
|
|
nativeCameraPhotoUri = null;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 由宿主 Activity 转发调用
|
|
|
|
|
|
*/
|
|
|
|
|
|
public boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
|
|
|
|
if (requestCode != REQUEST_CODE_PERMISSION_CAMERA) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
boolean granted = grantResults != null && grantResults.length > 0
|
|
|
|
|
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
|
|
|
|
|
if (granted) {
|
|
|
|
|
|
openNativeCamera(pendingCameraCallback);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
dispatchCameraResultToJs(null, "permission_denied");
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private boolean checkCameraPermission() {
|
|
|
|
|
|
return ContextCompat.checkSelfPermission(activity, android.Manifest.permission.CAMERA)
|
|
|
|
|
|
== PackageManager.PERMISSION_GRANTED;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private Intent createNativeCameraIntent() {
|
|
|
|
|
|
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
|
|
|
|
|
if (cameraIntent.resolveActivity(activity.getPackageManager()) == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
File photoFile = createImageFile();
|
|
|
|
|
|
if (photoFile == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
nativeCameraPhotoUri = FileProvider.getUriForFile(
|
|
|
|
|
|
activity,
|
|
|
|
|
|
activity.getPackageName() + ".fileprovider",
|
|
|
|
|
|
photoFile
|
|
|
|
|
|
);
|
|
|
|
|
|
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, nativeCameraPhotoUri);
|
|
|
|
|
|
cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
|
|
|
|
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
|
|
|
|
return cameraIntent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private File createImageFile() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
|
|
|
|
|
|
String imageFileName = "JPEG_" + timeStamp + "_";
|
|
|
|
|
|
File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
|
|
|
|
|
if (storageDir != null && !storageDir.exists()) {
|
|
|
|
|
|
//noinspection ResultOfMethodCallIgnored
|
|
|
|
|
|
storageDir.mkdirs();
|
|
|
|
|
|
}
|
|
|
|
|
|
return File.createTempFile(imageFileName, ".jpg", storageDir);
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
|
Log.e(TAG, "创建图片文件失败", e);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将拍照结果转为 dataUrl(base64)
|
|
|
|
|
|
*/
|
|
|
|
|
|
private String buildCameraPhotoDataUrl(Uri uri) {
|
|
|
|
|
|
if (uri == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
InputStream inputStream = null;
|
|
|
|
|
|
try {
|
|
|
|
|
|
inputStream = context.getContentResolver().openInputStream(uri);
|
|
|
|
|
|
if (inputStream == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BitmapFactory.Options options = new BitmapFactory.Options();
|
|
|
|
|
|
options.inJustDecodeBounds = true;
|
|
|
|
|
|
BitmapFactory.decodeStream(inputStream, null, options);
|
|
|
|
|
|
int srcW = options.outWidth;
|
|
|
|
|
|
int srcH = options.outHeight;
|
|
|
|
|
|
|
|
|
|
|
|
safeClose(inputStream);
|
|
|
|
|
|
inputStream = context.getContentResolver().openInputStream(uri);
|
|
|
|
|
|
if (inputStream == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
options.inSampleSize = calculateInSampleSize(srcW, srcH, CAMERA_IMAGE_MAX_DIMENSION);
|
|
|
|
|
|
options.inJustDecodeBounds = false;
|
|
|
|
|
|
|
|
|
|
|
|
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
|
|
|
|
|
|
if (bitmap == null) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
|
|
|
bitmap.compress(Bitmap.CompressFormat.JPEG, CAMERA_IMAGE_JPEG_QUALITY, baos);
|
|
|
|
|
|
byte[] bytes = baos.toByteArray();
|
|
|
|
|
|
|
|
|
|
|
|
String base64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
|
|
|
|
|
|
return CAMERA_DATA_URL_PREFIX + base64;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
Log.e(TAG, "图片转base64失败", e);
|
|
|
|
|
|
return null;
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
safeClose(inputStream);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int calculateInSampleSize(int srcW, int srcH, int maxDim) {
|
|
|
|
|
|
if (srcW <= 0 || srcH <= 0) {
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
int maxSrc = Math.max(srcW, srcH);
|
|
|
|
|
|
if (maxSrc <= maxDim) {
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
int inSampleSize = 1;
|
|
|
|
|
|
while (maxSrc / inSampleSize > maxDim) {
|
|
|
|
|
|
inSampleSize *= 2;
|
|
|
|
|
|
}
|
|
|
|
|
|
return Math.max(1, inSampleSize);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void safeClose(InputStream is) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (is != null) {
|
|
|
|
|
|
is.close();
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception ignored) {
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void dispatchCameraResultToJs(String dataUrl, String error) {
|
|
|
|
|
|
if (!(view instanceof WebView)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
WebView webView = (WebView) view;
|
|
|
|
|
|
String cb = (pendingCameraCallback == null || pendingCameraCallback.trim().isEmpty())
|
|
|
|
|
|
? DEFAULT_CAMERA_CALLBACK
|
|
|
|
|
|
: pendingCameraCallback.trim();
|
|
|
|
|
|
|
|
|
|
|
|
String js = "try{" +
|
|
|
|
|
|
"var cb=window[" + JSONObject.quote(cb) + "];" +
|
|
|
|
|
|
"if(typeof cb==='function'){cb(" + JSONObject.quote(dataUrl) + "," + JSONObject.quote(error) + ");}" +
|
|
|
|
|
|
"}catch(e){}";
|
|
|
|
|
|
|
|
|
|
|
|
webView.post(() -> {
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
|
|
|
|
webView.evaluateJavascript(js, null);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
webView.loadUrl("javascript:" + js);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-20 14:22:04 +08:00
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String getIpAddress() {
|
|
|
|
|
|
try {
|
|
|
|
|
|
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
|
|
|
|
|
|
NetworkInterface intf = en.nextElement();
|
|
|
|
|
|
// if(!intf.getDisplayName().equals("eth0")) continue;
|
|
|
|
|
|
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
|
|
|
|
|
|
InetAddress inetAddress = enumIpAddr.nextElement();
|
|
|
|
|
|
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
|
|
|
|
|
|
return inetAddress.getHostAddress();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (SocketException ex) {
|
|
|
|
|
|
Log.e("address: local", ex.toString());
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String getMacAddress(){//可以兼容安卓7以下
|
2025-04-18 09:57:07 +08:00
|
|
|
|
SharedPreferences spf = context.getSharedPreferences("chaoran_mac", Context.MODE_PRIVATE);
|
|
|
|
|
|
String saveMac = spf.getString("chaoran_mac", "");
|
|
|
|
|
|
if (!"".equalsIgnoreCase(saveMac)) {
|
|
|
|
|
|
return saveMac;
|
|
|
|
|
|
}
|
|
|
|
|
|
SharedPreferences.Editor editor = spf.edit();
|
|
|
|
|
|
String androidMac = getAndroidMac();
|
|
|
|
|
|
editor.putString("chaoran_mac", androidMac);
|
|
|
|
|
|
editor.apply();
|
|
|
|
|
|
return androidMac;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取安卓的mac
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
private String getAndroidMac() {
|
2024-12-11 14:15:57 +08:00
|
|
|
|
if (Build.VERSION.SDK_INT >= 34) { // Android 14 is code-named Tiramisu
|
|
|
|
|
|
try {
|
|
|
|
|
|
return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
|
|
|
|
|
}catch (Exception e) {
|
|
|
|
|
|
e.printStackTrace();
|
2025-04-18 09:57:07 +08:00
|
|
|
|
return generateRandomMacAddress();
|
2024-12-11 14:15:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-10-20 14:22:04 +08:00
|
|
|
|
String macAddress = null;
|
|
|
|
|
|
StringBuffer buf = new StringBuffer();
|
|
|
|
|
|
NetworkInterface networkInterface = null;
|
|
|
|
|
|
try {
|
|
|
|
|
|
networkInterface = NetworkInterface.getByName("eth1");
|
|
|
|
|
|
if (networkInterface == null) {
|
|
|
|
|
|
networkInterface = NetworkInterface.getByName("wlan0");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (networkInterface == null) {
|
2025-04-18 09:57:07 +08:00
|
|
|
|
return generateRandomMacAddress();
|
2022-10-20 14:22:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
byte[] addr = networkInterface.getHardwareAddress();
|
|
|
|
|
|
for (byte b : addr) {
|
|
|
|
|
|
buf.append(String.format("%02X:", b));
|
|
|
|
|
|
}
|
|
|
|
|
|
if (buf.length() > 0) {
|
|
|
|
|
|
buf.deleteCharAt(buf.length() - 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
macAddress = buf.toString();
|
2025-04-18 09:57:07 +08:00
|
|
|
|
} catch (Exception e) {
|
2022-10-20 14:22:04 +08:00
|
|
|
|
e.printStackTrace();
|
2025-04-18 09:57:07 +08:00
|
|
|
|
macAddress = generateRandomMacAddress();
|
|
|
|
|
|
}
|
|
|
|
|
|
if (macAddress.length() < 4) {
|
|
|
|
|
|
macAddress = generateRandomMacAddress();
|
2022-10-20 14:22:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
return macAddress;
|
|
|
|
|
|
}
|
2025-04-18 09:57:07 +08:00
|
|
|
|
|
|
|
|
|
|
private static String generateRandomMacAddress() {
|
|
|
|
|
|
Random rand = new Random();
|
|
|
|
|
|
byte[] macBytes = new byte[6];
|
|
|
|
|
|
rand.nextBytes(macBytes);
|
|
|
|
|
|
macBytes[0] = (byte) (macBytes[0] & 0xfe | 0x02);
|
|
|
|
|
|
StringBuilder macAddress = new StringBuilder();
|
|
|
|
|
|
for (int i = 0; i < macBytes.length; i++) {
|
|
|
|
|
|
macAddress.append(String.format("%02X%s", macBytes[i], (i < macBytes.length - 1) ? ":" : ""));
|
|
|
|
|
|
}
|
|
|
|
|
|
return macAddress.toString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-20 14:22:04 +08:00
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String getInfo(int type){
|
|
|
|
|
|
String info;
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case 1: info = Build.BRAND;break;//品牌
|
|
|
|
|
|
case 2: info = Build.MODEL;break;//型号
|
|
|
|
|
|
case 3: info = Build.MANUFACTURER;break;//厂商
|
|
|
|
|
|
case 4: info = Build.DEVICE;break;//设备名
|
|
|
|
|
|
case 5: info = Build.ID;break;//设备硬件id
|
|
|
|
|
|
// case 6: info = Build.SERIAL;break;//序列号,可能获取不到
|
|
|
|
|
|
default: info = "";break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return info;
|
2022-10-31 11:51:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-01 11:28:44 +08:00
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
2022-10-31 11:51:27 +08:00
|
|
|
|
public String getHeight(int type) {
|
|
|
|
|
|
String info = "";
|
|
|
|
|
|
switch (type) {
|
|
|
|
|
|
case 1 : info = String.valueOf(this.heights[0]); break;
|
|
|
|
|
|
case 2 : info = String.valueOf(this.heights[1]); break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return info;
|
2022-10-20 14:22:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void test(){
|
|
|
|
|
|
Log.e("test", "MANUFACTURER=" + Build.MANUFACTURER);
|
|
|
|
|
|
Log.e("test", "BRAND=" + Build.BRAND);
|
|
|
|
|
|
Log.e("test", "MODEL=" + Build.MODEL);
|
|
|
|
|
|
Log.e("test", "VERSION.RELEASE=" + Build.VERSION.RELEASE);
|
|
|
|
|
|
Log.e("test", "VERSION.SDK_INT=" + Build.VERSION.SDK_INT);
|
|
|
|
|
|
Log.e("test", "DEVICE=" + Build.DEVICE);
|
|
|
|
|
|
Log.e("test", "HOST=" + Build.HOST);
|
|
|
|
|
|
Log.e("test", "ID=" + Build.ID);
|
|
|
|
|
|
Log.e("test", "TIME=" + Build.TIME);
|
|
|
|
|
|
Log.e("test", "TYPE=" + Build.TYPE);
|
|
|
|
|
|
Log.e("test", "PRODUCT=" + Build.PRODUCT);
|
|
|
|
|
|
Log.e("test", "BOARD=" + Build.BOARD);
|
|
|
|
|
|
Log.e("test", "DISPLAY=" + Build.DISPLAY);
|
|
|
|
|
|
Log.e("test", "FINGERPRINT=" + Build.FINGERPRINT);
|
|
|
|
|
|
Log.e("test", "HARDWARE=" + Build.HARDWARE);
|
|
|
|
|
|
Log.e("test", "BOOTLOADER=" + Build.BOOTLOADER);
|
|
|
|
|
|
Log.e("test", "TAGS=" + Build.TAGS);
|
|
|
|
|
|
Log.e("test", "UNKNOWN=" + Build.UNKNOWN);
|
|
|
|
|
|
Log.e("test", "USER=" + Build.USER);
|
|
|
|
|
|
}
|
2022-11-01 11:28:44 +08:00
|
|
|
|
|
|
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
2022-11-02 09:32:52 +08:00
|
|
|
|
public void rotateScreen() {
|
|
|
|
|
|
int angle = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
|
|
|
|
|
|
|
|
|
|
|
|
switch (angle) {
|
|
|
|
|
|
case Surface.ROTATION_0:
|
|
|
|
|
|
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Surface.ROTATION_90:
|
|
|
|
|
|
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Surface.ROTATION_180:
|
|
|
|
|
|
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Surface.ROTATION_270:
|
|
|
|
|
|
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
2022-11-01 14:55:18 +08:00
|
|
|
|
}
|
2022-11-01 11:28:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-09 15:14:20 +08:00
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String registerMac(String applyMac) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
String mac = this.getMacAddress();
|
|
|
|
|
|
String md5Hash = MD5.md5(mac + SSO_KEY);
|
2025-05-21 15:18:37 +08:00
|
|
|
|
if ("Crtech!register@PDA#APK".equals(applyMac) || (md5Hash != null && md5Hash.equals(applyMac))) {
|
2024-12-09 15:14:20 +08:00
|
|
|
|
// 将允许注册适配的mac写入文件中
|
|
|
|
|
|
SharedPreferences.Editor editor = context.getSharedPreferences("CrtechPdaConfig", Context.MODE_PRIVATE).edit();
|
|
|
|
|
|
editor.putString("checkMac", "success");
|
2025-05-21 15:18:37 +08:00
|
|
|
|
if ("Crtech!register@PDA#APK".equals(applyMac)) {
|
|
|
|
|
|
editor.putString("checkMacTime", String.valueOf(System.currentTimeMillis()));
|
|
|
|
|
|
editor.putString("checkMacType", "1");
|
|
|
|
|
|
}else {
|
|
|
|
|
|
editor.putString("checkMacType", "0");
|
|
|
|
|
|
}
|
2024-12-09 15:14:20 +08:00
|
|
|
|
editor.commit();
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
}
|
|
|
|
|
|
}catch (Exception ignored) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
return "error";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String checkMacRegister() {
|
|
|
|
|
|
SharedPreferences sharedPreferences = context.getSharedPreferences("CrtechPdaConfig", Context.MODE_PRIVATE);
|
2025-05-21 15:18:37 +08:00
|
|
|
|
String checkMac = sharedPreferences.getString("checkMac", "error");
|
|
|
|
|
|
if (!"success".equals(checkMac)) {
|
|
|
|
|
|
return "error";
|
|
|
|
|
|
}
|
|
|
|
|
|
if ("1".equals(sharedPreferences.getString("checkMacType", "0"))) {
|
2025-06-25 11:04:14 +08:00
|
|
|
|
// 判断是否是强行注册的,强行注册的只允许使用一个小时;一但判断到,就取消注册
|
2025-05-21 15:18:37 +08:00
|
|
|
|
Long aLong = Long.valueOf(sharedPreferences.getString("checkMacTime", String.valueOf(System.currentTimeMillis())));
|
2025-06-25 11:04:14 +08:00
|
|
|
|
if ((aLong + 1 * 60 * 60 * 1000) < System.currentTimeMillis()) {
|
2025-05-21 15:18:37 +08:00
|
|
|
|
SharedPreferences.Editor edit = sharedPreferences.edit();
|
|
|
|
|
|
edit.putString("checkMac", "error");
|
|
|
|
|
|
edit.commit();
|
|
|
|
|
|
return "error";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return "success";
|
2024-12-09 15:14:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-04-20 10:40:28 +08:00
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String getApkVersion() {
|
|
|
|
|
|
return BuildConfig.VERSION_NAME;
|
|
|
|
|
|
}
|
2024-07-24 10:04:56 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 暴露PDA的厂家和型号
|
|
|
|
|
|
* @return String 格式:厂家:型号
|
|
|
|
|
|
*/
|
|
|
|
|
|
@SuppressLint("JavascriptInterface")
|
|
|
|
|
|
@JavascriptInterface
|
|
|
|
|
|
public String getPdaInfo() {
|
|
|
|
|
|
return Build.MANUFACTURER + ":" + Build.MODEL.toLowerCase();
|
|
|
|
|
|
}
|
2022-10-20 14:22:04 +08:00
|
|
|
|
}
|