# Conflicts:
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/com/xinyingpower/microphoto/MainActivity.java
#	app/src/main/res/layout/activity_main.xml
serial
liuguijing 2 years ago
commit 17cf85489b

@ -2,8 +2,8 @@ plugins {
id 'com.android.application'
}
def AppVersionName = "1.0.0"
def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 0
def AppVersionName = "1.0.7"
def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 7
android {
namespace 'com.xinyingpower.microphoto'

@ -31,9 +31,8 @@
<uses-permission android:name="android.permission.DEVICE_POWER" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-feature android:name="android.hardware.camera" />

@ -34,6 +34,8 @@ set(OPENCV_EXTRA_MODULES_PATH D:/Workspace/Github/opencv_contrib/modules)
project("microphoto")
# message(FATAL_ERROR "OpenCV ${OpenCV_DIR}")
find_package(OpenCV REQUIRED core imgproc highgui)
if(OpenCV_FOUND)
include_directories(${OpenCV_INCLUDE_DIRS})
@ -281,12 +283,13 @@ add_library( # Sets the name of the library.
${TERM_CORE_ROOT}/SpecData_I1_SHX.cpp
${TERM_CORE_ROOT}/SpecData_XY.cpp
${TERM_CORE_ROOT}/SpecData_ZJ.cpp
${TERM_CORE_ROOT}/TermClient.cpp
${TERM_CORE_ROOT}/Timer.cpp
${TERM_CORE_ROOT}/TimerThread.cpp
${TERM_CORE_ROOT}/Utils.cpp
${TERM_CORE_ROOT}/Client/TerminalService.cpp
${TERM_CORE_ROOT}/Client/Terminal.cpp
${TERM_CORE_ROOT}/Client/Terminal_HN.cpp
${TERM_CORE_ROOT}/Client/Terminal_AH.cpp
${TERM_CORE_ROOT}/Client/Terminal_HEN_ZZ.cpp
${TERM_CORE_ROOT}/Client/Terminal_HEN.cpp
${TERM_CORE_ROOT}/Client/Terminal_SHX.cpp

@ -21,10 +21,7 @@
#include "Camera.h"
#include <android/log.h>
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#include <AndroidHelper.h>
CCamera::CCamera()
{

@ -1,6 +1,7 @@
#include <jni.h>
#include <string>
#include <TermClient.h>
#include <Factory.h>
#include <Client/Terminal.h>
#include "TerminalDevice.h"
#include "PhoneDevice.h"
#include "PhoneDevice2.h"
@ -15,17 +16,17 @@
#include "Camera.h"
#include "Camera2Reader.h"
bool GetJniEnv(JavaVM *vm, JNIEnv **env)
bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread)
{
bool did_attach_thread = false;
didAttachThread = false;
*env = nullptr;
// Check if the current thread is attached to the VM
auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED)
{
if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
did_attach_thread = true;
get_env_result = vm->AttachCurrentThread(env, NULL);
if (get_env_result == JNI_OK) {
didAttachThread = true;
} else {
// Failed to attach thread. Throw an exception if you want to.
}
@ -34,10 +35,9 @@ bool GetJniEnv(JavaVM *vm, JNIEnv **env)
// Unsupported JNI version. Throw an exception if you want to.
}
return did_attach_thread;
return get_env_result == JNI_OK;
}
// #include "client/linux/handler/exception_handler.h"
// #include "client/linux/handler/minidump_descriptor.h"
@ -74,7 +74,6 @@ Java_com_xinyingpower_microphoto_MainActivity_takePhoto(
unsigned char id = (unsigned char)channel - 1;
Camera2Reader *camera = new Camera2Reader(id);
const char *pathStr = env->GetStringUTFChars(path, 0);
const char *fileNameStr = env->GetStringUTFChars(fileName, 0);
@ -88,10 +87,10 @@ Java_com_xinyingpower_microphoto_MainActivity_takePhoto(
return JNI_TRUE;
}
extern "C" JNIEXPORT jboolean JNICALL
extern "C" JNIEXPORT jlong JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_init(
JNIEnv* env,
jobject pThis, jstring appPath, jstring ip, jint port, jstring cmdid) {
jobject pThis, jstring appPath, jstring ip, jint port, jstring cmdid, jint protocol) {
/*
google_breakpad::MinidumpDescriptor descriptor(".");
@ -107,35 +106,48 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
JavaVM* vm = NULL;
jint ret = env->GetJavaVM(&vm);
// const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp
CTermClient& service = CTermClient::GetService();
// CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
// CTerminalDevice* device = new CTerminalDevice(vm, pThis);
// CPhoneDevice2* device = new CPhoneDevice2(vm, pThis);
CTerminal* pTerminal = NewTerminal(GetCurrentProtocol());
CPhoneDevice* device = new CPhoneDevice(vm, pThis);
bool res = service.InitService(appPathStr, cmdidStr, ipStr, (unsigned short)port, "", device);
device->SetListener(pTerminal);
pTerminal->InitServerInfo(appPathStr, cmdidStr, ipStr, port);
pTerminal->SetPacketSize(1 * 1024); // 1K
bool res = pTerminal->Startup(device);
env->ReleaseStringUTFChars(appPath, appPathStr);
env->ReleaseStringUTFChars(ip, ipStr);
env->ReleaseStringUTFChars(cmdid, cmdidStr);
return res ? JNI_TRUE : JNI_FALSE;
if (!res)
{
delete pTerminal;
pTerminal = NULL;
}
return reinterpret_cast<jlong>(pTerminal);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto(
JNIEnv* env,
jobject pThis, jint channel, jint preset, jlong scheduleTime, jstring path, jstring fileName, jboolean sendToCma) {
jobject pThis, jlong handler, jint channel, jint preset, jlong scheduleTime, jstring path, jstring fileName, jboolean sendToCma) {
if (channel < 1 || channel > 0xFF)
{
return JNI_FALSE;
}
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return JNI_FALSE;
}
pTerminal->NotifyToTakePhoto((unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime);
pTerminal->RequestCapture((unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime);
return JNI_TRUE;
}
@ -144,9 +156,10 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto(
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat(
JNIEnv* env,
jobject pThis) {
jobject pThis,
jlong handler) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return JNI_FALSE;
@ -161,45 +174,58 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat(
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout(
JNIEnv* env,
jobject pThis, jlong uid) {
jobject pThis, jlong handler, jlong uid, jlong times) {
IDevice* dev = CTermClient::GetService().GetDevice();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
IDevice* dev = pTerminal->GetDevice();
if (dev == NULL)
{
return JNI_FALSE;
}
CPhoneDevice* phoneDevice = (CPhoneDevice *)dev;
return phoneDevice->FireTimer((IDevice::timer_uid_t)uid) ? JNI_TRUE : JNI_FALSE;
return phoneDevice->FireTimer((IDevice::timer_uid_t)uid, static_cast<unsigned long>(times)) ? JNI_TRUE : JNI_FALSE;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_uninit(
JNIEnv* env,
jobject pThis) {
jobject pThis, jlong handler) {
CTermClient::GetService().ExitService();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return JNI_FALSE;
}
pTerminal->SignalExit();
pTerminal->Shutdown();
delete pTerminal;
return JNI_TRUE;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getHeartbeatDuration(
JNIEnv* env,
jobject pThis) {
jobject pThis, jlong handler) {
// CTermClient::GetService().ExitService();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return DEFAULT_HEARTBEAT_DURATION;
}
return 60000;
return pTerminal->GetHeartbeatDuration();
}
extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
JNIEnv* env,
jobject pThis) {
jobject pThis, jlong handler) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return NULL;
@ -259,13 +285,13 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
return data;
}
/*
extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem(
JNIEnv* env,
jobject pThis) {
jobject pThis, jlong handler) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return NULL;
@ -324,3 +350,4 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem(
return data;
}
*/

@ -17,9 +17,8 @@
*/
#define LOG_TAG "CameraTestHelpers"
#include <AndroidHelper.h>
#include "PhoneDevice.h"
#include "TermClient.h"
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
@ -34,17 +33,10 @@
#include <android/log.h>
#include <sys/system_properties.h>
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define ASSERT(cond, fmt, ...) \
if (!(cond)) { \
__android_log_assert(#cond, LOG_TAG, fmt, ##__VA_ARGS__); \
}
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
#define WAKELOCK_NAME "NDK_WK_"
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
// ranges
// are normalized to eight bits.
@ -143,46 +135,73 @@ CPhoneDevice::CPhoneCamera::CPhoneCamera(CPhoneDevice* dev, int32_t width, int32
{
}
void CPhoneDevice::CPhoneCamera::on_image(const cv::Mat& rgb) const
bool CPhoneDevice::CPhoneCamera::on_image(const cv::Mat& rgb) const
{
if (m_dev != NULL)
{
m_dev->OnImageReady(rgb);
return m_dev->OnImageReady(rgb);
}
return false;
}
void CPhoneDevice::CPhoneCamera::on_error(const std::string& msg) const
{
if (m_dev != NULL)
{
m_dev->onError(msg);
}
}
CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
{
mCamera = NULL;
m_listener = NULL;
mHeartbeatStartTime = 0;
mHeartbeatDuration = 0;
m_javaService = NULL;
m_vm = vm;
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service);
mHeartbeatStartTime = 0;
mHeartbeatDuration = 0;
jclass classService = env->GetObjectClass(m_javaService);
mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JI)Z");
mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JIJ)Z");
mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V");
mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z");
mUpdateTimeMid = env->GetMethodID(classService, "updateTime", "(J)Z");
mRequestWakelockMid = env->GetMethodID(classService, "requestWakelock", "(Ljava/lang/String;J)V");
mReleaseWakelockMid = env->GetMethodID(classService, "releaseWakelock", "(Ljava/lang/String;)V");
env->DeleteLocalRef(classService);
if (attached)
if (didAttachThread)
{
vm->DetachCurrentThread();
}
m_timerUidFeed = time(NULL);
m_timerUidFeed = time(NULL) * 1000;
m_wakelockIdFeed = (unsigned long)m_timerUidFeed;
}
CPhoneDevice::~CPhoneDevice()
{
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService);
if (attached)
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
@ -198,17 +217,27 @@ bool CPhoneDevice::UpdateTime(time_t ts)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (didAttachThread)
{
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
m_vm->DetachCurrentThread();
}
return (ret == JNI_TRUE);
}
bool CPhoneDevice::UpdateSchedules()
{
return true;
}
bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
{
char value[PROP_VALUE_MAX] = { 0 };
@ -220,11 +249,9 @@ bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
__system_property_get("ro.product.model", value);
properties[PROP_MODEL] = value;
__system_property_get("ro.product.manufacturer", value);
properties[PROP_BS_MANU] = value;
properties[PROP_BS_ID] = "SHXY";
__system_property_get("ro.build.version.release", value);
@ -239,7 +266,6 @@ bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
__system_property_get("phone.imei", value);
properties[PROP_IMEI] = value;
return true;
}
@ -254,18 +280,23 @@ bool CPhoneDevice::Reboot()
return false;
}
IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout)
IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times/* = 0*/)
{
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
jboolean ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout, (jlong)times);
if (didAttachThread)
{
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
m_vm->DetachCurrentThread();
}
@ -280,12 +311,18 @@ IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigne
bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
if (didAttachThread)
{
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
m_vm->DetachCurrentThread();
}
@ -297,7 +334,67 @@ bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
return false;
}
bool CPhoneDevice::FireTimer(timer_uid_t uid)
unsigned long CPhoneDevice::RequestWakelock(unsigned long timeout)
{
unsigned long wakelockId = m_wakelockIdFeed.fetch_add(1);
std::string name = WAKELOCK_NAME;
name += to_string(wakelockId);
ALOGI("RequestWakelock=%lld",wakelockId);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
jstring jname = env->NewStringUTF(name.c_str());
jlong jtimeout = (jlong)timeout;
env->CallVoidMethod(m_javaService, mRequestWakelockMid, jname, jtimeout);
// env->ReleaseStringUTFChars(jname, name.c_str());
env->DeleteLocalRef(jname);
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return wakelockId;
}
bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock)
{
ALOGI("ReleaseWakelock=%lld", wakelock);
std::string name = WAKELOCK_NAME;
name += to_string(wakelock);
jboolean ret = JNI_FALSE;
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
jstring jname = env->NewStringUTF(name.c_str());
env->CallVoidMethod(m_javaService, mReleaseWakelockMid, jname);
env->DeleteLocalRef(jname);
// env->ReleaseStringUTFChars(jname, name.c_str());
if (didAttachThread)
{
m_vm->DetachCurrentThread();
}
return true;
}
bool CPhoneDevice::FireTimer(timer_uid_t uid, unsigned long times)
{
std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid);
if (it == mTimers.end())
@ -306,21 +403,21 @@ bool CPhoneDevice::FireTimer(timer_uid_t uid)
}
unsigned long timerType = it->second & 0xFFFFFFFF;
unsigned long times = (it->second & 0xFFFFFFFF00000000) >> 32;
times++;
unsigned long ntimes = (it->second & 0xFFFFFFFF00000000) >> 32;
ntimes++;
if (timerType != 100)
{
int aa = 0;
}
it->second = timerType | (times << 32);
it->second = timerType | (ntimes << 32);
if (m_listener == NULL)
{
return false;
}
m_listener->OnTimeout(uid, timerType, times);
m_listener->OnTimeout(uid, timerType, ntimes);
return true;
}
@ -332,10 +429,16 @@ IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, uns
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
JNIEnv* env = NULL;
bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
if (didAttachThread)
{
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
m_vm->DetachCurrentThread();
@ -346,43 +449,100 @@ IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, uns
bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path)
{
LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
if (mCamera != NULL)
{
delete mCamera;
mCamera = NULL;
}
ALOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
mPhotoInfo = photoInfo;
mPath = path;
mOsds = osds;
mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height);
mCamera->open(to_string(photoInfo.channel - 1).c_str());
if (mCamera->open(to_string(photoInfo.channel - 1).c_str()) == 0)
{
}
else
{
delete mCamera;
mCamera = NULL;
return false;
}
return true;
}
void CPhoneDevice::OnImageReady(const cv::Mat& mat) const
bool CPhoneDevice::CloseCamera()
{
if (mCamera != NULL)
{
delete mCamera;
mCamera = NULL;
}
return true;
}
bool CPhoneDevice::OnImageReady(const cv::Mat& mat) const
{
int baseline = 0;
cv::Size textSize, textSize2;
double fontScale = 1; // base 1024
double height = mat.size().height;
double width = mat.size().width;
double ratio = std::min(height / 1024, width / 1920);
fontScale = fontScale * ratio;
double thickness1 = 4 * ratio;
double thickness2 = 2 * ratio;
for (vector<OSD_INFO>::const_iterator it = mOsds.cbegin(); it != mOsds.cend(); ++it)
{
// getTextSize(value, font, scale, 1, &bottom);
textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, 1, 4, &baseline);
cv::Point pt(it->x, it->y + textSize.height);
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 0), 4,cv::LINE_AA);
textSize2 = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, 1, 2, &baseline);
textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness1, &baseline);
cv::Point pt(it->x * ratio, it->y * ratio + textSize.height);
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, fontScale, cv::Scalar(0, 0, 0), thickness1,cv::LINE_AA);
textSize2 = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness2, &baseline);
pt.y -= (textSize.height - textSize2.height) / 2;
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 255, 255), 2,cv::LINE_AA);
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, fontScale, cv::Scalar(255, 255, 255), thickness2,cv::LINE_AA);
}
vector <int> compression_params;
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
compression_params.push_back(80);
compression_params.push_back(mPhotoInfo.quality);
bool res = cv::imwrite(mPath.c_str(), mat, compression_params);
if (!std::filesystem::exists(std::filesystem::path(mPath)))
{
bool res = cv::imwrite(mPath.c_str(), mat, compression_params);
if (!res)
{
ALOGE("Failed to write photo: %s", mPath.c_str());
}
else
{
ALOGI("Succeeded to write photo: %s", mPath.c_str());
}
TakePhotoCb(res, mPhotoInfo, mPath, time(NULL));
return res;
}
else
{
ALOGI("Photo file exists: %s", mPath.c_str());
}
// mCamera->close();
// delete mCamera;
// mCamera = NULL;
return true;
}
void CPhoneDevice::onError(const std::string& msg) const
{
// XFLOG(XFLOG_SEVERITY_ERROR, "Failed to Take Photo: %s", msg.c_str());
TakePhotoCb(res, mPhotoInfo, mPath, time(NULL));
ALOGE("Failed to Take Photo: %s", msg.c_str());
delete mCamera;
mCamera = NULL;
// mCamera->close();
TakePhotoCb(false, mPhotoInfo, mPath, 0);
}
std::string CPhoneDevice::GetFileName() const

