页面修改

yt_mpremote
liuguijing 3 months ago
parent fcb880375f
commit 5bb02cd10d

@ -37,7 +37,6 @@ public class AdbManager {
}
public static Dadb getAdb(String ip, int port) {
synchronized (mLocker) {
if (mAdbs.containsKey(ip)) {
InternalAdb adb = mAdbs.get(ip);
@ -57,15 +56,11 @@ public class AdbManager {
}
adb = null;
}
InternalAdb adb = new InternalAdb();
adb.ip = ip;
adb.port = port;
adb.adb = Dadb.create(ip, port, mAdbKeyPair);
mAdbs.put(ip, adb);
return adb.adb;
}
}

@ -0,0 +1,30 @@
package com.xypower.mpremote;
public class Constants {
public static final String PACKAGE_NAME_MP = "com.xypower.mpapp";
public static final String REMOTE_PATH_ROOT = "/sdcard/" + PACKAGE_NAME_MP + "/";
public static final String REMOTE_PATH_DATA = REMOTE_PATH_ROOT + "data/";
public static final String REMOTE_PATH_DATA_CHANNELS = REMOTE_PATH_ROOT + "data/channels/";
public static final String REMOTE_PATH_PHOTOS = REMOTE_PATH_ROOT + "photos/";
public static final String REMOTE_PATH_TMP = REMOTE_PATH_ROOT + "tmp/";
public static final String KEY_APP_BV = "app.bv";
public static final String KEY_APP_BCV = "app.bcv";
public static final String KEY_RO_SERIALNO = "ro.serialno";
public static final String KEY_RO_CUSTOM_OTA_VERSION = "ro.custom.ota.version";
public static final String KEY_RO_MODEMS_MAX_COUNT = "telephony.active_modems.max_count";
// ro.telephony.sim.count
public static final String KEY_RO_SIGNAL_STRNGTH_PREFIX = "vendor.ril.nw.signalstrength.lte.";
public static final String KEY_RO_ICCID_PREFIX = "persist.vendor.radio.cfu.iccid.";
public static final String KEY_GSM_VENDOR_NAME = "gsm.operator.alpha";
public static final String KEY_APP_MP_VERSION = "mpapp.version";
public static final String KEY_PREFIX_GLOBAL_SETTING = "settings.global.";
public static final String KEY_IMEI = KEY_PREFIX_GLOBAL_SETTING + "dev_imei";
public static final String KEY_IMEI2 = KEY_PREFIX_GLOBAL_SETTING + "dev_imei2";
}

