优化android拍照流程

serial
Matthew 2 years ago
parent d514b2889e
commit caa31cb865

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

@ -17,6 +17,7 @@
#include "Camera2Reader.h" #include "Camera2Reader.h"
bool GetJniEnv(JavaVM *vm, JNIEnv **env) bool GetJniEnv(JavaVM *vm, JNIEnv **env)
{ {
bool did_attach_thread = false; bool did_attach_thread = false;
@ -75,7 +76,6 @@ Java_com_xinyingpower_microphoto_MainActivity_takePhoto(
unsigned char id = (unsigned char)channel - 1; unsigned char id = (unsigned char)channel - 1;
Camera2Reader *camera = new Camera2Reader(id); Camera2Reader *camera = new Camera2Reader(id);
const char *pathStr = env->GetStringUTFChars(path, 0); const char *pathStr = env->GetStringUTFChars(path, 0);
const char *fileNameStr = env->GetStringUTFChars(fileName, 0); const char *fileNameStr = env->GetStringUTFChars(fileName, 0);
@ -143,7 +143,7 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto(
return JNI_FALSE; 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; return JNI_TRUE;
} }
@ -207,8 +207,13 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getHeartbeatDuration(
JNIEnv* env, JNIEnv* env,
jobject pThis, jlong handler) { jobject pThis, jlong handler) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return DEFAULT_HEARTBEAT_DURATION;
}
return 60000; return pTerminal->GetHeartbeatDuration();
} }
extern "C" JNIEXPORT jlongArray JNICALL extern "C" JNIEXPORT jlongArray JNICALL
@ -276,7 +281,7 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
return data; return data;
} }
/*
extern "C" JNIEXPORT jlongArray JNICALL extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem( Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem(
JNIEnv* env, JNIEnv* env,
@ -341,3 +346,4 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getNextScheduleItem(
return data; return data;
} }
*/

