package com.xypower.mpremote; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AppCompatActivity; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; import android.text.format.Formatter; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.xypower.common.FileUtils; import com.xypower.common.MicroPhotoContext; import com.xypower.mpremote.databinding.ActivityMainBinding; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.security.PrivateKey; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import dadb.AdbKeyPair; import dadb.AdbShellResponse; import dadb.AdbShellStream; import dadb.AdbStream; import dadb.Dadb; public class MainActivity extends AppCompatActivity { // Used to load the 'mpremote' library on application startup. static { System.loadLibrary("mpremote"); } 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_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 int ADB_SERVER_PORT = 5555; private static final String WIFI_IP_PREFIX = "192.168."; // private static final String WIFI_IP_DEVIDE = "192.168.50.1"; private static final String WIFI_IP_DEVIDE = "192.168.50.137"; // [vendor.ril.nw.signalstrength.lte.1]: [-85,27] //[vendor.ril.nw.signalstrength.lte.2]: [-86,27] private ActivityMainBinding binding; private Handler mHandler; private Dadb mAdb; private Map mProps = new HashMap<>(); private int mBatteryVoltage = -1; private int mBatteryChargingVoltage = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); 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); } final File fileTmp = new File(getFilesDir(), "tmp"); if (!fileTmp.exists()) { fileTmp.mkdirs(); } final AdbKeyPair adbKeyPair = AdbKeyPair.read(priKeyFile, pubKeyFile); final Context context = getApplicationContext(); (new Thread(new Runnable() { @Override public void run() { WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); String ipAddressByWifi = null; if (wifiManager != null) { ipAddressByWifi = Formatter.formatIpAddress(wifiManager.getDhcpInfo().ipAddress); } if (ipAddressByWifi.contains(WIFI_IP_PREFIX)) { String deviceId = Formatter.formatIpAddress(wifiManager.getDhcpInfo().gateway); Socket mSocket = null; try { mSocket = new Socket(WIFI_IP_DEVIDE, ADB_SERVER_PORT); if (mSocket.isConnected()) { mSocket.close(); } } catch (Exception ex) { ex.printStackTrace(); } Dadb adb = Dadb.discover(WIFI_IP_DEVIDE, adbKeyPair); if (adb != null) { mAdb = adb; AdbShellResponse adbShellResponse = null; try { adbShellResponse = mAdb.shell("getprop"); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse.getExitCode() == 0) { String[] lines = FileUtils.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); } } } String remoteFilePath = REMOTE_PATH_TMP + "bv.txt"; String cmd = "am start -n " + PACKAGE_NAME_MP + "/" + PACKAGE_NAME_MP + ".BridgeActivity --es action \"query_bv\" --es path \"" + remoteFilePath + "\""; adbShellResponse = null; try { adbShellResponse = mAdb.shell(cmd); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse.getExitCode() == 0) { File localFilePath = new File(fileTmp, "bv.txt"); if (localFilePath.exists()) { localFilePath.delete(); } for (int idx = 0; idx < 10; idx++) { boolean res = pullFile(mAdb, remoteFilePath, localFilePath); if (res) { String content = FileUtils.readTextFile(localFilePath.getAbsolutePath()); if (!TextUtils.isEmpty(content)) { int pos = content.indexOf(" "); if (pos != -1) { String bv = content.substring(0, pos); String bcv = content.substring(pos + 1); if (!TextUtils.isEmpty(bv)) { mBatteryVoltage = Integer.parseInt(bv); } if (!TextUtils.isEmpty(bcv)) { mBatteryChargingVoltage = Integer.parseInt(bcv); } } } localFilePath.delete(); break; } try { Thread.sleep(1000); } catch (Exception ex) { ex.printStackTrace(); } } try { mAdb.shell("rm " + remoteFilePath); } catch (Exception ex) { ex.printStackTrace(); } } File appConfigFile = new File(fileTmp, "App.json"); boolean res = pullFile(adb, REMOTE_PATH_DATA + "App.json", appConfigFile); if (res) { final MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getMpAppConfig(context, appConfigFile.getAbsolutePath()); MainActivity.this.mHandler.post(new Runnable() { @Override public void run() { MainActivity.this.showAppInfo(appConfig); } }); } } else { mHandler.post(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, R.string.err_dev_not_found, Toast.LENGTH_LONG).show(); } }); } } // Dadb dadb = Dadb.create("localhost", 5555, adbKeyPair); // Dadb.discover(); } })).start(); binding.takePhoto1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takePhoto(1, 255, true); } }); } protected boolean pullFile(Dadb adb, String remoteFilePath, File localFilePath) { if (localFilePath.exists()) { localFilePath.delete(); } boolean res = false; try { adb.pull(localFilePath, remoteFilePath); res = true; } catch (Exception ex) { ex.printStackTrace(); } return res && localFilePath.exists(); } protected long takePhoto(int channel, int preset, boolean photoOrVideo) { if (mAdb == null) { return 0; } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmss"); Date dt = new Date(); int cameraId = channel - 1; final String fileName = "IMG-" + Integer.toString(channel) + simpleDateFormat.format(dt) + ".jpg"; final String remoteFilePath = REMOTE_PATH_TMP + fileName; String usb = (channel == 4) ? "true" : "false"; final String cmd = "am start -n " + PACKAGE_NAME_MP + "/" + PACKAGE_NAME_MP + ".BridgeActivity --es action \"take_photo\" --es path \"" + remoteFilePath + "\" --ez usb " + usb + " --ei cameraId " + Integer.toString(cameraId) + " --ei channel " + Integer.toString(channel) + " --ei preset " + Integer.toString(preset); // adbShellResponse = null; (new Thread(new Runnable() { @Override public void run() { AdbShellResponse adbShellResponse = null; try { adbShellResponse = mAdb.shell(cmd); } catch (Exception ex) { ex.printStackTrace(); } if (adbShellResponse != null) { if (adbShellResponse.getExitCode() == 0) { File localFilePath = new File(getFilesDir(), fileName); for (int idx = 0; idx < 10; idx++) { boolean res = pullFile(mAdb, remoteFilePath, localFilePath); if (res) { mHandler.post(new Runnable() { @Override public void run() { showPhoto(localFilePath.getAbsolutePath()); } }); break; } try { Thread.sleep(1000); } catch (Exception ex) { ex.printStackTrace(); } } try { mAdb.shell("rm " + remoteFilePath); } catch (Exception ex) { ex.printStackTrace(); } } } } })).start(); return 0; } private void showPhoto(final String filePath) { Intent intent = new Intent(MainActivity.this, ImageActivity.class); intent.putExtra("path", filePath); // intent.putExtra("info", info); startActivity(intent); } private void showVideo(final String filePath) { } private void showAppInfo(final MicroPhotoContext.AppConfig appConfig) { 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 (!TextUtils.isEmpty(appConfig.cmdid)) { title += " - " + appConfig.cmdid; } actionBar.setTitle(title); StringBuilder stringBuilder = new StringBuilder(); if (mProps.containsKey(KEY_RO_SERIALNO)) { String val = (String)mProps.get(KEY_RO_SERIALNO); stringBuilder.append("序列号:" + val); stringBuilder.append("\r\n"); } stringBuilder.append("主站:" + appConfig.server + ":" + Integer.toString(appConfig.port)); stringBuilder.append("\r\n"); stringBuilder.append("通道数:" + Integer.toString(appConfig.channels)); stringBuilder.append("\r\n"); if (mBatteryVoltage != -1) { stringBuilder.append("电池电压:" + Integer.toString(mBatteryVoltage / 1000) + "." + Integer.toString((mBatteryVoltage % 1000) / 100)); stringBuilder.append("\r\n"); } if (mBatteryChargingVoltage != -1) { stringBuilder.append("充电电压:" + Integer.toString(mBatteryChargingVoltage / 1000) + "." + Integer.toString((mBatteryChargingVoltage % 1000) / 100)); stringBuilder.append("\r\n"); } binding.deviceInfo.setText(stringBuilder.toString()); } /** * A native method that is implemented by the 'mpremote' native library, * which is packaged with this application. */ public native String stringFromJNI(); }