@ -11,21 +11,17 @@
#include <map>
#include <atomic>
#include <filesystem>
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraMetadataTags.h>
#include <media/NdkImageReader.h>
#include <android/log.h>
// #define LOG_TAG "native-camera2-jni"
#define PD_LOG_TAG "PhoneDev"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,PD_LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,PD_LOG_TAG,__VA_ARGS__)
#include <Client/Device.h>
#include <string>
#include "Camera2Helper.h"
#include "camera2/Camera2Helper.h"
#include "camera2/ndkcamera.h"
@ -37,14 +33,18 @@ public:
virtual void SetListener(IListener* listener);
virtual bool UpdateTime(time_t ts);
virtual bool UpdateSchedules();
virtual bool QuerySystemProperties(map<string, string>& properties);
virtual bool Reboot();
virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout);
virtual bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path);
virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout);
virtual bool CloseCamera();
virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times = 0);
virtual bool UnregisterTimer(timer_uid_t uid);
virtual unsigned long RequestWakelock(unsigned long timeout);
virtual bool ReleaseWakelock(unsigned long wakelock);
virtual bool FireTimer(timer_uid_t uid);
virtual bool FireTimer(timer_uid_t uid, unsigned long times);
bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector<uint32_t>& items);
@ -65,7 +65,8 @@ protected:
return false;
}
void OnImageReady(const cv::Mat& mat) const;
bool OnImageReady(const cv::Mat& mat) const;
void onError(const std::string& msg) const;
protected:
@ -77,18 +78,23 @@ protected:
jmethodID mUnregisterTimerMid;
jmethodID mUpdateTimeMid;
jmethodID mRequestWakelockMid;
jmethodID mReleaseWakelockMid;
std::string mPath;
IDevice::PHOTO_INFO mPhotoInfo;
vector<IDevice::OSD_INFO> mOsds;
IListener* m_listener;
atomic_ulong m_timerUidFeed;
atomic_ulong m_wakelockIdFeed;
std::map<IDevice::timer_uid_t, unsigned long> mTimers;
class CPhoneCamera : public NdkCamera {
public:
CPhoneCamera(CPhoneDevice* dev, int32_t width, int32_t height);
virtual void on_image(const cv::Mat& rgb) const;
virtual bool on_image(const cv::Mat& rgb) const;
virtual void on_error(const std::string& msg) const;
protected:
CPhoneDevice* m_dev;
@ -98,7 +104,6 @@ protected:
time_t mHeartbeatStartTime;
unsigned int mHeartbeatDuration;
};