@ -43,7 +43,7 @@
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env); extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
#define WAKELOCK_NAME "NDK_WK_"
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their // This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
// ranges // ranges
// are normalized to eight bits. // are normalized to eight bits.
@ -142,30 +142,45 @@ 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)
{
return m_dev->OnImageReady(rgb);
}
return false;
}
void CPhoneDevice::CPhoneCamera::on_error(const std::string& msg) const
{ {
if (m_dev != NULL) if (m_dev != NULL)
{ {
m_dev->OnImageReady(rgb); m_dev->onError(msg);
} }
} }
CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service) CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
{ {
mCamera = NULL;
m_listener = NULL;
mHeartbeatStartTime = 0;
mHeartbeatDuration = 0;
m_vm = vm; m_vm = vm;
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool attached = GetJniEnv(m_vm, &env);
m_javaService = env->NewGlobalRef(service); m_javaService = env->NewGlobalRef(service);
mHeartbeatStartTime = 0;
mHeartbeatDuration = 0;
jclass classService = env->GetObjectClass(m_javaService); jclass classService = env->GetObjectClass(m_javaService);
mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JI)Z"); mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JI)Z");
mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V"); mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V");
mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z"); mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z");
mUpdateTimeMid = env->GetMethodID(classService, "updateTime", "(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); env->DeleteLocalRef(classService);
if (attached) if (attached)
@ -173,7 +188,8 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
vm->DetachCurrentThread(); vm->DetachCurrentThread();
} }
m_timerUidFeed = time(NULL); m_timerUidFeed = time(NULL) * 1000;
m_wakelockIdFeed = (unsigned long)m_timerUidFeed;
} }
CPhoneDevice::~CPhoneDevice() CPhoneDevice::~CPhoneDevice()
@ -219,11 +235,9 @@ bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
__system_property_get("ro.product.model", value); __system_property_get("ro.product.model", value);
properties[PROP_MODEL] = value; properties[PROP_MODEL] = value;
__system_property_get("ro.product.manufacturer", value); __system_property_get("ro.product.manufacturer", value);
properties[PROP_BS_MANU] = value; properties[PROP_BS_MANU] = value;
properties[PROP_BS_ID] = "SHXY"; properties[PROP_BS_ID] = "SHXY";
__system_property_get("ro.build.version.release", value); __system_property_get("ro.build.version.release", value);
@ -238,7 +252,6 @@ bool CPhoneDevice::QuerySystemProperties(map<string, string>& properties)
__system_property_get("phone.imei", value); __system_property_get("phone.imei", value);
properties[PROP_IMEI] = value; properties[PROP_IMEI] = value;
return true; return true;
} }
@ -296,6 +309,54 @@ bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
return false; return false;
} }
unsigned long CPhoneDevice::RequestWakelock(unsigned long timeout)
{
unsigned long wakelockId = m_wakelockIdFeed.fetch_add(1);
std::string name = WAKELOCK_NAME;
name += to_string(wakelockId);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
{
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);
m_vm->DetachCurrentThread();
}
// return (ret == JNI_TRUE);
return wakelockId;
}
bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock)
{
std::string name = WAKELOCK_NAME;
name += to_string(wakelock);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
{
jstring jname = env->NewStringUTF(name.c_str());
env->CallVoidMethod(m_javaService, mReleaseWakelockMid, jname);
env->DeleteLocalRef(jname);
// env->ReleaseStringUTFChars(jname, name.c_str());
m_vm->DetachCurrentThread();
}
return true;
}
bool CPhoneDevice::FireTimer(timer_uid_t uid) bool CPhoneDevice::FireTimer(timer_uid_t uid)
{ {
std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid); std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid);
@ -345,43 +406,91 @@ 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) bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path)
{ {
if (mCamera != NULL)
{
delete mCamera;
mCamera = NULL;
}
LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset); LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
mPhotoInfo = photoInfo; mPhotoInfo = photoInfo;
mPath = path; mPath = path;
mOsds = osds; mOsds = osds;
mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height); 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; 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; int baseline = 0;
cv::Size textSize, textSize2; 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) for (vector<OSD_INFO>::const_iterator it = mOsds.cbegin(); it != mOsds.cend(); ++it)
{ {
// getTextSize(value, font, scale, 1, &bottom); // getTextSize(value, font, scale, 1, &bottom);
textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, 1, 4, &baseline); textSize = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness1, &baseline);
cv::Point pt(it->x, it->y + textSize.height); cv::Point pt(it->x * ratio, it->y * ratio + textSize.height);
putText(mat, it->text, pt, cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(0, 0, 0), 4,cv::LINE_AA); 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, 1, 2, &baseline); textSize2 = cv::getTextSize(it->text, cv::FONT_HERSHEY_COMPLEX, fontScale, thickness2, &baseline);
pt.y -= (textSize.height - textSize2.height) / 2; 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; vector <int> compression_params;
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
compression_params.push_back(80); compression_params.push_back(mPhotoInfo.quality);
ALOGI("Will write photo: %s", mPath.c_str());
bool res = cv::imwrite(mPath.c_str(), mat, compression_params); bool res = cv::imwrite(mPath.c_str(), mat, compression_params);
if (!res)
{
ALOGE("Failed to write photo: %s", mPath.c_str());
}
// mCamera->close();
TakePhotoCb(res, mPhotoInfo, mPath, time(NULL)); TakePhotoCb(res, mPhotoInfo, mPath, time(NULL));
delete mCamera; // delete mCamera;
mCamera = NULL; // mCamera = NULL;
return res;
}
void CPhoneDevice::onError(const std::string& msg) const
{
// XFLOG(XFLOG_SEVERITY_ERROR, "Failed to Take Photo: %s", msg.c_str());
ALOGE("Failed to Take Photo: %s", msg.c_str());
// mCamera->close();
TakePhotoCb(false, mPhotoInfo, mPath, 0);
} }
std::string CPhoneDevice::GetFileName() const std::string CPhoneDevice::GetFileName() const