@ -1,12 +1,10 @@
package com.xypower.mpremote;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
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;
@ -15,11 +13,8 @@ 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;
@ -28,12 +23,12 @@ import com.xypower.common.JSONUtils;
import com.xypower.common.MicroPhotoContext;
import com.xypower.mpremote.databinding.ActivityDeviceBinding;
import com.xypower.mpremote.utils.AdbUtils;
import com.xypower.mpremote.utils.AlertDialogUtils;
import com.xypower.mpremote.utils.FileUtils;
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;
@ -43,362 +38,224 @@ 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 {
public class DeviceActivity extends AppCompatActivity implements View.OnClickListener {
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";
// [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 Handler mHandler = new Handler();
private String mCmdId;
private String mDeviceIp;
private Map<String, String> mProps = new HashMap<>();
private Map<Integer, JSONObject> mChannelCfgs = new HashMap();
private String mSerialNo = "";
private MicroPhotoContext.AppConfig mAppConfig = new MicroPhotoContext.AppConfig();
private int mBatteryVoltage = -1;
private int mBatteryChargingVoltage = -1;
private String mDeviceIp;
private String localIp;
private String configPath;//存放App配置文件
private String tmp;//存放配置文件的目录
private AlertDialog alertDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityDeviceBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
initData();
initView();
initEvent();
}
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// actionBar.setTitle(R.string.title_activity_device);
Intent intent = getIntent();
mDeviceIp = intent.getStringExtra("deviceIp");
mHandler = new Handler();
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);
}
});
private void initEvent() {
//加载设备信息
loadDeviceInfo( true);
}
binding.takePhoto4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
takePhoto(4, 255, true);
}
});
private void initView() {
binding.takePhoto1.setOnClickListener(this);
binding.takePhoto2.setOnClickListener(this);
binding.takePhoto3.setOnClickListener(this);
binding.takePhoto4.setOnClickListener(this);
binding.takeVideo1.setOnClickListener(this);
binding.takeVideo2.setOnClickListener(this);
binding.takeVideo3.setOnClickListener(this);
binding.takeVideo4.setOnClickListener(this);
}
binding.takeVideo4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
takeVideo(4, 255, false);
}
});
private void initData() {
Intent intent = getIntent();
mDeviceIp = intent.getStringExtra("deviceIp");//
localIp = intent.getStringExtra("localIp");//
final Context context = getApplicationContext();
loadDeviceInfo(context, true);
//获取配置文件在本机的存储路径
tmp = FileUtils.join(getFilesDir(), "tmp");
configPath = FileUtils.join(tmp, "App.json");
}
@Override
protected void onDestroy() {
super.onDestroy();
AdbManager.releaseAdb(mDeviceIp);
}
protected void loadDeviceInfo(final Context context, boolean firstConnect) {
protected void loadDeviceInfo(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() {
alertDialog = AlertDialogUtils.show(this, msg);
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();
alertDialog.dismiss();
showAppInfo();
}
});
}
private void runImpl() {
Log.d(TAG, "Adb discovering " + mDeviceIp);
Dadb adb = AdbManager.getAdb(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT);
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);
}
}
}).start();
}
private void runImpl() {
Dadb adb = AdbManager.getAdb(mDeviceIp, AdbUtils.DEFAULT_ADB_PORT);
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();
}
Log.d(TAG, "Global settings Pulled");
adbShellResponse = null;
try {
adbShellResponse = adb.shell("getprop");
} catch (Exception ex) {
ex.printStackTrace();
}, 100);
return;
}
boolean res = false;
File file = FileUtils.getFile(configPath);
if (file != null) {
res = pullFile(adb, Constants.REMOTE_PATH_DATA + "App.json", file);
}
if (res) {
final MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getMpAppConfig(getApplicationContext(), configPath);
if (appConfig != null) {
mAppConfig = appConfig;
}
DeviceActivity.this.mHandler.post(new Runnable() {
@Override
public void run() {
DeviceActivity.this.showAppInfo();
}
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);
}
});
}
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 = Constants.REMOTE_PATH_DATA_CHANNELS + Integer.toString(channel) + ".json";
String join = FileUtils.join(tmp, Integer.toString(channel) + ".json");
File channelfile = FileUtils.getFile(join);
res = pullFile(adb, remoteFilePath, channelfile);
if (res) {
JSONObject channelJson = JSONUtils.loadJson(channelfile.getAbsolutePath());
if (channelJson != null) {
mChannelCfgs.put(new Integer(channel), channelJson);
}
channelfile.delete();
}
Log.d(TAG, "getprop Finished");
if (mProps.containsKey(KEY_RO_SERIALNO)) {
mSerialNo = (String)mProps.get(KEY_RO_SERIALNO);
}
}
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(Constants.KEY_PREFIX_GLOBAL_SETTING + key, val);
}
// 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();
}
}
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);
}
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;
}
}
}
}
if (mProps.containsKey(Constants.KEY_RO_SERIALNO)) {
mSerialNo = (String)mProps.get(Constants.KEY_RO_SERIALNO);
}
// adb shell pm dump com.xypower.mpremote | grep "versionName"
adbShellResponse = null;
try {
adbShellResponse = adb.shell("pm dump " + Constants.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(Constants.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();
}
}
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 (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);
}
}
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);
@ -406,7 +263,6 @@ public class DeviceActivity extends AppCompatActivity {
} catch (Exception ex) {
ex.printStackTrace();
}
return res && localFilePath.exists();
}
@ -507,7 +363,7 @@ public class DeviceActivity extends AppCompatActivity {
int cameraId = channel - 1;
final String fileName = "IMG-" + Integer.toString(channel) + "-" + simpleDateFormat.format(dt) + (photoOrVideo ? ".jpg" : ".mp4");
final String remoteFilePath = REMOTE_PATH_TMP + fileName;
final String remoteFilePath = Constants.REMOTE_PATH_TMP + fileName;
String leftTopOsd = "";
if (mAppConfig != null) {
@ -529,7 +385,7 @@ public class DeviceActivity extends AppCompatActivity {
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:\""
final String cmd = "content update --uri content://" + Constants.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;
@ -540,8 +396,7 @@ public class DeviceActivity extends AppCompatActivity {
}
protected long takeVideo(int channel, int preset, final boolean photoOrVideo) {
Intent intent = getIntent();
String localIp = intent.getStringExtra("localIp");
showStreaming(channel, channel - 1, "rtmp://" + mDeviceIp + "/live/0", localIp);
return 0;
@ -701,10 +556,7 @@ public class DeviceActivity extends AppCompatActivity {
}
private void showAppInfo() {
ActionBar actionBar = getSupportActionBar();
// 视频浏览,拍照,设备信息及状态查询(编号版本双SIM卡状态电池及太阳能电压等),可以参考东视
Resources resources = getResources();
// String buildTime = BuildConfig.BUILD_
// Date date = new Date(BuildConfig.BUILD_TIMESTAMP);
@ -714,32 +566,31 @@ public class DeviceActivity extends AppCompatActivity {
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);
if (mProps.containsKey(Constants.KEY_RO_SERIALNO)) {
String val = (String)mProps.get(Constants.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);
if (mProps.containsKey(Constants.KEY_RO_CUSTOM_OTA_VERSION)) {
String val = (String)mProps.get(Constants.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);
if (mProps.containsKey(Constants.KEY_RO_MODEMS_MAX_COUNT)) {
String val = (String)mProps.get(Constants.KEY_RO_MODEMS_MAX_COUNT);
numberOfSimcard = Integer.parseInt(val);
}
String signalLevel = "";
List<String> iccids = new ArrayList<>();
for (int idx = 1; idx <= numberOfSimcard; idx++) {
String key = KEY_RO_SIGNAL_STRNGTH_PREFIX + Integer.toString(idx);
String key = Constants.KEY_RO_SIGNAL_STRNGTH_PREFIX + Integer.toString(idx);
if (mProps.containsKey(key)) {
String val = (String)mProps.get(key);
int pos = val.indexOf(",");
@ -755,7 +606,7 @@ public class DeviceActivity extends AppCompatActivity {
}
}
key = KEY_RO_ICCID_PREFIX + Integer.toString(idx - 1);
key = Constants.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);
@ -770,14 +621,14 @@ public class DeviceActivity extends AppCompatActivity {
appendKeyValue(stringBuilder, "通道数", Integer.toString(mAppConfig.channels));
if (mProps.containsKey(KEY_APP_MP_VERSION)) {
String val = (String)mProps.get(KEY_APP_MP_VERSION);
if (mProps.containsKey(Constants.KEY_APP_MP_VERSION)) {
String val = (String)mProps.get(Constants.KEY_APP_MP_VERSION);
appendKeyValue(stringBuilder, "APP版本", val);
}
String vendorName = "";
if (mProps.containsKey(KEY_GSM_VENDOR_NAME)) {
vendorName = mProps.get(KEY_GSM_VENDOR_NAME);
if (mProps.containsKey(Constants.KEY_GSM_VENDOR_NAME)) {
vendorName = mProps.get(Constants.KEY_GSM_VENDOR_NAME);
}
appendKeyValue(stringBuilder, "移动运营商", vendorName);
@ -786,13 +637,13 @@ public class DeviceActivity extends AppCompatActivity {
appendKeyValue(stringBuilder, "ICCID", iccid);
}
if (mProps.containsKey(KEY_IMEI)) {
String val = (String)mProps.get(KEY_IMEI);
if (mProps.containsKey(Constants.KEY_IMEI)) {
String val = (String)mProps.get(Constants.KEY_IMEI);
appendKeyValue(stringBuilder, "IMEI1", val);
}
if (mProps.containsKey(KEY_IMEI2)) {
String val = (String)mProps.get(KEY_IMEI2);
if (mProps.containsKey(Constants.KEY_IMEI2)) {
String val = (String)mProps.get(Constants.KEY_IMEI2);
appendKeyValue(stringBuilder, "IMEI2", val);
}
@ -819,25 +670,36 @@ public class DeviceActivity extends AppCompatActivity {
stringBuilder.append("<br>");
}
@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);
public void onClick(View v) {
switch (v.getId()) {
case R.id.takePhoto1:
takePhoto(1, 255, true);
break;
case R.id.takePhoto2:
takePhoto(2, 255, true);
break;
case R.id.takePhoto3:
takePhoto(3, 255, true);
break;
case R.id.takePhoto4:
takePhoto(4, 255, true);
break;
case R.id.takeVideo1:
takeVideo(1, 255, false);
break;
case R.id.takeVideo2:
takeVideo(2, 255, false);
break;
case R.id.takeVideo3:
takeVideo(3, 255, false);
break;
case R.id.takeVideo4:
takeVideo(4, 255, false);
break;
}
}
}

@ -8,7 +8,6 @@ import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import android.Manifest;
import android.app.AlertDialog;
@ -19,7 +18,9 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@ -39,27 +40,20 @@ import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.xypower.mpremote.adapter.ItemAdapter;
import com.xypower.mpremote.bean.WifiInfoBean;
import com.xypower.mpremote.databinding.ActivityMainBinding;
import com.xypower.mpremote.interfaces.OnItemClickListener;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements OnItemClickListener, View.OnClickListener {
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// Used to load the 'mpremote' library on application startup.
private static final String TAG = "ADB";
public static final int RSSI_LEVELS = 5;
private static final String DEFAULT_PRE_SHARED_KEY = SettingsActivity.DEFAULT_PRE_SHARED_KEY;
private static final int REQUEST_CODE_PERMISSIONS = 1025;
@ -67,18 +61,6 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
private static final String WIFI_IP_PREFIX = "192.168.";
private ActivityMainBinding binding;
private Handler mHandler= new Handler();
private List<ScanResult> mScanResults = new ArrayList<>();//扫描到的wifi集合
private ScanResult mCurrentScanResult;
private String mPassword = DEFAULT_PRE_SHARED_KEY;
private boolean mUsingGatewayIp = true;
private String mAssignedIp = "";
private List<WifiInfoBean> mItems = new ArrayList<>();
private ConnectivityManager mConnectivityManager;
private NetworkConnectChangedReceiver mNetworkConnectChangedReceiver;
private ConnectivityManager.NetworkCallback mNetworkCallback;
private ActivityResultLauncher<Intent> settingLauncher;
private ItemAdapter adapter;
private WifiManager wifiManager;
private ActivityResultLauncher<Intent> wifiLauncher;
@ -87,55 +69,38 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);//获取wifi管理器
initActivityResult();//初始化页面回调
initView();//初始化页面显示
initActivityResult();//初始化页面回调
initEvent();//初始化事件
}
private void initEvent() {
AdbManager.initManager(this);//初始化Adb
loadSettings();//获取wifi配置
if (applyForPermissions()) {
scanWifi();
getConnectWiFi();//获取已连接wifi
}
}
private void initView() {
adapter = new ItemAdapter();
adapter.setOnClickListener(this);
binding.listView.setAdapter(adapter);
binding.listView.setLayoutManager(new LinearLayoutManager(this));
binding.refresh.setOnClickListener(this);
binding.setting.setOnClickListener(this);
// 设置完全透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
binding.toolbar.back.setVisibility(View.INVISIBLE);
binding.selectWifi.setOnClickListener(this);
binding.control.setOnClickListener(this);
}
private void initActivityResult() {
settingLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
loadSettings();
}
});
wifiLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String s2 = normalizeSSID(wifiInfo.getSSID());
if (wifiInfo != null) {
String ssid = wifiInfo.getSSID();
if (!TextUtils.isEmpty(ssid)) {
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
ssid = ssid.substring(1, ssid.length() - 1);
}
}
if (ssid.startsWith("XY") || ssid.startsWith("xy")) {
openDeviceActivity();
}
}
getConnectWiFi();
}
});
}
@ -143,37 +108,8 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
@Override
protected void onDestroy() {
super.onDestroy();
if (mConnectivityManager != null && mNetworkCallback != null) {
mConnectivityManager.bindProcessToNetwork(null);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_activity_actions, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
//当点击不同的menu item 是执行不同的操作
switch (id) {
case R.id.action_refresh:
scanWifi();
break;
case R.id.action_settings:
openSettingActivity();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
@ -203,7 +139,6 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
showTipDialog(requestList);
} else {
// showToast("权限授权成功");
scanWifi();
}
} catch (Exception e) {
e.printStackTrace();
@ -241,224 +176,38 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
.create();
dialog.show();
}
protected void scanWifi() {
mScanResults.clear();
new Thread(new Runnable() {
@Override
public void run() {
wifiManager.startScan();
List<ScanResult> scanResults = wifiManager.getScanResults();
for (ScanResult scanResult : scanResults) {
if (TextUtils.isEmpty(scanResult.SSID)) {
continue;
}
mScanResults.add(scanResult);
}
mHandler.post(new Runnable() {
@Override
public void run() {
refreshListView();
}
});
}
}).start();
}
private void connectWifi(String ssid, String bssid, String pwd) {
// Android 10
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setWpa2Passphrase((pwd))
.setIsAppInteractionRequired(true)
.build();
List<WifiNetworkSuggestion> suggestionsList = new ArrayList<>();
suggestionsList.add(suggestion);
wifiManager.removeNetworkSuggestions(suggestionsList);
int status = wifiManager.addNetworkSuggestions(suggestionsList);
// step2
if ((status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) || (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE)) {
WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(pwd)
.build();
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(wifiNetworkSpecifier)
.build();
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull Network network) {
super.onAvailable(network);
NetworkInfo networkInfo = mConnectivityManager.getNetworkInfo(network);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String s1 = normalizeSSID(wifiInfo.getSSID());
String s2 = normalizeSSID(mCurrentScanResult.SSID);
if (TextUtils.equals(s1, s2)) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// requires android.permission.INTERNET
mConnectivityManager.bindProcessToNetwork(network);
openDeviceActivity();
}
});
}
}
@Override
public void onUnavailable() {
super.onUnavailable();
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnectivityManager.bindProcessToNetwork(null);
}
});
}
};
mConnectivityManager.requestNetwork(request, mNetworkCallback);
} else {
}
} else {
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + ssid + "\"";
wifiConfiguration.BSSID = "\"" + bssid + "\"";
wifiConfiguration.preSharedKey = "\"" + pwd + "\"";
int nerworkId = wifiManager.addNetwork(wifiConfiguration);
try {
wifiManager.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
/*
if (mNetworkConnectChangedReceiver != null) {
unregisterReceiver(mNetworkConnectChangedReceiver);
mNetworkConnectChangedReceiver = null;
registerNetworkConnectChangeReceiver();
}
*/
wifiManager.enableNetwork(nerworkId, true);
wifiManager.reconnect();
}
}
private void refreshListView() {
mItems.clear();
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = "";
if (wifiInfo != null) {
ssid = wifiInfo.getSSID();
if (!TextUtils.isEmpty(ssid)) {
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
ssid = ssid.substring(1, ssid.length() - 1);
}
}
}
for (ScanResult scanResult : mScanResults) {
WifiInfoBean bean = new WifiInfoBean();
int signalLevel = WifiManager.calculateSignalLevel(scanResult.level, RSSI_LEVELS);
boolean connected = TextUtils.equals(ssid, scanResult.SSID);
bean.setConnected(connected);
bean.setSignalLevel(signalLevel);
bean.setText(scanResult.SSID);
mItems.add(bean);
}
adapter.setItemList(mItems);
}
//每个item的点击事件
@Override
public void onItemClick(View v, int position) {
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
openWifiActivity();
}
//页面按钮的点击事件
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.refresh:
scanWifi();
case R.id.selectWifi:
openWifiActivity();
break;
case R.id.setting:
openSettingActivity();
case R.id.control:
openDeviceActivity();
break;
}
}
class NetworkConnectChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
// 这个监听wifi的连接状态即是否连上了一个有效无线路由当上边广播的状态是WifiManager.WIFI_STATE_DISABLING和WIFI_STATE_DISABLED的时候根本不会接到这个广播。
// 在上边广播接到广播是WifiManager.WIFI_STATE_ENABLED状态的同时也会接到这个广播当然刚打开wifi肯定还没有连接到有效的无线
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
Parcelable parcelableExtra = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
String bssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
if (null == parcelableExtra) {
return;
}
if (mCurrentScanResult != null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) parcelableExtra;
NetworkInfo.State state = networkInfo.getState();
// Log.e("NetWork Sate Change:"+state+" connectedBssid:" + connectedBssid);
if (state == NetworkInfo.State.CONNECTED) {
String ssid = wifiInfo.getSSID();
String addSSID = mCurrentScanResult.SSID;
if (!(mCurrentScanResult.SSID.startsWith("\"") && mCurrentScanResult.SSID.endsWith("\""))) {
addSSID = "\"" + addSSID + "\"";
}
// Log.i(ssid + "***>" + mCurrentScanResult.SSID);
// Log.i("总共耗时:"+((System.currentTimeMillis()-start)/1000.0));
if (ssid.equals(addSSID)) {
unregisterReceiver(mNetworkConnectChangedReceiver);
mNetworkConnectChangedReceiver = null;
//获取已连接WIFI
private void getConnectWiFi() {
if (wifiManager != null) {
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if (wifiInfo != null) {
String ssid = wifiInfo.getSSID();
if (!TextUtils.isEmpty(ssid)) {
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
ssid = ssid.substring(1, ssid.length() - 1);
}
}
binding.selectWifi.setText("已连接WIFI" + ssid);
}
}
}
private void registerNetworkConnectChangeReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
filter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
mNetworkConnectChangedReceiver = new NetworkConnectChangedReceiver();
registerReceiver(mNetworkConnectChangedReceiver, filter);
}
public boolean applyForPermissions() {
String[] PM_MULTIPLE = {
@ -492,58 +241,30 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
return true;
}
protected void loadSettings() {
SharedPreferences preferences = getSharedPreferences("mpremote", MODE_PRIVATE);
mPassword = preferences.getString("password", DEFAULT_PRE_SHARED_KEY);
mUsingGatewayIp = preferences.getBoolean("usingGateway", true);
mAssignedIp = preferences.getString("assignedIp", "");
}
//打开设备控制页面
protected void openDeviceActivity() {
String ipAddressByWifi = null;
if (wifiManager != null) {
ipAddressByWifi = Formatter.formatIpAddress(wifiManager.getDhcpInfo().ipAddress);
if (!wifiManager.isWifiEnabled()) {
wifiManager.setWifiEnabled(true);
}
DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
ipAddressByWifi = Formatter.formatIpAddress(dhcpInfo.ipAddress);
if (ipAddressByWifi.contains(WIFI_IP_PREFIX)) {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String localIP = Formatter.formatIpAddress(wifiInfo.getIpAddress());
String deviceIP = Formatter.formatIpAddress(wifiManager.getDhcpInfo().gateway);
if (!mUsingGatewayIp) {
deviceIP = mAssignedIp;
}
String deviceIP = Formatter.formatIpAddress(dhcpInfo.gateway);
Intent intent = new Intent(MainActivity.this, DeviceActivity.class);
// intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("deviceIp", deviceIP);
intent.putExtra("localIp", localIP);
intent.putExtra("SSID", mCurrentScanResult.SSID);
startActivity(intent);
}
}
}
//打开WIFI连接页面
private void openWifiActivity() {
Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
wifiLauncher.launch(intent);
}
private void openSettingActivity() {
Intent intent = new Intent(getApplicationContext(), SettingsActivity.class);
settingLauncher.launch(intent);
}
private String normalizeSSID(String ssid) {
if (TextUtils.isEmpty(ssid)) {
return ssid;
}
if (!(ssid.startsWith("\"") && ssid.endsWith("\""))) {
return "\"" + ssid + "\"";
}
return ssid;
}
}

