|
|
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 android.util.Base64;
|
|
|
|
|
|
import com.dev.devapi.api.SysApi;
|
|
|
import com.xypower.common.FileDownloader;
|
|
|
import com.xypower.common.FileUploader;
|
|
|
import com.xypower.common.InetAddressUtils;
|
|
|
import com.xypower.common.JSONUtils;
|
|
|
import com.xypower.common.MicroPhotoContext;
|
|
|
import com.xypower.common.ZipUtils;
|
|
|
|
|
|
import org.json.JSONArray;
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.BufferedWriter;
|
|
|
import java.io.File;
|
|
|
import java.io.FileOutputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.io.OutputStream;
|
|
|
import java.io.OutputStreamWriter;
|
|
|
import java.net.HttpURLConnection;
|
|
|
import java.net.URL;
|
|
|
import java.net.URLEncoder;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
|
|
|
public class AppMaster {
|
|
|
|
|
|
private MpMasterService mService;
|
|
|
private String mMasterUrl;
|
|
|
private String mCmdid;
|
|
|
private PowerManager.WakeLock mWakelock;
|
|
|
|
|
|
public static final String CMD_REBOOT_APP = "cmd_reboot_app";
|
|
|
public static final String CMD_REBOOT_MASTER = "cmd_reboot_mpmaster";
|
|
|
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 static final String CMD_PULL_FILE = "pull_files";
|
|
|
public static final String CMD_PUSH_FILE = "push_file";
|
|
|
public static final String CMD_HOT_SPOT = "yw_cmd_hot_spot";
|
|
|
public static final String CMD_ENABLE_GPS = "yw_cmd_enable_gps";
|
|
|
public static final String CMD_ENABLE_OTG = "yw_cmd_enable_otg";
|
|
|
|
|
|
public AppMaster(MpMasterService service, String masterUrl, String cmdid) {
|
|
|
|
|
|
mService = service;
|
|
|
mMasterUrl = masterUrl;
|
|
|
mCmdid = cmdid;
|
|
|
mWakelock = null;
|
|
|
|
|
|
try {
|
|
|
PowerManager powerManager = (PowerManager) service.getSystemService(Context.POWER_SERVICE);
|
|
|
mWakelock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "com.xypower.mpmaster:MpMaster");
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected void finalize() {
|
|
|
try {
|
|
|
if (mWakelock != null) {
|
|
|
mWakelock.setReferenceCounted(false);
|
|
|
mWakelock.release();
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
} finally {
|
|
|
mWakelock = null;
|
|
|
}
|
|
|
mService = null;
|
|
|
}
|
|
|
|
|
|
public void start() {
|
|
|
|
|
|
new Thread(new Runnable() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
|
|
|
String masterUrl = mMasterUrl;
|
|
|
|
|
|
if (TextUtils.isEmpty(masterUrl)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
HttpURLConnection httpURLConnection = null;
|
|
|
InputStream inputStream = null;
|
|
|
|
|
|
try {
|
|
|
if (masterUrl.indexOf('?') != -1) {
|
|
|
masterUrl += "&" + MicroPhotoContext.MASTER_URL_CMDID + "=" + URLEncoder.encode(mCmdid, "UTF-8");
|
|
|
} else {
|
|
|
masterUrl += "?" + MicroPhotoContext.MASTER_URL_CMDID + "=" + URLEncoder.encode(mCmdid, "UTF-8");
|
|
|
}
|
|
|
URL url = new URL(masterUrl);
|
|
|
httpURLConnection = (HttpURLConnection) url.openConnection();
|
|
|
httpURLConnection.setConnectTimeout(15000);
|
|
|
httpURLConnection.setReadTimeout(15000);
|
|
|
httpURLConnection.setRequestMethod("POST");
|
|
|
// httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
|
|
|
httpURLConnection.setDoInput(true);
|
|
|
httpURLConnection.setDoOutput(true);
|
|
|
|
|
|
httpURLConnection.setRequestProperty("Accept-Cmds", "Multiple");
|
|
|
|
|
|
List<Pair<String, String>> postParams = new ArrayList<>();
|
|
|
postParams.add(new Pair<String, String>("id", mCmdid));
|
|
|
postParams.add(new Pair<String, String>("i1Version", mService.getMpAppVersion()));
|
|
|
postParams.add(new Pair<String, String>("maintainVersion", mService.getMasterAppVersion()));
|
|
|
|
|
|
// postParams(httpURLConnection.getOutputStream(), postParams);
|
|
|
buildParams(httpURLConnection.getOutputStream());
|
|
|
httpURLConnection.connect();
|
|
|
inputStream = httpURLConnection.getInputStream();
|
|
|
|
|
|
int responseCode = httpURLConnection.getResponseCode();
|
|
|
|
|
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
|
|
//在子线程中不能操作UI线程,通过handler在UI线程中进行操作
|
|
|
// handler.sendEmptyMessage(0x00);
|
|
|
String response = convertStreamToString(inputStream);
|
|
|
process(response);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}).start();
|
|
|
}
|
|
|
|
|
|
private void process(String content) {
|
|
|
if (TextUtils.isEmpty(content)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
JSONObject jsonObject = new JSONObject(content);
|
|
|
int isUpgrade = jsonObject.optInt("isUpgrade", 0);
|
|
|
String url = jsonObject.optString("url", null);
|
|
|
|
|
|
int mntnMode = jsonObject.optInt("yw", 0);
|
|
|
int quickHbMode = jsonObject.optInt("kxt", 0);
|
|
|
|
|
|
mService.setMntnMode(mntnMode != 0, quickHbMode != 0);
|
|
|
|
|
|
if (isUpgrade == 1 && !TextUtils.isEmpty(url)) {
|
|
|
upgradeApp(url);
|
|
|
}
|
|
|
|
|
|
processCmd(jsonObject);
|
|
|
|
|
|
JSONArray cmdObjects = jsonObject.optJSONArray("cmds");
|
|
|
|
|
|
if (cmdObjects != null) {
|
|
|
int cnt = cmdObjects.length();
|
|
|
for (int idx = 0; idx < cnt; idx++) {
|
|
|
JSONObject cmdObject = cmdObjects.getJSONObject(idx);
|
|
|
if (cmdObject != null) {
|
|
|
processCmd(cmdObject);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void processCmd(JSONObject jsonObject) {
|
|
|
String cmd = jsonObject.optString("cmd", "");
|
|
|
|
|
|
if (TextUtils.equals(cmd, CMD_REBOOT_DEV)) {
|
|
|
SysApi.reboot(mService.getApplicationContext());
|
|
|
} else if (TextUtils.equals(cmd, CMD_UPLOAD_LOGS)) {
|
|
|
String url = jsonObject.optString("url", null);
|
|
|
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);
|
|
|
String newUrl = buildMntnServer(ip, port);
|
|
|
if (newUrl != null) {
|
|
|
mService.updateMntn(newUrl);
|
|
|
}
|
|
|
} 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");
|
|
|
} else if (TextUtils.equals(cmd, CMD_PUSH_FILE)) {
|
|
|
String path = jsonObject.optString("path", null);
|
|
|
String content = jsonObject.optString("content", null);
|
|
|
|
|
|
File file = new File(path);
|
|
|
File parentPath = file.getParentFile();
|
|
|
if (!parentPath.exists()) {
|
|
|
parentPath.mkdirs();
|
|
|
}
|
|
|
|
|
|
byte[] data = null;
|
|
|
try {
|
|
|
data = Base64.decode(content, Base64.DEFAULT);
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
}
|
|
|
|
|
|
if (data != null) {
|
|
|
OutputStream outputStream = null;
|
|
|
try {
|
|
|
outputStream = new FileOutputStream(file);
|
|
|
outputStream.write(data);
|
|
|
} catch (IOException e) {
|
|
|
e.printStackTrace();
|
|
|
} finally {
|
|
|
if (outputStream != null) {
|
|
|
try {
|
|
|
outputStream.close();
|
|
|
} catch (Exception ex) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
} else if (TextUtils.equals(cmd, CMD_HOT_SPOT)) {
|
|
|
int enable = jsonObject.optInt("enable", 1);
|
|
|
String name = jsonObject.optString("name", "XYMP");
|
|
|
if (enable != 0) {
|
|
|
SysApi.enableApp(mService.getApplicationContext(), name);
|
|
|
} else {
|
|
|
SysApi.disableApp(mService.getApplicationContext(), name);
|
|
|
}
|
|
|
} else if (TextUtils.equals(cmd, CMD_ENABLE_GPS)) {
|
|
|
int enable = jsonObject.optInt("enable", 1);
|
|
|
SysApi.enableGps(mService.getApplicationContext(), (enable != 0));
|
|
|
} else if (TextUtils.equals(cmd, CMD_ENABLE_OTG)) {
|
|
|
int enable = jsonObject.optInt("enable", 1);
|
|
|
SysApi.setOtgState((enable != 0));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
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 String buildMntnServer(String server, int port) {
|
|
|
if (TextUtils.isEmpty(server) && port == 0) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
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) + "/";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return url;
|
|
|
}
|
|
|
|
|
|
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();
|
|
|
File path = new File(MicroPhotoContext.buildAppDir(mService.getApplicationContext()), "packages");
|
|
|
if (!path.exists()) {
|
|
|
path.mkdirs();
|
|
|
}
|
|
|
|
|
|
File file = new File(path, "app.apk");
|
|
|
if (file.exists()) {
|
|
|
file.delete();
|
|
|
}
|
|
|
String apkPath = file.getAbsolutePath();
|
|
|
if (dl.download(url, apkPath)) {
|
|
|
Context context = mService.getApplicationContext();
|
|
|
SysApi.installApk(context, apkPath, context.getPackageName(), true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void uploadLogs(String url) {
|
|
|
String appDir = mService.buildAppDir();
|
|
|
|
|
|
try {
|
|
|
|
|
|
long ts = System.currentTimeMillis();//long now = android.os.SystemClock.uptimeMillis();
|
|
|
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
|
Date dt = new Date(ts);
|
|
|
|
|
|
final String fileName = mCmdid + "_" + format.format(dt) + ".zip";
|
|
|
final File file = File.createTempFile(fileName, null, new File(appDir));
|
|
|
if (file == null) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
final String mpAppDir = MicroPhotoContext.buildMpAppDir(mService.getApplicationContext());
|
|
|
final File logDir = new File(mpAppDir + "logs" + File.separator);
|
|
|
if (!logDir.exists()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
ZipUtils.ZipFolder(logDir, file);
|
|
|
|
|
|
if (!file.exists()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
FileUploader fileUploader = new FileUploader(url);
|
|
|
fileUploader.addFilePart("file", file, fileName, "application/x-zip-compressed");
|
|
|
|
|
|
String response = fileUploader.finish();
|
|
|
if (response != null) {
|
|
|
|
|
|
}
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void uploadFiles(String url, List<String> paths) {
|
|
|
String appDir = mService.buildAppDir();
|
|
|
|
|
|
try {
|
|
|
|
|
|
long ts = System.currentTimeMillis();//long now = android.os.SystemClock.uptimeMillis();
|
|
|
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
|
Date dt = new Date(ts);
|
|
|
|
|
|
final String fileName = mCmdid + "_" + format.format(dt) + ".zip";
|
|
|
final File file = File.createTempFile(fileName, null, new File(appDir));
|
|
|
if (file == null) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// ZipUtils
|
|
|
// ZipUtils.ZipFiles(logDir, file);
|
|
|
|
|
|
if (!file.exists()) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
FileUploader fileUploader = new FileUploader(url);
|
|
|
fileUploader.addFilePart("file", file, fileName, "application/x-zip-compressed");
|
|
|
|
|
|
String response = fileUploader.finish();
|
|
|
if (response != null) {
|
|
|
|
|
|
}
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void buildParams(OutputStream output) {
|
|
|
BufferedWriter bufferedWriter = null;
|
|
|
try {
|
|
|
JSONObject jsonObject = new JSONObject();
|
|
|
jsonObject.put("id", mCmdid);
|
|
|
jsonObject.put("i1Version", mService.getMpAppVersion());
|
|
|
jsonObject.put("maintainVersion", mService.getMasterAppVersion());
|
|
|
|
|
|
bufferedWriter = new BufferedWriter(new OutputStreamWriter(output, "UTF-8"));
|
|
|
bufferedWriter.write(jsonObject.toString());
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
} finally {
|
|
|
try {
|
|
|
if (bufferedWriter != null) {
|
|
|
bufferedWriter.close();
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public static void postParams(OutputStream output, List<Pair<String, String>> paramsList) {
|
|
|
|
|
|
BufferedWriter bufferedWriter = null;
|
|
|
try {
|
|
|
StringBuilder stringBuilder = new StringBuilder();
|
|
|
for (Pair<String, String> pair : paramsList) {
|
|
|
if (!TextUtils.isEmpty(stringBuilder)) {
|
|
|
stringBuilder.append("&");
|
|
|
}
|
|
|
stringBuilder.append(URLEncoder.encode(pair.first, "UTF-8"));
|
|
|
stringBuilder.append("=");
|
|
|
stringBuilder.append(URLEncoder.encode(pair.second, "UTF-8"));
|
|
|
bufferedWriter = new BufferedWriter(new OutputStreamWriter(output, "UTF-8"));
|
|
|
bufferedWriter.write(stringBuilder.toString());
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
} finally {
|
|
|
try {
|
|
|
if (bufferedWriter != null) {
|
|
|
bufferedWriter.close();
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private String convertStreamToString(InputStream inputStream) {
|
|
|
BufferedReader bufferedReader = null;
|
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
String line;
|
|
|
try {
|
|
|
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
|
|
|
while ((line = bufferedReader.readLine()) != null) {
|
|
|
stringBuffer.append(line).append("\n");
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
} finally {
|
|
|
try {
|
|
|
if (bufferedReader != null) {
|
|
|
bufferedReader.close();
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
return stringBuffer.toString();
|
|
|
}
|
|
|
|
|
|
|
|
|
}
|