@ -25,7 +25,7 @@
#include <Client/Device.h> #include <Client/Device.h>
#include <string> #include <string>
#include "Camera2Helper.h" #include "camera2/Camera2Helper.h"
#include "camera2/ndkcamera.h" #include "camera2/ndkcamera.h"
@ -41,8 +41,11 @@ public:
virtual bool Reboot(); virtual bool Reboot();
virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout); 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 bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path);
virtual bool CloseCamera();
virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout); virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout);
virtual bool UnregisterTimer(timer_uid_t uid); 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);
@ -65,7 +68,8 @@ protected:
return false; return false;
} }
void OnImageReady(const cv::Mat& mat) const; bool OnImageReady(const cv::Mat& mat) const;
void onError(const std::string& msg) const;
protected: protected:
@ -77,18 +81,23 @@ protected:
jmethodID mUnregisterTimerMid; jmethodID mUnregisterTimerMid;
jmethodID mUpdateTimeMid; jmethodID mUpdateTimeMid;
jmethodID mRequestWakelockMid;
jmethodID mReleaseWakelockMid;
std::string mPath; std::string mPath;
IDevice::PHOTO_INFO mPhotoInfo; IDevice::PHOTO_INFO mPhotoInfo;
vector<IDevice::OSD_INFO> mOsds; vector<IDevice::OSD_INFO> mOsds;
IListener* m_listener; IListener* m_listener;
atomic_ulong m_timerUidFeed; atomic_ulong m_timerUidFeed;
atomic_ulong m_wakelockIdFeed;
std::map<IDevice::timer_uid_t, unsigned long> mTimers; std::map<IDevice::timer_uid_t, unsigned long> mTimers;
class CPhoneCamera : public NdkCamera { class CPhoneCamera : public NdkCamera {
public: public:
CPhoneCamera(CPhoneDevice* dev, int32_t width, int32_t height); 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: protected:
CPhoneDevice* m_dev; CPhoneDevice* m_dev;
@ -98,7 +107,6 @@ protected:
time_t mHeartbeatStartTime; time_t mHeartbeatStartTime;
unsigned int mHeartbeatDuration; unsigned int mHeartbeatDuration;
}; };