@ -0,0 +1,32 @@
package com.xypower.mpremote.utils;
import android.app.AlertDialog;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import com.xypower.mpremote.R;
public class AlertDialogUtils {
public static AlertDialog show(Context context,String hint) {
// 创建 AlertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(context);
View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_loading, null);
TextView viewById = dialogView.findViewById(R.id.tvLoading);
viewById.setText(hint);
builder.setView(dialogView);
builder.setCancelable(false); // 是否允许用户取消
AlertDialog loadingDialog = builder.create();
loadingDialog.show();
return loadingDialog;
}
public static void dismiss(AlertDialog loadingDialog) {
if (loadingDialog != null) {
loadingDialog.dismiss();
}
}
}

@ -0,0 +1,229 @@
package com.xypower.mpremote.utils;
import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
public class FileUtils {
private static final String TAG = "FileUtils";
/**
* 使 File
*
* @param basePath
* @param subPath
* @return
*/
public static String join(String basePath, String subPath) {
File file = new File(basePath, subPath);
return file.getAbsolutePath();
}
public static String join(File basePath, String subPath) {
File file = new File(basePath, subPath);
return file.getAbsolutePath();
}
/**
*
*/
public static boolean isExternalStorageAvailable() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
/**
*
*/
public static File getCacheDir(Context context) {
return context.getCacheDir();
}
/**
*
*/
public static File getExternalFilesDir(Context context) {
return context.getExternalFilesDir(null);
}
/**
*
*
* @param dirPath
* @return
*/
public static boolean createDir(String dirPath) {
File dir = new File(dirPath);
if (!dir.exists()) {
return dir.mkdirs();
}
return true;
}
/**
*
*
* @param filePath
* @return
*/
public static boolean createFile(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
try {
return file.createNewFile();
} catch (IOException e) {
Log.e(TAG, "Failed to create file: " + filePath, e);
return false;
}
}
return true;
}
/**
*
*
* @param filePath
* @return
*/
public static File getFile(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
try {
boolean newFile = file.createNewFile();
if (newFile) {
return file;
}
} catch (IOException e) {
Log.e(TAG, "Failed to create file: " + filePath, e);
}
}
return file;
}
/**
*
*
* @param path
* @return
*/
public static boolean delete(String path) {
if (TextUtils.isEmpty(path)) {
return false;
}
File file = new File(path);
if (file.isDirectory()) {
return deleteDir(file);
} else {
return deleteFile(file);
}
}
/**
*
*/
private static boolean deleteDir(File dir) {
if (dir == null || !dir.exists() || !dir.isDirectory()) {
return false;
}
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDir(file);
} else {
deleteFile(file);
}
}
}
return dir.delete();
}
/**
*
*/
private static boolean deleteFile(File file) {
return file != null && file.exists() && file.isFile() && file.delete();
}
/**
*
*
* @param srcPath
* @param destPath
* @return
*/
public static boolean copyFile(String srcPath, String destPath) {
File srcFile = new File(srcPath);
File destFile = new File(destPath);
if (!srcFile.exists() || !srcFile.isFile()) {
return false;
}
try (FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
inChannel.transferTo(0, inChannel.size(), outChannel);
return true;
} catch (IOException e) {
Log.e(TAG, "Failed to copy file: " + srcPath, e);
return false;
}
}
/**
*
*
* @param oldPath
* @param newPath
* @return
*/
public static boolean rename(String oldPath, String newPath) {
File oldFile = new File(oldPath);
File newFile = new File(newPath);
return oldFile.exists() && oldFile.renameTo(newFile);
}
/**
*
*
* @param path
* @return
*/
public static long getFileSize(String path) {
File file = new File(path);
if (file.exists() && file.isFile()) {
return file.length();
}
return 0;
}
/**
*
*
* @param path
* @return
*/
public static long getDirSize(String path) {
File dir = new File(path);
if (dir.exists() && dir.isDirectory()) {
long size = 0;
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
size += getDirSize(file.getAbsolutePath());
} else {
size += file.length();
}
}
}
return size;
}
return 0;
}
}

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable/rounded_button.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置背景颜色 -->
<solid android:color="#C0C0C0" />
<!-- 设置圆角半径 -->
<corners android:radius="15dp" />
<!-- 可选:设置边框 -->
<stroke android:width="2dp" android:color="#fff" />
</shape>

