Compare commits

...

27 Commits
lowmem ... main

Author SHA1 Message Date
Matthew dcd1d20a75 先移除fps的设置 2 days ago
Matthew f9b79e67fd Update version to 1.3.196
Based Core Version to 1.4.106
5 days ago
Matthew 024d7f73b8 Update MpMaster version to 1.1.36 5 days ago
Matthew 476fa0ab7c 优化代码 6 days ago
Matthew 9ea9043a0e 优化代码 6 days ago
Matthew 8acd884797 改成常量 6 days ago
Matthew bbcd2691ed 增加flag 6 days ago
Matthew c65ffab9dd 加注释 6 days ago
Matthew 99d08c30ef 增加异常捕获 6 days ago
Matthew a38e3801ae 对于旧版本,直接注册重启设备的延迟广播来保活 6 days ago
Matthew a9ac0743f7 优化服务的返回值 6 days ago
Matthew a7c4356d93 移除不需要的代码和功能 6 days ago
Matthew 2baf96fe67 移除不需要的代码和功能 6 days ago
Matthew 913747e6c3 Update version to 1.3.195
Based Core Version to 1.4.105
6 days ago
Matthew 0b1aa8a13a Update version to 1.3.194
Based Core Version to 1.4.104
1 week ago
Matthew b5aec7ae17 增加清除缓存的拍照计划功能 1 week ago
Matthew 6f3cae9d02 根据新的接口调整实现 1 week ago
Matthew 7a67a142cb Merge branch 'main' of http://61.169.135.146:41230/xymp/TermApp 1 week ago
XI.CHEN 0a6850d92b 调整名字 1 week ago
Matthew 42dab55bc4 Merge branch 'main' of http://61.169.135.146:41230/xymp/TermApp 1 week ago
Matthew 662d3307b0 Update version to 1.3.193
Based Core Version to 1.4.103
1 week ago
XI.CHEN 2b9c1feae5 增加查询当日流量 1 week ago
Matthew aa04fca845 Update version to 1.3.192
Based Core Version to 1.4.101
1 week ago
Matthew a72118a5a6 优化回车换行的处理 1 week ago
Matthew d50b21d0d6 Update version to 1.3.191
Based Core Version to 1.4.101
1 week ago
Matthew 6255fa932c 增加最小fps控制 1 week ago
Matthew 8aec5f30ef 处理资源未释放的问题 2 weeks ago

