From 55bdaa9baee19e614c1c21806dcac7e58e2a9602 Mon Sep 17 00:00:00 2001 From: BlueMatthew Date: Sat, 23 Dec 2023 13:55:39 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=90=E7=BB=B4APP=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 8 +- app/src/main/AndroidManifest.xml | 3 +- .../java/com/xypower/mpapp/AppMaster.java | 12 +- .../xypower/mpapp/BootBroadcastReceiver.java | 5 +- .../java/com/xypower/mpapp/MainActivity.java | 197 +----- .../com/xypower/mpapp/MicroPhotoService.java | 73 ++- .../main/res/layout-land/activity_main.xml | 13 +- app/src/main/res/layout/activity_main.xml | 4 +- app/src/main/res/values/dimens.xml | 8 +- .../com/xypower/common/MicroPhotoContext.java | 185 +++++- mpmaster/build.gradle | 17 +- mpmaster/src/main/AndroidManifest.xml | 63 +- .../java/com/xypower/mpmaster/AppMaster.java | 5 +- .../com/xypower/mpmaster/FloatingWindow.java | 222 +++++++ .../com/xypower/mpmaster/MainActivity.java | 47 ++ .../xypower/mpmaster/MicroPhotoService.java | 16 - .../com/xypower/mpmaster/MpMasterService.java | 607 ++++++++++++++++++ .../mpmaster/ScreenActionReceiver.java | 81 +++ mpmaster/src/main/res/layout/notification.xml | 36 ++ .../src/main/res/layout/ovelay_window.xml | 34 + mpmaster/src/main/res/values/dimens.xml | 5 + mpmaster/src/main/res/values/strings.xml | 2 + .../main/res/xml/network_security_config.xml | 4 + 23 files changed, 1401 insertions(+), 246 deletions(-) create mode 100644 mpmaster/src/main/java/com/xypower/mpmaster/FloatingWindow.java delete mode 100644 mpmaster/src/main/java/com/xypower/mpmaster/MicroPhotoService.java create mode 100644 mpmaster/src/main/java/com/xypower/mpmaster/MpMasterService.java create mode 100644 mpmaster/src/main/java/com/xypower/mpmaster/ScreenActionReceiver.java create mode 100644 mpmaster/src/main/res/layout/notification.xml create mode 100644 mpmaster/src/main/res/layout/ovelay_window.xml create mode 100644 mpmaster/src/main/res/values/dimens.xml create mode 100644 mpmaster/src/main/res/xml/network_security_config.xml 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 @@ + + + + + + + + + + +