运维app功能实现

serial
BlueMatthew 2 years ago
parent 55bdaa9bae
commit da65e70976

@ -0,0 +1,164 @@
package com.xypower.common;
import android.content.Context;
import android.os.Environment;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class JSONUtils {
public static JSONObject loadJson(String path) {
JSONObject jsonObject = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
StringBuilder stringBuilder = null;
try {
File appCfgFile = new File(path);
if (appCfgFile.exists()) {
inputStreamReader = new InputStreamReader(new FileInputStream(appCfgFile), "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String line;
stringBuilder = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
}
if (stringBuilder != null) {
jsonObject = new JSONObject(stringBuilder.toString());
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception ex) {
}
}
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (Exception ex) {
}
}
}
return jsonObject;
}
public static boolean saveJson(String path, JSONObject jsonObject) {
OutputStreamWriter outputStreamWriter = null;
try {
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File(path)), "UTF-8");
outputStreamWriter.write(jsonObject.toString());
return true;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStreamWriter != null) {
try {
outputStreamWriter.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return false;
}
public static boolean updateJsonProperty(JSONObject jsonObject, String name, int fieldType, JSONObject val) {
if (name == null) {
return false;
}
JSONArray arr;
String[] fields = name.split("\\.");
if (fields == null || fields.length == 0) {
return false;
}
int arrayIndex = 0;
boolean isArray = false;
String fieldName = null;
JSONObject node = jsonObject;
int i = 0;
try {
for (; i < fields.length - 1; i++) {
int pos = fields[i].indexOf('[');
if (pos != -1) {
// Array
isArray = true;
int pos2 = fields[i].indexOf(']', pos + 1);
if (pos == 0 || pos2 == -1 || pos2 == (pos + 1)) {
return false;
}
fieldName = fields[i].substring(0, pos);
arrayIndex = Integer.parseInt(fields[i].substring(pos + 1, pos2 - pos - 1));
if (!node.has(fieldName) && val == null) {
return true;
}
JSONArray jsonArray = node.optJSONArray(fieldName);
if (jsonArray == null) {
jsonArray = new JSONArray();
node.put(fieldName, jsonArray);
jsonArray = node.optJSONArray(fieldName);
}
while (arrayIndex >= jsonArray.length()) {
jsonArray.put(new JSONObject());
}
node = jsonArray.optJSONObject(arrayIndex);
} else {
if (!node.has(fields[i])) {
if (val == null)
return true;
else {
node.put(fields[i], new JSONObject());
}
}
node = node.optJSONObject(fields[i]);
}
}
if (node == null) {
return (val == null);
}
if (val == null) {
node.remove(fields[i]);
} else {
node.put(fields[i], val);
}
return true;
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
}

@ -1,6 +1,7 @@
package com.xypower.common;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Environment;
@ -20,24 +21,36 @@ public class MicroPhotoContext {
public static final String PACKAGE_NAME_MPAPP = "com.xypower.mpapp";
public static final String PACKAGE_NAME_MPMASTER = "com.xypower.mpmaster";
public final static String MASTER_URL = "http://180.166.218.222:40101/?cmdid=";
public final static String DEFAULT_MASTER_URL = "http://180.166.218.222:40101/?cmdid=";
public final static int DEFAULT_PROTOCOL = 0xFF00;
public static String buildAppDir(Context contxt) {
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!path.endsWith(File.separator)) {
path += File.separator;
}
if (PACKAGE_NAME_MPAPP.equals(contxt.getPackageName())) {
path += contxt.getPackageName() + File.separator;
File pathFile = new File(path);
if (!pathFile.exists() && !pathFile.mkdirs()) {
return null;
}
path += contxt.getPackageName() + File.separator;
File pathFile = new File(path);
if (!pathFile.exists() && !pathFile.mkdirs()) {
return null;
}
else {
path += PACKAGE_NAME_MPAPP + File.separator;
return path;
}
public static String buildMpAppDir(Context contxt) {
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!path.endsWith(File.separator)) {
path += File.separator;
}
path += contxt.getPackageName() + File.separator;
File pathFile = new File(path);
if (!pathFile.exists() && !pathFile.mkdirs()) {
return null;
}
return path;
@ -100,6 +113,63 @@ public class MicroPhotoContext {
return appConfig;
}
public static AppConfig getMpAppConfig(Context context) {
AppConfig appConfig = new AppConfig();
String appPath = buildMpAppDir(context);
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
StringBuilder stringBuilder = null;
try {
File appCfgFile = new File(appPath + "data/App.json");
if (appCfgFile.exists()) {
inputStreamReader = new InputStreamReader(new FileInputStream(appCfgFile), "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String line;
stringBuilder = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
}
JSONObject jsonObject = stringBuilder == null ? new JSONObject() : new JSONObject(stringBuilder.toString());
appConfig.cmdid = jsonObject.optString("CMDID", "");
appConfig.server = jsonObject.optString("Server", "");
appConfig.port = jsonObject.optInt("Port", 0);
appConfig.protocol = jsonObject.optInt("Protocol", DEFAULT_PROTOCOL);
appConfig.networkProtocol = jsonObject.optInt("NetworkProtocol", 0);
appConfig.heartbeat = jsonObject.optInt("heartbeat", 0);
appConfig.packetSize = jsonObject.optInt("packetSize", 0);
if (appConfig.protocol == 0) {
appConfig.protocol = DEFAULT_PROTOCOL;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception ex) {
}
}
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (Exception ex) {
}
}
}
return appConfig;
}
public static void saveAppConfig(Context context, AppConfig appConfig) {
String appPath = buildAppDir(context);
@ -175,6 +245,106 @@ public class MicroPhotoContext {
}
}
public static void restartMpApp(Context context) {
/*
Context context = MicroPhotoService.this.getApplicationContext();
Intent intent = getPackageManager().getLaunchIntentForPackage(context.getPackageName());
int noDelay = 1;
intent.putExtra("noDelay", noDelay);
PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent, 0);
AlarmManager mgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
System.exit(0);
*/
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(PACKAGE_NAME_MPAPP);
LaunchIntent.putExtra("noDelay", 1);
LaunchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(LaunchIntent);
}
public static void saveMpAppConfig(Context context, AppConfig appConfig) {
String appPath = buildMpAppDir(context);
saveMpAppConfig(appPath, appConfig);
}
public static void saveMpAppConfig(String path, AppConfig appConfig) {
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
File dataPath = new File(path + "data/");
if (!dataPath.exists()) {
dataPath.mkdirs();
}
StringBuilder stringBuilder = new StringBuilder();
File file = new File(dataPath, "App.json");
if (file.exists()) {
inputStreamReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
}
JSONObject jsonObject = stringBuilder.length() > 0 ? (new JSONObject(stringBuilder.toString())) : (new JSONObject());
jsonObject.put("CMDID", appConfig.cmdid);
jsonObject.put("Server", appConfig.server);
jsonObject.put("Port", appConfig.port);
jsonObject.put("Protocol", appConfig.protocol);
jsonObject.put("NetworkProtocol", appConfig.networkProtocol);
if (appConfig.heartbeat > 0) {
jsonObject.put("heartbeat", appConfig.heartbeat);
} else {
jsonObject.remove("heartbeat");
}
if (appConfig.packetSize > 0) {
jsonObject.put("packetSize", appConfig.packetSize);
} else {
jsonObject.remove("packetSize");
}
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File(path + "data/App.json")), "UTF-8");
outputStreamWriter.write(jsonObject.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception ex) {
}
}
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (Exception ex) {
}
}
if (outputStreamWriter != null) {
try {
outputStreamWriter.close();
} catch (Exception ex) {
}
}
}
}
public static String getVersionName(Context context) {
String verName = "";
try {

@ -1,12 +1,15 @@
package com.xypower.mpmaster;
import android.content.Context;
import android.os.Environment;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.Pair;
import com.dev.devapi.api.SysApi;
import com.xypower.common.FileDownloader;
import com.xypower.common.InetAddressUtils;
import com.xypower.common.JSONUtils;
import com.xypower.common.MicroPhotoContext;
import org.json.JSONObject;
@ -14,6 +17,10 @@ import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
@ -23,6 +30,8 @@ import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class AppMaster {
@ -30,13 +39,22 @@ public class AppMaster {
private String mCmdid;
private PowerManager.WakeLock mWakelock;
public AppMaster(MpMasterService service, String cmdid) {
public static final String CMD_REBOOT_APP = "";
public static final String CMD_REBOOT_DEV = "yw_cmd_android_reboot";
public static final String CMD_UPGRADE = "upgrade";
public static final String CMD_UPLOAD_LOGS = "yw_cmd_upload_i1_zip_log";
public static final String CMD_SET_CMA = "i1_cmd_set_i1_server_ip_port";
public static final String CMD_SET_MNTN = "i1_cmd_set_xy_yw_ip_port";
public static final String CMD_SET_APP_HB = "i1_cmd_set_i1_heart_beat_time";
public static final String CMD_UPDATE_CONFIG = "upd_cfg";
public AppMaster(MpMasterService service) {
PowerManager powerManager = (PowerManager) service.getSystemService(Context.POWER_SERVICE);
mWakelock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "com.xinyingpower.microphoto:Upgrader");
mService = service;
mCmdid = cmdid;
// mCmdid = cmdid;
}
@Override
@ -59,13 +77,36 @@ public class AppMaster {
new Thread(new Runnable() {
@Override
public void run() {
String masterUrl = MicroPhotoContext.DEFAULT_MASTER_URL;
String path = mService.buildAppDir();
path += "data/Master.json";
JSONObject jsonObject = JSONUtils.loadJson(path);
if (jsonObject.has("url")) {
masterUrl = jsonObject.optString("url");
}
MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getAppConfig(mService.getApplicationContext());
mCmdid = appConfig.cmdid;
if (TextUtils.isEmpty(masterUrl)) {
return;
}
HttpURLConnection httpURLConnection = null;
InputStream inputStream = null;
try {
String url = MicroPhotoContext.MASTER_URL + URLEncoder.encode(mCmdid, "UTF-8");
URL mUrl = new URL(url);
httpURLConnection = (HttpURLConnection) mUrl.openConnection();
if (masterUrl.indexOf('?') != -1) {
masterUrl += "&cmdid=" + URLEncoder.encode(mCmdid, "UTF-8");
} else {
masterUrl += "?cmdid=" + URLEncoder.encode(mCmdid, "UTF-8");
}
URL url = new URL(masterUrl);
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(15000);
httpURLConnection.setReadTimeout(15000);
httpURLConnection.setRequestMethod("POST");
@ -105,9 +146,30 @@ public class AppMaster {
JSONObject jsonObject = new JSONObject(content);
int isUpgrade = jsonObject.optInt("isUpgrade", 0);
String url = jsonObject.optString("url", null);
String cmd = jsonObject.optString("cmd", "");
if (isUpgrade == 1 && !TextUtils.isEmpty(url)) {
upgradeApp(url);
} else if (TextUtils.equals(cmd, CMD_REBOOT_DEV)) {
SysApi.reboot(mService.getApplicationContext());
} else if (TextUtils.equals(cmd, CMD_UPLOAD_LOGS)) {
uploadLogs(url);
} else if (TextUtils.equals(cmd, CMD_SET_CMA)) {
String ip = jsonObject.optString("value_str", null);
int port = jsonObject.optInt("value_int", 0);
updateCma(ip, port);
} else if (TextUtils.equals(cmd, CMD_SET_MNTN)) {
String ip = jsonObject.optString("value_str", null);
int port = jsonObject.optInt("value_int", 0);
updateMntnServer(ip, port);
} else if (TextUtils.equals(cmd, CMD_UPDATE_CONFIG)) {
String path = jsonObject.optString("path", null);
String fileName = jsonObject.optString("fileName", null);
String name = jsonObject.optString("name", null);
int fieldType = jsonObject.optInt("type", 0);
JSONObject val = jsonObject.optJSONObject("value");
}
} catch (Exception e) {
@ -116,6 +178,86 @@ public class AppMaster {
}
private boolean updateConfig(String path, String fileName, String name, int fieldType, JSONObject val) {
if (name == null) {
return false;
}
File configFile = new File(Environment.getExternalStorageDirectory(), path);
if (!configFile.exists()) {
if (val == null) {
// Should delete the config field
return true;
}
configFile.mkdirs();
}
configFile = new File(configFile, fileName);
if (!configFile.exists() && val == null) {
return true;
}
JSONObject jsonObject = JSONUtils.loadJson(configFile.getAbsolutePath());
if (jsonObject == null) {
if (val == null) {
return true;
}
jsonObject = new JSONObject();
}
if (!JSONUtils.updateJsonProperty(jsonObject, name, fieldType, val)) {
return false;
}
return JSONUtils.saveJson(configFile.getAbsolutePath(), jsonObject);
}
private boolean updateMntnServer(String server, int port) {
if (TextUtils.isEmpty(server) && port == 0) {
return false;
}
String url = null;
if (server.startsWith("http://") || server.startsWith("https://")) {
url = server;
} else {
if ((InetAddressUtils.isIPv4Address(server) || InetAddressUtils.isIPv6Address(server)) && port > 0) {
url = "http://" + server + ":" + Integer.toString(port) + "/";
}
}
if (url == null) {
return false;
}
mService.updateMntn(url);
return true;
}
private boolean updateCma(String ip, int port) {
if ((InetAddressUtils.isIPv4Address(ip) && InetAddressUtils.isIPv6Address(ip)) || port <= 0) {
return false;
}
MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getMpAppConfig(mService.getApplicationContext());
if (TextUtils.equals(ip, appConfig.server) && port == appConfig.port) {
return true;
}
appConfig.server = ip;
appConfig.port = port;
MicroPhotoContext.saveMpAppConfig(mService.getApplicationContext(), appConfig);
MicroPhotoContext.restartMpApp(mService.getApplicationContext());
return true;
}
private void upgradeApp(String url) {
FileDownloader dl = new FileDownloader();
@ -135,6 +277,58 @@ public class AppMaster {
}
}
private void uploadLogs(String url) {
}
public static void ZipFolder(File srcFile, File zipFile) {
try {
ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFile));
ZipFiles(srcFile.getParent() + File.separator, srcFile.getName(), outZip);
outZip.finish();
outZip.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void ZipFiles(String srcFileParentName, String srcFileName, ZipOutputStream zipOutputSteam) throws Exception {
if (zipOutputSteam == null)
return;
File file = new File(srcFileParentName + srcFileName);
if (file.isFile()) {
ZipEntry zipEntry = new ZipEntry(srcFileName);
FileInputStream inputStream = new FileInputStream(file);
zipOutputSteam.putNextEntry(zipEntry);
int len;
byte[] buffer = new byte[1024 * 256];
while ((len = inputStream.read(buffer)) != -1) {
zipOutputSteam.write(buffer, 0, len);
}
zipOutputSteam.closeEntry();
} else {
// folder
String fileList[] = file.list();
// NO sub file
if (fileList.length <= 0) {
ZipEntry zipEntry = new ZipEntry(srcFileName + File.separator);
zipOutputSteam.putNextEntry(zipEntry);
zipOutputSteam.closeEntry();
}
//
for (int i = 0; i < fileList.length; i++) {
ZipFiles(srcFileParentName + srcFileName + "/", fileList[i], zipOutputSteam);
}
}
}
private void buildParams(OutputStream output) {
BufferedWriter bufferedWriter = null;
try {

@ -13,6 +13,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.BatteryManager;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@ -32,8 +33,12 @@ import androidx.core.app.NotificationCompat;
import com.dev.devapi.api.SysApi;
import com.xypower.common.FileDownloader;
import com.xypower.common.InetAddressUtils;
import com.xypower.common.JSONUtils;
import com.xypower.common.MicroPhotoContext;
import org.json.JSONObject;
import org.w3c.dom.Text;
import java.io.File;
import java.net.InetAddress;
import java.util.Date;
@ -87,8 +92,10 @@ public class MpMasterService extends Service {
private static int mStateService = STATE_SERVICE.NOT_CONNECTED;
private boolean mQuickHbMode = false;
private String mCmdid = "";
private NotificationManager mNotificationManager;
private int mQuickHeartbeatDuration = 60000; // 1m = 60 * 1000 ms
private int mHeartbeatDuration = 600000; // 10m = 10 * 60 * 1000 ms
private long mNextHeartbeatTime = 0;
@ -194,11 +201,9 @@ public class MpMasterService extends Service {
mService.registerHeartbeatTimer();
String cmdid = mService.getCmdid();
if (!TextUtils.isEmpty(cmdid)) {
AppMaster appMaster = new AppMaster(mService, cmdid);
appMaster.start();
}
AppMaster appMaster = new AppMaster(mService);
appMaster.start();
} else if (TextUtils.equals(ACTION_MSG_BROADCAST, action)) {
int what = intent.getIntExtra("what", 0);
@ -354,7 +359,7 @@ public class MpMasterService extends Service {
mCmdid = cmdid;
registerHeartbeatTimer();
AppMaster appMaster = new AppMaster(this, cmdid);
AppMaster appMaster = new AppMaster(this);
appMaster.start();
break;
@ -450,6 +455,48 @@ public class MpMasterService extends Service {
return notificationBuilder.build();
}
public String buildAppDir() {
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!path.endsWith(File.separator)) {
path += File.separator;
}
path += getApplicationContext().getPackageName() + File.separator;
File pathFile = new File(path);
if (!pathFile.exists() && !pathFile.mkdirs()) {
return null;
}
return path;
}
public boolean updateMntn(String url) {
if (TextUtils.isEmpty(url)) {
return false;
}
String path = buildAppDir();
path += "data/Master.json";
JSONObject jsonObject = JSONUtils.loadJson(path);
String oldUrl = null;
try {
oldUrl = jsonObject.getString("url");
} catch (Exception ex) {
ex.printStackTrace();
}
if (TextUtils.equals(url, oldUrl)) {
return true;
}
try {
jsonObject.put("url", url);
} catch (Exception ex) {
ex.printStackTrace();
}
return JSONUtils.saveJson(path, jsonObject);
}
public boolean updateTime(long timeInMillis) {
try {
SysApi.setSystemTime(getApplicationContext(), timeInMillis);

Loading…
Cancel
Save