@ -5,7 +5,7 @@ plugins {
// 10,00,000 major-minor-build
def AppMajorVersion = 1
def AppMinorVersion = 3
def AppBuildNumber = 190
def AppBuildNumber = 196
def AppVersionName = AppMajorVersion + "." + AppMinorVersion + "." + AppBuildNumber
def AppVersionCode = AppMajorVersion * 100000 + AppMinorVersion * 1000 + AppBuildNumber

@ -174,8 +174,6 @@
<category android:name="android.intent.category.default" />
</intent-filter>
</service>
<service android:name=".FloatingWindow" />
<receiver
android:name=".MicroPhotoService$AlarmReceiver"
android:exported="true" >
@ -193,16 +191,7 @@
</intent-filter>
</receiver>
<receiver android:name=".NetworkChangedReceiver" />
<receiver
android:name=".ScreenActionReceiver"
android:exported="true">
<intent-filter android:priority="90000">
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.USER_UNLOCKED" />
</intent-filter>
</receiver>
<receiver
android:name="com.xypower.common.UpdateReceiver"
android:enabled="true"

@ -967,19 +967,21 @@ Java_com_xypower_mpapp_MicroPhotoService_recordingFinished(
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xypower_mpapp_MicroPhotoService_reloadConfigs(
JNIEnv* env,
jobject pThis, jlong handler) {
jobject pThis, jlong handler, jint channelToClean) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return JNI_FALSE;
}
if (channelToClean != -1)
{
pTerminal->CleanCaptureSchedules((uint32_t)((int)channelToClean));
}
bool res = pTerminal->LoadAppConfigs(true);
return res ? JNI_TRUE : JNI_FALSE;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xypower_mpapp_MicroPhotoService_sendExternalPhoto(
JNIEnv* env, jclass cls, jlong handler, jstring path, jlong photoInfo) {

@ -1073,7 +1073,7 @@ bool CPhoneDevice::QuerySystemProperties(std::map<std::string, std::string>& pro
{
it->second = std::to_string((m_signalLevel >> 8));
}
else if ((it->first == (PROP_MOBILE_FLOW_TX)) || (it->first == (PROP_MOBILE_FLOW_RX)))
else if ((it->first == (PROP_MOBILE_FLOW_TX)) || (it->first == (PROP_MOBILE_FLOW_RX))|| (it->first == (PROP_MOBILE_FLOW_TODAY_TX))|| (it->first == (PROP_MOBILE_FLOW_TODAY_RX)))
{
if (flowInfo.empty())
{
@ -1595,7 +1595,7 @@ IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, uns
return uid;
}
bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr)
bool CPhoneDevice::TakePhotoWithNetCamera(const IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, const std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr)
{
// AutoEnv autoEnv(pThis->m_vm);
time_t ts = time(NULL);
@ -1721,15 +1721,13 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
}
}
localPhotoInfo.photoTime = takingTime;
// Notify to take next photo
TakePhotoCb(1, localPhotoInfo, "", takingTime);
#ifdef _DEBUG
// cv::imwrite("/sdcard/com.xypower.mpapp/tmp/netimg2.jpg", rgb);
#endif
netCaptureResult = PostProcessPhoto(localPhotoInfo, osds, path, "", rgb);
netCaptureResult = PostProcessPhoto(localPhotoInfo, osds, path, "", rgb, takingTime);
}
else
{
@ -1742,7 +1740,7 @@ bool CPhoneDevice::TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
}
bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr)
bool CPhoneDevice::TakeVideoWithNetCamera(const IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, const std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr)
{
// AutoEnv autoEnv(pThis->m_vm);
time_t ts = time(NULL);
@ -1794,7 +1792,7 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
// strcpy(netPhotoInfo.interface, "eth0");
localPhotoInfo.photoTime = time(NULL);
time_t photoTime = time(NULL);
std::string tmpFile = m_appPath + (APP_PATH_TMP DIR_SEP_STR) + std::to_string(localPhotoInfo.photoId) + ".mp4";
// RTSPToMP4 dumper(netPhotoInfo.url, tmpFile.c_str(), localPhotoInfo.duration * 1000);
// dumper.start();
@ -1814,12 +1812,12 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
ethernetPowerCtrl.reset();
XYLOG(XYLOG_SEVERITY_DEBUG, "Ethernet Power OFF");
std::string fullPath = endsWith(mPath, ".mp4") ? mPath : (mPath + CTerminal::BuildPhotoFileName(mPhotoInfo));
std::string fullPath = endsWith(mPath, ".mp4") ? mPath : (mPath + CTerminal::BuildPhotoFileName(mPhotoInfo, photoTime));
if (existsFile(tmpFile))
{
std::rename(tmpFile.c_str(), fullPath.c_str());
TakePhotoCb(3, localPhotoInfo, fullPath, localPhotoInfo.photoTime);
TakePhotoCb(3, localPhotoInfo, fullPath, photoTime);
}
else
{
@ -1837,7 +1835,7 @@ bool CPhoneDevice::TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, c
return true;
}
bool CPhoneDevice::StartPushStreaming(IDevice::PHOTO_INFO& photoInfo, const std::string& url, std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr)
bool CPhoneDevice::StartPushStreaming(const IDevice::PHOTO_INFO& photoInfo, const std::string& url, const std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr)
{
if (photoInfo.mediaType == XY_MEDIA_TYPE_STREAM)
{
@ -2051,6 +2049,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
params.wait3ALocked = mPhotoInfo.wait3ALocked;
params.customHdr = mPhotoInfo.customHdr;
params.hdrStep = mPhotoInfo.hdrStep;
params.minFps = mPhotoInfo.minFps;
params.burstRawCapture = mPhotoInfo.usingRawFormat;
params.burstCaptures = mPhotoInfo.burstCaptures;
if (params.requestTemplate <= 0 || params.requestTemplate > 5)
@ -2121,7 +2120,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
osds.swap(mOsds);
IDevice::PHOTO_INFO localPhotoInfo = mPhotoInfo;
std::thread t([localPhotoInfo, path, pThis, osds, powerCtrlPtr]() mutable
std::thread t([localPhotoInfo, path, pThis, osds, powerCtrlPtr]()
{
uint32_t waitTime = localPhotoInfo.selfTestingTime;
XYLOG(XYLOG_SEVERITY_INFO, "Camera is SelfTesting Time=%u s", waitTime);
@ -2147,7 +2146,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
vector<IDevice::OSD_INFO> osds;
osds.swap(mOsds);
std::thread t([localPhotoInfo, param, pThis, path, osds, wid_serial]() mutable
std::thread t([localPhotoInfo, param, pThis, path, osds, wid_serial]()
{
time_t ts = time(NULL);
if(localPhotoInfo.scheduleTime != 0)
@ -2191,13 +2190,12 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
if(photo.state == 5)
{
XYLOG(XYLOG_SEVERITY_INFO,"Get Serials Photo, PhotoID = %s", photo.photoname);
localPhotoInfo.photoTime = takingTime;
cv::Mat img = cv::imread(photo.photoname, cv::IMREAD_COLOR);
if (!img.empty())
{
int result = std::remove(photo.photoname);
pThis->TakePhotoCb(1, localPhotoInfo, "", takingTime, objects);
pThis->PostProcessPhoto(localPhotoInfo, osds, path, "", img);
pThis->PostProcessPhoto(localPhotoInfo, osds, path, "", img, takingTime);
}
}else
@ -2223,7 +2221,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
vector<IDevice::OSD_INFO> osds;
osds.swap(mOsds);
std::thread t([localPhotoInfo, param, pThis, path, osds, wid_serial, powerCtrlPtr]() mutable
std::thread t([localPhotoInfo, param, pThis, path, osds, wid_serial, powerCtrlPtr]()
{
uint32_t waitTime = localPhotoInfo.selfTestingTime;
if(!GpioControl::GetSelftestStatus(waitTime))
@ -2268,7 +2266,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
m_ptzController->AddPhotoCommand(localPhotoInfo, path, osds);
}else
{
std::thread t([localPhotoInfo, path, pThis, osds, powerCtrlPtr]() mutable
std::thread t([localPhotoInfo, path, pThis, osds, powerCtrlPtr]()
{
pThis->TakePhotoCb(1, localPhotoInfo, "", 0);
pThis->StartPushStreaming(localPhotoInfo, path, osds, powerCtrlPtr);
@ -2288,7 +2286,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
GetPhotoSerialsParamCb(param);
vector<IDevice::OSD_INFO> osds;
osds.swap(mOsds);
std::thread t([localPhotoInfo, param, pThis, path, osds, wid_serial, powerCtrlPtr]() mutable
std::thread t([localPhotoInfo, param, pThis, path, osds, wid_serial, powerCtrlPtr]()
{
uint32_t waitTime = localPhotoInfo.selfTestingTime;
if(!GpioControl::GetSelftestStatus(waitTime))
@ -2324,7 +2322,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
vector<IDevice::OSD_INFO> osds;
osds.swap(mOsds);
std::thread t([localPhotoInfo, pThis, path, osds, wid_serial, powerCtrlPtr]() mutable
std::thread t([localPhotoInfo, pThis, path, osds, wid_serial, powerCtrlPtr]()
{
uint32_t waitTime = localPhotoInfo.selfTestingTime;
if(!GpioControl::GetSelftestStatus(waitTime))
@ -2572,7 +2570,6 @@ bool CPhoneDevice::onOneCapture(std::shared_ptr<ACameraMetadata> characteristics
takingTime = scheduleTime + mPhotoInfo.channel * 2;
}
}
mPhotoInfo.photoTime = takingTime;
vector<IDevice::OSD_INFO> osds;
osds.swap(mOsds);
@ -2674,11 +2671,14 @@ bool CPhoneDevice::onOneCapture(std::shared_ptr<ACameraMetadata> characteristics
XYLOG(XYLOG_SEVERITY_INFO, "TP: Notofy to Take Next CUR Info: CH=%u PR=%u IMGID=%u", (uint32_t)photoInfo.channel, (uint32_t)photoInfo.preset, (uint32_t)photoInfo.photoId);
pThis->TakePhotoCb(1, photoInfo, "", takingTime);
bool res = pThis->PostProcessPhoto(photoInfo, osds, path, cameraInfo, rgb);
bool res = pThis->PostProcessPhoto(photoInfo, osds, path, cameraInfo, rgb, takingTime);
if (res)
{
// TakePhotoCb(2, photoInfo, path, takingTime);
ALOGW("Current allocated matrices %u", (uint32_t)rgb.total());
}
});
th.detach();
@ -2728,7 +2728,7 @@ bool CPhoneDevice::onBurstCapture(std::shared_ptr<ACameraMetadata> characteristi
}
CPhoneDevice* pThis = this;
std::thread th([pThis, characteristics, results, photoInfo, osds, path, pByteArrays, ldr, duration, takingTime]()mutable
std::thread th([pThis, characteristics, results, photoInfo, osds, path, pByteArrays, ldr, duration, takingTime]()
{
cv::Mat rgb;
std::string cameraInfo;
@ -3046,7 +3046,7 @@ bool CPhoneDevice::onBurstCapture(std::shared_ptr<ACameraMetadata> characteristi
}
else
{
bool res = pThis->PostProcessPhoto(photoInfo, osds, path, cameraInfo, rgb);
bool res = pThis->PostProcessPhoto(photoInfo, osds, path, cameraInfo, rgb, takingTime);
if (res)
{
// TakePhotoCb(2, photoInfo, path, takingTime);
@ -3097,7 +3097,6 @@ bool CPhoneDevice::onBurstCapture(std::shared_ptr<ACameraMetadata> characteristi
takingTime = scheduleTime + mPhotoInfo.channel * 2;
}
}
mPhotoInfo.photoTime = takingTime;
vector<IDevice::OSD_INFO> osds;
osds.swap(mOsds);
@ -3375,7 +3374,7 @@ bool CPhoneDevice::onBurstCapture(std::shared_ptr<ACameraMetadata> characteristi
}
else
{
bool res = pThis->PostProcessPhoto(photoInfo, osds, path, cameraInfo, rgb);
bool res = pThis->PostProcessPhoto(photoInfo, osds, path, cameraInfo, rgb, takingTime);
if (res)
{
// TakePhotoCb(2, photoInfo, path, takingTime);
@ -3436,7 +3435,7 @@ bool CPhoneDevice::OnImageReady(cv::Mat mat)
takingTime = scheduleTime + mPhotoInfo.channel * 2;
}
}
mPhotoInfo.photoTime = takingTime;
// mPhotoInfo.photoTime = takingTime;
int baseline = 0;
cv::Size textSize;
double height = mat.size().height;
@ -3663,7 +3662,7 @@ bool CPhoneDevice::OnImageReady(cv::Mat mat)
params.push_back((int)((uint32_t)mPhotoInfo.quality));
bool res = false;
std::string fullPath = endsWith(mPath, ".jpg") ? mPath : (mPath + CTerminal::BuildPhotoFileName(mPhotoInfo));
std::string fullPath = endsWith(mPath, ".jpg") ? mPath : (mPath + CTerminal::BuildPhotoFileName(mPhotoInfo, takingTime));
#ifdef OUTPUT_DBG_INFO
@ -3748,7 +3747,7 @@ bool CPhoneDevice::OnImageReady(cv::Mat mat)
return res;
}
bool CPhoneDevice::PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<IDevice::OSD_INFO>& osds, const std::string& path, const std::string& cameraInfo, cv::Mat mat)
bool CPhoneDevice::PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<IDevice::OSD_INFO>& osds, const std::string& path, const std::string& cameraInfo, cv::Mat mat, time_t takingTime)
{
int baseline = 0;
cv::Size textSize;
@ -3893,7 +3892,6 @@ bool CPhoneDevice::PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<ID
cv::Point rb(0 + textSize.width + 2 * ratio, lt2.y + textSize.height + 8 * ratio);
cv::Point rt(0 + textSize.width + 2 * ratio, mat.rows - fs - 20 * ratio);
if (rb.x > (int)width - 1)
{
rb.x = (int)width - 1;
@ -3973,7 +3971,7 @@ bool CPhoneDevice::PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<ID
params.push_back((int)((uint32_t)photoInfo.quality));
bool res = false;
std::string fullPath = endsWith(path, ".jpg") ? path : (path + CTerminal::BuildPhotoFileName(photoInfo));
std::string fullPath = endsWith(path, ".jpg") ? path : (path + CTerminal::BuildPhotoFileName(photoInfo, takingTime));
bool imgExisted = std::filesystem::exists(std::filesystem::path(fullPath));
if (imgExisted)
@ -4057,7 +4055,7 @@ bool CPhoneDevice::PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<ID
XYLOG(XYLOG_SEVERITY_INFO, "Succeeded to Write File: %s, FileSize=%u", fullPath.c_str() + m_appPath.size(), (uint32_t)imgFileSize);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
TakePhotoCb(res ? 2 : 0, photoInfo, fullPath, photoInfo.photoTime, objs);
TakePhotoCb(res ? 2 : 0, photoInfo, fullPath, takingTime, objs);
}
else
{
@ -4101,16 +4099,16 @@ bool CPhoneDevice::OnVideoReady(bool photoOrVideo, bool result, const char* path
{
if (photoOrVideo)
{
mPhotoInfo.photoTime = time(NULL);
time_t photoTime = time(NULL);
CPhoneCamera* pCamera = NULL;
std::vector<IDevice::RECOG_OBJECT> objs;
std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo);
std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo, photoTime);
if (result)
{
std::rename(path, fullPath.c_str());
}
TakePhotoCb(result ? 3 : 0, mPhotoInfo, fullPath, time(NULL), objs);
TakePhotoCb(result ? 3 : 0, mPhotoInfo, fullPath, photoTime, objs);
bool turnOffOtg = (mPhotoInfo.usbCamera != 0);
std::thread closeThread(&CPhoneDevice::CloseCamera2, this, pCamera, mPhotoInfo.photoId, mPhotoInfo.cameraType);
@ -4118,16 +4116,16 @@ bool CPhoneDevice::OnVideoReady(bool photoOrVideo, bool result, const char* path
}
else
{
mPhotoInfo.photoTime = time(NULL);
time_t photoTime = time(NULL);
CPhoneCamera* pCamera = NULL;
std::vector<IDevice::RECOG_OBJECT> objs;
std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo);
std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo, photoTime);
if (result)
{
std::rename(path, fullPath.c_str());
}
TakePhotoCb(result ? 3 : 0, mPhotoInfo, fullPath, time(NULL), objs);
TakePhotoCb(result ? 3 : 0, mPhotoInfo, fullPath, photoTime, objs);
bool turnOffOtg = (mPhotoInfo.usbCamera != 0);
std::thread closeThread(&CPhoneDevice::CloseCamera2, this, pCamera, mPhotoInfo.photoId, mPhotoInfo.cameraType);
@ -4372,7 +4370,7 @@ void CPhoneDevice::CameraCtrl(unsigned short waitTime, unsigned short delayTime,
CPhoneDevice *pThis = this;
string serfileStr(serfile);
std::thread ctrlThread([pThis, waitTime, delayTime, cmdidx, channel, preset, serfileStr, baud,
addr]() mutable {
addr]() {
uint64_t wid = pThis->RequestWakelock(0);
XYLOG(XYLOG_SEVERITY_INFO,"CameraCtrl Command= %d, preset = %u", cmdidx, preset);
pThis->OpenPTZSensors(waitTime);

@ -289,10 +289,10 @@ protected:
bool SendBroadcastMessage(std::string action, int value);
// bool MatchCaptureSizeRequest(ACameraManager *cameraManager, const char *selectedCameraId, unsigned int width, unsigned int height, uint32_t cameraOrientation_,
bool TakePhotoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr);
bool TakeVideoWithNetCamera(IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr);
bool StartPushStreaming(IDevice::PHOTO_INFO& localPhotoInfo, const std::string& url, std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr);
bool PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<IDevice::OSD_INFO>& osds, const std::string& path, const std::string& cameraInfo, cv::Mat mat);
bool TakePhotoWithNetCamera(const IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, const std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr);
bool TakeVideoWithNetCamera(const IDevice::PHOTO_INFO& localPhotoInfo, const std::string& path, const std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr);
bool StartPushStreaming(const IDevice::PHOTO_INFO& localPhotoInfo, const std::string& url, const std::vector<IDevice::OSD_INFO>& osds, std::shared_ptr<PowerControl> powerCtrlPtr);
bool PostProcessPhoto(const PHOTO_INFO& photoInfo, const vector<IDevice::OSD_INFO>& osds, const std::string& path, const std::string& cameraInfo, cv::Mat mat, time_t takingTime);
inline bool TakePhotoCb(int res, const IDevice::PHOTO_INFO& photoInfo, const string& path, time_t photoTime, const std::vector<IDevice::RECOG_OBJECT>& objects) const
{
if (m_listener != NULL)

@ -903,6 +903,16 @@ NdkCamera::CaptureRequest* NdkCamera::CreateRequest(bool isPreviewRequest, int32
status = ACaptureRequest_setEntry_u8(request->request, ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
if (m_params.minFps != 0)
{
int32_t fpsRange[2] = {m_params.minFps, 60};
// status = ACaptureRequest_setEntry_i32(request->request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE, 2, fpsRange);
if (status != ACAMERA_OK)
{
ALOGE("Failed to set ACAMERA_CONTROL_AE_TARGET_FPS_RANGE: %d", status);
}
}
if ((aeCompensationRange.min_ != 0 || aeCompensationRange.max_ != 0) && m_params.compensation != 0)
{
int32_t compensation = m_params.compensation;

@ -88,7 +88,8 @@ public:
unsigned int burstRawCapture : 3;
unsigned int customHdr : 1;
unsigned int hdrStep : 3;
unsigned int reserved : 11;
unsigned int minFps : 4;
unsigned int reserved : 7;
int64_t exposureTime;
unsigned int sensitivity;
int compensation;

@ -1,270 +0,0 @@
package com.xypower.mpapp;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
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;
import androidx.core.app.NotificationCompat;
public class FloatingWindow extends Service {
private static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466506;
private static final String FOREGROUND_CHANNEL_ID = "floatingwin_mpapp";
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();
final Context context = getApplicationContext();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
createNotificationChannel();
Notification notification = new NotificationCompat.Builder(context, FOREGROUND_CHANNEL_ID)
.setContentTitle("FloatingWindow")
.setContentText("App Running")
// .setSmallIcon(R.drawable.ic_notification)
.setPriority(NotificationCompat.PRIORITY_LOW)
.build();
// 启动前台服务
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, notification);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 4000);
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();
}
private void createNotificationChannel() {
// >= Android 8.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
FOREGROUND_CHANNEL_ID,
"FloatingWindow",
NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
if (manager != null) {
manager.createNotificationChannel(channel);
}
}
}
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);
}
}
}

@ -170,7 +170,6 @@ public class MicroPhotoService extends Service {
protected long mNativeHandle = 0;
private AlarmReceiver mAlarmReceiver = null;
private AlarmReceiver mLocalMsgReceiver = null;
private ScreenActionReceiver mScreenaAtionReceiver = null;
private NetworkChangedReceiver mNetworkChangedReceiver = null;
private long mGpsTimeout = 60000; // 1 minute
@ -270,6 +269,8 @@ public class MicroPhotoService extends Service {
public void onCreate() {
super.onCreate();
Log.i(TAG, "MicroPhotoService::onCreate");
Context context = getApplicationContext();
try {
if (usingEthernet()) {
@ -279,7 +280,9 @@ public class MicroPhotoService extends Service {
if (ethShellFile.exists()) {
ethShellFile.delete();
}
FilesUtils.copyAssetsFile(context, "eth.sh", ethShellFile.getAbsolutePath());
FilesUtils.copyAndNormalizeTextAssetsFile(context, "eth.sh", ethShellFile.getAbsolutePath());
// sed -i 's/\r$//' eth.sh
File ethToolFile = new File(filesDir, "ethtool");
if (ethToolFile.exists()) {
@ -318,8 +321,6 @@ public class MicroPhotoService extends Service {
ex.printStackTrace();
}
mScreenaAtionReceiver = new ScreenActionReceiver();
// 注册广播接受者
{
mAlarmReceiver = new AlarmReceiver(this);
@ -393,7 +394,6 @@ public class MicroPhotoService extends Service {
}
getApplicationContext().unregisterReceiver(mAlarmReceiver);
getApplicationContext().unregisterReceiver(mScreenaAtionReceiver);
getApplicationContext().unregisterReceiver(mNetworkChangedReceiver);
getApplicationContext().unregisterReceiver(mHeartBeatReceiver);
@ -479,7 +479,7 @@ public class MicroPhotoService extends Service {
}
private boolean isMpMasterAlive(Context context) {
if (Build.TIME < 1744905600000L) {
if (Build.TIME < MicroPhotoContext.BUILD_TIME_WO_SID_20250418) {
// 2025-04-18 old firmware
// Check Log file time
File file = new File(MicroPhotoContext.buildMasterAppDir(context) + "logs/mlog.txt");
@ -595,7 +595,7 @@ public class MicroPhotoService extends Service {
try {
boolean mpmstAlive = isMpMasterAlive(context);
if (!mpmstAlive) {
if (Build.TIME >= 1744905600000L) {
if (Build.TIME >= MicroPhotoContext.BUILD_TIME_WO_SID_20250418) {
int pid = MicroPhotoContext.getProcessIdOfService(context, MicroPhotoContext.PACKAGE_NAME_MPMASTER, MicroPhotoContext.SERVICE_NAME_MPMASTER);
if (pid != 0) {
android.os.Process.killProcess(pid);
@ -659,13 +659,18 @@ public class MicroPhotoService extends Service {
int cmd = intent.getIntExtra("cmd", 0);
mService.sendCameraCtrl(mService.mNativeHandle, channel, preset, cmd);
} else if (TextUtils.equals(ACTION_UPDATE_CONFIGS, action)) {
int restart = intent.getIntExtra("restart", 0);
final int restart = intent.getIntExtra("restart", 0);
final int channelToClean = intent.getIntExtra("channelToClean", -1);
Log.i(TAG, "UPD CFG Fired ACTION=" + action + " restart=" + restart);
new Thread(new Runnable() {
@Override
public void run() {
mService.reloadConfigs(mService.mNativeHandle, channelToClean);
if (restart != 0) {
restartSelfImpl(context, "Cfg Updated");
} else if (mService.mNativeHandle != 0) {
mService.reloadConfigs(mService.mNativeHandle);
}
}
}).start();
} else if (TextUtils.equals(ACTION_VIDEO_FINISHED, action)) {
final boolean photoOrVideo = intent.getBooleanExtra("photoOrVideo", false);
final boolean result = intent.getBooleanExtra("result", false);
@ -1057,7 +1062,6 @@ public class MicroPhotoService extends Service {
connect();
getApplicationContext().registerReceiver(mScreenaAtionReceiver, mScreenaAtionReceiver.getFilter());
if (intent.hasExtra("messenger")) {
mMessenger = intent.getParcelableExtra("messenger");
}
@ -1112,11 +1116,6 @@ public class MicroPhotoService extends Service {
break;
case ACTION_STOP:
try {
getApplicationContext().unregisterReceiver(mScreenaAtionReceiver);
} catch (Exception ex) {
}
stopForeground(true);
stopSelf();
break;
@ -1387,11 +1386,6 @@ public class MicroPhotoService extends Service {
uninit(mNativeHandle);
mNativeHandle = 0;
try {
getApplicationContext().unregisterReceiver(mScreenaAtionReceiver);
} catch (Exception ex) {
}
stopForeground(true);
stopSelf();
}
@ -1674,7 +1668,13 @@ public class MicroPhotoService extends Service {
long endTime = dt.getTime() - 1;
NetworkUtils.Usage usage = NetworkUtils.getApplicationQuerySummary(this.getApplicationContext(), startTime, endTime, getApplicationInfo().uid);
return "RX=" + Long.toString(usage.mobleRxBytes) + "&TX=" + Long.toString(usage.mobleTxBytes);
Date now = new Date();
Date todayStart = new Date(now.getYear(), now.getMonth(), now.getDate(), 0, 0, 0);
long todayStartTime = todayStart.getTime();
long todayEndTime = now.getTime();
NetworkUtils.Usage todayUsage = NetworkUtils.getApplicationQuerySummary(this.getApplicationContext(), todayStartTime, todayEndTime, getApplicationInfo().uid);
return "DRX=" + Long.toString(todayUsage.mobleRxBytes) + "&DTX=" + Long.toString(todayUsage.mobleTxBytes) + "&RX=" + Long.toString(usage.mobleRxBytes) + "&TX=" + Long.toString(usage.mobleTxBytes);
}
public boolean installApp(final String path, long delayedTime) {
@ -1829,21 +1829,28 @@ public class MicroPhotoService extends Service {
public void setStaticNetwork(String iface, String ip, String gateway, String ipPrefix, int ipPrefixLength) {
int exitValue = -1;
boolean success = false;
try {
File ethShellFile = new File(getFilesDir(), "eth.sh");
if (ethShellFile.exists()) {
Process process = Runtime.getRuntime().exec("/system/xbin/su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
Process process = null;
DataOutputStream os = null;
BufferedReader inputReader = null;
try {
process = Runtime.getRuntime().exec("/system/xbin/su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes("/system/bin/sh " + ethShellFile.getAbsolutePath() + "\n");
os.writeBytes("exit\n"); // 重要退出su shell
os.flush();
exitValue = process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
inputReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
StringBuilder error = new StringBuilder();
while ((line = reader.readLine()) != null) {
while ((line = inputReader.readLine()) != null) {
error.append(line);
error.append("\n");
}
@ -1853,6 +1860,15 @@ public class MicroPhotoService extends Service {
} else {
infoLog(error.toString());
}
} catch (Exception ex) {
} finally {
FilesUtils.closeFriendly(os);
FilesUtils.closeFriendly(inputReader);
if (process != null) {
process.destroy();
}
}
} else {
Process process = Runtime.getRuntime().exec("/system/xbin/su root");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
@ -1977,7 +1993,7 @@ cellSignalStrengthGsm.getDbm();
protected native boolean sendBasicInfo(long handler);
protected native boolean sendWorkStatus(long handler);
protected native boolean sendFault(long handler, String faultCode, String faultInfo);
protected native boolean reloadConfigs(long handler);
protected native boolean reloadConfigs(long handler, int channelToClean);
protected native void updatePosition(long handler, double lon, double lat, double radius, long ts);
protected native boolean updateEhernet(long handler, long nativeNetworkHandle, boolean available);
protected native boolean updateActiveNetwork(long handler, long nativeNetworkHandle, boolean available);

@ -1,76 +0,0 @@
package com.xypower.mpapp;
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();
try {
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));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public IntentFilter getFilter(){
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
return filter;
}
}

@ -8,6 +8,7 @@ import android.util.Log;
import org.w3c.dom.Text;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
@ -16,6 +17,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.channels.Channels;
import java.nio.channels.SeekableByteChannel;
@ -412,4 +414,59 @@ public class FilesUtils {
FilesUtils.closeFriendly(fos);
}
}
/**
* AssetsCRLFLF
*
* @param context
* @param fileName Assets
* @param destPath
*/
public static void copyAndNormalizeTextAssetsFile(Context context, String fileName, String destPath) {
InputStream inputStream = null;
BufferedReader reader = null;
BufferedWriter writer = null;
try {
inputStream = context.getAssets().open(fileName);
reader = new BufferedReader(new InputStreamReader(inputStream));
// 创建目标文件
File file = new File(destPath);
if (file.exists()) {
file.delete();
}
File parentDir = file.getParentFile();
if (parentDir != null && !parentDir.exists()) {
parentDir.mkdirs();
}
if (parentDir != null && !parentDir.canWrite()) {
Log.e("FilesUtils", "No write permission to directory: " + parentDir.getAbsolutePath());
return;
}
// 使用BufferedWriter写入文件同时处理行尾符
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
String line;
// 逐行读取并写入由BufferedWriter自动处理行尾
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine(); // 使用平台默认的换行符在Android上是LF
}
writer.flush();
Log.d("FilesUtils", "File normalized and copied successfully: " + destPath);
} catch (Exception e) {
Log.e("FilesUtils", "Error normalizing file: " + e.getMessage(), e);
} finally {
closeFriendly(reader);
closeFriendly(writer);
closeFriendly(inputStream);
}
}
}

@ -50,6 +50,8 @@ public class MicroPhotoContext {
public final static int DEFAULT_HEARTBEAT_FOR_SHARED_NW = 10; // minutes
public final static int DEFAULT_QUICK_HEARTBEAT = 60; // second
public static final long BUILD_TIME_WO_SID_20250418 = 1744905600000L;
public static class AppConfig {
public String cmdid;
public String server;

@ -4,7 +4,7 @@ plugins {
def AppMajorVersion = 1
def AppMinorVersion = 1
def AppBuildNumber = 35
def AppBuildNumber = 36
def AppVersionName = AppMajorVersion + "." + AppMinorVersion + "." + AppBuildNumber
def AppVersionCode = AppMajorVersion * 100000 + AppMinorVersion * 1000 + AppBuildNumber

@ -117,7 +117,6 @@
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

@ -1,269 +0,0 @@
package com.xypower.mpmaster;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
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;
import androidx.core.app.NotificationCompat;
public class FloatingWindow extends Service {
private static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466505;
private static final String FOREGROUND_CHANNEL_ID = "floatingwin_mpmst";
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();
final Context context = getApplicationContext();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
createNotificationChannel();
Notification notification = new NotificationCompat.Builder(context, FOREGROUND_CHANNEL_ID)
.setContentTitle("FloatingWindow")
.setContentText("App Running")
// .setSmallIcon(R.drawable.ic_notification)
.setPriority(NotificationCompat.PRIORITY_LOW)
.build();
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, notification);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, 4000);
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();
}
private void createNotificationChannel() {
// >= Android 8.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
FOREGROUND_CHANNEL_ID,
"FloatingWindow",
NotificationManager.IMPORTANCE_LOW);
NotificationManager manager = getSystemService(NotificationManager.class);
if (manager != null) {
manager.createNotificationChannel(channel);
}
}
}
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);
}
}
}

@ -114,7 +114,6 @@ public class MpMasterService extends Service {
private boolean mSyncTime = false;
private AlarmReceiver mAlarmReceiver = null;
private ScreenActionReceiver mScreenaAtionReceiver = null;
private UpdateReceiver mUpdateReceiver = null;
private Handler mHander = null;
@ -245,8 +244,6 @@ public class MpMasterService extends Service {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mStateService = STATE_SERVICE.NOT_CONNECTED;
mScreenaAtionReceiver = new ScreenActionReceiver();
// 注册广播接受者
{
mAlarmReceiver = new AlarmReceiver(this);
@ -328,7 +325,6 @@ public class MpMasterService extends Service {
logger.warning("MicroPhotoService::onDestroy called");
unregisterReceiver(mAlarmReceiver);
unregisterReceiver(mScreenaAtionReceiver);
unregisterReceiver(mUpdateReceiver);
unregisterReceiver(mSmsSnedReceiver);
@ -416,7 +412,7 @@ public class MpMasterService extends Service {
}
private boolean isMpAppAlive(Context context) {
if (Build.TIME < 1744905600000L) {
if (Build.TIME < MicroPhotoContext.BUILD_TIME_WO_SID_20250418) {
// 2025-04-18 old firmware
// Check Log file time
File file = new File(MicroPhotoContext.buildMpAppDir(context) + "logs/log.txt");
@ -875,20 +871,34 @@ public class MpMasterService extends Service {
mPreviousHeartbeatTime = triggerTime;
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent);
try {
Intent relaunchIntent = new Intent();
if (Build.TIME < MicroPhotoContext.BUILD_TIME_WO_SID_20250418) {
// Earlier than 2025-04-18
relaunchIntent.putExtra("cmd", "reboot");
} else {
relaunchIntent.putExtra("cmd", "forceLaunch");
}
relaunchIntent.putExtra("pkname", MicroPhotoContext.PACKAGE_NAME_MPMASTER);
relaunchIntent.setAction("com.xy.xsetting.action");
relaunchIntent.setPackage("com.android.systemui");
relaunchIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
// getApplicationContext().sendBroadcast(restartIntent);
long launchTs = System.currentTimeMillis() + (mHeartbeatDuration + 120) * 1000;
PendingIntent sysKAPendingIntent = PendingIntent.getBroadcast(this, BROADCAST_REQUEST_CODE_SYS_KEEPALIVE, relaunchIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, launchTs, sysKAPendingIntent);
if (Build.TIME < MicroPhotoContext.BUILD_TIME_WO_SID_20250418) {
logger.info(String.format("Register KeepAlive Reboot Clock: " + format.format(new Date(launchTs))));
} else {
logger.info(String.format("Register KeepAlive Launch Clock: " + format.format(new Date(launchTs))));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@ -896,8 +906,9 @@ public class MpMasterService extends Service {
Log.d(TAG, "MpMasterService::onStartCommand");
if (intent == null) {
Log.d(TAG, "MpMasterService::onStartCommand intent is null. Stop self");
stopForeground(true);
stopSelf();
stopSelf(startId);
return START_NOT_STICKY;
}
@ -909,8 +920,6 @@ public class MpMasterService extends Service {
connect();
registerReceiver(mScreenaAtionReceiver, mScreenaAtionReceiver.getFilter());
String appPath = MicroPhotoContext.buildAppDir(this.getApplicationContext());
String cmdid = intent.getStringExtra("cmdid");
@ -936,17 +945,15 @@ public class MpMasterService extends Service {
break;
case ACTION_STOP:
unregisterReceiver(mScreenaAtionReceiver);
stopForeground(true);
stopSelf();
stopSelf(startId);
break;
default:
stopForeground(true);
stopSelf();
}
return START_NOT_STICKY;
return START_STICKY;
}
private void connect() {
@ -1285,7 +1292,8 @@ public class MpMasterService extends Service {
}
private static void forceStopMpApp(Context context) {
if (Build.TIME < 1744905600000L) {
if (Build.TIME < MicroPhotoContext.BUILD_TIME_WO_SID_20250418) {
// 2025-04-18
SysApi.forceStopApp(context, MicroPhotoContext.PACKAGE_NAME_MPAPP);
} else {
int pid = MicroPhotoContext.getProcessIdOfService(context, MicroPhotoContext.PACKAGE_NAME_MPAPP, MicroPhotoContext.SERVICE_NAME_MPSERVICE);

@ -1,81 +0,0 @@
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;
}
}
Loading…
Cancel
Save