@ -19,7 +19,6 @@
#define LOG_TAG "CameraTestHelpers"
#include "PhoneDevice2.h"
#include "TermClient.h"
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
@ -33,15 +32,9 @@
#include <android/log.h>
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define ASSERT(cond, fmt, ...) \
if (!(cond)) { \
__android_log_assert(#cond, LOG_TAG, fmt, ##__VA_ARGS__); \
}
#include <AndroidHelper.h>
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
@ -80,7 +73,12 @@ CPhoneDevice2::CPhoneDevice2(JavaVM* vm, jobject service)
{
m_vm = vm;
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service);
jclass classService = env->GetObjectClass(m_javaService);
@ -103,7 +101,12 @@ CPhoneDevice2::CPhoneDevice2(JavaVM* vm, jobject service)
CPhoneDevice2::~CPhoneDevice2()
{
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService);
if (attached)
{
@ -121,11 +124,17 @@ bool CPhoneDevice2::UpdateTime(time_t ts)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (attached)
{
jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
m_vm->DetachCurrentThread();
}
@ -145,10 +154,17 @@ IDevice::timer_uid_t CPhoneDevice2::RegisterTimer(unsigned int timerType, unsign
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
if (attached)
{
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
m_vm->DetachCurrentThread();
}
@ -165,10 +181,16 @@ bool CPhoneDevice2::UnregisterTimer(IDevice::timer_uid_t uid)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
return false;
}
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
if (attached)
{
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
m_vm->DetachCurrentThread();
}
@ -214,10 +236,16 @@ IDevice::timer_uid_t CPhoneDevice2::RegisterHeartbeat(unsigned int timerType, un
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
if (attached)
{
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
m_vm->DetachCurrentThread();
}
@ -226,15 +254,15 @@ IDevice::timer_uid_t CPhoneDevice2::RegisterHeartbeat(unsigned int timerType, un
bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path)
{
LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
ALOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
mPhotoInfo = photoInfo;
mPath = path;
mDisplayDimension = DisplayDimension(photoInfo.width, photoInfo.height);
LOGE("Image Buffer Size: %d", photoInfo.width * photoInfo.height * 4);
ALOGE("Image Buffer Size: %d", photoInfo.width * photoInfo.height * 4);
imageBuffer_ = (uint8_t*)malloc(photoInfo.width * photoInfo.height * 4);
ASSERT(imageBuffer_ != nullptr, "Failed to allocate imageBuffer_");
AASSERT(imageBuffer_ != nullptr, "Failed to allocate imageBuffer_");
int cameraId = (int)photoInfo.channel - 1;
@ -247,33 +275,33 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
camera_status = ACameraManager_getCameraIdList(cameraManager, &cameraIdList);
if (camera_status != ACAMERA_OK) {
LOGI("Failed to get camera id list (reason: %d)\n", camera_status);
ALOGI("Failed to get camera id list (reason: %d)\n", camera_status);
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
if (cameraIdList->numCameras < 1 ) {
LOGI("No camera device detected.\n");
ALOGI("No camera device detected.\n");
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
if (cameraIdList->numCameras <= cameraId ) {
LOGI("No required camera device %d detected.\n", cameraId);
ALOGI("No required camera device %d detected.\n", cameraId);
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
selectedCameraId = cameraIdList->cameraIds[cameraId];
LOGI("Trying to open Camera2 (id: %s, num of camera : %d)\n", selectedCameraId,
ALOGI("Trying to open Camera2 (id: %s, num of camera : %d)\n", selectedCameraId,
cameraIdList->numCameras);
camera_status = ACameraManager_getCameraCharacteristics(cameraManager, selectedCameraId,
&cameraMetadata);
if (camera_status != ACAMERA_OK) {
LOGI("Failed to get camera meta data of ID:%s\n", selectedCameraId);
ALOGI("Failed to get camera meta data of ID:%s\n", selectedCameraId);
}
ACameraMetadata_const_entry face, orientation;
@ -287,7 +315,7 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
camera_status = ACameraMetadata_getConstEntry(cameraMetadata, ACAMERA_SENSOR_ORIENTATION, &orientation);
LOGI("====Current SENSOR_ORIENTATION: %8d", orientation.data.i32[0]);
ALOGI("====Current SENSOR_ORIENTATION: %8d", orientation.data.i32[0]);
uint32_t cameraOrientation_ = orientation.data.i32[0];
if (cameraOrientation_ == 90 || cameraOrientation_ == 270)
{
@ -304,14 +332,14 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
&deviceStateCallbacks, &cameraDevice);
if (camera_status != ACAMERA_OK) {
LOGI("Failed to open camera device (id: %s)\n", selectedCameraId);
ALOGI("Failed to open camera device (id: %s)\n", selectedCameraId);
}
camera_status = ACameraDevice_createCaptureRequest(cameraDevice, TEMPLATE_STILL_CAPTURE/*TEMPLATE_PREVIEW*/,
&captureRequest);
if (camera_status != ACAMERA_OK) {
LOGI("Failed to create preview capture request (id: %s)\n", selectedCameraId);
ALOGI("Failed to create preview capture request (id: %s)\n", selectedCameraId);
}
ACaptureSessionOutputContainer_create(&captureSessionOutputContainer);
@ -329,7 +357,7 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
status = AImageReader_new(resCap.width, resCap.height, resCap.format, 5, &mAImageReader);
if (status != AMEDIA_OK)
{
LOGI("AImageReader_new error\n");
ALOGI("AImageReader_new error\n");
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@ -344,12 +372,12 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
status = AImageReader_getWindow(mAImageReader, &theNativeWindow);
if (status != AMEDIA_OK)
{
LOGI("AImageReader_getWindow error\n");
ALOGI("AImageReader_getWindow error\n");
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
LOGI("Surface is prepared in %p.\n", theNativeWindow);
ALOGI("Surface is prepared in %p.\n", theNativeWindow);
// theNativeWindow
ACameraOutputTarget_create(theNativeWindow, &cameraOutputTarget);
@ -363,7 +391,7 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
// ACameraCaptureSession_setRepeatingRequest(captureSession, NULL, 1, &captureRequest, NULL);
ACameraCaptureSession_capture(captureSession, NULL, 1, &captureRequest, NULL);
LOGI("Surface is prepared in here.\n");
ALOGI("Surface is prepared in here.\n");
return true;
}
@ -389,10 +417,10 @@ void CPhoneDevice2::ImageCallback(AImageReader *reader)
{
int32_t srcFormat = -1;
AImage_getFormat(image, &srcFormat);
ASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
AASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
int32_t srcPlanes = 0;
AImage_getNumberOfPlanes(image, &srcPlanes);
ASSERT(srcPlanes == 3, "Is not 3 planes");
AASSERT(srcPlanes == 3, "Is not 3 planes");
AImageCropRect srcRect;
AImage_getCropRect(image, &srcRect);
@ -475,10 +503,10 @@ bool CPhoneDevice2::WriteFile(AImage *image, const string& path)
int planeCount = 0;
media_status_t status = AImage_getNumberOfPlanes(image, &planeCount);
LOGI("Info: getNumberOfPlanes() planeCount = %d", planeCount);
ALOGI("Info: getNumberOfPlanes() planeCount = %d", planeCount);
if (!(status == AMEDIA_OK && planeCount == 1))
{
LOGE("Error: getNumberOfPlanes() planeCount = %d", planeCount);
ALOGE("Error: getNumberOfPlanes() planeCount = %d", planeCount);
return false;
}
@ -493,7 +521,7 @@ bool CPhoneDevice2::WriteFile(AImage *image, const string& path)
fwrite(data, 1, len, file);
fclose(file);
LOGI("Capture: %s", path.c_str());
ALOGI("Capture: %s", path.c_str());
res = true;
@ -546,7 +574,7 @@ bool CPhoneDevice2::MatchCaptureSizeRequest(ACameraManager *cameraManager, const
if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) {
DisplayDimension res(entry.data.i32[i + 1], entry.data.i32[i + 2]);
LOGI("Camera Resolution: %d x %d fmt=%d", res.width(), res.height(), format);
ALOGI("Camera Resolution: %d x %d fmt=%d", res.width(), res.height(), format);
if (!disp.IsSameRatio(res)) continue;
if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) {
foundIt = true;
@ -563,7 +591,7 @@ bool CPhoneDevice2::MatchCaptureSizeRequest(ACameraManager *cameraManager, const
resCap->width = foundRes.org_width();
resCap->height = foundRes.org_height();
} else {
LOGI("Did not find any compatible camera resolution, taking 640x480");
ALOGI("Did not find any compatible camera resolution, taking 640x480");
resCap->width = disp.org_width();
resCap->height = disp.org_height();
// *resCap = *resView;
@ -584,16 +612,16 @@ bool CPhoneDevice2::MatchCaptureSizeRequest(ACameraManager *cameraManager, const
* it will be deleted via {@link AImage_delete}
*/
bool CPhoneDevice2::DisplayImage(ANativeWindow_Buffer *buf, AImage *image) {
ASSERT(buf->format == WINDOW_FORMAT_RGBX_8888 ||
AASSERT(buf->format == WINDOW_FORMAT_RGBX_8888 ||
buf->format == WINDOW_FORMAT_RGBA_8888,
"Not supported buffer format");
int32_t srcFormat = -1;
AImage_getFormat(image, &srcFormat);
ASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
AASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
int32_t srcPlanes = 0;
AImage_getNumberOfPlanes(image, &srcPlanes);
ASSERT(srcPlanes == 3, "Is not 3 planes");
AASSERT(srcPlanes == 3, "Is not 3 planes");
switch (presentRotation_) {
case 0:
@ -609,7 +637,7 @@ bool CPhoneDevice2::DisplayImage(ANativeWindow_Buffer *buf, AImage *image) {
PresentImage270(buf, image);
break;
default:
ASSERT(0, "NOT recognized display rotation: %d", presentRotation_);
AASSERT(0, "NOT recognized display rotation: %d", presentRotation_);
}
AImage_delete(image);
@ -858,27 +886,27 @@ bool CPhoneDevice2::SendBroadcastMessage(String16 action, int value)
void CPhoneDevice2::camera_device_on_disconnected(void *context, ACameraDevice *device)
{
LOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device));
ALOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device));
CPhoneDevice2* pThis = (CPhoneDevice2*)context;
// delete pThis;
}
void CPhoneDevice2::camera_device_on_error(void *context, ACameraDevice *device, int error)
{
LOGI("Error(code: %d) on Camera(id: %s).\n", error, ACameraDevice_getId(device));
ALOGI("Error(code: %d) on Camera(id: %s).\n", error, ACameraDevice_getId(device));
}
void CPhoneDevice2::capture_session_on_ready(void *context, ACameraCaptureSession *session)
{
LOGI("Session is ready. %p\n", session);
ALOGI("Session is ready. %p\n", session);
}
void CPhoneDevice2::capture_session_on_active(void *context, ACameraCaptureSession *session)
{
LOGI("Session is activated. %p\n", session);
ALOGI("Session is activated. %p\n", session);
}
void CPhoneDevice2::capture_session_on_closed(void *context, ACameraCaptureSession *session)
{
LOGI("Session is closed. %p\n", session);
ALOGI("Session is closed. %p\n", session);
}

@ -17,15 +17,10 @@
#include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraMetadataTags.h>
#include <media/NdkImageReader.h>
#include <android/log.h>
// #define LOG_TAG "native-camera2-jni"
#define PD_LOG_TAG "PhoneDev"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,PD_LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,PD_LOG_TAG,__VA_ARGS__)
#include <Client/Device.h>
#include <string>
#include "Camera2Helper.h"
#include "camera2/Camera2Helper.h"
class CPhoneDevice2 : public IDevice
{

@ -0,0 +1,201 @@
/* ---------------------------------------------------------------------
* Luiz Carlos doleron @ 2021
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero Public License for more details.
* ----------------------------------------------------------------------
*/
#ifndef _GET_CPU_USAGE_LINUX_
#define _GET_CPU_USAGE_LINUX_
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/statvfs.h>
namespace get_system_usage_linux
{
struct CPU_stats
{
// see http://www.linuxhowtos.org/manpages/5/proc.htm
int user;
int nice;
int system;
int idle;
int iowait;
int irq;
int softirq;
int steal;
int guest;
int guest_nice;
int get_total_idle()
const {
return idle + iowait;
}
int get_total_active()
const {
return user + nice + system + irq + softirq + steal + guest + guest_nice;
}
};
struct Memory_stats
{
int total_memory;
int available_memory;
int total_swap;
int free_swap;
float get_memory_usage() {
const float result = static_cast<float>(total_memory - available_memory) / total_memory;
return result;
}
float get_swap_usage() {
const float result = static_cast<float>(total_swap - free_swap) / total_swap;
return result;
}
};
inline CPU_stats read_cpu_data()
{
CPU_stats result;
std::ifstream proc_stat("/proc/stat");
if (proc_stat.good())
{
std::string line;
getline(proc_stat, line);
unsigned int *stats_p = (unsigned int *)&result;
std::stringstream iss(line);
std::string cpu;
iss >> cpu;
while (iss >> *stats_p)
{
stats_p++;
};
}
proc_stat.close();
return result;
}
inline int get_val(const std::string &target, const std::string &content) {
int result = -1;
std::size_t start = content.find(target);
if (start != std::string::npos) {
int begin = start + target.length();
std::size_t end = content.find("kB", start);
std::string substr = content.substr(begin, end - begin);
result = std::stoi(substr);
}
return result;
}
inline Memory_stats read_memory_data()
{
Memory_stats result;
std::ifstream proc_meminfo("/proc/meminfo");
if (proc_meminfo.good())
{
std::string content((std::istreambuf_iterator<char>(proc_meminfo)),
std::istreambuf_iterator<char>());
result.total_memory = get_val("MemTotal:", content);
result.total_swap = get_val("SwapTotal:", content);
result.free_swap = get_val("SwapFree:", content);
result.available_memory = get_val("MemAvailable:", content);
}
proc_meminfo.close();
return result;
}
inline float get_cpu_usage(const CPU_stats &first, const CPU_stats &second) {
const float active_time = static_cast<float>(second.get_total_active() - first.get_total_active());
const float idle_time = static_cast<float>(second.get_total_idle() - first.get_total_idle());
const float total_time = active_time + idle_time;
return active_time / total_time;
}
inline float get_disk_usage(const std::string & disk) {
struct statvfs diskData;
statvfs(disk.c_str(), &diskData);
auto total = diskData.f_blocks;
auto free = diskData.f_bfree;
auto diff = total - free;
float result = static_cast<float>(diff) / total;
return result;
}
//see https://unix.stackexchange.com/questions/304845/discrepancy-between-number-of-cores-and-thermal-zones-in-sys-class-thermal/342023
inline int find_thermalzone_index() {
int result = 0;
bool stop = false;
// 20 must stop anyway
for (int i = 0; !stop && i < 20; ++i) {
std::ifstream thermal_file("/sys/class/thermal/thermal_zone" + std::to_string(i) + "/type");
if (thermal_file.good())
{
std::string line;
getline(thermal_file, line);
if (line.compare("x86_pkg_temp") == 0) {
result = i;
stop = true;
}
} else {
stop = true;
}
thermal_file.close();
}
return result;
}
inline int get_thermalzone_temperature(int thermal_index) {
int result = -1;
std::ifstream thermal_file("/sys/class/thermal/thermal_zone" + std::to_string(thermal_index) + "/temp");
if (thermal_file.good())
{
std::string line;
getline(thermal_file, line);
std::stringstream iss(line);
iss >> result;
} else {
throw std::invalid_argument(std::to_string(thermal_index) + " doesn't refer to a valid thermal zone.");
}
thermal_file.close();
return result;
}
}
#endif

@ -1,16 +1,22 @@
#include "TerminalDevice.h"
#include <dlfcn.h>
#include "Camera.h"
#include <AndroidHelper.h>
typedef jbyteArray (*TakePhotoFunc)(int, int, int, int);
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
CTerminalDevice::CTerminalDevice(JavaVM* vm, jobject service)
{
m_vm = vm;
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service);
if (attached)
{
@ -21,7 +27,12 @@ CTerminalDevice::CTerminalDevice(JavaVM* vm, jobject service)
CTerminalDevice::~CTerminalDevice()
{
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService);
if (attached)
{

@ -17,6 +17,24 @@
#ifndef __CAMERA2_HELPER_H__
#define __CAMERA2_HELPER_H__
template <typename T>
class RangeValue {
public:
T min_, max_;
/**
* return absolute value from relative value
* value: in percent (50 for 50%)
*/
T value(int percent) {
return static_cast<T>(min_ + (max_ - min_) * percent / 100);
}
RangeValue() { min_ = max_ = static_cast<T>(0); }
bool Supported(void) const { return (min_ != max_); }
};
struct ImageFormat {
int32_t width;
int32_t height;

@ -19,6 +19,8 @@
#include <android/log.h>
#include <opencv2/core/core.hpp>
#include "mat.h"
#include "Camera2Helper.h"
#include <AndroidHelper.h>
static void onDisconnected(void* context, ACameraDevice* device)
{
@ -27,7 +29,9 @@ static void onDisconnected(void* context, ACameraDevice* device)
static void onError(void* context, ACameraDevice* device, int error)
{
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onError %p %d", device, error);
std::string msg = "NdkCamera error code=" + std::to_string(error);
((NdkCamera*)context)->on_error(msg);
// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onError %p %d", device, error);
}
static void onImageAvailable(void* context, AImageReader* reader)
@ -67,7 +71,7 @@ void onCaptureSequenceAborted(void* context, ACameraCaptureSession* session, int
void onCaptureCompleted(void* context, ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result)
{
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result);
((NdkCamera*)context)->onCaptureCompleted(session, request, result);
}
NdkCamera::NdkCamera(int32_t width, int32_t height)
@ -76,6 +80,12 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
camera_orientation = 0;
m_firstFrame = true;
mWidth = width;
mHeight = height;
hdrSupported = false;
nightModeSupported = false;
nightPortraitModeSupported = false;
camera_manager = 0;
camera_device = 0;
@ -86,23 +96,6 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
capture_session_output_container = 0;
capture_session_output = 0;
capture_session = 0;
// setup imagereader and its surface
{
AImageReader_new(width, height, AIMAGE_FORMAT_YUV_420_888, /*maxImages*/2, &image_reader);
AImageReader_ImageListener listener;
listener.context = this;
listener.onImageAvailable = ::onImageAvailable;
AImageReader_setImageListener(image_reader, &listener);
AImageReader_getWindow(image_reader, &image_reader_surface);
// ANativeWindow_setBuffersGeometry(image_reader_surface, width, height,WINDOW_FORMAT_RGBX_8888);
ANativeWindow_acquire(image_reader_surface);
}
}
NdkCamera::~NdkCamera()
@ -124,7 +117,7 @@ NdkCamera::~NdkCamera()
int NdkCamera::open(const char* cameraId)
{
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open");
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "DBG::open %s", cameraId);
// camera_facing = _camera_facing;
@ -132,6 +125,10 @@ int NdkCamera::open(const char* cameraId)
// find front camera
std::string camera_id;
bool foundIt = false;
DisplayDimension disp(mWidth, mHeight);
DisplayDimension foundRes = disp;
{
ACameraIdList* camera_id_list = 0;
ACameraManager_getCameraIdList(camera_manager, &camera_id_list);
@ -181,6 +178,95 @@ int NdkCamera::open(const char* cameraId)
camera_orientation = orientation;
{
ACameraMetadata_const_entry e = { 0 };
ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &e);
// format of the data: format, width, height, input?, type int32
// DisplayDimension foundRes(4000, 4000);
// DisplayDimension maxJPG(0, 0);
for (int i = 0; i < e.count; i += 4) {
int32_t input = e.data.i32[i + 3];
int32_t format = e.data.i32[i + 0];
if (input) continue;
if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) {
DisplayDimension res(e.data.i32[i + 1], e.data.i32[i + 2]);
if (!disp.IsSameRatio(res)) continue;
if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) {
foundIt = true;
foundRes = res;
}/* else if (format == AIMAGE_FORMAT_JPEG && res > maxJPG) {
maxJPG = res;
}*/
}
}
}
{
ACameraMetadata_const_entry val = { 0 };
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val);
if (status == ACAMERA_OK) {
exposureRange.min_ = val.data.i64[0];
if (exposureRange.min_ < kMinExposureTime) {
exposureRange.min_ = kMinExposureTime;
}
exposureRange.max_ = val.data.i64[1];
if (exposureRange.max_ > kMaxExposureTime) {
exposureRange.max_ = kMaxExposureTime;
}
// exposureTime = exposureRange.value(2);
} else {
ALOGW("Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE");
exposureRange.min_ = exposureRange.max_ = 0l;
// exposureTime_ = 0l;
}
}
{
ACameraMetadata_const_entry val = { 0 };
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);
if (status == ACAMERA_OK) {
sensitivityRange.min_ = val.data.i32[0];
sensitivityRange.max_ = val.data.i32[1];
// sensitivity = sensitivityRange.value(2);
} else {
ALOGW("failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE");
sensitivityRange.min_ = sensitivityRange.max_ = 0;
// sensitivity_ = 0;
}
}
{
ACameraMetadata_const_entry e = { 0 };
ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_CONTROL_AVAILABLE_SCENE_MODES, &e);
for (int i = 0; i < e.count; i ++)
{
if (ACAMERA_CONTROL_SCENE_MODE_HDR == e.data.u8[i])
{
hdrSupported = true;
break;
}
else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT == e.data.u8[i])
{
nightModeSupported = true;
}
else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT == e.data.u8[i])
{
nightPortraitModeSupported = true;
}
}
}
ACameraMetadata_free(camera_metadata);
break;
@ -189,11 +275,36 @@ int NdkCamera::open(const char* cameraId)
ACameraManager_deleteCameraIdList(camera_id_list);
}
if (camera_id.empty())
if (camera_id.empty() || !foundIt)
{
return 1;
}
if (camera_id == "1")
{
camera_facing = 1;
}
mCameraId = camera_id;
camera_status_t res = ACAMERA_OK;
// setup imagereader and its surface
{
AImageReader_new(foundRes.width(), foundRes.height(), AIMAGE_FORMAT_YUV_420_888, /*maxImages*/2, &image_reader);
AImageReader_ImageListener listener;
listener.context = this;
listener.onImageAvailable = ::onImageAvailable;
AImageReader_setImageListener(image_reader, &listener);
AImageReader_getWindow(image_reader, &image_reader_surface);
// ANativeWindow_setBuffersGeometry(image_reader_surface, width, height,WINDOW_FORMAT_RGBX_8888);
ANativeWindow_acquire(image_reader_surface);
}
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open %s %d", camera_id.c_str(), camera_orientation);
// open camera
@ -203,16 +314,69 @@ int NdkCamera::open(const char* cameraId)
camera_device_state_callbacks.onDisconnected = onDisconnected;
camera_device_state_callbacks.onError = onError;
ACameraManager_openCamera(camera_manager, camera_id.c_str(), &camera_device_state_callbacks, &camera_device);
res = ACameraManager_openCamera(camera_manager, camera_id.c_str(), &camera_device_state_callbacks, &camera_device);
if (res != ACAMERA_OK)
{
return 1;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(128));
// capture request
{
ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request);
res = ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request);
int32_t fpsRange[2] = {10,15};
res = ACaptureRequest_setEntry_i32(capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,2,fpsRange);
ACameraOutputTarget_create(image_reader_surface, &image_reader_target);
ACaptureRequest_addTarget(capture_request, image_reader_target);
bool usingAE = true;
if (usingAE) {
uint8_t aeMode = ACAMERA_CONTROL_AE_MODE_ON;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
uint8_t aeLockOff = ACAMERA_CONTROL_AE_LOCK_OFF;
ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_LOCK, 1, &aeLockOff);
} else {
uint8_t aeMode = ACAMERA_CONTROL_AE_MODE_OFF;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_MODE, 1, &aeMode);
uint8_t hdrMode = ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10; // ACAMERA_CONTROL_SCENE_MODE_HDR
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_HDR, 1, &hdrMode);
int32_t sensitivity = sensitivityRange.value(2);
res = ACaptureRequest_setEntry_i32(capture_request,ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity);
int64_t exposureTime = exposureRange.value(5);
res = ACaptureRequest_setEntry_i64(capture_request, ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime);
}
uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AF_MODE, 1, &afMode);
uint8_t awbMode = ACAMERA_CONTROL_AWB_MODE_AUTO;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AWB_MODE, 1, &awbMode);
if (hdrSupported) {
uint8_t hdrMode = ACAMERA_CONTROL_SCENE_MODE_HDR; // ACAMERA_CONTROL_SCENE_MODE_HDR
// res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_HDR, 1, &hdrMode);
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE, 1, &hdrMode);
}
if (nightModeSupported) {
uint8_t modeEnabled = 1; // ACAMERA_CONTROL_SCENE_MODE_HDR
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_NIGHT, 1, &modeEnabled);
}
if (nightPortraitModeSupported) {
uint8_t modeEnabled = 1; // ACAMERA_CONTROL_SCENE_MODE_HDR
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT, 1, &modeEnabled);
}
res = ACameraOutputTarget_create(image_reader_surface, &image_reader_target);
res = ACaptureRequest_addTarget(capture_request, image_reader_target);
}
// capture session
@ -223,7 +387,7 @@ int NdkCamera::open(const char* cameraId)
camera_capture_session_state_callbacks.onReady = onSessionReady;
camera_capture_session_state_callbacks.onClosed = onSessionClosed;
ACaptureSessionOutputContainer_create(&capture_session_output_container);
res = ACaptureSessionOutputContainer_create(&capture_session_output_container);
ACaptureSessionOutput_create(image_reader_surface, &capture_session_output);
@ -235,14 +399,14 @@ int NdkCamera::open(const char* cameraId)
camera_capture_session_capture_callbacks.context = this;
camera_capture_session_capture_callbacks.onCaptureStarted = 0;
camera_capture_session_capture_callbacks.onCaptureProgressed = 0;
camera_capture_session_capture_callbacks.onCaptureCompleted = onCaptureCompleted;
camera_capture_session_capture_callbacks.onCaptureCompleted = ::onCaptureCompleted;
camera_capture_session_capture_callbacks.onCaptureFailed = onCaptureFailed;
camera_capture_session_capture_callbacks.onCaptureSequenceCompleted = onCaptureSequenceCompleted;
camera_capture_session_capture_callbacks.onCaptureSequenceAborted = onCaptureSequenceAborted;
camera_capture_session_capture_callbacks.onCaptureBufferLost = 0;
ACameraCaptureSession_setRepeatingRequest(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request, nullptr);
// ACameraCaptureSession_capture(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request,nullptr);
// ACameraCaptureSession_setRepeatingRequest(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request, nullptr);
ACameraCaptureSession_capture(capture_session, &camera_capture_session_capture_callbacks, 1, &capture_request,nullptr);
}
return 0;
@ -250,7 +414,7 @@ int NdkCamera::open(const char* cameraId)
void NdkCamera::close()
{
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "close");
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "DBG::close %s", mCameraId.c_str());
if (capture_session)
{
@ -316,7 +480,6 @@ void NdkCamera::onImageAvailable(AImageReader* reader)
// return;
}
int32_t format;
AImage_getFormat(image, &format);
@ -397,12 +560,15 @@ void NdkCamera::onImageAvailable(AImageReader* reader)
}
AImage_delete(image);
}
ACameraCaptureSession_stopRepeating(capture_session);
void NdkCamera::on_error(const std::string& msg) const
{
}
void NdkCamera::on_image(const cv::Mat& rgb) const
bool NdkCamera::on_image(const cv::Mat& rgb) const
{
return false;
}
void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const
@ -413,7 +579,8 @@ void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_hei
int h = 0;
int rotate_type = 0;
// TODO !!!???
int co = camera_orientation > 0 ? camera_orientation - 90 : camera_orientation;
// int co = camera_orientation > 0 ? camera_orientation + 90 : camera_orientation;
int co = (camera_orientation + 90) % 360;
// int co = 0;
if (co == 0)
{
@ -464,3 +631,26 @@ void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_hei
on_image(rgb);
}
void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result)
{
// CALL_REQUEST(setEntry_i64(requests_[PREVIEW_REQUEST_IDX].request_,
// ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime_));
// ACameraMetadata_getConstEntry(result, )
ACameraMetadata_const_entry val = { 0 };
camera_status_t status = ACameraMetadata_getConstEntry(result, ACAMERA_SENSOR_EXPOSURE_TIME, &val);
int64_t exTime = val.data.i64[0];
val = { 0 };
status = ACameraMetadata_getConstEntry(result, ACAMERA_CONTROL_AE_MODE, &val);
uint8_t aeMode = val.data.u8[0];
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
ALOGD("onCaptureCompleted EXPOSURE_TIME=%lld, camera id=%s, AE=%s", exTime, mCameraId.c_str(), ((aeMode == 1) ? "ON" : "OFF"));
// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result);
}