@ -25,7 +25,7 @@
#include <Client/Device.h> #include <Client/Device.h>
#include <string> #include <string>
#include "Camera2Helper.h" #include "camera2/Camera2Helper.h"
class CPhoneDevice2 : public IDevice class CPhoneDevice2 : public IDevice
{ {

@ -19,6 +19,7 @@
#include <android/log.h> #include <android/log.h>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "mat.h" #include "mat.h"
#include "Camera2Helper.h"
static void onDisconnected(void* context, ACameraDevice* device) static void onDisconnected(void* context, ACameraDevice* device)
{ {
@ -27,7 +28,9 @@ static void onDisconnected(void* context, ACameraDevice* device)
static void onError(void* context, ACameraDevice* device, int error) 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) static void onImageAvailable(void* context, AImageReader* reader)
@ -76,6 +79,8 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
camera_orientation = 0; camera_orientation = 0;
m_firstFrame = true; m_firstFrame = true;
mWidth = width;
mHeight = height;
camera_manager = 0; camera_manager = 0;
camera_device = 0; camera_device = 0;
@ -87,22 +92,7 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
capture_session_output = 0; capture_session_output = 0;
capture_session = 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() NdkCamera::~NdkCamera()
@ -124,7 +114,7 @@ NdkCamera::~NdkCamera()
int NdkCamera::open(const char* cameraId) 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; // camera_facing = _camera_facing;
@ -132,6 +122,10 @@ int NdkCamera::open(const char* cameraId)
// find front camera // find front camera
std::string camera_id; std::string camera_id;
bool foundIt = false;
DisplayDimension disp(mWidth, mHeight);
DisplayDimension foundRes = disp;
{ {
ACameraIdList* camera_id_list = 0; ACameraIdList* camera_id_list = 0;
ACameraManager_getCameraIdList(camera_manager, &camera_id_list); ACameraManager_getCameraIdList(camera_manager, &camera_id_list);
@ -181,6 +175,36 @@ int NdkCamera::open(const char* cameraId)
camera_orientation = orientation; 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_free(camera_metadata); ACameraMetadata_free(camera_metadata);
break; break;
@ -189,11 +213,31 @@ int NdkCamera::open(const char* cameraId)
ACameraManager_deleteCameraIdList(camera_id_list); ACameraManager_deleteCameraIdList(camera_id_list);
} }
if (camera_id.empty()) if (camera_id.empty() || !foundIt)
{ {
return 1; return 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); __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "open %s %d", camera_id.c_str(), camera_orientation);
// open camera // open camera
@ -203,16 +247,20 @@ int NdkCamera::open(const char* cameraId)
camera_device_state_callbacks.onDisconnected = onDisconnected; camera_device_state_callbacks.onDisconnected = onDisconnected;
camera_device_state_callbacks.onError = onError; 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)); std::this_thread::sleep_for(std::chrono::milliseconds(128));
// capture request // capture request
{ {
ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request); res = ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request);
ACameraOutputTarget_create(image_reader_surface, &image_reader_target); res = ACameraOutputTarget_create(image_reader_surface, &image_reader_target);
ACaptureRequest_addTarget(capture_request, image_reader_target); res = ACaptureRequest_addTarget(capture_request, image_reader_target);
} }
// capture session // capture session
@ -223,7 +271,7 @@ int NdkCamera::open(const char* cameraId)
camera_capture_session_state_callbacks.onReady = onSessionReady; camera_capture_session_state_callbacks.onReady = onSessionReady;
camera_capture_session_state_callbacks.onClosed = onSessionClosed; 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); ACaptureSessionOutput_create(image_reader_surface, &capture_session_output);
@ -250,7 +298,7 @@ int NdkCamera::open(const char* cameraId)
void NdkCamera::close() 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) if (capture_session)
{ {
@ -316,7 +364,6 @@ void NdkCamera::onImageAvailable(AImageReader* reader)
// return; // return;
} }
int32_t format; int32_t format;
AImage_getFormat(image, &format); AImage_getFormat(image, &format);
@ -401,7 +448,11 @@ void NdkCamera::onImageAvailable(AImageReader* reader)
ACameraCaptureSession_stopRepeating(capture_session); ACameraCaptureSession_stopRepeating(capture_session);
} }
void NdkCamera::on_image(const cv::Mat& rgb) const void NdkCamera::on_error(const std::string& msg) const
{
}
bool NdkCamera::on_image(const cv::Mat& rgb) const
{ {
} }
@ -461,6 +512,12 @@ void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_hei
// cv::Mat rgb(h, w, CV_8UC3); // cv::Mat rgb(h, w, CV_8UC3);
// ncnn::yuv420sp2rgb_nv12(nv21, w, h, rgb.data); // ncnn::yuv420sp2rgb_nv12(nv21, w, h, rgb.data);
on_image(rgb); if (on_image(rgb))
{
if (capture_session)
{
ACameraCaptureSession_stopRepeating(capture_session);
}
}
} }

@ -33,7 +33,8 @@ public:
void close(); void close();
void onImageAvailable(AImageReader* reader); 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; virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const;
@ -41,6 +42,9 @@ public:
int camera_facing; int camera_facing;
int camera_orientation; int camera_orientation;
bool m_firstFrame; bool m_firstFrame;
int32_t mWidth;
int32_t mHeight;
std::string mCameraId;
private: private:
ACameraManager* camera_manager; ACameraManager* camera_manager;

@ -77,7 +77,9 @@ class counting_semaphore {
static void throw_errno(const char* what_arg) static void throw_errno(const char* what_arg)
{ {
#ifndef __ANDROID__
throw std::system_error(std::error_code(errno, std::generic_category()), what_arg); 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) 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;
}
}

