运维APP实现

serial
BlueMatthew 2 years ago
parent 5386d56b14
commit 55bdaa9bae

@ -2,8 +2,12 @@ plugins {
id 'com.android.application'
}
def AppVersionName = "1.0.30"
def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 30
def AppMajorVersion = 1
def AppMinorVersion = 0
def AppBuildNumber = 30
def AppVersionName = AppMajorVersion + "." + AppMinorVersion + "." + AppBuildNumber
def AppVersionCode = AppMajorVersion * 100000 + AppMinorVersion * 1000 + AppBuildNumber
android {
namespace 'com.xypower.mpapp'

@ -25,6 +25,7 @@
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.REBOOT"
tools:ignore="ProtectedPermissions" />
@ -95,7 +96,7 @@
<category android:name="android.intent.category.default" />
</intent-filter>
</service>
<service android:name=".FloatingWindow" />
<service android:name="com.xypower.common.FloatingWindow" />
<receiver
android:name=".MicroPhotoService$AlarmReceiver"

@ -45,6 +45,7 @@ public class AppMaster {
protected void finalize() {
try {
if (mWakelock != null) {
mWakelock.setReferenceCounted(false);
mWakelock.release();
}
} catch (Exception e) {
@ -91,6 +92,16 @@ public class AppMaster {
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (AppMaster.this.mWakelock != null) {
try {
AppMaster.this.mWakelock.setReferenceCounted(false);
AppMaster.this.mWakelock.release();
} catch (Exception e) {
e.printStackTrace();
}
AppMaster.this.mWakelock = null;
}
}
}
@ -110,7 +121,6 @@ public class AppMaster {
if (isUpgrade == 1 && !TextUtils.isEmpty(url)) {
upgradeApp(url);
}
} catch (Exception e) {
e.printStackTrace();
}

@ -1,11 +1,12 @@
package com.xypower.mpapp;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.xypower.common.MicroPhotoContext;
public class BootBroadcastReceiver extends BroadcastReceiver {
private static final String ACTION = "android.intent.action.BOOT_COMPLETED";
@ -29,7 +30,7 @@ public class BootBroadcastReceiver extends BroadcastReceiver {
}
*/
MainActivity.AppConfig appConfig = MainActivity.getAppConfig(context);
MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getAppConfig(context);
MainActivity.startMicroPhotoService(context, appConfig, null);
/*

@ -1,7 +1,6 @@
package com.xypower.mpapp;
import android.Manifest;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -44,21 +43,11 @@ import com.xypower.mpapp.utils.RandomReader;
//import com.xinyingpower.microphoto.request.INettyMessageListener;
//import com.xinyingpower.microphoto.request.NettyChatClient;
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;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
@ -66,8 +55,6 @@ public class MainActivity extends AppCompatActivity {
public static final int MSG_WHAT_LOG_OBSERVER = MicroPhotoService.MSG_WHAT_MAX + 10;
public final static int DEFAULT_PROTOCOL = 0xFF00;
// Used to load the 'microphoto' library on application startup.
static {
System.loadLibrary("microphoto");
@ -118,17 +105,6 @@ public class MainActivity extends AppCompatActivity {
}
public static class AppConfig {
public String cmdid;
public String server;
public int port;
public int protocol;
public int networkProtocol;
public int heartbeat;
public int packetSize;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -143,7 +119,7 @@ public class MainActivity extends AppCompatActivity {
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");
actionBar.setTitle(actionBar.getTitle().toString() + " v" + getVersionName(getApplicationContext()) + " " + sdf.format(date));
actionBar.setTitle(actionBar.getTitle().toString() + " v" + MicroPhotoContext.getVersionName(getApplicationContext()) + " " + sdf.format(date));
binding.logs.setText("");
binding.logs.setMovementMethod(ScrollingMovementMethod.getInstance());
@ -226,9 +202,9 @@ public class MainActivity extends AppCompatActivity {
String cmdid = "";
String server = "";
Integer port = new Integer(6891);
Integer protocol = new Integer(DEFAULT_PROTOCOL); // 0xFF00
Integer protocol = new Integer(MicroPhotoContext.DEFAULT_PROTOCOL); // 0xFF00
AppConfig appConfig = getAppConfig();
MicroPhotoContext.AppConfig appConfig = getAppConfig();
binding.cmdid.setText(appConfig.cmdid);
binding.server.setText(appConfig.server);
binding.port.setText(appConfig.port != 0 ? Integer.toString(appConfig.port) : "");
@ -267,7 +243,7 @@ public class MainActivity extends AppCompatActivity {
return;
}
AppConfig curAppConfig = retrieveAndSaveAppConfig();
MicroPhotoContext.AppConfig curAppConfig = retrieveAndSaveAppConfig();
startMicroPhotoService(MainActivity.this, appConfig, mMessenger);
@ -475,14 +451,10 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onClick(View v) {
if (mMessenger != null) {
Message msg = Message.obtain();
msg.what = MicroPhotoService.MSG_WHAT_SENDING_HB;
try {
mMessenger.send(msg);
} catch(Exception e) {
}
}
String path = "/sdcard/com.xypower.mpapp/packages/app.apk";
SysApi.installApk(getApplicationContext(), path, v.getContext().getPackageName(), true);
// Context context = MainActivity.this.getApplicationContext();
// MicroPhotoService.sendMessage(context, MicroPhotoService.MSG_WHAT_SENDING_HB, 0);
}
});
@ -503,7 +475,7 @@ public class MainActivity extends AppCompatActivity {
}
public static void startMicroPhotoService(Context context, AppConfig curAppConfig, Messenger messenger) {
public static void startMicroPhotoService(Context context, MicroPhotoContext.AppConfig curAppConfig, Messenger messenger) {
if (TextUtils.isEmpty(curAppConfig.cmdid) || TextUtils.isEmpty(curAppConfig.server) || curAppConfig.port == 0) {
return;
@ -569,15 +541,15 @@ public class MainActivity extends AppCompatActivity {
}
}
private AppConfig retrieveAndSaveAppConfig() {
AppConfig appConfig = new AppConfig();
private MicroPhotoContext.AppConfig retrieveAndSaveAppConfig() {
MicroPhotoContext.AppConfig appConfig = new MicroPhotoContext.AppConfig();
appConfig.cmdid = MainActivity.this.binding.cmdid.getText().toString();
appConfig.server = MainActivity.this.binding.server.getText().toString();
String portStr = MainActivity.this.binding.port.getText().toString();
appConfig.port = TextUtils.isEmpty(portStr) ? 0 : Integer.parseInt(portStr);
String protocolStr = MainActivity.this.binding.protocol.getSelectedItem().toString();
appConfig.protocol = DEFAULT_PROTOCOL;
appConfig.protocol = MicroPhotoContext.DEFAULT_PROTOCOL;
String[] parts = protocolStr.split("-");
if (parts != null) {
appConfig.protocol = Integer.parseInt(parts[0]);
@ -592,136 +564,12 @@ public class MainActivity extends AppCompatActivity {
return appConfig;
}
private AppConfig getAppConfig() {
return getAppConfig(this.getApplicationContext());
}
public static AppConfig getAppConfig(Context context) {
AppConfig appConfig = new AppConfig();
String appPath = MicroPhotoContext.buildAppDir(context);
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try {
inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "data/App.json")), "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String line;
StringBuilder stringBuilder = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
appConfig.cmdid = jsonObject.getString("CMDID");
appConfig.server = jsonObject.getString("Server");
appConfig.port = jsonObject.getInt("Port");
appConfig.protocol = jsonObject.getInt("Protocol");
appConfig.networkProtocol = jsonObject.getInt("NetworkProtocol");
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;
}
private void saveAppConfig(AppConfig appConfig) {
String appPath = MicroPhotoContext.buildAppDir(this.getApplicationContext());
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
File dataPath = new File(appPath + "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(appPath + "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) {
private MicroPhotoContext.AppConfig getAppConfig() {
return MicroPhotoContext.getAppConfig(this.getApplicationContext());
}
}
}
private void saveAppConfig(MicroPhotoContext.AppConfig appConfig) {
MicroPhotoContext.saveAppConfig(getApplicationContext(), appConfig);
}
private int getDefaultDataSubId() {
@ -944,18 +792,7 @@ public class MainActivity extends AppCompatActivity {
}
}
public static String getVersionName(Context context) {
String verName = "";
try {
verName = context.getPackageManager().
getPackageInfo(context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return verName;
}
// private void initSocket() {
// private void initSocket() {
// NettyChatClient nettyChatClient = NettyChatClient.newInstance("47.96.238.157", 6891);
//// NettyChatClient nettyChatClient = NettyChatClient.newInstance("180.166.218.222", 40032);
// nettyChatClient.init(new INettyMessageListener() {

@ -9,6 +9,7 @@ import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@ -50,8 +51,6 @@ import com.xypower.common.MicroPhotoContext;
import java.io.File;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@ -79,6 +78,8 @@ public class MicroPhotoService extends Service {
private static final String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver";
public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503;
// public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 0;
public static final String ACTION_MSG_BROADCAST = "ACT_MSG_BROADCAST";
public static final String ACTION_START = "ACT_START";
public static final String ACTION_STOP = "ACT_STOP";
public static final String ACTION_MAIN = "ACT_MAIN";
@ -152,7 +153,13 @@ public class MicroPhotoService extends Service {
intentFilter.addAction(ACTION_TAKE_PHOTO);
intentFilter.addAction(ACTION_TIMEOUT);
intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY);
intentFilter.addAction(ACTION_MSG_BROADCAST);
registerReceiver(mAlarmReceiver, intentFilter);
// IntentFilter intentFilter2 = new IntentFilter(ACTION_MSG_BROADCAST);
// registerReceiver(mAlarmReceiver, intentFilter2);
// registerRe
}
{
mNetworkChangedReceiver = new NetworkChangedReceiver(this);
@ -200,7 +207,14 @@ public class MicroPhotoService extends Service {
unregisterReceiver(mNetworkChangedReceiver);
for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) {
entry.getValue().release();
try {
PowerManager.WakeLock wl = entry.getValue();
wl.setReferenceCounted(false);
wl.release();
wl = null;
} catch (Exception ex) {
ex.printStackTrace();
}
}
mWakeLocks.clear();
@ -226,6 +240,16 @@ public class MicroPhotoService extends Service {
return mCmdid;
}
public static void sendMessage(Context context, int what, int data) {
Intent intent = new Intent(ACTION_MSG_BROADCAST);
intent.putExtra("what", what);
intent.putExtra("data", data);
intent.setPackage(context.getPackageName());
String typeName = AlarmReceiver.class.getTypeName();
intent.setComponent( new ComponentName(context.getPackageName(), AlarmReceiver.class.getTypeName()) );
context.sendBroadcast(intent);
}
public static class AlarmReceiver extends BroadcastReceiver {
private MicroPhotoService mService;
public AlarmReceiver() {
@ -241,13 +265,6 @@ public class MicroPhotoService extends Service {
mService.sendHeartbeat(mService.mNativeHandle);
mService.registerHeartbeatTimer();
String cmdid = mService.getCmdid();
if (!TextUtils.isEmpty(cmdid)) {
AppMaster appMaster = new AppMaster(mService, cmdid);
appMaster.start();
}
} else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) {
long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0);
int cnt = intent.getIntExtra(EXTRA_PARAM_SCHEDULES, 0);
@ -305,6 +322,14 @@ public class MicroPhotoService extends Service {
} else {
mService.mTimers.remove(uidObj);
}
} else if (TextUtils.equals(ACTION_MSG_BROADCAST, action)) {
int what = intent.getIntExtra("what", 0);
int data = intent.getIntExtra("data", 0);
if (what == MSG_WHAT_SENDING_HB) {
mService.sendHeartbeat(mService.mNativeHandle);
}
}
}
}
@ -565,10 +590,6 @@ public class MicroPhotoService extends Service {
long baseTime = nowTs - startTime;
service.registerCaptureSchedule(startTime, baseTime);
// AppMaster appMaster = new AppMaster(this, cmdid);
// appMaster.start();
}
break;
@ -596,6 +617,7 @@ public class MicroPhotoService extends Service {
}
if (wl2 != null) {
Log.i(TAG, "Release same name wakelock:" + name);
wl2.setReferenceCounted(false);
wl2.release();
}
Log.i(TAG, "Request wakelock:" + name);
@ -606,12 +628,22 @@ public class MicroPhotoService extends Service {
public void releaseWakelock(String name) {
PowerManager.WakeLock wl = null;
synchronized (mWakeLocks) {
try {
wl = mWakeLocks.get(name);
mWakeLocks.remove(name);
} catch (Exception ex) {
ex.printStackTrace();
}
}
if (wl != null) {
Log.i(TAG, "Release wakelock:" + name);
try {
wl.setReferenceCounted(false);
wl.release();
} catch (Exception ex) {
ex.printStackTrace();
}
wl = null;
}
}
@ -754,7 +786,12 @@ public class MicroPhotoService extends Service {
SysApi.installApk(context, filePath, context.getPackageName(), true);
try {
wl.setReferenceCounted(false);
wl.release();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
th.start();

@ -62,7 +62,7 @@
android:maxLines="1"
android:inputType="text"
android:imeOptions="actionDone"
android:hint="main_server"
android:hint="@string/main_server"
app:layout_constraintStart_toStartOf="@+id/cmdid"
app:layout_constraintTop_toBottomOf="@+id/cmdid" />
@ -310,15 +310,16 @@
android:text="录制视频结束" />
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="363dp"
android:layout_height="85dp"
android:layout_marginStart="16dp"
android:layout_marginTop="48dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
app:constraint_referenced_ids="gps,netgps,tcpudp,tcpudpsend,video,video2"
app:flow_horizontalGap="20dp"
app:flow_wrapMode="chain"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/takePhotoBtn4" />
app:layout_constraintEnd_toStartOf="@+id/logs"
app:layout_constraintTop_toBottomOf="@+id/btnSendHb" />
<TextView
android:id="@+id/logs"

@ -12,7 +12,7 @@
android:id="@+id/textViewCmdId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:text="CMDID"
app:layout_constraintBottom_toBottomOf="@+id/cmdid"
app:layout_constraintStart_toStartOf="parent"
@ -23,7 +23,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginTop="8dp"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:ems="10"
android:singleLine="true"
android:text="XY-ANDROIDSIM-001"

@ -1,5 +1,9 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="activity_horizontal_margin">8dp</dimen>
<dimen name="activity_vertical_margin">8dp</dimen>
<dimen name="activity_horizontal_margin_small">4dp</dimen>
<dimen name="activity_vertical_margin_small">4dp</dimen>
<dimen name="activity_horizontal_spacing">8dp</dimen>
<dimen name="activity_vertical_spacing">8dp</dimen>
</resources>

@ -1,27 +1,198 @@
package com.xypower.common;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
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 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 int DEFAULT_PROTOCOL = 0xFF00;
public static String buildAppDir(Context contxt) {
File path = new File(Environment.getExternalStorageDirectory(), contxt.getPackageName() + "/");
if (!path.exists() && !path.mkdirs()) {
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;
}
String p = path.getAbsolutePath();
if (!p.endsWith(File.separator)) {
p += File.separator;
}
return p;
else {
path += PACKAGE_NAME_MPAPP + File.separator;
}
return path;
}
public static AppConfig getAppConfig(Context context) {
AppConfig appConfig = new AppConfig();
String appPath = buildAppDir(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);
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
File dataPath = new File(appPath + "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(appPath + "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 {
verName = context.getPackageManager().
getPackageInfo(context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return verName;
}
public static class AppConfig {
public String cmdid;
public String server;
public int port;
public int protocol;
public int networkProtocol;
public int heartbeat;
public int packetSize;
}
}

@ -2,15 +2,24 @@ plugins {
id 'com.android.application'
}
def AppMajorVersion = 1
def AppMinorVersion = 0
def AppBuildNumber = 1
def AppVersionName = AppMajorVersion + "." + AppMinorVersion + "." + AppBuildNumber
def AppVersionCode = AppMajorVersion * 100000 + AppMinorVersion * 1000 + AppBuildNumber
android {
compileSdk 32
compileSdk 33
defaultConfig {
applicationId "com.xypower.mpmaster"
minSdk 25
targetSdk 32
versionCode 1
versionName "1.0"
targetSdk 25
versionCode AppVersionCode
versionName AppVersionName
buildConfigField "long","BUILD_TIMESTAMP", System.currentTimeMillis() + "L"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

@ -3,21 +3,78 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.xypower.mpmaster">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.SET_TIME"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.CHANGE_CONFIGURATION"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.SET_TIME_ZONE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission
android:name="android.permission.REBOOT"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.INSTALL_PACKAGES"
tools:ignore="ProtectedPermissions" /> <!-- 关机权限 -->
<uses-permission
android:name="android.permission.RECOVERY"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.SHUTDOWN"
tools:ignore="ProtectedPermissions" /> <!-- 添加访问手机状态的权限 -->
<uses-permission
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <!-- 接收短信权限 -->
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission
android:name="android.permission.DEVICE_POWER"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.MODIFY_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
tools:ignore="ProtectedPermissions" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/Theme.MpMaster"
tools:targetApi="31">
tools:targetApi="28">
<service
android:name=".MicroPhotoService"
android:name=".MpMasterService"
android:enabled="true"
android:exported="true"></service>

@ -26,11 +26,11 @@ import java.util.List;
public class AppMaster {
private MicroPhotoService mService;
private MpMasterService mService;
private String mCmdid;
private PowerManager.WakeLock mWakelock;
public AppMaster(MicroPhotoService service, String cmdid) {
public AppMaster(MpMasterService service, String cmdid) {
PowerManager powerManager = (PowerManager) service.getSystemService(Context.POWER_SERVICE);
mWakelock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "com.xinyingpower.microphoto:Upgrader");
@ -43,6 +43,7 @@ public class AppMaster {
protected void finalize() {
try {
if (mWakelock != null) {
mWakelock.setReferenceCounted(false);
mWakelock.release();
}
} catch (Exception e) {

@ -0,0 +1,222 @@
package com.xypower.mpmaster;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class FloatingWindow extends Service {
private Context mContext;
private WindowManager mWindowManager;
private View mView;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
allAboutLayout(intent);
moveView();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
try {
if (mView != null) {
mWindowManager.removeView(mView);
}
} catch (Exception ex) {
// ex.printStackTrace();
Log.e("FW", "Exception " + ex.getMessage());
}
super.onDestroy();
}
WindowManager.LayoutParams mWindowsParams;
private void moveView() {
/*
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int width = (int) (metrics.widthPixels * 1f);
int height = (int) (metrics.heightPixels * 1f);
mWindowsParams = new WindowManager.LayoutParams(
width,//WindowManager.LayoutParams.WRAP_CONTENT,
height,//WindowManager.LayoutParams.WRAP_CONTENT,
//WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
(Build.VERSION.SDK_INT <= 25) ? WindowManager.LayoutParams.TYPE_PHONE : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
,
//WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN // Not displaying keyboard on bg activity's EditText
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
//WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, //Not work with EditText on keyboard
PixelFormat.TRANSLUCENT);
mWindowsParams.gravity = Gravity.TOP | Gravity.LEFT;
//params.x = 0;
mWindowsParams.y = 100;
mWindowManager.addView(mView, mWindowsParams);
mView.setOnTouchListener(new View.OnTouchListener() {
private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;
long startTime = System.currentTimeMillis();
@Override
public boolean onTouch(View v, MotionEvent event) {
if (System.currentTimeMillis() - startTime <= 300) {
return false;
}
if (isViewInBounds(mView, (int) (event.getRawX()), (int) (event.getRawY()))) {
editTextReceiveFocus();
} else {
editTextDontReceiveFocus();
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
initialX = mWindowsParams.x;
initialY = mWindowsParams.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
mWindowsParams.x = initialX + (int) (event.getRawX() - initialTouchX);
mWindowsParams.y = initialY + (int) (event.getRawY() - initialTouchY);
mWindowManager.updateViewLayout(mView, mWindowsParams);
break;
}
return false;
}
});
*/
}
private boolean isViewInBounds(View view, int x, int y) {
Rect outRect = new Rect();
int[] location = new int[2];
view.getDrawingRect(outRect);
view.getLocationOnScreen(location);
outRect.offset(location[0], location[1]);
return outRect.contains(x, y);
}
private void editTextReceiveFocus() {
if (!wasInFocus) {
mWindowsParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
mWindowManager.updateViewLayout(mView, mWindowsParams);
wasInFocus = true;
}
}
private void editTextDontReceiveFocus() {
if (wasInFocus) {
mWindowsParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
mWindowManager.updateViewLayout(mView, mWindowsParams);
wasInFocus = false;
hideKeyboard(mContext, edt1);
}
}
private boolean wasInFocus = true;
private EditText edt1;
private void allAboutLayout(Intent intent) {
LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mView = layoutInflater.inflate(R.layout.ovelay_window, null);
edt1 = (EditText) mView.findViewById(R.id.edt1);
final TextView tvValue = (TextView) mView.findViewById(R.id.tvValue);
Button btnClose = (Button) mView.findViewById(R.id.btnClose);
edt1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mWindowsParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
mWindowsParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
mWindowManager.updateViewLayout(mView, mWindowsParams);
wasInFocus = true;
showSoftKeyboard(v);
}
});
edt1.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
tvValue.setText(edt1.getText());
}
@Override
public void afterTextChanged(Editable editable) {
}
});
btnClose.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopSelf();
}
});
}
private void hideKeyboard(Context context, View view) {
if (view != null) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
public void showSoftKeyboard(View view) {
if (view.requestFocus()) {
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
}
}

@ -1,8 +1,19 @@
package com.xypower.mpmaster;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.StrictMode;
import android.text.TextUtils;
import com.xypower.common.MicroPhotoContext;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
@ -10,5 +21,41 @@ public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
// 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");
actionBar.setTitle(actionBar.getTitle().toString() + " v" + MicroPhotoContext.getVersionName(getApplicationContext()) + " " + sdf.format(date));
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
startMicroPhotoService(getApplicationContext());
}
public static void startMicroPhotoService(Context context) {
MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getAppConfig(context.getApplicationContext());
if (TextUtils.isEmpty(appConfig.cmdid) || TextUtils.isEmpty(appConfig.server) || appConfig.port == 0) {
return;
}
Intent intent = new Intent(context, MpMasterService.class);
intent.setAction(MpMasterService.ACTION_START);
intent.putExtra("cmdid", appConfig.cmdid);
intent.putExtra("server", appConfig.server);
intent.putExtra("port", appConfig.port);
intent.putExtra("protocol", appConfig.protocol);
intent.putExtra("networkProtocol", appConfig.networkProtocol);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
}
}