@ -21,10 +21,23 @@
#include <media/NdkImageReader.h>
#include <opencv2/core/core.hpp>
#include "Camera2Helper.h"
/**
* Range of Camera Exposure Time:
* Camera's capability range have a very long range which may be disturbing
* on camera. For this sample purpose, clamp to a range showing visible
* video on preview: 100000ns ~ 250000000ns
*/
static const uint64_t kMinExposureTime = static_cast<uint64_t>(1000000);
static const uint64_t kMaxExposureTime = static_cast<uint64_t>(250000000);
class NdkCamera
{
public:
NdkCamera(int32_t width, int32_t height);
virtual ~NdkCamera();
@ -33,14 +46,32 @@ public:
void close();
void onImageAvailable(AImageReader* reader);
virtual void on_image(const cv::Mat& rgb) const;
virtual bool on_image(const cv::Mat& rgb) const;
virtual void on_error(const std::string& msg) const;
virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const;
void onCaptureCompleted(ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result);
public:
int camera_facing;
int camera_orientation;
bool m_firstFrame;
int32_t mWidth;
int32_t mHeight;
std::string mCameraId;
bool hdrSupported;
bool nightModeSupported;
bool nightPortraitModeSupported;
bool afSupported;
bool awbSupported;
// int64_t exposureTime_;
RangeValue<int64_t> exposureRange;
// int32_t sensitivity_;
RangeValue<int32_t> sensitivityRange;
private:
ACameraManager* camera_manager;

@ -77,7 +77,9 @@ class counting_semaphore {
static void throw_errno(const char* what_arg)
{
#ifndef __ANDROID__
throw std::system_error(std::error_code(errno, std::generic_category()), what_arg);
#endif
}
bool do_try_acquirewait(const std::chrono::system_clock::time_point& tp)

@ -0,0 +1,169 @@
package com.xinyingpower.microphoto;
import android.app.AlarmManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
public class DeviceUtil {
public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
public static final int SIGNAL_STRENGTH_POOR = 1;
public static final int SIGNAL_STRENGTH_MODERATE = 2;
public static final int SIGNAL_STRENGTH_GOOD = 3;
public static final int SIGNAL_STRENGTH_GREAT = 4;
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
//无 ,低劣的 ,适度的 ,好 ,优异的
public static final String[] SIGNAL_STRENGTH_NAMES = {
"none", "poor", "moderate", "good", "great"
};
public static String getNetworkType(Context context) {
// ConnectionManager instance
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
// If not connected, "-" will be displayed
if (ni == null || !ni.isConnected()) return "";
// If Connected to Wifi
if (ni.getType() == ConnectivityManager.TYPE_WIFI) return "WIFI";
// If Connected to Mobile
String subTypeName = "";
if (ni.getType() == ConnectivityManager.TYPE_MOBILE) {
int subType = ni.getSubtype();
switch (subType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
case TelephonyManager.NETWORK_TYPE_GSM:
subTypeName = "2G";
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
subTypeName = "3G";
break;
case TelephonyManager.NETWORK_TYPE_LTE:
case TelephonyManager.NETWORK_TYPE_IWLAN:
case 19:
subTypeName = "4G";
break;
case TelephonyManager.NETWORK_TYPE_NR:
subTypeName = "5G";
break;
default:
subTypeName = "";
break;
}
}
return subTypeName;
}
public static void getPhoneState(Context context) {
final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener MyPhoneListener = new PhoneStateListener() {
@Override
//获取对应网络的ID这个方法在这个程序中没什么用处
public void onCellLocationChanged(CellLocation location) {
if (location instanceof GsmCellLocation) {
int CID = ((GsmCellLocation) location).getCid();
} else if (location instanceof CdmaCellLocation) {
int ID = ((CdmaCellLocation) location).getBaseStationId();
}
}
//系统自带的服务监听器,实时监听网络状态
@Override
public void onServiceStateChanged(ServiceState serviceState) {
super.onServiceStateChanged(serviceState);
}
//这个是我们的主角,就是获取对应网络信号强度
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
//这个ltedbm 是4G信号的值
String signalinfo = signalStrength.toString();
String[] parts = signalinfo.split(" ");
String ltedbm = parts[9];
//这个dbm 是2G和3G信号的值
int asu = signalStrength.getGsmSignalStrength();
int dbm = -113 + 2 * asu;
if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
Log.i("NetWorkUtil", "网络LTE 信号强度:" + ltedbm + "======Detail:" + signalinfo);
} else if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSDPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSUPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS) {
String bin;
if (dbm > -75) {
bin = "网络很好";
} else if (dbm > -85) {
bin = "网络不错";
} else if (dbm > -95) {
bin = "网络还行";
} else if (dbm > -100) {
bin = "网络很差";
} else {
bin = "网络错误";
}
Log.i("NetWorkUtil", "网络WCDMA 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
} else {
String bin;
if (asu < 0 || asu >= 99) bin = "网络错误";
else if (asu >= 16) bin = "网络很好";
else if (asu >= 8) bin = "网络不错";
else if (asu >= 4) bin = "网络还行";
else bin = "网络很差";
Log.i("NetWorkUtil", "网络GSM 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
}
super.onSignalStrengthsChanged(signalStrength);
}
};
telephonyManager.listen(MyPhoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
public static boolean updateTime(Context context, long timeInMillis) {
boolean res = false;
try {
// Calendar c = Calendar.getInstance();
// c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setTime(timeInMillis);
res = true;
} catch (Exception ex) {
int aa = 0;
}
return true;
}
}

@ -50,9 +50,14 @@ public class FloatingWindow extends Service {
@Override
public void onDestroy() {
if (mView != null) {
mWindowManager.removeView(mView);
try {
if (mView != null) {
mWindowManager.removeView(mView);
}
} catch (Exception ex) {
ex.printStackTrace();
}
super.onDestroy();
}

@ -1,9 +1,11 @@
package com.xinyingpower.microphoto;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Path;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.location.Location;
@ -13,17 +15,16 @@ import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
//import androidx.camera.video.FallbackStrategy;
//import androidx.camera.video.Quality;
//import androidx.camera.video.QualitySelector;
import androidx.core.app.ActivityCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.Display;
import android.view.View;
@ -35,17 +36,25 @@ import com.xinyingpower.microphoto.databinding.ActivityMainBinding;
//import com.xinyingpower.microphoto.request.INettyMessageListener;
//import com.xinyingpower.microphoto.request.NettyChatClient;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
//import io.netty.util.Constant;
import android.content.SharedPreferences;
public class MainActivity extends AppCompatActivity {
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
private static int MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE = 100;
@ -53,17 +62,25 @@ public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("microphoto");
}
private ActivityMainBinding binding;
private int defaultDataSubId;
// private MediaRecorder mediaRecorder;
@Override
protected void onDestroy() {
super.onDestroy();
}
protected class AppConfig {
public String cmdid;
public String server;
public int port;
public int protocol;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display defaultDisplay = windowManager.getDefaultDisplay();
@ -72,13 +89,27 @@ public class MainActivity extends AppCompatActivity {
Log.d(TAG, "Screen Size: " + width + " x " + height);
String cmdid = "0123456789ABCDEFG";
String server = "47.96.238.157";
Integer port = new Integer(6891);
Integer protocol = new Integer(0xFF00); // 0xFF00
AppConfig appConfig = getAppConfig();
binding.cmdid.setText(appConfig.cmdid);
binding.server.setText(appConfig.server);
binding.port.setText(Integer.toString(appConfig.port));
this.binding.startServBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String[] accessPermissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.FOREGROUND_SERVICE, Manifest.permission.READ_PHONE_STATE,
/*Manifest.permission.SET_TIME,*/};
String[] accessPermissions = new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.FOREGROUND_SERVICE,
Manifest.permission.READ_PHONE_STATE,
/*Manifest.permission.PACKAGE_USAGE_STATS,*/
/*Manifest.permission.SET_TIME,*/
};
boolean needRequire = false;
for (String access : accessPermissions) {
int curPermission = ActivityCompat.checkSelfPermission(MainActivity.this, access);
@ -88,7 +119,10 @@ public class MainActivity extends AppCompatActivity {
}
}
if (needRequire) {
ActivityCompat.requestPermissions(MainActivity.this, accessPermissions, MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE);
ActivityCompat.requestPermissions(
MainActivity.this,
accessPermissions,
MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE);
return;
}
@ -97,8 +131,19 @@ public class MainActivity extends AppCompatActivity {
String fileName = buildPhotoFileName(channel, 255);
// MainActivity.this.takePhoto(channel, 255, path, fileName);
String cmdid = MainActivity.this.binding.cmdid.getText().toString();
String server = MainActivity.this.binding.server.getText().toString();
int port = Integer.parseInt(MainActivity.this.binding.port.getText().toString());
int protocol = 0xFF00;
MainActivity.this.saveAppConfig(cmdid, server, port, protocol);
Intent intent = new Intent(MainActivity.this, MicroPhotoService.class);
intent.setAction(MicroPhotoService.ACTION_START);
intent.putExtra("cmdid", cmdid);
intent.putExtra("server", server);
intent.putExtra("port", port);
intent.putExtra("protocol", protocol);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MainActivity.this.startForegroundService(intent);
@ -108,25 +153,30 @@ public class MainActivity extends AppCompatActivity {
binding.startServBtn.setEnabled(false);
binding.stopServBtn.setEnabled(true);
}
});
this.binding.takePhotoBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 1, 255, true);
// setDefaultDataSubId(1);
MicroPhotoService.takePhoto(MainActivity.this.getApplicationContext(), 1, 255, true);
}
});
this.binding.takePhotoBtn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 2, 255, true);
// setDefaultDataSubId(2);
}
});
this.binding.takePhotoBtn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 3, 255, true);
}
});
this.binding.takePhotoBtn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 4, 255, true);
}
});
@ -142,11 +192,8 @@ public class MainActivity extends AppCompatActivity {
binding.startServBtn.setEnabled(true);
binding.stopServBtn.setEnabled(false);
}
});
binding.simchange.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@ -216,14 +263,19 @@ public class MainActivity extends AppCompatActivity {
});
}
});
Handler handler=new Handler();
Runnable runnable=new Runnable(){
@Override
public void run() {
binding.startServBtn.performClick();
}
};
handler.postDelayed(runnable, 1000);
if (!TextUtils.isEmpty(appConfig.cmdid) && !TextUtils.isEmpty(appConfig.server) && appConfig.port != 0) {
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
if (binding.startServBtn.isEnabled()) {
binding.startServBtn.performClick();
}
}
};
handler.postDelayed(runnable, 5000);
}
binding.tcpudp.setOnClickListener(new View.OnClickListener() {
@Override
@ -295,7 +347,81 @@ public class MainActivity extends AppCompatActivity {
} catch (Exception e) {
Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage());
}
}
private AppConfig getAppConfig() {
AppConfig appConfig = new AppConfig();
String appPath = MicroPhotoService.buildAppDir(this.getApplicationContext());
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "data/App.json")), "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
StringBuilder stringBuilder = new StringBuilder();
while((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
bufferedReader.close();
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
appConfig.cmdid = jsonObject.getString("CMDID");
appConfig.server = jsonObject.getString("Server");
appConfig.port = jsonObject.getInt("Port");
appConfig.protocol = jsonObject.getInt("Protocol");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
finally {
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (Exception ex) {
}
}
}
return appConfig;
}
private void saveAppConfig(String cmdid, String server, int port, int protocol) {
String appPath = MicroPhotoService.buildAppDir(this.getApplicationContext());
OutputStreamWriter outputStreamWriter = null;
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("CMDID", cmdid);
jsonObject.put("Server", server);
jsonObject.put("Port", port);
jsonObject.put("Protocol", protocol);
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 (outputStreamWriter != null) {
try {
outputStreamWriter.close();
} catch (Exception ex) {
}
}
}
}
private int getDefaultDataSubId() {

@ -1,6 +1,5 @@
package com.xinyingpower.microphoto;
import android.Manifest;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
@ -11,32 +10,22 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.SystemClock;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.dowse.camera.client.DSCameraManager;
import java.io.File;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@ -52,62 +41,45 @@ public class MicroPhotoService extends Service {
static {
System.loadLibrary("microphoto");
}
private static String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver";
private static final String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver";
public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503;
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 String ACTION_HEARTBEAT = "ACT_HB";
private static String ACTION_TAKE_PHOTO = "ACT_TP";
private static String ACTION_TAKE_PHOTO_MANUALLY = "ACT_TP_M";
private static String ACTION_TIMEOUT = "ACT_TIMEOUT";
private static String EXTRA_PARAM_CHANNEL = "Channel";
private static String EXTRA_PARAM_PRESET = "Preset";
private static String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo";
private static String EXTRA_PARAM_SCHEDULES = "Schedules";
private static String EXTRA_PARAM_SCHEDULE = "Schedule_";
private static String EXTRA_PARAM_TIME = "Time";
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 String EXTRA_PARAM_TIMER_UID = "TimerUid";
private static final String EXTRA_PARAM_TIMER_UID = "TimerUid";
// private static String EXTRA_PARAM_TIMER_TYPE = "TimerType";
private static String EXTRA_PARAM_TIMEOUT = "Timeout";
private final static String FOREGROUND_CHANNEL_ID = "foreground_channel_id";
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 AlarmManager mAlarmManager;
private NotificationManager mNotificationManager;
private final Map<String, PowerManager.WakeLock> mWakeLocks = new HashMap<>();
private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000
private long mNextHeartbeatTime = 0;
private Map<Long, PendingIntent> mTimers = new HashMap<>();
private final Map<Long, PendingIntent> mTimers = new HashMap<>();
private static int stateService = STATE_SERVICE.NOT_CONNECTED;
public MicroPhotoService() {
}
@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();
@ -115,9 +87,11 @@ public class MicroPhotoService extends Service {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
stateService = STATE_SERVICE.NOT_CONNECTED;
getPhoneState(this.getApplicationContext());
DeviceUtil.getPhoneState(this.getApplicationContext());
alarmReceiver = new AlarmReceiver(this);
screenactionreceiver = new ScreenActionReceiver();
// 注册广播接受者
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO);
@ -133,69 +107,51 @@ public class MicroPhotoService extends Service {
break;
}
/*
if (aci.getShowIntent().isBroadcast()) {
// alarmManager.cancel(aci.getShowIntent());
}
*/
}
// alarmManager.cancel();
boolean res = false;
/*
res = DSCameraManager.getInstace().init();
ChannelPicParam picParam = new ChannelPicParam();
picParam.setColor(1);
picParam.setWidth(1920);
picParam.setHeight(1080);
picParam.setCompress_radio(40);
DSCameraManager.getInstace().setPicParam(1, picParam);
*/
// boolean res = false;
// Environment.getExternalStoragePublicDirectory(String)
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/");
if (!path.exists()) {
path.mkdirs();
}
// File path = getApplicationContext().getFilesDir();
String appPath = path.getAbsolutePath();
Log.i(TAG, "AppPath=" + appPath);
// String ip = "180.166.218.222";
String ip = "47.96.238.157";
// int port = 40032;
// String ip = "192.168.50.50";
int port = 6891;
String cmdid = "XY-ANDROIDSIM-002";
init(appPath, ip, port, cmdid);
// registerHeartbeatTimer(getHeartbeatDuration());
}
@Override
public void onDestroy() {
Date date = new Date();
long nowTs = date.getTime() / 1000;
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
long startTime = date.getTime() / 1000;
long baseTime = nowTs - startTime;
stateService = STATE_SERVICE.NOT_CONNECTED;
registerCaptureSchedule(startTime, baseTime);
uninit(mHandler);
mHandler = 0;
// registerPhotoTimer();
}
unregisterReceiver(alarmReceiver);
unregisterReceiver(screenactionreceiver);
for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) {
entry.getValue().release();
}
mWakeLocks.clear();
super.onDestroy();
}
public static class AlarmReceiver extends BroadcastReceiver {
private MicroPhotoService mService;
public AlarmReceiver() {
mService = null;
}
public AlarmReceiver(MicroPhotoService service) {
mService = service;
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (TextUtils.equals(ACTION_HEARTBEAT, action)) {
Log.i(TAG, "receiver ACTION=" + action);
mService.sendHeartbeat();
Log.i(TAG, "HB Timer Fired ACTION=" + action);
mService.sendHeartbeat(mService.mHandler);
mService.registerHeartbeatTimer();
} else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) {
long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0);
@ -207,7 +163,8 @@ public class MicroPhotoService extends Service {
int channel = (int) ((val & 0xFF0000L) >> 16);
int preset = (int) ((val & 0xFF00L) >> 8);
mService.notifyToTakePhoto(channel, preset, ts, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), true);
Log.i(TAG, "PhotoTimer Fired: CH=" + channel + " PR=" + preset);
mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), true);
}
}
@ -228,23 +185,34 @@ public class MicroPhotoService extends Service {
boolean photoOrVideo = intent.getBooleanExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, true);
long ts = System.currentTimeMillis() / 1000;
mService.notifyToTakePhoto(channel, preset, ts, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo);
Log.i(TAG, "Take Photo CH=" + channel + " PR=" + preset + " Mannually");
mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo);
} else if (TextUtils.equals(ACTION_TIMEOUT, action)) {
long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0);
Log.i(TAG, "Timeout:" + uid);
mService.fireTimeout(uid);
long expectedTimes = intent.getLongExtra(EXTRA_PARAM_TIMES, 0);
long elapsedTimes = intent.getLongExtra(EXTRA_PARAM_ELASPED_TIMES, 0);
elapsedTimes++;
Log.i(TAG, "Timeout uid=" + uid + " expectedTimes=" + expectedTimes + " Times=" + elapsedTimes);
mService.fireTimeout(mService.mHandler, uid, elapsedTimes);
intent.putExtra(EXTRA_PARAM_ELASPED_TIMES, elapsedTimes);
int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0);
Long uidObj = Long.valueOf(uid);
PendingIntent pendingIntent = mService.mTimers.get(uidObj);
if ((expectedTimes == 0) || (elapsedTimes < expectedTimes)) {
int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0);
if (pendingIntent != null) {
mService.registerTimer(pendingIntent, uid, timeout);
PendingIntent pendingIntent = mService.mTimers.get(uidObj);
if (pendingIntent != null) {
mService.registerTimer(pendingIntent, uid, timeout);
}
} else {
mService.mTimers.remove(uidObj);
}
}
}
}
private void registerHeartbeatTimer(int duration) {
int orgHeartbeatDuration = mHeartbeatDuration;
mHeartbeatDuration = duration;
@ -253,7 +221,6 @@ public class MicroPhotoService extends Service {
}
}
private void registerHeartbeatTimer() {
// 创建延迟意图
@ -268,7 +235,7 @@ public class MicroPhotoService extends Service {
// alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent);
}
private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List<Long> schedules) {
private static void registerPhotoTimer(Context context, int channel, int preset, long ts, long timeout, List<Long> schedules) {
// 创建延迟意图
Intent alarmIntent = new Intent();
@ -277,33 +244,39 @@ public class MicroPhotoService extends Service {
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 += schedules.get(idx).toString() + " ";
channelStr += "CH=" + ((val & 0XFF0000) >> 16) + "-PR=" + ((val & 0XFF00) >> 8) + " ";
}
alarmIntent.putExtra(EXTRA_PARAM_TIME, ts);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
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, "Register Photo Timer: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " Channels=" + channelStr);
Log.d(TAG, "PhotoTimer Reg: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " Channels=" + channelStr);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
}
private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List<Long> schedules) {
// private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>();
registerPhotoTimer(this.getApplicationContext(), channel, preset, ts, timeout, schedules);
}
public boolean registerTimer(long uid, int timeout) {
// private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>();
public boolean registerTimer(long uid, int timeout, long times) {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TIMEOUT);
alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid);
alarmIntent.putExtra(EXTRA_PARAM_TIMEOUT, timeout);
alarmIntent.putExtra(EXTRA_PARAM_TIMES, times);
alarmIntent.putExtra(EXTRA_PARAM_ELASPED_TIMES, 0L);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
@ -311,6 +284,28 @@ public class MicroPhotoService extends Service {
return registerTimer(pendingIntent, uid, timeout);
}
private void setDefaultDataSubId(int subId) {
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
try {
Method method = subscriptionManager.getClass().getDeclaredMethod("setDefaultDataSubId", int.class);
method.invoke(subscriptionManager, subId);
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
Method method1 = telephonyManager.getClass().getDeclaredMethod("setDataEnabled", boolean.class);
method1.invoke(telephonyManager, true);
} catch (Exception e) {
Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage());
}
}
private int getDefaultDataSubId() {
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
try {
Method method = subscriptionManager.getClass().getDeclaredMethod("getDefaultDataSubscriptionId");
return (int) method.invoke(subscriptionManager);
} catch (Exception e) {
Log.e(TAG, "wjz debug getDefaultDataSubId: error is " + e.getMessage());
}
return 0;
}
public boolean registerTimer(PendingIntent pendingIntent, long uid, int timeout) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
@ -320,7 +315,6 @@ public class MicroPhotoService extends Service {
Log.i(TAG, "RegTimer:" + uid + " timeout=" + timeout);
return true;
}
public boolean unregisterTimer(long uid) {
Long uidObj = Long.valueOf(uid);
@ -336,10 +330,9 @@ public class MicroPhotoService extends Service {
return true;
}
private boolean registerCaptureSchedule(long startTime, long baseTime) {
long[] photoTimeData = getPhotoTimeData();
long[] photoTimeData = getPhotoTimeData(mHandler);
if (photoTimeData == null) {
return false;
}
@ -373,9 +366,16 @@ public class MicroPhotoService extends Service {
preset = (short) ((val & 0xFF00L) >> 8);
schedules.add(Long.valueOf(val));
Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset);
} else if (ts > currentTs) {
break;
} else {
channel = (short) ((val & 0xFF0000L) >> 16);
preset = (short) ((val & 0xFF00L) >> 8);
Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset);
schedules.add(Long.valueOf(val));
}
}
@ -398,11 +398,14 @@ public class MicroPhotoService extends Service {
public static void takePhoto(Context context, int channel, int preset, boolean photoOrVideo) {
Intent intent = new Intent(ACTION_TAKE_PHOTO_MANUALLY);
intent.putExtra(EXTRA_PARAM_CHANNEL, channel);
intent.putExtra(EXTRA_PARAM_PRESET, preset);
intent.putExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, photoOrVideo);
context.sendBroadcast(intent);
List<Long> schedules = new ArrayList<>();
long ts = System.currentTimeMillis() / 1000;
long val = (ts << 24);
val |= ((long)channel << 16);
val |= ((long)preset << 8);
schedules.add(Long.valueOf(val));
registerPhotoTimer(context, channel, preset, System.currentTimeMillis() / 1000, 0, schedules);
}
@Override
@ -420,13 +423,42 @@ public class MicroPhotoService extends Service {
Log.d(TAG, "Received user starts foreground intent");
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
// Start the locker receiver
final ScreenActionReceiver screenactionreceiver = new ScreenActionReceiver();
connect();
registerReceiver(screenactionreceiver, screenactionreceiver.getFilter());
connect();
// File path = getApplicationContext().getFilesDir();
String appPath = buildAppDir(this.getApplicationContext());
String ip = intent.getStringExtra("server");
int port = intent.getIntExtra("port", 0);
String cmdid = intent.getStringExtra("cmdid");
int protocol = intent.getIntExtra("protocol", 0);
Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid + " protocol" + protocol);
mHandler = init(appPath, ip, port, cmdid, protocol);
// Start the locker receiver
if (mHandler !=0) {
Date date = new Date();
long nowTs = date.getTime() / 1000;
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
long startTime = date.getTime() / 1000;
long baseTime = nowTs - startTime;
registerCaptureSchedule(startTime, baseTime);
}
// registerPhotoTimer();
break;
case ACTION_STOP:
unregisterReceiver(screenactionreceiver);
stopForeground(true);
stopSelf();
break;
@ -438,6 +470,31 @@ public class MicroPhotoService extends Service {
return START_NOT_STICKY;
}
public void requestWakelock(String name, long timeout) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, name);
PowerManager.WakeLock wl2 = null;
synchronized (mWakeLocks) {
wl2 = mWakeLocks.replace(name, wl);
}
if (wl2 != null) {
wl2.release();
}
if (timeout == 0) wl.acquire();
else wl.acquire(timeout);
}
public void releaseWakelock(String name) {
PowerManager.WakeLock wl = null;
synchronized (mWakeLocks) {
wl = mWakeLocks.get(name);
mWakeLocks.remove(name);
}
if (wl != null) {
wl.release();
}
}
private void connect() {
// after 10 seconds its connected
new android.os.Handler().postDelayed(
@ -510,188 +567,42 @@ public class MicroPhotoService extends Service {
.setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
notificationBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
}
return notificationBuilder.build();
}
protected String getNetworkType() {
// ConnectionManager instance
ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
// If not connected, "-" will be displayed
if (ni == null || !ni.isConnected()) return "";
// If Connected to Wifi
if (ni.getType() == ConnectivityManager.TYPE_WIFI) return "WIFI";
// If Connected to Mobile
String subTypeName = "";
if (ni.getType() == ConnectivityManager.TYPE_MOBILE) {
int subType = ni.getSubtype();
switch (subType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
case TelephonyManager.NETWORK_TYPE_GSM:
subTypeName = "2G";
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
subTypeName = "3G";
break;
case TelephonyManager.NETWORK_TYPE_LTE:
case TelephonyManager.NETWORK_TYPE_IWLAN:
case 19:
subTypeName = "4G";
break;
case TelephonyManager.NETWORK_TYPE_NR:
subTypeName = "5G";
break;
default:
subTypeName = "";
break;
}
}
return subTypeName;
}
public static void getPhoneState(Context context) {
final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener MyPhoneListener = new PhoneStateListener() {
@Override
//获取对应网络的ID这个方法在这个程序中没什么用处
public void onCellLocationChanged(CellLocation location) {
if (location instanceof GsmCellLocation) {
int CID = ((GsmCellLocation) location).getCid();
} else if (location instanceof CdmaCellLocation) {
int ID = ((CdmaCellLocation) location).getBaseStationId();
}
}
//系统自带的服务监听器,实时监听网络状态
@Override
public void onServiceStateChanged(ServiceState serviceState) {
super.onServiceStateChanged(serviceState);
}
//这个是我们的主角,就是获取对应网络信号强度
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
//这个ltedbm 是4G信号的值
String signalinfo = signalStrength.toString();
String[] parts = signalinfo.split(" ");
String ltedbm = parts[9];
//这个dbm 是2G和3G信号的值
int asu = signalStrength.getGsmSignalStrength();
int dbm = -113 + 2 * asu;
if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
Log.i("NetWorkUtil", "网络LTE 信号强度:" + ltedbm + "======Detail:" + signalinfo);
} else if (telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSDPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_HSUPA ||
telephonyManager.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS) {
String bin;
if (dbm > -75) {
bin = "网络很好";
} else if (dbm > -85) {
bin = "网络不错";
} else if (dbm > -95) {
bin = "网络还行";
} else if (dbm > -100) {
bin = "网络很差";
} else {
bin = "网络错误";
}
Log.i("NetWorkUtil", "网络WCDMA 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
} else {
String bin;
if (asu < 0 || asu >= 99) bin = "网络错误";
else if (asu >= 16) bin = "网络很好";
else if (asu >= 8) bin = "网络不错";
else if (asu >= 4) bin = "网络还行";
else bin = "网络很差";
Log.i("NetWorkUtil", "网络GSM 信号值:" + dbm + "========强度:" + bin + "======Detail:" + signalinfo);
}
super.onSignalStrengthsChanged(signalStrength);
}
};
telephonyManager.listen(MyPhoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
/*
public boolean takePhoto(short channel, short preset, String path) {
boolean res = DSCameraManager.getInstace().takePhoto(path, channel, 0, 0);
public static String buildAppDir(Context contxt) {
if (!res) {
File[] paths = contxt.getExternalFilesDirs(null);
int idx = 0;
do {
res = DSCameraManager.getInstace().isCameraServiceOK();
if (!res)
{
try {
Thread.sleep(1000L);
} catch (InterruptedException ex) {
// ex.printStackTrace();
}
}
} while(idx < 6);
if (DSCameraManager.getInstace().isCameraServiceOK()) {
res = DSCameraManager.getInstace().takePhoto(path, channel, 0, 0);
}
if (paths == null || paths.length == 0) {
return null;
}
return res;
File path = paths[0];
if (!path.exists() && !path.mkdirs()) {
return null;
}
String p = path.getAbsolutePath();
if (!p.endsWith(File.separator)) {
p += File.separator;
}
return p;
}
*/
@Override
public void onDestroy() {
stateService = STATE_SERVICE.NOT_CONNECTED;
uninit();
DSCameraManager.getInstace().unInit();
super.onDestroy();
}
public static String buildPhotoDir(Context contxt, int channel) {
// File path = new File(Environment.getExternalStorageDirectory(), "com.xinyingpower.mp/photos/");
protected boolean updateTime(long timeInMillis) {
boolean res = false;
try {
// Calendar c = Calendar.getInstance();
// c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(timeInMillis);
res = true;
} catch (Exception ex) {
int aa = 0;
String appDir = buildAppDir(contxt);
if (appDir == null) {
return null;
}
return true;
}
public String buildPhotoDir(int channel) {
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/photos/");
File path = new File(appDir, "photos/");
if (!path.exists() && !path.mkdirs()) {
return null;
@ -711,16 +622,38 @@ public class MicroPhotoService extends Service {
}
public boolean updateTime(long timeInMillis) {
boolean res = false;
try {
// Calendar c = Calendar.getInstance();
// c.set(2010, 1, 1, 12, 00, 00);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(timeInMillis);
res = true;
} catch (Exception ex) {
int aa = 0;
}
return true;
}
/*
TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
// for example value of first element
CellInfoGsm cellInfoGsm = (CellInfoGsm)telephonyManager.getAllCellInfo().get(0);
CellSignalStrengthGsm cellSignalStrengthGsm = cellInfoGsm.getCellSignalStrength();
cellSignalStrengthGsm.getDbm();
*/
protected native boolean init(String appPath, String ip, int port, String cmdid);
protected native long getHeartbeatDuration();
protected native long[] getPhotoTimeData();
protected native long[] getNextScheduleItem();
protected native boolean notifyToTakePhoto(int channel, int preset, long scheduleTime, String path, String fileName, boolean sendToCma);
protected native boolean sendHeartbeat();
protected native boolean fireTimeout(long uid);
protected native boolean uninit();
protected native long init(String appPath, String ip, int port, String cmdid, int protocol);
protected native long getHeartbeatDuration(long handler);
protected native long[] getPhotoTimeData(long handler);
// protected native long[] getNextScheduleItem(long handler);
protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, String path, String fileName, boolean sendToCma);
protected native boolean sendHeartbeat(long handler);
protected native boolean fireTimeout(long handler, long uid, long times);
protected native boolean uninit(long handler);
protected long mHandler = 0;
private AlarmReceiver alarmReceiver = null;
private ScreenActionReceiver screenactionreceiver = null;
}

@ -15,7 +15,6 @@ public class ScreenActionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//LOG
StringBuilder sb = new StringBuilder();
sb.append("Action: " + intent.getAction() + "\n");
@ -34,8 +33,6 @@ public class ScreenActionReceiver extends BroadcastReceiver {
//Run the locker
context.startService(new Intent(context, FloatingWindow.class));
}
else if(Intent.ACTION_SCREEN_OFF.equals(action))

@ -4,91 +4,156 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="false"
android:orientation="horizontal"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:id="@+id/textViewCmdId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="38dp"
android:layout_marginTop="38dp"
android:text="Server"
android:layout_marginLeft="20dp"
android:text="CMDID"
app:layout_constraintBottom_toBottomOf="@+id/cmdid"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="@+id/cmdid" />
<EditText
android:id="@+id/server"
android:id="@+id/cmdid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="114dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:ems="10"
android:inputType=""
app:layout_constraintBottom_toBottomOf="@+id/textView"
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintTop_toTopOf="@+id/textView" />
android:text="XY-ANDROIDSIM-001"
app:layout_constraintLeft_toRightOf="@+id/textViewCmdId"
app:layout_constraintTop_toTopOf="parent" />
<Spinner
android:id="@+id/protocol"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
app:layout_constraintLeft_toRightOf="@+id/cmdid"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/cmdid" />
<TextView
android:id="@+id/textView2"
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="52dp"
android:gravity="center"
android:text="Port"
app:layout_constraintLeft_toLeftOf="@+id/textView"
app:layout_constraintTop_toBottomOf="@+id/textView" />
android:layout_marginTop="20dp"
android:text="Server"
app:layout_constraintBottom_toBottomOf="@+id/server"
app:layout_constraintStart_toStartOf="@id/textViewCmdId"
app:layout_constraintTop_toTopOf="@+id/server" />
<EditText
android:id="@+id/port"
android:layout_width="wrap_content"
android:id="@+id/server"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType=""
android:text="Name"
app:layout_constraintBottom_toBottomOf="@+id/textView2"
app:layout_constraintLeft_toLeftOf="@+id/server"
app:layout_constraintLeft_toRightOf="@+id/textView2"
app:layout_constraintTop_toTopOf="@+id/textView2" />
android:text="47.96.238.157"
app:layout_constraintStart_toStartOf="@+id/cmdid"
app:layout_constraintTop_toBottomOf="@+id/cmdid" />
<EditText
android:id="@+id/port"
android:layout_width="64dp"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:text="6891"
app:layout_constraintBottom_toBottomOf="@+id/server"
app:layout_constraintLeft_toRightOf="@+id/server"
app:layout_constraintTop_toTopOf="@+id/server" />
<Button
android:id="@+id/startServBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="24dp"
android:text="Start"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/port"
/>
<Button
android:id="@+id/stopServBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="24dp"
android:enabled="false"
android:text="Stop" />
android:text="Stop"
app:layout_constraintStart_toEndOf="@+id/startServBtn"
app:layout_constraintTop_toBottomOf="@+id/port" />
<Button
android:id="@+id/startServBtn"
android:id="@+id/simchange"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start" />
android:layout_marginStart="20dp"
android:layout_marginTop="24dp"
android:text="sim卡获取"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" />
<Button
android:id="@+id/takePhotoBtn2"
android:id="@+id/simchange2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take Photo2" />
android:layout_marginStart="4dp"
android:layout_marginTop="24dp"
android:text="切换sim2"
app:layout_constraintStart_toEndOf="@+id/simchange"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" />
<Button
android:id="@+id/takePhotoBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take Photo" />
android:layout_marginTop="16dp"
android:text="TK Photo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button
android:id="@+id/simchange"
android:id="@+id/takePhotoBtn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="sim卡获取" />
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="TP 2"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button
android:id="@+id/simchange2"
android:id="@+id/takePhotoBtn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="切换sim2" />
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="TP 3"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn2"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button
android:id="@+id/takePhotoBtn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:text="TP 4"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn3"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button
android:id="@+id/gps"
android:layout_width="wrap_content"
@ -142,11 +207,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.929" />
app:layout_constraintTop_toTopOf="parent" />
<SurfaceView
android:id="@+id/surfaceView"

@ -18,6 +18,7 @@ android.nonTransitiveRClass=true
android.useAndroidX=true
android.enableJetifier=true
opencvsdk=D:/Workspace/deps/opencv-mobile-4.6.0-android
# opencvsdk=D:/Workspace/deps/opencv-mobile-4.8.0-android
opencvsdk=D:/Workspace/deps/opencv-v5
asioroot=D:/Workspace/deps/asio-1.28.0
evpproot=D:/Workspace/Github/evpp
Loading…
Cancel
Save