@ -1,6 +1,7 @@
package com.xinyingpower.microphoto; package com.xinyingpower.microphoto;
import android.Manifest; import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -9,6 +10,7 @@ import android.hardware.Camera;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.Handler; import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
@ -31,6 +33,8 @@ import java.lang.reflect.Method;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import android.content.SharedPreferences;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
@ -45,12 +49,18 @@ public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding; private ActivityMainBinding binding;
private int defaultDataSubId; private int defaultDataSubId;
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater()); binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display defaultDisplay = windowManager.getDefaultDisplay(); Display defaultDisplay = windowManager.getDefaultDisplay();
@ -59,11 +69,17 @@ public class MainActivity extends AppCompatActivity {
Log.d(TAG, "Screen Size: " + width + " x " + height); Log.d(TAG, "Screen Size: " + width + " x " + height);
SharedPreferences sp = MainActivity.this.getApplicationContext().getSharedPreferences("xymp", Context.MODE_PRIVATE);
binding.cmdid.setText(sp.getString("cmdid", "XY-ANDROIDSIM-001"));
binding.server.setText(sp.getString("server", "47.96.238.157"));
binding.port.setText(sp.getString("port", "6891"));
this.binding.startServBtn.setOnClickListener(new View.OnClickListener() { this.binding.startServBtn.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
String[] accessPermissions = new String[]{ String[] accessPermissions = new String[]{
Manifest.permission.CAMERA, Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
@ -93,8 +109,19 @@ public class MainActivity extends AppCompatActivity {
String fileName = buildPhotoFileName(channel, 255); String fileName = buildPhotoFileName(channel, 255);
// MainActivity.this.takePhoto(channel, 255, path, fileName); // MainActivity.this.takePhoto(channel, 255, path, fileName);
SharedPreferences sp = MainActivity.this.getApplicationContext().getSharedPreferences("xymp", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("cmdid", MainActivity.this.binding.cmdid.getText().toString());
editor.putString("server", MainActivity.this.binding.server.getText().toString());
editor.putString("port", MainActivity.this.binding.port.getText().toString());
editor.commit();
Intent intent = new Intent(MainActivity.this, MicroPhotoService.class); Intent intent = new Intent(MainActivity.this, MicroPhotoService.class);
intent.setAction(MicroPhotoService.ACTION_START); intent.setAction(MicroPhotoService.ACTION_START);
intent.putExtra("cmdid", MainActivity.this.binding.cmdid.getText().toString());
intent.putExtra("server", MainActivity.this.binding.server.getText().toString());
String port = MainActivity.this.binding.port.getText().toString();
intent.putExtra("port", Integer.parseInt(port));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
MainActivity.this.startForegroundService(intent); MainActivity.this.startForegroundService(intent);
@ -187,7 +214,7 @@ public class MainActivity extends AppCompatActivity {
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
binding.startServBtn.performClick(); // binding.startServBtn.performClick();
} }
}; };
handler.postDelayed(runnable, 1000); handler.postDelayed(runnable, 1000);

@ -16,6 +16,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.os.Environment; import android.os.Environment;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
@ -35,8 +36,6 @@ import android.util.Log;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import android.widget.Toast; import android.widget.Toast;
import com.dowse.camera.client.DSCameraManager;
import java.io.File; import java.io.File;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@ -44,6 +43,7 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -87,23 +87,6 @@ public class MicroPhotoService extends Service {
private final static String FOREGROUND_CHANNEL_ID = "foreground_channel_id"; private final static String FOREGROUND_CHANNEL_ID = "foreground_channel_id";
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 class STATE_SERVICE { public static class STATE_SERVICE {
public static final int CONNECTED = 10; public static final int CONNECTED = 10;
public static final int NOT_CONNECTED = 0; public static final int NOT_CONNECTED = 0;
@ -111,6 +94,10 @@ public class MicroPhotoService extends Service {
private NotificationManager mNotificationManager; private NotificationManager mNotificationManager;
private PowerManager.WakeLock wakeLock = null;
private Map<String, PowerManager.WakeLock> mWakeLocks = new HashMap<>();
private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000 private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000
private long mNextHeartbeatTime = 0; private long mNextHeartbeatTime = 0;
@ -130,10 +117,15 @@ public class MicroPhotoService extends Service {
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MicroPhoto::MyWakelockTag");
wakeLock.acquire();
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
stateService = STATE_SERVICE.NOT_CONNECTED; stateService = STATE_SERVICE.NOT_CONNECTED;
getPhoneState(this.getApplicationContext()); DeviceUtil.getPhoneState(this.getApplicationContext());
alarmReceiver = new AlarmReceiver(this); alarmReceiver = new AlarmReceiver(this);
// 注册广播接受者 // 注册广播接受者
@ -155,52 +147,15 @@ public class MicroPhotoService extends Service {
// alarmManager.cancel(aci.getShowIntent()); // alarmManager.cancel(aci.getShowIntent());
} }
} }
// alarmManager.cancel(); // alarmManager.cancel();
boolean res = false; 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);
*/
// Environment.getExternalStoragePublicDirectory(String) // 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-003";
mHandler = init(appPath, ip, port, cmdid);
// registerHeartbeatTimer(getHeartbeatDuration()); // registerHeartbeatTimer(getHeartbeatDuration());
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();
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
@ -210,7 +165,17 @@ public class MicroPhotoService extends Service {
mHandler = 0; mHandler = 0;
unregisterReceiver(alarmReceiver); unregisterReceiver(alarmReceiver);
DSCameraManager.getInstace().unInit();
if (wakeLock != null) {
wakeLock.release();
wakeLock = null;
}
for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) {
entry.getValue().release();
}
mWakeLocks.clear();
super.onDestroy(); super.onDestroy();
} }
@ -241,7 +206,7 @@ public class MicroPhotoService extends Service {
int channel = (int) ((val & 0xFF0000L) >> 16); int channel = (int) ((val & 0xFF0000L) >> 16);
int preset = (int) ((val & 0xFF00L) >> 8); int preset = (int) ((val & 0xFF00L) >> 8);
mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), true); mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), true);
} }
} }
@ -262,7 +227,8 @@ public class MicroPhotoService extends Service {
boolean photoOrVideo = intent.getBooleanExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, true); boolean photoOrVideo = intent.getBooleanExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, true);
long ts = System.currentTimeMillis() / 1000; long ts = System.currentTimeMillis() / 1000;
mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo); Log.i(TAG, "Take Photo CH=" + channel + " PR=" + preset);
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)) { } else if (TextUtils.equals(ACTION_TIMEOUT, action)) {
long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0); long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0);
Log.i(TAG, "Timeout:" + uid); Log.i(TAG, "Timeout:" + uid);
@ -431,9 +397,16 @@ public class MicroPhotoService extends Service {
preset = (short) ((val & 0xFF00L) >> 8); preset = (short) ((val & 0xFF00L) >> 8);
schedules.add(Long.valueOf(val)); schedules.add(Long.valueOf(val));
Log.i(TAG, "Reg Photo Timer: CH=" + channel + " PR=" + preset);
} else if (ts > currentTs) { } else if (ts > currentTs) {
break; break;
} else { } else {
channel = (short) ((val & 0xFF0000L) >> 16);
preset = (short) ((val & 0xFF00L) >> 8);
Log.i(TAG, "Reg Photo Timer: CH=" + channel + " PR=" + preset);
schedules.add(Long.valueOf(val)); schedules.add(Long.valueOf(val));
} }
} }
@ -478,11 +451,33 @@ public class MicroPhotoService extends Service {
Log.d(TAG, "Received user starts foreground intent"); Log.d(TAG, "Received user starts foreground intent");
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification()); startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
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");
Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid);
mHandler = init(appPath, ip, port, cmdid);
// Start the locker receiver // Start the locker receiver
registerReceiver(screenactionreceiver, screenactionreceiver.getFilter()); registerReceiver(screenactionreceiver, screenactionreceiver.getFilter());
connect(); 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; break;
case ACTION_STOP: case ACTION_STOP:
unregisterReceiver(screenactionreceiver); unregisterReceiver(screenactionreceiver);
@ -498,6 +493,31 @@ public class MicroPhotoService extends Service {
return START_NOT_STICKY; 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, 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() { private void connect() {
// after 10 seconds its connected // after 10 seconds its connected
new android.os.Handler().postDelayed( new android.os.Handler().postDelayed(
@ -576,173 +596,36 @@ public class MicroPhotoService extends Service {
return notificationBuilder.build(); 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 String buildAppDir(Context contxt) {
if (!res) { File[] paths = contxt.getExternalFilesDirs(null);
int idx = 0; if (paths == null || paths.length == 0) {
do { return null;
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);
}
} }
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;
} }
*/ public String buildPhotoDir(Context contxt, int channel) {
// File path = new File(Environment.getExternalStorageDirectory(), "com.xinyingpower.mp/photos/");
protected boolean updateTime(long timeInMillis) { String appDir = buildAppDir(contxt);
boolean res = false; if (appDir == null) {
try { return null;
// 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;
}
public String buildPhotoDir(int channel) { File path = new File(appDir, "photos/");
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/photos/");
if (!path.exists() && !path.mkdirs()) { if (!path.exists() && !path.mkdirs()) {
return null; return null;
@ -762,6 +645,20 @@ 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); TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
// for example value of first element // for example value of first element
@ -773,7 +670,7 @@ cellSignalStrengthGsm.getDbm();
protected native long init(String appPath, String ip, int port, String cmdid); protected native long init(String appPath, String ip, int port, String cmdid);
protected native long getHeartbeatDuration(long handler); protected native long getHeartbeatDuration(long handler);
protected native long[] getPhotoTimeData(long handler); protected native long[] getPhotoTimeData(long handler);
protected native long[] getNextScheduleItem(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 notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, String path, String fileName, boolean sendToCma);
protected native boolean sendHeartbeat(long handler); protected native boolean sendHeartbeat(long handler);
protected native boolean fireTimeout(long handler, long uid); protected native boolean fireTimeout(long handler, long uid);

@ -4,133 +4,145 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clickable="false"
android:orientation="horizontal" android:orientation="horizontal"
tools:context=".MainActivity"> tools:context=".MainActivity">
<TextView <TextView
android:id="@+id/textView" android:id="@+id/textViewCmdId"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="38dp" android:layout_marginLeft="20dp"
android:layout_marginTop="38dp" android:text="CMDID"
android:text="Server" app:layout_constraintBottom_toBottomOf="@+id/cmdid"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="@+id/cmdid" />
<EditText <EditText
android:id="@+id/server" android:id="@+id/cmdid"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="40dp" android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:ems="10" android:ems="10"
android:inputType="" android:text="XY-ANDROIDSIM-001"
app:layout_constraintBottom_toBottomOf="@+id/textView" app:layout_constraintLeft_toRightOf="@+id/textViewCmdId"
app:layout_constraintStart_toEndOf="@+id/textView" app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="@+id/textView" />
<TextView <TextView
android:id="@+id/textView2" android:id="@+id/textView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="12dp" android:layout_marginTop="20dp"
android:layout_marginTop="52dp" android:text="Server"
android:gravity="center" app:layout_constraintBottom_toBottomOf="@+id/server"
android:text="Port" app:layout_constraintStart_toStartOf="@id/textViewCmdId"
app:layout_constraintLeft_toLeftOf="@+id/textView" app:layout_constraintTop_toTopOf="@+id/server" />
app:layout_constraintTop_toBottomOf="@+id/textView" />
<EditText <EditText
android:id="@+id/port" android:id="@+id/server"
android:layout_width="wrap_content" android:layout_width="160dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ems="10" android:ems="10"
android:inputType="" android:inputType=""
android:text="" android:text="47.96.238.157"
app:layout_constraintBottom_toBottomOf="@+id/textView2" app:layout_constraintStart_toStartOf="@+id/cmdid"
app:layout_constraintLeft_toLeftOf="@+id/server" app:layout_constraintTop_toBottomOf="@+id/cmdid" />
app:layout_constraintLeft_toRightOf="@+id/textView2"
app:layout_constraintTop_toTopOf="@+id/textView2" /> <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 <Button
android:id="@+id/startServBtn" android:id="@+id/startServBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginLeft="20dp"
android:layout_marginTop="24dp"
android:text="Start"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/port" app:layout_constraintTop_toBottomOf="@+id/port"
android:text="Start" />
/>
<Button <Button
android:id="@+id/stopServBtn" android:id="@+id/stopServBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginStart="20dp"
android:layout_marginStart="12dp" android:layout_marginTop="24dp"
android:enabled="false" android:enabled="false"
app:layout_constraintTop_toBottomOf="@+id/port" android:text="Stop"
app:layout_constraintStart_toEndOf="@+id/startServBtn" app:layout_constraintStart_toEndOf="@+id/startServBtn"
android:text="Stop" /> app:layout_constraintTop_toBottomOf="@+id/port" />
<Button <Button
android:id="@+id/simchange" android:id="@+id/simchange"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginStart="20dp"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" android:layout_marginTop="24dp"
app:layout_constraintStart_toStartOf="@+id/startServBtn" android:text="sim卡获取"
android:text="sim卡获取" /> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" />
<Button <Button
android:id="@+id/simchange2" android:id="@+id/simchange2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginStart="4dp"
android:layout_marginStart="12dp" android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@+id/startServBtn" android:text="切换sim2"
app:layout_constraintStart_toEndOf="@+id/simchange" app:layout_constraintStart_toEndOf="@+id/simchange"
android:text="切换sim2" /> app:layout_constraintTop_toBottomOf="@+id/startServBtn" />
<Button <Button
android:id="@+id/takePhotoBtn" android:id="@+id/takePhotoBtn"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/simchange" android:text="TK Photo"
android:text="Take Photo" app:layout_constraintStart_toStartOf="parent"
/> app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button <Button
android:id="@+id/takePhotoBtn2" android:id="@+id/takePhotoBtn2"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginStart="16dp"
android:layout_marginStart="12dp" android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@+id/simchange"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn"
android:text="TP 2" android:text="TP 2"
/> app:layout_constraintStart_toEndOf="@+id/takePhotoBtn"
app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button <Button
android:id="@+id/takePhotoBtn3" android:id="@+id/takePhotoBtn3"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="12dp" android:layout_marginStart="8dp"
android:layout_marginStart="12dp" android:layout_marginTop="16dp"
android:text="TP 3" android:text="TP 3"
app:layout_constraintTop_toBottomOf="@+id/simchange"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn2" app:layout_constraintStart_toEndOf="@+id/takePhotoBtn2"
/> app:layout_constraintTop_toBottomOf="@+id/simchange" />
<Button <Button
android:id="@+id/takePhotoBtn4" android:id="@+id/takePhotoBtn4"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="8dp"
android:layout_marginTop="12dp" android:layout_marginTop="16dp"
android:text="TP 4" android:text="TP 4"
app:layout_constraintTop_toBottomOf="@+id/simchange"
app:layout_constraintStart_toEndOf="@+id/takePhotoBtn3" app:layout_constraintStart_toEndOf="@+id/takePhotoBtn3"
/> app:layout_constraintTop_toBottomOf="@+id/simchange" />
<TextView <TextView
@ -139,6 +151,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!" android:text="Hello World!"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -152,4 +165,5 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="288dp" /> tools:layout_editor_absoluteY="288dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save