package com.xypower.mpremote; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.net.ConnectivityManager; import android.os.Bundle; import android.os.Handler; import android.text.Html; import android.text.TextUtils; import android.text.format.Formatter; import android.util.Base64; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import com.xypower.common.FilesUtils; import com.xypower.common.JSONUtils; import com.xypower.common.MicroPhotoContext; import com.xypower.mpremote.databinding.ActivityDeviceBinding; import com.xypower.mpremote.utils.AdbUtils; import org.json.JSONObject; import org.w3c.dom.Text; import java.io.File; import java.net.Socket; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import dadb.AdbKeyPair; import dadb.AdbShellResponse; import dadb.Dadb; public class DeviceActivity extends AppCompatActivity { private static final String TAG = "ADB"; private static final boolean DEBUG = false; public static final int RSSI_LEVELS = 5; private static final String PACKAGE_NAME_MP = "com.xypower.mpapp"; private static final String REMOTE_PATH_ROOT = "/sdcard/" + PACKAGE_NAME_MP + "/"; private static final String REMOTE_PATH_DATA = REMOTE_PATH_ROOT + "data/"; private static final String REMOTE_PATH_DATA_CHANNELS = REMOTE_PATH_ROOT + "data/channels/"; private static final String REMOTE_PATH_PHOTOS = REMOTE_PATH_ROOT + "photos/"; private static final String REMOTE_PATH_TMP = REMOTE_PATH_ROOT + "tmp/"; private static final String KEY_APP_BV = "app.bv"; private static final String KEY_APP_BCV = "app.bcv"; private static final String KEY_RO_SERIALNO = "ro.serialno"; private static final String KEY_RO_CUSTOM_OTA_VERSION = "ro.custom.ota.version"; private static final String KEY_RO_MODEMS_MAX_COUNT = "telephony.active_modems.max_count"; // ro.telephony.sim.count private static final String KEY_RO_SIGNAL_STRNGTH_PREFIX = "vendor.ril.nw.signalstrength.lte."; private static final String KEY_RO_ICCID_PREFIX = "persist.vendor.radio.cfu.iccid."; private static final String KEY_GSM_VENDOR_NAME = "gsm.operator.alpha"; // private static final String KEY_RO_MODEMS_MAX_COUNT = "telephony.active_modems.max_count"; // // [ro.bootimage.build.date.utc]: [1716880263] // // [ro.build.date.utc]: [1716880263] // // [ro.product.model]: [MSRDT-1-WP] // // [ro.serialno]: [XYV12WPC202406215] // // [telephony.active_modems.max_count]: [2] // // [vendor.ril.nw.signalstrength.lte.1]: [-93,-2] // //[vendor.ril.nw.signalstrength.lte.2]: [-103,21] private static final String KEY_APP_MP_VERSION = "mpapp.version"; private static final String KEY_PREFIX_GLOBAL_SETTING = "settings.global."; private static final String KEY_IMEI = KEY_PREFIX_GLOBAL_SETTING + "dev_imei"; private static final String KEY_IMEI2 = KEY_PREFIX_GLOBAL_SETTING + "dev_imei2"; private static final int ADB_SERVER_PORT = 5555; // [vendor.ril.nw.signalstrength.lte.1]: [-85,27] //[vendor.ril.nw.signalstrength.lte.2]: [-86,27] private ActivityDeviceBinding binding; private ProgressDialog mProgressDialog; private Handler mHandler; private String mDeviceIp; private AdbKeyPair mAdbKeyPair; private Map mProps = new HashMap<>(); private Map mChannelCfgs = new HashMap(); private String mSerialNo = ""; private MicroPhotoContext.AppConfig mAppConfig = new MicroPhotoContext.AppConfig(); private int mBatteryVoltage = -1; private int mBatteryChargingVoltage = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityDeviceBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); // actionBar.setTitle(R.string.title_activity_device); Intent intent = getIntent(); mDeviceIp = intent.getStringExtra("deviceIp"); mHandler = new Handler(); File file = new File(getFilesDir(), ".keypair"); if (!file.exists()) { file.mkdirs(); } final File pubKeyFile = new File(file, "pub.key"); final File priKeyFile = new File(file, "pri.key"); if (!priKeyFile.exists() || !pubKeyFile.exists()) { AdbKeyPair.generate(priKeyFile, pubKeyFile); } mAdbKeyPair = AdbKeyPair.read(priKeyFile, pubKeyFile); final Context context = getApplicationContext(); binding.takePhoto1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePhoto(1, 255, true); } }); binding.takeVideo1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takeVideo(1, 255, false); } }); binding.takePhoto2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePhoto(2, 255, true); } }); binding.takeVideo2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takeVideo(2, 255, false); } }); binding.takePhoto3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePhoto(3, 255, true); } }); binding.takeVideo3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takeVideo(3, 255, false); } }); binding.takePhoto4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePhoto(4, 255, true); } }); binding.takeVideo4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takeVideo(4, 255, false); } }); loadDeviceInfo(context, true); } protected void loadDeviceInfo(final Context context, boolean firstConnect) { binding.deviceInfo.setText(""); String msg = firstConnect ? "连接" + mDeviceIp + "中" : "刷新数据中"; mProgressDialog = ProgressDialog.show(this, "", msg, true, true); mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { DeviceActivity.this.finish(); } }); final File fileTmp = new File(getFilesDir(), "tmp"); if (!fileTmp.exists()) { fileTmp.mkdirs(); } (new Thread(new Runnable() { @Override public void run() { try { runImpl(); } catch (Exception ex) { ex.printStackTrace(); } mHandler.post(new Runnable() { @Override public void run() { mProgressDialog.dismiss(); showAppInfo(); } }); } private void runImpl() { Log.d(TAG, "Adb discovering " + mDeviceIp); Dadb adb = Dadb.create(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT, mAdbKeyPair); Log.d(TAG, "Adb Connected"); if (adb == null) { mHandler.postDelayed(new Runnable() { @Override public void run() { Toast.makeText(DeviceActivity.this, R.string.err_dev_failed_to_connect, Toast.LENGTH_LONG).show(); } }, 100); return; } Log.d(TAG, mDeviceIp + " Connected"); boolean res = false; File appConfigFile = new File(fileTmp, "App.json"); res = pullFile(adb, REMOTE_PATH_DATA + "App.json", appConfigFile); if (res) { final MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getMpAppConfig(context, appConfigFile.getAbsolutePath()); if (appConfig != null) { mAppConfig = appConfig; } DeviceActivity.this.mHandler.post(new Runnable() { @Override public void run() { DeviceActivity.this.showAppInfo(); } }); } Log.d(TAG, "App.json Pulled"); final int numberOfChannels = (mAppConfig != null) ? mAppConfig.channels : 0; mHandler.post(new Runnable() { @Override public void run() { updateButtons(numberOfChannels); } }); mChannelCfgs.clear(); if (mAppConfig != null && mAppConfig.channels > 0) { for (int channel = 1; channel <= mAppConfig.channels; channel++) { String remoteFilePath = REMOTE_PATH_DATA_CHANNELS + Integer.toString(channel) + ".json"; File localFilePath = new File(fileTmp, Integer.toString(channel) + ".json"); if (localFilePath.exists()) { localFilePath.delete(); } res = pullFile(adb, remoteFilePath, localFilePath); if (res) { JSONObject channelJson = JSONUtils.loadJson(localFilePath.getAbsolutePath()); if (channelJson != null) { mChannelCfgs.put(new Integer(channel), channelJson); } localFilePath.delete(); } } } Log.d(TAG, "Channel config Pulled"); AdbShellResponse adbShellResponse = null; try { adbShellResponse = adb.shell("settings list global"); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse.getExitCode() == 0) { String[] lines = FilesUtils.splitLines(adbShellResponse.getAllOutput()); for (String line : lines) { int pos = line.indexOf("="); if (pos != -1) { String key = line.substring(0, pos); String val = line.substring(pos + 1); mProps.put(KEY_PREFIX_GLOBAL_SETTING + key, val); } } } Log.d(TAG, "Global settings Pulled"); adbShellResponse = null; try { adbShellResponse = adb.shell("getprop"); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse.getExitCode() == 0) { String[] lines = FilesUtils.splitLines(adbShellResponse.getAllOutput()); for (String line : lines) { int pos = line.indexOf("]: ["); if (pos != -1) { String key = line.substring(1, pos); String val = line.substring(pos + 4, line.length() - 1); mProps.put(key, val); } } } Log.d(TAG, "getprop Finished"); if (mProps.containsKey(KEY_RO_SERIALNO)) { mSerialNo = (String)mProps.get(KEY_RO_SERIALNO); } // adb shell pm dump com.xypower.mpremote | grep "versionName" adbShellResponse = null; try { adbShellResponse = adb.shell("pm dump " + PACKAGE_NAME_MP + " | grep \"versionName\""); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse.getExitCode() == 0) { String[] lines = FilesUtils.splitLines(adbShellResponse.getAllOutput()); for (String line : lines) { int pos = line.indexOf("versionName="); if (pos != -1) { String val = line.substring(pos + 12); mProps.put(KEY_APP_MP_VERSION, val); break; } } } Log.d(TAG, "Dump App version Finished"); String cmd = "content query --uri content://com.xypower.mpapp.provider/queryBatVol"; adbShellResponse = null; try { adbShellResponse = adb.shell(cmd); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse.getExitCode() == 0) { Cursor cursor = AdbUtils.parseContentResponse(adbShellResponse.getAllOutput()); if (cursor != null && cursor.getCount() > 0) { cursor.moveToFirst(); @SuppressLint("Range") String bv = cursor.getString(cursor.getColumnIndex("bv")); @SuppressLint("Range") String bcv = cursor.getString(cursor.getColumnIndex("bcv")); if (!TextUtils.isEmpty(bv)) { mBatteryVoltage = Integer.parseInt(bv); } if (!TextUtils.isEmpty(bcv)) { mBatteryChargingVoltage = Integer.parseInt(bcv); } } } Log.d(TAG, "queryBatVol Finished"); } })).start(); } protected boolean pullFile(Dadb adb, String remoteFilePath, File localFilePath) { if (localFilePath.exists()) { localFilePath.delete(); } Log.i(TAG, "PULL: " + remoteFilePath); boolean res = false; try { adb.pull(localFilePath, remoteFilePath); res = true; } catch (Exception ex) { ex.printStackTrace(); } return res && localFilePath.exists(); } protected void takePhotoImpl(final String cmd, final int channel, final int preset, final String localFileName, final String remoteFilePath, final boolean photoOrVideo, long sleepTime) { Thread th = new Thread(new Runnable() { @Override public void run() { Dadb adb = null; try { Log.i(TAG, "Start connecting " + mDeviceIp); adb = Dadb.create(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT, mAdbKeyPair); Log.i(TAG, "Finish connecting " + mDeviceIp); if (adb == null) { mHandler.postDelayed(new Runnable() { @Override public void run() { Toast.makeText(DeviceActivity.this, R.string.err_dev_failed_to_connect, Toast.LENGTH_LONG).show(); } }, 100); return; } AdbShellResponse adbShellResponse = null; try { adbShellResponse = adb.shell(cmd); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse != null) { if (adbShellResponse.getExitCode() == 0) { if (sleepTime > 0) { try { Thread.sleep(sleepTime); } catch (Exception ex) { } } File localDevicePath = new File(getFilesDir(), "Photos" + File.separator + mSerialNo); if (!localDevicePath.exists()) { localDevicePath.mkdirs(); } final File localFilePath = new File(localDevicePath, localFileName); for (int idx = 0; idx < 10; idx++) { boolean res = pullFile(adb, remoteFilePath, localFilePath); if (res) { mHandler.post(new Runnable() { @Override public void run() { if (photoOrVideo) { showPhoto(localFilePath.getAbsolutePath()); } else { showVideo(localFilePath.getAbsolutePath()); } } }); break; } try { Thread.sleep(1000); } catch (Exception ex) { ex.printStackTrace(); } } try { // mAdb.shell("rm " + remoteFilePath); } catch (Exception ex) { ex.printStackTrace(); } } } } finally { try { if (adb != null) { adb.close(); } } catch (Exception ex) { ex.printStackTrace(); } } } }); th.start(); } protected long takePhoto(int channel, int preset, final boolean photoOrVideo) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); Date dt = new Date(); int cameraId = channel - 1; final String fileName = "IMG-" + Integer.toString(channel) + "-" + simpleDateFormat.format(dt) + (photoOrVideo ? ".jpg" : ".mp4"); final String remoteFilePath = REMOTE_PATH_TMP + fileName; String leftTopOsd = ""; if (mAppConfig != null) { leftTopOsd += mAppConfig.cmdid + " "; } SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); leftTopOsd += simpleDateFormat2.format(dt) + " "; leftTopOsd += "CH:" + Integer.toString(channel) + " "; // leftTopOsd = leftTopOsd.replaceAll("\\\\", "\\\\\\\\"); // leftTopOsd = leftTopOsd.replaceAll(" ", "\\\\ "); byte[] leftTopOsdBytes = leftTopOsd.getBytes(StandardCharsets.UTF_8); String usb = (channel == 4) ? "true" : "false"; JSONObject channelJson = (JSONObject) mChannelCfgs.get(Integer.valueOf(channel)); if (channelJson != null) { int usbCamera = channelJson.optInt("usbCamera", 0); usb = (usbCamera != 0) ? "true" : "false"; cameraId = channelJson.optInt("cameraId", cameraId); } // content update --uri content://com.xypower.mpapp.provider/importPriKey final String cmd = "content update --uri content://" + PACKAGE_NAME_MP + ".provider/takePhoto --bind path:s:\"" + remoteFilePath + "\" --bind usb:b:" + usb + " --bind cameraId:i:" + Integer.toString(cameraId) + " --bind channel:i:" + Integer.toString(channel) + " --bind preset:i:" + Integer.toString(preset) + " --bind leftTopOsd:s:" + Base64.encodeToString(leftTopOsdBytes, Base64.DEFAULT | Base64.NO_WRAP) + ""; // adbShellResponse = null; takePhotoImpl(cmd, channel, preset, fileName, remoteFilePath, photoOrVideo, 0); return 0; } protected long takeVideo(int channel, int preset, final boolean photoOrVideo) { // Intent intent = getIntent(); String localIp = intent.getStringExtra("localIp"); showStreaming(channel, channel - 1, "rtmp://" + localIp + "/live/0", localIp); return 0; /* SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); Date dt = new Date(); int cameraId = channel - 1; int duration = 5; String leftTopOsd = ""; if (mAppConfig != null) { leftTopOsd += mAppConfig.cmdid + " "; } SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); leftTopOsd += simpleDateFormat2.format(dt) + " "; leftTopOsd += "CH:" + Integer.toString(channel) + " "; byte[] leftTopOsdBytes = leftTopOsd.getBytes(StandardCharsets.UTF_8); final String fileName = "IMG-" + Integer.toString(channel) + "-" + simpleDateFormat.format(dt) + (photoOrVideo ? ".jpg" : ".mp4"); final String remoteFilePath = REMOTE_PATH_TMP + fileName; // int quality = intent.getIntExtra("quality", 0); // int width = intent.getIntExtra("width", 1280); // int height = intent.getIntExtra("height", 720); // int duration = intent.getIntExtra("duration", 15); // int orientation = intent.getIntExtra("orientation", 0); // long videoId = System.currentTimeMillis() / 1000; // // String leftTopOsd = intent.getStringExtra("leftTopOsd"); // String rightTopOsd = intent.getStringExtra("rightTopOsd"); // String rightBottomOsd = intent.getStringExtra("rightBottomOsd"); // String leftBottomOsd = intent.getStringExtra("leftBottomOsd"); int width = 1280; int height = 720; String usb = (channel == 4) ? "true" : "false"; JSONObject channelJson = (JSONObject) mChannelCfgs.get(Integer.valueOf(channel)); if (channelJson != null) { int usbCamera = channelJson.optInt("usbCamera", 0); usb = (usbCamera != 0) ? "true" : "false"; cameraId = channelJson.optInt("cameraId", cameraId); width = channelJson.optInt("videoCX", width); height = channelJson.optInt("videoCY", height); } //final String cmd = "am start -n " + PACKAGE_NAME_MP + "/" + PACKAGE_NAME_MP + ".BridgeActivity --es action \"recording\" --es path \"" // + remoteFilePath + "\" --ez usb " + usb + " --ei cameraId " + Integer.toString(cameraId) + " --ei channel " // + Integer.toString(channel) + " --ei preset " + Integer.toString(preset) + " --ei duration " + Integer.toString(duration) // + " --el videoId " + Long.toString(dt.getTime() / 1000) + " --ei width " + Integer.toString(height) + " --ei height " // + Integer.toString(height) + " --es leftTopOsd \"" + leftTopOsd + "\""; final String cmd = "content update --uri content://" + PACKAGE_NAME_MP + ".provider/takeVideo --bind path:s:\"" + remoteFilePath + "\" --bind usb:b:" + usb + " --bind cameraId:i:" + Integer.toString(cameraId) + " --bind channel:i:" + Integer.toString(channel) + " --bind preset:i:" + Integer.toString(preset) + " --bind duration:i:" + Integer.toString(duration) + " --bind videoId:l:" + Long.toString(dt.getTime() / 1000) + " --bind width:i:" + Integer.toString(width) + " --bind height:i:" + Integer.toString(height) + " --bind leftTopOsd:s:" + Base64.encodeToString(leftTopOsdBytes, Base64.DEFAULT | Base64.NO_WRAP) + ""; // adbShellResponse = null; Log.d(TAG, cmd); takePhotoImpl(cmd, channel, preset, fileName, remoteFilePath, photoOrVideo, duration * 1000); return 0; */ } private void showPhoto(final String filePath) { Intent intent = new Intent(this, ImageActivity.class); intent.putExtra("path", filePath); intent.putExtra("cmdid", TextUtils.isEmpty(mAppConfig.cmdid) ? "" : mAppConfig.cmdid); // intent.putExtra("info", info); startActivity(intent); } private void showVideo(final String filePath) { Intent intent = new Intent(DeviceActivity.this, VideoActivity.class); intent.putExtra("path", filePath); // intent.putExtra("info", info); startActivity(intent); } private void updateButtons(int numberOfChannels) { if (numberOfChannels > 0) { binding.takePhoto1.setVisibility(View.VISIBLE); binding.takeVideo1.setVisibility(View.VISIBLE); } if (numberOfChannels > 1) { binding.takePhoto2.setVisibility(View.VISIBLE); binding.takeVideo2.setVisibility(View.VISIBLE); } if (numberOfChannels > 2) { binding.takePhoto3.setVisibility(View.VISIBLE); binding.takeVideo3.setVisibility(View.VISIBLE); } if (numberOfChannels > 3) { binding.takePhoto4.setVisibility(View.VISIBLE); binding.takeVideo4.setVisibility(View.VISIBLE); } } private void showStreaming(int channel, int cameraId, final String url, String localIp) { int rotation = -1; int usb = 0; Integer chVal = Integer.valueOf(channel); if (mChannelCfgs.containsKey(chVal)) { JSONObject jsonChannel = mChannelCfgs.get(chVal); if (jsonChannel != null) { int orientation = jsonChannel.optInt("orientation", 0); if (orientation > 0) { rotation = (orientation - 1) * 90; } usb = jsonChannel.optInt("usbCamera", 0); } } Intent intent = new Intent(this, StreamActivity.class); intent.putExtra("url", url); intent.putExtra("localIp", localIp); intent.putExtra("deviceIp", mDeviceIp); intent.putExtra("cameraId", cameraId); intent.putExtra("channel", channel); intent.putExtra("rotation", rotation); intent.putExtra("usb", usb); intent.putExtra("cmdid", TextUtils.isEmpty(mAppConfig.cmdid) ? "" : mAppConfig.cmdid); // intent.putExtra("info", info); startActivity(intent); } public static int calculateSignalLevel(int rsrp, int numLevels) { int signalLevel = 0; if (rsrp >= -97) { signalLevel = 4; } else if (rsrp >= -107) { signalLevel = 3; } else if (rsrp >= -117) { signalLevel = 2; } else if (rsrp >= -125) { signalLevel = 1; } else if (rsrp >= -140) { signalLevel = 0; } return signalLevel; } private void showAppInfo() { ActionBar actionBar = getSupportActionBar(); // 视频浏览,拍照,设备信息及状态查询(编号,版本,双SIM卡状态,电池及太阳能电压等),可以参考东视 Resources resources = getResources(); // String buildTime = BuildConfig.BUILD_ // Date date = new Date(BuildConfig.BUILD_TIMESTAMP); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); String title = resources.getString(R.string.app_name); if (mAppConfig != null && !TextUtils.isEmpty(mAppConfig.cmdid)) { title = mAppConfig.cmdid; } actionBar.setTitle(title); StringBuilder stringBuilder = new StringBuilder(); ConnectivityManager mConnectivityManager; if (mProps.containsKey(KEY_RO_SERIALNO)) { String val = (String)mProps.get(KEY_RO_SERIALNO); appendKeyValue(stringBuilder, "序列号", val, true); } if (mProps.containsKey(KEY_RO_CUSTOM_OTA_VERSION)) { String val = (String)mProps.get(KEY_RO_CUSTOM_OTA_VERSION); appendKeyValue(stringBuilder, "系统版本", val, true); } int numberOfSimcard = 0; if (mProps.containsKey(KEY_RO_MODEMS_MAX_COUNT)) { String val = (String)mProps.get(KEY_RO_MODEMS_MAX_COUNT); numberOfSimcard = Integer.parseInt(val); } String signalLevel = ""; List iccids = new ArrayList<>(); for (int idx = 1; idx <= numberOfSimcard; idx++) { String key = KEY_RO_SIGNAL_STRNGTH_PREFIX + Integer.toString(idx); if (mProps.containsKey(key)) { String val = (String)mProps.get(key); int pos = val.indexOf(","); if (pos != -1) { String ss = val.substring(0, pos); int signalStrength = Integer.parseInt(ss); int sl = calculateSignalLevel(signalStrength, RSSI_LEVELS); if (!TextUtils.isEmpty(signalLevel)) { signalLevel += "/"; } signalLevel += ss + "," + Integer.toString(sl); } } key = KEY_RO_ICCID_PREFIX + Integer.toString(idx - 1); if (mProps.containsKey(key)) { String val = (String)mProps.get(key); byte[] bytes = Base64.decode(val, Base64.DEFAULT); String str = new String(bytes, Charset.defaultCharset()); iccids.add(str); } } appendKeyValue(stringBuilder, "CMDID", mAppConfig.cmdid, true); appendKeyValue(stringBuilder, "主站", (TextUtils.isEmpty(mAppConfig.server) ? "" : mAppConfig.server) + ":" + Integer.toString(mAppConfig.port)); appendKeyValue(stringBuilder, "通道数", Integer.toString(mAppConfig.channels)); if (mProps.containsKey(KEY_APP_MP_VERSION)) { String val = (String)mProps.get(KEY_APP_MP_VERSION); appendKeyValue(stringBuilder, "APP版本", val); } String vendorName = ""; if (mProps.containsKey(KEY_GSM_VENDOR_NAME)) { vendorName = mProps.get(KEY_GSM_VENDOR_NAME); } appendKeyValue(stringBuilder, "移动运营商", vendorName); appendKeyValue(stringBuilder, "移动信号", signalLevel); for (String iccid : iccids) { appendKeyValue(stringBuilder, "ICCID", iccid); } if (mProps.containsKey(KEY_IMEI)) { String val = (String)mProps.get(KEY_IMEI); appendKeyValue(stringBuilder, "IMEI1", val); } if (mProps.containsKey(KEY_IMEI2)) { String val = (String)mProps.get(KEY_IMEI2); appendKeyValue(stringBuilder, "IMEI2", val); } if (mBatteryVoltage != -1) { appendKeyValue(stringBuilder, "电池电压", Integer.toString(mBatteryVoltage / 1000) + "." + Integer.toString((mBatteryVoltage % 1000) / 100)); } if (mBatteryChargingVoltage != -1) { appendKeyValue(stringBuilder, "充电电压", Integer.toString(mBatteryChargingVoltage / 1000) + "." + Integer.toString((mBatteryChargingVoltage % 1000) / 100)); } binding.deviceInfo.setText(Html.fromHtml(stringBuilder.toString())); } private void appendKeyValue(StringBuilder stringBuilder, String key, String val) { appendKeyValue(stringBuilder, key, val, false); } private void appendKeyValue(StringBuilder stringBuilder, String key, String val, boolean highlignt) { if (highlignt) { stringBuilder.append(key + ":" + (TextUtils.isEmpty(val) ? "" : val) + ""); } else { stringBuilder.append(key + ":" + (TextUtils.isEmpty(val) ? "" : val)); } stringBuilder.append("
"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.device_activity_actions, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return false; case R.id.action_refresh: loadDeviceInfo(getApplicationContext(), false); return false; default: return super.onOptionsItemSelected(item); } } }