@ -1,16 +0,0 @@
package com.xypower.mpmaster;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MicroPhotoService extends Service {
public MicroPhotoService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}

@ -0,0 +1,607 @@
package com.xypower.mpmaster;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.SystemClock;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
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.MicroPhotoContext;
import java.io.File;
import java.net.InetAddress;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MpMasterService extends Service {
public static final String TAG = "MpMaster";
public static final int MSG_WHAT_LOG = 10;
public final static int MSG_WHAT_NETWORK_CHANGE = 20;
public final static int MSG_WHAT_SERVICE_STATUS_CHANGE = 30;
public final static int MSG_WHAT_SENDING_HB = 40;
public final static int MSG_WHAT_MAX = 1000;
private static final String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver";
public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503;
// public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 0;
public static final String ACTION_MSG_BROADCAST = "ACT_MSG_BROADCAST";
public static final String ACTION_START = "ACT_START";
public static final String ACTION_STOP = "ACT_STOP";
public static final String ACTION_MAIN = "ACT_MAIN";
private static final String ACTION_HEARTBEAT = "ACT_HB";
private static final String ACTION_TAKE_PHOTO = "ACT_TP";
private static final String ACTION_TAKE_PHOTO_MANUALLY = "ACT_TP_M";
private static final String ACTION_TIMEOUT = "ACT_TIMEOUT";
private static final String EXTRA_PARAM_CHANNEL = "Channel";
private static final String EXTRA_PARAM_PRESET = "Preset";
private static final String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo";
private static final String EXTRA_PARAM_SCHEDULES = "Schedules";
private static final String EXTRA_PARAM_SCHEDULE = "Schedule_";
private static final String EXTRA_PARAM_TIME = "Time";
// private static String EXTRA_PARAM_FILENAME = "FileName";
private static final String EXTRA_PARAM_TIMER_UID = "TimerUid";
// private static String EXTRA_PARAM_TIMER_TYPE = "TimerType";
private static final String EXTRA_PARAM_TIMEOUT = "Timeout";
private static final String EXTRA_PARAM_TIMES = "Times";
private static final String EXTRA_PARAM_ELASPED_TIMES = "ElapsedTimes";
private static final String FOREGROUND_CHANNEL_ID = "foreground_channel_id";
public static class STATE_SERVICE {
public static final int CONNECTED = 10;
public static final int NOT_CONNECTED = 0;
}
private static int mStateService = STATE_SERVICE.NOT_CONNECTED;
private String mCmdid = "";
private NotificationManager mNotificationManager;
private int mHeartbeatDuration = 600000; // 10m = 10 * 60 * 1000 ms
private long mNextHeartbeatTime = 0;
private final Map<Long, PendingIntent> mTimers = new HashMap<>();
protected long mNativeHandle = 0;
private AlarmReceiver mAlarmReceiver = null;
private ScreenActionReceiver mScreenaAtionReceiver = null;
private ServiceHandler mHander = null;
private Messenger mMessenger = null;
private String mModelName = null;
public MpMasterService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
mHander = new ServiceHandler();
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mStateService = STATE_SERVICE.NOT_CONNECTED;
mScreenaAtionReceiver = new ScreenActionReceiver();
// 注册广播接受者
{
mAlarmReceiver = new AlarmReceiver(this);
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO);
intentFilter.addAction(ACTION_TIMEOUT);
intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY);
intentFilter.addAction(ACTION_MSG_BROADCAST);
registerReceiver(mAlarmReceiver, intentFilter);
}
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
registerHeartbeatTimer();
}
@Override
public void onDestroy() {
mStateService = STATE_SERVICE.NOT_CONNECTED;
Log.w(TAG, "MicroPhotoService::onDestroy called");
unregisterReceiver(mAlarmReceiver);
unregisterReceiver(mScreenaAtionReceiver);
super.onDestroy();
}
public static class ServiceHandler extends Handler {
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
// Log.i("life", "MyHandler----dispatchMessage");
// Log.i("life", Thread.currentThread().getName());
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// Log.i("life", "MyHandler----handleMessage");
}
}
public String getCmdid() {
return mCmdid;
}
public static void sendMessage(Context context, int what, int data) {
Intent intent = new Intent(ACTION_MSG_BROADCAST);
intent.putExtra("what", what);
intent.putExtra("data", data);
intent.setPackage(context.getPackageName());
String typeName = AlarmReceiver.class.getTypeName();
intent.setComponent( new ComponentName(context.getPackageName(), AlarmReceiver.class.getTypeName()) );
context.sendBroadcast(intent);
}
public static class AlarmReceiver extends BroadcastReceiver {
private MpMasterService mService;
public AlarmReceiver() {
mService = null;
}
public AlarmReceiver(MpMasterService service) {
mService = service;
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.equals(ACTION_HEARTBEAT, action)) {
Log.i(TAG, "HB Timer Fired ACTION=" + action);
mService.registerHeartbeatTimer();
String cmdid = mService.getCmdid();
if (!TextUtils.isEmpty(cmdid)) {
AppMaster appMaster = new AppMaster(mService, cmdid);
appMaster.start();
}
} else if (TextUtils.equals(ACTION_MSG_BROADCAST, action)) {
int what = intent.getIntExtra("what", 0);
int data = intent.getIntExtra("data", 0);
if (what == MSG_WHAT_SENDING_HB) {
// mService.sendHeartbeat(mService.mNativeHandle);
}
}
}
}
private void registerHeartbeatTimer(int duration) {
int orgHeartbeatDuration = mHeartbeatDuration;
mHeartbeatDuration = duration;
if (orgHeartbeatDuration == 0) {
registerHeartbeatTimer();
}
}
private void registerHeartbeatTimer() {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_HEARTBEAT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + mHeartbeatDuration, pendingIntent);
mNextHeartbeatTime = System.currentTimeMillis() + mHeartbeatDuration;
// alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent);
}
private static void registerPhotoTimer(Context context, int channel, int preset, long ts, long timeout, List<Long> schedules) {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TAKE_PHOTO);
int cnt = schedules.size();
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULES, cnt);
String channelStr = "";
for (int idx = 0; idx < cnt; idx++) {
long val = schedules.get(idx).longValue();
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue());
channelStr += "CH=" + ((val & 0XFF0000) >> 16) + "-PR=" + ((val & 0XFF00) >> 8) + " ";
}
alarmIntent.putExtra(EXTRA_PARAM_TIME, ts);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
long currentTimeMillis = System.currentTimeMillis();
Date date = new Date(currentTimeMillis + timeout);
String dateStr = (String) DateFormat.format("MM-dd kk:mm:ss", date);
Log.d(TAG, "PhotoTimer Reg: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " Channels=" + channelStr);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
}
private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List<Long> schedules) {
registerPhotoTimer(this.getApplicationContext(), channel, preset, ts, timeout, schedules);
}
// private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>();
public boolean registerTimer(long uid, int timeout, long times) {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TIMEOUT);
alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid);
alarmIntent.putExtra(EXTRA_PARAM_TIMEOUT, timeout);
alarmIntent.putExtra(EXTRA_PARAM_TIMES, times);
alarmIntent.putExtra(EXTRA_PARAM_ELASPED_TIMES, 0L);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mTimers.put(Long.valueOf(uid), pendingIntent);
return registerTimer(pendingIntent, uid, timeout);
}
public boolean registerTimer(PendingIntent pendingIntent, long uid, int timeout) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + timeout, pendingIntent);
Log.i(TAG, "RegTimer:" + uid + " timeout=" + timeout);
return true;
}
public boolean unregisterTimer(long uid) {
Long uidObj = Long.valueOf(uid);
PendingIntent pendingIntent = mTimers.get(uidObj);
if (pendingIntent != null) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
mTimers.remove(uidObj);
Log.i(TAG, "UnregTimer:" + uid);
}
return true;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent == null) {
stopForeground(true);
stopSelf();
return START_NOT_STICKY;
}
// if user starts the service
switch (intent.getAction()) {
case ACTION_START:
Log.d(TAG, "Received user starts foreground intent");
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
connect();
registerReceiver(mScreenaAtionReceiver, mScreenaAtionReceiver.getFilter());
if (intent.hasExtra("messenger")) {
mMessenger = intent.getParcelableExtra("messenger");
}
String appPath = MicroPhotoContext.buildAppDir(this.getApplicationContext());
String server = intent.getStringExtra("server");
int port = intent.getIntExtra("port", 0);
String cmdid = intent.getStringExtra("cmdid");
int protocol = intent.getIntExtra("protocol", 0);
int networkProtocol = intent.getIntExtra("networkProtocol", 0);
if (!InetAddressUtils.isIPv4Address(server) && !InetAddressUtils.isIPv6Address(server)) {
// It is a domain
InetAddress addr = null;
try {
addr = InetAddress.getByName(server);
} catch (Exception e) {
e.printStackTrace();
}
if (addr != null) {
server = addr.getHostAddress();
}
}
Log.i(TAG, "AppPath=" + appPath + " Server=" + server + ":" + port + " cmdid=" + cmdid + " Protocol=" + protocol + " Network=" + networkProtocol);
mCmdid = cmdid;
registerHeartbeatTimer();
AppMaster appMaster = new AppMaster(this, cmdid);
appMaster.start();
break;
case ACTION_STOP:
unregisterReceiver(mScreenaAtionReceiver);
stopForeground(true);
stopSelf();
break;
default:
stopForeground(true);
stopSelf();
}
return START_NOT_STICKY;
}
private void connect() {
// after 10 seconds its connected
mHander.postDelayed(
new Runnable() {
public void run() {
Log.d(TAG, "Bluetooth Low Energy device is connected!!");
Toast.makeText(getApplicationContext(), "Connected!", Toast.LENGTH_SHORT).show();
mStateService = STATE_SERVICE.CONNECTED;
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
}
}, 10000);
}
private Notification prepareNotification() {
// handle build version above android oreo
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O &&
mNotificationManager.getNotificationChannel(FOREGROUND_CHANNEL_ID) == null) {
CharSequence name = getString(R.string.text_name_notification);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(FOREGROUND_CHANNEL_ID, name, importance);
channel.enableVibration(false);
mNotificationManager.createNotificationChannel(channel);
}
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(ACTION_MAIN);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// if min sdk goes below honeycomb
/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
} else {
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}*/
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// make a stop intent
Intent stopIntent = new Intent(this, MpMasterService.class);
stopIntent.setAction(ACTION_STOP);
PendingIntent pendingStopIntent = PendingIntent.getService(this, 0, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification);
remoteViews.setOnClickPendingIntent(R.id.btn_stop, pendingStopIntent);
// if it is connected
switch (mStateService) {
case STATE_SERVICE.NOT_CONNECTED:
remoteViews.setTextViewText(R.id.tv_state, "DISCONNECTED");
break;
case STATE_SERVICE.CONNECTED:
remoteViews.setTextViewText(R.id.tv_state, "CONNECTED");
break;
}
// notification builder
NotificationCompat.Builder notificationBuilder;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notificationBuilder = new NotificationCompat.Builder(this, FOREGROUND_CHANNEL_ID);
} else {
notificationBuilder = new NotificationCompat.Builder(this);
}
notificationBuilder
.setContent(remoteViews)
.setSmallIcon(R.mipmap.ic_launcher)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setOnlyAlertOnce(true)
.setOngoing(true)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
}
return notificationBuilder.build();
}
public boolean updateTime(long timeInMillis) {
try {
SysApi.setSystemTime(getApplicationContext(), timeInMillis);
} catch (Exception ex) {
}
return true;
}
public void downloadAndInstall(final String url) {
final Context context = getApplicationContext();
final String tempPath = MicroPhotoContext.buildAppDir(context) + File.separator + "tmp";
File file = new File(tempPath);
file.mkdirs();
final String filePath = tempPath + File.separator + "mp.apk";
Thread th =new Thread(new Runnable() {
@Override
public void run() {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "com.xinyingpower.microphoto:Upgrader");
FileDownloader fd = new FileDownloader();
fd.download(url, filePath);
SysApi.installApk(context, filePath, context.getPackageName(), true);
try {
wl.setReferenceCounted(false);
wl.release();
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
th.start();
}
public String getSystemInfo() {
boolean isXyPlatform = mModelName.startsWith("tb8788");
StringBuilder sb = new StringBuilder();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent intent = getApplicationContext().registerReceiver(null, intentFilter);
int batteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
int isCahrging = ((batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) ||
(batteryStatus == BatteryManager.BATTERY_STATUS_FULL)) ? 1 : 0;
int level = intent.getIntExtra("level", 0); ///电池剩余电量
int scale = intent.getIntExtra("scale", 0); ///获取电池满电量数值
// intent.getStringExtra("technology"); ///获取电池技术支持
// intent.getIntExtra("status",BatteryManager.BATTERY_STATUS_UNKNOWN); ///获取电池状态
// intent.getIntExtra("plugged", 0); ///获取电源信息
// intent.getIntExtra("health",BatteryManager.BATTERY_HEALTH_UNKNOWN); ///获取电池健康度
int bv = intent.getIntExtra("voltage", 0); /// mv
int temp = intent.getIntExtra("temperature", 0); ///获取电池温度
BatteryManager manager = (BatteryManager) getSystemService(BATTERY_SERVICE);
// manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER);
int bca = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE);
int bc = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW);
level = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
float bcaVal = (bca < 0) ? ((-bca)/1000000000) : (bca / 1000000000);
sb.append("&BC=" + Float.toString(bcaVal));
sb.append("&BV=" + Float.toString(((float)bv) / 1000));
sb.append("&BP=" + level);
sb.append("&BS=" + scale);
sb.append("&CS=" + isCahrging);
ConnectivityManager cm = (ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isMetered = cm.isActiveNetworkMetered();
sb.append("&NS=" + (isMetered ? "1" : "0"));
final TelephonyManager telephonyManager = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
SignalStrength ss = telephonyManager.getSignalStrength();
// List<CellSignalStrength> css = ss.getCellSignalStrengths();
if (ss != null) {
int signalLevel = ss.getLevel();
sb.append("&Signal4G=" + signalLevel);
sb.append("&Signal2G=" + signalLevel);
sb.append("&SL=" + signalLevel);
}
if (isXyPlatform) {
java.text.DecimalFormat fmt=new java.text.DecimalFormat("0.0");
double val = SysApi.getChargingVoltage() / 200.0;
sb.append("&CV=" + fmt.format(val)); // ChargeVol *5/1000
sb.append("&CC=" + SysApi.getChargingCurrent()); // ChargeCurrent
sb.append("&CP=" + SysApi.getChargingPower()); // ChargePower:
sb.append("&CBV=" + SysApi.getChargingBusVoltage()); // ChargeBusVol
val = SysApi.getBatteryVoltage() * 3.0 / 1000.0;
sb.append("&BV=" + fmt.format(val)); // BatVol
sb.append("&BC=" + SysApi.getBatteryCurrent()); // BatCurrent
sb.append("&BP=" + SysApi.getBatteryPower()); // BattaryPower
sb.append("&BBV=" + SysApi.getBatteryBusVoltage()); // BattaryBusVol
}
// SysApi.getCpuRate();
return sb.toString();
}
public void reboot(final int rebootType) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (rebootType == 0) {
Context context = MpMasterService.this.getApplicationContext();
restartApp(context, context.getPackageName());
} else {
Log.w(TAG, "Recv REBOOT command");
SysApi.reboot(MpMasterService.this.getApplicationContext());
}
}
};
mHander.postDelayed(runnable, 1000);
}
public static void restartApp(Context context, String packageName) {
/*
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(packageName);
LaunchIntent.putExtra("noDelay", 1);
LaunchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(LaunchIntent);
}
public void selectSimCard(int num) {
SysApi.selectSimCard4Data(getApplicationContext(), num);
}
////////////////////////GPS////////////////////
}

@ -0,0 +1,81 @@
package com.xypower.mpmaster;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
public class ScreenActionReceiver extends BroadcastReceiver {
private String TAG = "ScreenActionReceiver";
@Override
public void onReceive(Context context, Intent intent) {
//LOG
StringBuilder sb = new StringBuilder();
sb.append("Action: " + intent.getAction() + "\n");
// sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");
String log = sb.toString();
Log.d(TAG, log);
Toast.makeText(context, log, Toast.LENGTH_SHORT).show();
String action = intent.getAction();
if(Intent.ACTION_SCREEN_ON.equals(action))
{
Log.d(TAG, "screen is on...");
Toast.makeText(context,"screen ON",Toast.LENGTH_SHORT);
//Run the locker
context.startService(new Intent(context, FloatingWindow.class));
}
else if(Intent.ACTION_SCREEN_OFF.equals(action))
{
Log.d(TAG, "screen is off...");
Toast.makeText(context,"screen OFF",Toast.LENGTH_SHORT);
}
else if(Intent.ACTION_USER_PRESENT.equals(action))
{
Log.d(TAG, "screen is unlock...");
Toast.makeText(context,"screen UNLOCK",Toast.LENGTH_SHORT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, FloatingWindow.class));
} else {
context.startService(new Intent(context, FloatingWindow.class));
}
}
else if(Intent.ACTION_BOOT_COMPLETED.equals(action)){
Log.d(TAG, "boot completed...");
Toast.makeText(context,"BOOTED..",Toast.LENGTH_SHORT);
//Run the locker
/* Intent i = new Intent(context, FloatingWindow.class);
context.startService(i);
*/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, FloatingWindow.class));
} else {
context.startService(new Intent(context, FloatingWindow.class));
}
}
}
public IntentFilter getFilter(){
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
return filter;
}
}

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:weightSum="4">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:gravity="center">
<TextView
android:id="@+id/tv_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="STATES"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center">
<Button
android:id="@+id/btn_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="STOP"
android:textSize="13sp" />
</LinearLayout>
</LinearLayout>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:background="#548F32"
tools:context=".MainActivity">
<EditText
android:id="@+id/edt1"
android:hint="Type here"
android:layout_toLeftOf="@+id/btnClose"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Close"
android:layout_alignParentRight="true"
android:id="@+id/btnClose"
/>
<TextView
android:id="@+id/tvValue"
android:layout_below="@+id/edt1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
</RelativeLayout>

@ -0,0 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

@ -1,3 +1,5 @@
<resources>
<string name="app_name">MpMaster</string>
<string name="text_name_notification">Notification Name</string>
</resources>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
Loading…
Cancel
Save