diff --git a/app/build.gradle b/app/build.gradle
index 5abb04aa..2ece8f9b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -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'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 38cf727b..6e39e421 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -25,6 +25,7 @@
+
@@ -95,7 +96,7 @@
-
+
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 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() {
diff --git a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java
index 8bd753ee..b34852ee 100644
--- a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java
+++ b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java
@@ -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 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) {
- wl = mWakeLocks.get(name);
- mWakeLocks.remove(name);
+ try {
+ wl = mWakeLocks.get(name);
+ mWakeLocks.remove(name);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
}
if (wl != null) {
Log.i(TAG, "Release wakelock:" + name);
- wl.release();
+ 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);
- wl.release();
+ try {
+ wl.setReferenceCounted(false);
+ wl.release();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
}
});
th.start();
diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml
index 63e5a89c..97480e92 100644
--- a/app/src/main/res/layout-land/activity_main.xml
+++ b/app/src/main/res/layout-land/activity_main.xml
@@ -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="录制视频结束" />
+ app:layout_constraintEnd_toStartOf="@+id/logs"
+ app:layout_constraintTop_toBottomOf="@+id/btnSendHb" />
- 16dp
- 16dp
+ 8dp
+ 8dp
+ 4dp
+ 4dp
+ 8dp
+ 8dp
diff --git a/common/src/main/java/com/xypower/common/MicroPhotoContext.java b/common/src/main/java/com/xypower/common/MicroPhotoContext.java
index 31b6ffdc..d9386136 100644
--- a/common/src/main/java/com/xypower/common/MicroPhotoContext.java
+++ b/common/src/main/java/com/xypower/common/MicroPhotoContext.java
@@ -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() + "/");
+ 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;
+ }
+ }
+ 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());
- if (!path.exists() && !path.mkdirs()) {
- return null;
+ 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) {
+ }
+
+ }
}
- String p = path.getAbsolutePath();
- if (!p.endsWith(File.separator)) {
- p += File.separator;
+ }
+
+ public static String getVersionName(Context context) {
+ String verName = "";
+ try {
+ verName = context.getPackageManager().
+ getPackageInfo(context.getPackageName(), 0).versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
}
- return p;
+ 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;
}
}
diff --git a/mpmaster/build.gradle b/mpmaster/build.gradle
index f2f1953f..c95a6f9e 100644
--- a/mpmaster/build.gradle
+++ b/mpmaster/build.gradle
@@ -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"
}
diff --git a/mpmaster/src/main/AndroidManifest.xml b/mpmaster/src/main/AndroidManifest.xml
index 2d6bde42..79d1b128 100644
--- a/mpmaster/src/main/AndroidManifest.xml
+++ b/mpmaster/src/main/AndroidManifest.xml
@@ -3,21 +3,78 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.xypower.mpmaster">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tools:targetApi="28">
diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/AppMaster.java b/mpmaster/src/main/java/com/xypower/mpmaster/AppMaster.java
index 9f50428f..afa3c935 100644
--- a/mpmaster/src/main/java/com/xypower/mpmaster/AppMaster.java
+++ b/mpmaster/src/main/java/com/xypower/mpmaster/AppMaster.java
@@ -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) {
diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/FloatingWindow.java b/mpmaster/src/main/java/com/xypower/mpmaster/FloatingWindow.java
new file mode 100644
index 00000000..1bb2e569
--- /dev/null
+++ b/mpmaster/src/main/java/com/xypower/mpmaster/FloatingWindow.java
@@ -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);
+ }
+ }
+
+}
diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java b/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java
index 9ffe7744..a7a980d3 100644
--- a/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java
+++ b/mpmaster/src/main/java/com/xypower/mpmaster/MainActivity.java
@@ -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);
+ }
}
}
\ No newline at end of file
diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/MicroPhotoService.java b/mpmaster/src/main/java/com/xypower/mpmaster/MicroPhotoService.java
deleted file mode 100644
index aff437a5..00000000
--- a/mpmaster/src/main/java/com/xypower/mpmaster/MicroPhotoService.java
+++ /dev/null
@@ -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");
- }
-}
\ No newline at end of file
diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java b/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java
new file mode 100644
index 00000000..ff124c35
--- /dev/null
+++ b/mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java
@@ -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 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 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 schedules) {
+
+ registerPhotoTimer(this.getApplicationContext(), channel, preset, ts, timeout, schedules);
+ }
+
+ // private HashMap mTimers = new HashMap();
+ 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 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////////////////////
+}
\ No newline at end of file
diff --git a/mpmaster/src/main/java/com/xypower/mpmaster/ScreenActionReceiver.java b/mpmaster/src/main/java/com/xypower/mpmaster/ScreenActionReceiver.java
new file mode 100644
index 00000000..a0d9cc0c
--- /dev/null
+++ b/mpmaster/src/main/java/com/xypower/mpmaster/ScreenActionReceiver.java
@@ -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;
+ }
+
+}
\ No newline at end of file
diff --git a/mpmaster/src/main/res/layout/notification.xml b/mpmaster/src/main/res/layout/notification.xml
new file mode 100644
index 00000000..3f002ac8
--- /dev/null
+++ b/mpmaster/src/main/res/layout/notification.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mpmaster/src/main/res/layout/ovelay_window.xml b/mpmaster/src/main/res/layout/ovelay_window.xml
new file mode 100644
index 00000000..c7c834e1
--- /dev/null
+++ b/mpmaster/src/main/res/layout/ovelay_window.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
diff --git a/mpmaster/src/main/res/values/dimens.xml b/mpmaster/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..47c82246
--- /dev/null
+++ b/mpmaster/src/main/res/values/dimens.xml
@@ -0,0 +1,5 @@
+
+
+ 16dp
+ 16dp
+
diff --git a/mpmaster/src/main/res/values/strings.xml b/mpmaster/src/main/res/values/strings.xml
index 2b4e2255..e68d2c7a 100644
--- a/mpmaster/src/main/res/values/strings.xml
+++ b/mpmaster/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
MpMaster
+ Notification Name
+
\ No newline at end of file
diff --git a/mpmaster/src/main/res/xml/network_security_config.xml b/mpmaster/src/main/res/xml/network_security_config.xml
new file mode 100644
index 00000000..dca93c07
--- /dev/null
+++ b/mpmaster/src/main/res/xml/network_security_config.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file