@ -4,8 +4,11 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".DeviceActivity">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar"/>
<TextView
android:id="@+id/deviceInfo"
android:layout_width="wrap_content"
@ -15,9 +18,8 @@
android:singleLine="false"
android:lineSpacingMultiplier="1.25"
android:textSize="16sp"
android:text=""
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
<Button
android:id="@+id/takePhoto1"

@ -4,8 +4,12 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<!-- 自定义 Toolbar -->
<include
android:id="@+id/toolbar"
layout="@layout/toolbar"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
@ -15,7 +19,7 @@
android:text="请先连接到设备的热点"
android:textSize="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
<TextView
android:id="@+id/textView2"
@ -27,16 +31,31 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listView"
<Button
android:text="第一步连接WIFI"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:background="@drawable/rounded_button"
android:id="@+id/selectWifi"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="@+id/refresh"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<Button
android:text="第二步:进入控制页面"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:background="@drawable/rounded_button"
android:id="@+id/control"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/selectWifi" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
@ -44,24 +63,5 @@
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<Button
android:id="@+id/refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="刷新wifi"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@+id/guideline" />
<Button
android:id="@+id/setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="设置"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvLoading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Loading..."
android:textSize="16sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressbar" />
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,31 @@
<!-- res/layout/custom_title_bar.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="56dip"
android:orientation="horizontal"
android:background="@color/orange_dark">
<ImageView
android:layout_gravity="center"
android:id="@+id/back"
android:layout_width="40dp"
android:layout_height="match_parent"
android:src="@mipmap/back" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="欣影遥控"
android:textColor="@color/white"
android:textSize="20sp" />
<Space
android:layout_gravity="center"
android:layout_width="40dp"
android:layout_height="match_parent"
/>
</LinearLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

@ -7,4 +7,11 @@
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="orange_standard">#FFA500</color>
<color name="orange_dark">#FF8C00</color>
<color name="orange_light">#FFD700</color>
<color name="orange_material_500">#FF9800</color>
<color name="orange_material_700">#F57C00</color>
<color name="orange_material_300">#FFB74D</color>
</resources>

@ -1,8 +1,8 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MpRemote" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<style name="Theme.MpRemote" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimary">@color/purple_700</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
@ -10,7 +10,14 @@
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
<!-- 自定义 Toolbar 样式 -->
<style name="MyToolbarStyle" parent="Widget.AppCompat.Toolbar">
<item name="titleTextColor">@color/white</item>
<item name="android:textSize">18sp</item>
<item name="android:background">@color/orange_light</item>
</style>
</resources>
Loading…
Cancel
Save