diff --git a/app/build.gradle b/app/build.gradle index 2dcb550b..ab97dd6b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,8 +2,8 @@ plugins { id 'com.android.application' } -def AppVersionName = "1.0.7" -def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 7 +def AppVersionName = "1.0.8" +def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 8 android { namespace 'com.xinyingpower.microphoto' @@ -74,6 +74,7 @@ dependencies { // implementation 'com.tencent.mars:mars-core:1.2.5' // implementation 'com.tencent:mmkv-static:1.3.0' // implementation project(path: ':opencv') + implementation files('libs/devapi.aar') } \ No newline at end of file diff --git a/app/libs/devapi.aar b/app/libs/devapi.aar new file mode 100644 index 00000000..743280f4 Binary files /dev/null and b/app/libs/devapi.aar differ diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 58acfe94..62150282 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -285,6 +285,7 @@ add_library( # Sets the name of the library. ${TERM_CORE_ROOT}/SpecData_ZJ.cpp ${TERM_CORE_ROOT}/Timer.cpp ${TERM_CORE_ROOT}/TimerThread.cpp + ${TERM_CORE_ROOT}/Template.cpp ${TERM_CORE_ROOT}/Utils.cpp ${TERM_CORE_ROOT}/Client/TerminalService.cpp ${TERM_CORE_ROOT}/Client/Terminal.cpp @@ -327,7 +328,7 @@ target_link_libraries( # Specifies the target library. # included in the NDK. ${log-lib} - android camera2ndk mediandk + android camera2ndk mediandk z ncnn ${OpenCV_LIBS} diff --git a/app/src/main/cpp/MicroPhoto.cpp b/app/src/main/cpp/MicroPhoto.cpp index b11e375e..fa1e3f15 100644 --- a/app/src/main/cpp/MicroPhoto.cpp +++ b/app/src/main/cpp/MicroPhoto.cpp @@ -152,7 +152,6 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_notifyToTakePhoto( return JNI_TRUE; } - extern "C" JNIEXPORT jboolean JNICALL Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat( JNIEnv* env, @@ -170,7 +169,6 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat( return JNI_TRUE; } - extern "C" JNIEXPORT jboolean JNICALL Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout( JNIEnv* env, @@ -187,6 +185,22 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout( return phoneDevice->FireTimer((IDevice::timer_uid_t)uid, static_cast(times)) ? JNI_TRUE : JNI_FALSE; } +extern "C" JNIEXPORT void JNICALL +Java_com_xinyingpower_microphoto_MicroPhotoService_updatePosition( + JNIEnv* env, + jobject pThis, jlong handler, jdouble lon, jdouble lat, jlong ts) { + + CTerminal* pTerminal = reinterpret_cast(handler); + IDevice* dev = pTerminal->GetDevice(); + if (dev == NULL) + { + return; + } + + CPhoneDevice* phoneDevice = (CPhoneDevice *)dev; + phoneDevice->UpdatePosition(lon, lat, ts); +} + extern "C" JNIEXPORT jboolean JNICALL Java_com_xinyingpower_microphoto_MicroPhotoService_uninit( JNIEnv* env, diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index 3257f845..14ae85f1 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -19,6 +19,7 @@ #define LOG_TAG "CameraTestHelpers" #include #include "PhoneDevice.h" +#include #include #include @@ -180,6 +181,11 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service) mRequestWakelockMid = env->GetMethodID(classService, "requestWakelock", "(Ljava/lang/String;J)V"); mReleaseWakelockMid = env->GetMethodID(classService, "releaseWakelock", "(Ljava/lang/String;)V"); + mGetPowerInfoMid = env->GetMethodID(classService, "getPowerInfo", "()Ljava/lang/String;"); + mRebootMid = env->GetMethodID(classService, "reboot", "()V"); + mEnableGpsMid = env->GetMethodID(classService, "enableGps", "(Z)V"); + mRequestPositionMid = env->GetMethodID(classService, "requestPosition", "()Z"); + env->DeleteLocalRef(classService); if (didAttachThread) @@ -238,37 +244,83 @@ bool CPhoneDevice::UpdateSchedules() return true; } -bool CPhoneDevice::QuerySystemProperties(map& properties) +bool CPhoneDevice::QuerySystemProperties(std::map& properties) { char value[PROP_VALUE_MAX] = { 0 }; - __system_property_get("ro.telephony.default_network", value); + std::map powerInfo; - __system_property_get("ro.product.name", value); - properties[PROP_EQUIP_NAME] = value; + for (std::map::iterator it = properties.begin(); it != properties.end(); ++it) + { + if (it->first == PROP_EQUIP_NAME) + { + __system_property_get("ro.product.name", value); + it->second = value; + } + else if (it->first == PROP_MODEL) + { + __system_property_get("ro.product.model", value); + it->second = value; + } + else if (it->first == PROP_BS_MANU) + { + __system_property_get("ro.product.manufacturer", value); + it->second = value; + } + else if (it->first == PROP_VERSION) { + __system_property_get("ro.build.version.release", value); + it->second = value; + } + else if (it->first == PROP_PROD_DATE) { + __system_property_get("ro.build.date.utc", value); + it->second = value; + } + else if (it->first == PROP_SN) + { + __system_property_get("ro.serialno", value); + it->second = value; + } + else if (it->first == PROP_IMEI) + { + __system_property_get("phone.imei", value); + it->second = value; + } - __system_property_get("ro.product.model", value); - properties[PROP_MODEL] = value; + properties[PROP_BS_ID] = "SHXY"; - __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); - properties[PROP_VERSION] = value; - __system_property_get("ro.build.date.utc", value); - properties[PROP_PROD_DATE] = value; + } - __system_property_get("ro.serialno", value); - properties[PROP_SN] = value; + __system_property_get("ro.telephony.default_network", value); - __system_property_get("phone.imei", value); - properties[PROP_IMEI] = value; return true; } +void CPhoneDevice::QueryPowerInfo(std::map& powerInfo) +{ + JNIEnv* env = NULL; + jboolean ret = JNI_FALSE; + bool didAttachThread = false; + bool res = GetJniEnv(m_vm, &env, didAttachThread); + if (!res) + { + ALOGE("Failed to get JNI Env"); + } + jobject jobj = env->CallObjectMethod(m_javaService, mGetPowerInfoMid); + std::string str = jstring2string(env, (jstring)jobj); + if (didAttachThread) + { + m_vm->DetachCurrentThread(); + } + + if (!str.empty()) + { + std::map queries = parseQuery(str); + powerInfo.swap(queries); + } +} bool CPhoneDevice::GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector& items) { @@ -277,7 +329,58 @@ bool CPhoneDevice::GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTi bool CPhoneDevice::Reboot() { - return false; + JNIEnv* env = NULL; + bool didAttachThread = false; + bool res = GetJniEnv(m_vm, &env, didAttachThread); + if (!res) + { + ALOGE("Failed to get JNI Env"); + } + env->CallVoidMethod(m_javaService, mRebootMid); + if (didAttachThread) + { + m_vm->DetachCurrentThread(); + } + + return true; +} + +bool CPhoneDevice::EnableGPS(bool enabled) +{ + JNIEnv* env = NULL; + bool didAttachThread = false; + bool res = GetJniEnv(m_vm, &env, didAttachThread); + if (!res) + { + ALOGE("Failed to get JNI Env"); + return 0; + } + jboolean jenabled = enabled ? JNI_TRUE : JNI_FALSE; + env->CallVoidMethod(m_javaService, mEnableGpsMid, jenabled); + if (didAttachThread) + { + m_vm->DetachCurrentThread(); + } +} + +bool CPhoneDevice::RequestPosition() +{ + JNIEnv* env = NULL; + 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, mRequestPositionMid); + if (didAttachThread) + { + m_vm->DetachCurrentThread(); + } + + return (ret == JNI_TRUE); } IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times/* = 0*/) @@ -493,17 +596,44 @@ bool CPhoneDevice::OnImageReady(const cv::Mat& mat) const double width = mat.size().width; double ratio = std::min(height / 1024, width / 1920); fontScale = fontScale * ratio; - double thickness1 = 4 * ratio; - double thickness2 = 2 * ratio; + + int thickness2 = 1 * ratio; + if (thickness2 == 0) thickness2 = 1; + int thickness1 = thickness2 + 1; + + cv::Scalar scalar1(0, 0, 0); // black + cv::Scalar scalar2(255, 255, 255); // white + cv::Point pt1, pt2; for (vector::const_iterator it = mOsds.cbegin(); it != mOsds.cend(); ++it) { - // getTextSize(value, font, scale, 1, &bottom); 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, fontScale, cv::Scalar(255, 255, 255), thickness2,cv::LINE_AA); + + ALOGE("putText: w1=%d w2=%d tn=%d/%d", textSize.width, textSize2.width, thickness1, thickness2); + + if (it->alignment == OSD_ALIGNMENT_TOP_LEFT) + { + pt1.x = it->x * ratio; + pt1.y = it->y * ratio + textSize.height; + } + else if (it->alignment == OSD_ALIGNMENT_TOP_RIGHT) + { + pt1.x = width - textSize.width - it->x * ratio; + pt1.y= it->y * ratio + textSize.height; + } + else if (it->alignment == OSD_ALIGNMENT_BOTTOM_RIGHT) + { + pt1.x = width - textSize.width - it->x * ratio; + pt1.y = height - it->y * ratio; + } + else if (it->alignment == OSD_ALIGNMENT_BOTTOM_LEFT) + { + pt1.x = it->x * ratio; + pt1.y = height - it->y * ratio; + } + + cv::putText(mat, it->text, pt1, cv::FONT_HERSHEY_COMPLEX, fontScale, scalar1, thickness1,cv::LINE_AA); + cv::putText(mat, it->text, pt1, cv::FONT_HERSHEY_COMPLEX, fontScale, scalar2, thickness2,cv::LINE_AA); } vector compression_params; @@ -550,3 +680,10 @@ std::string CPhoneDevice::GetFileName() const return mPath; } +void CPhoneDevice::UpdatePosition(double lon, double lat, time_t ts) +{ + if (m_listener != NULL) + { + return m_listener->OnPositionDataArrived(lon, lat, ts); + } +} \ No newline at end of file diff --git a/app/src/main/cpp/PhoneDevice.h b/app/src/main/cpp/PhoneDevice.h index 0a828862..f2b2b58a 100644 --- a/app/src/main/cpp/PhoneDevice.h +++ b/app/src/main/cpp/PhoneDevice.h @@ -36,6 +36,8 @@ public: virtual bool UpdateSchedules(); virtual bool QuerySystemProperties(map& properties); virtual bool Reboot(); + virtual bool EnableGPS(bool enabled); + virtual bool RequestPosition(); virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout); virtual bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector& osds, const string& path); virtual bool CloseCamera(); @@ -48,6 +50,7 @@ public: bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector& items); + void UpdatePosition(double lon, double lat, time_t ts); protected: std::string GetFileName() const; @@ -65,6 +68,8 @@ protected: return false; } + void QueryPowerInfo(std::map& powerInfo); + bool OnImageReady(const cv::Mat& mat) const; void onError(const std::string& msg) const; @@ -81,6 +86,12 @@ protected: jmethodID mRequestWakelockMid; jmethodID mReleaseWakelockMid; + jmethodID mGetPowerInfoMid; + + jmethodID mRebootMid; + jmethodID mEnableGpsMid; + jmethodID mRequestPositionMid; + std::string mPath; IDevice::PHOTO_INFO mPhotoInfo; vector mOsds; diff --git a/app/src/main/cpp/camera2/OpenCVHdr.h b/app/src/main/cpp/camera2/OpenCVHdr.h new file mode 100644 index 00000000..f79ef57c --- /dev/null +++ b/app/src/main/cpp/camera2/OpenCVHdr.h @@ -0,0 +1,87 @@ +#ifndef __OPENCV_HDR_H__ +#define __OPENCV_HDR_H__ + +#include +#include +#include +#include +#include +using namespace std; +using namespace cv; + + +void Debevec(vectorexposureImages, vectorexposureTimes, Mat& output); +void Robertson(vectorexposureImages, vectorexposureTimes, Mat& output); +void Mertens(vectorexposureImages, Mat& output); + +//使用对比度、饱和度和曝光度好坏来对像素加权,而不是使用拉普拉斯金字塔来对图像进行加权。得到的图像权重被构造为对比度、饱和度和曝光度良好度量的加权平均值。 +//生成的图像不需要进行色调映射,并且可以通过乘以255转换为8位图像,但是建议应用伽马校正或线性色调映射。 +//不需要对应曝光时间, 可以在不需要HDR图像时使用,可直接得到低动态范围图像 +void Mertens(vectorexposureImages) +{ + auto merge_mertens = createMergeMertens(); + Mat fusion; + merge_mertens->process(exposureImages, fusion); + //进行伽马矫正,需根据实际图像调节参数,2.2f可满足大多数显示情况 + /*auto tonemap = createTonemap(2.2f); + tonemap->process(fusion, fusion);*/ + fusion = fusion * 255; + fusion.convertTo(fusion, CV_8UC3); + imshow("Mertens", fusion); + imwrite("D:\\opencv_c++\\Learning-OpenCV\\高动态(HDR)图像\\Mertens.png", fusion); +} + + +//使用Debevec方法进行HDR合成,将多张曝光时间不同的照片及其对应的曝光值进行加权平均,得到float32类型的高动态范围HDR图像 +//需要传入曝光图像序列和对应的曝光时间 +void Debevec(vectorexposureImages, vectorexposureTimes) +{ + //auto Debevec_response = createCalibrateDebevec(); + //Mat response; + //Debevec_response->process(exposureImages, response, exposureTimes); + + auto merge_Debevec = createMergeDebevec(); + Mat hdr; + merge_Debevec->process(exposureImages, hdr, exposureTimes); + //由于是在普通的LDR显示器上进行显示,因此我们必须将HDR图像映射到保留大多数细节的8位范围的低动态范围LDR图像。 + //这是进行色调映射的主要目标,伽玛校正值设置为2.2f适用于大多数情况 + Mat ldr; + auto tonemap = createTonemap(2.2f); + tonemap->process(hdr, ldr); + //HDR图像进行色调映射后得到的LDR图像取值范围在 [ 0 , 1 ] ,所以乘255将范围拉伸到 [ 0 , 255 ] + ldr = ldr * 255; + //将float32类型转化为uchar8类型 + ldr.convertTo(ldr, CV_8UC3); + imshow("Debevec_HDR", hdr); + imshow("Debevec_LDR", ldr); + imwrite("D:\\opencv_c++\\Learning-OpenCV\\高动态(HDR)图像\\Debevec_LDR.png", ldr); +} + + +//使用Robertson方法进行HDR图像合成,将多张曝光时间不同的照片及其对应的曝光值进行加权平均,得到float32类型的高动态范围HDR图像 +//需要传入曝光图像序列和对应的曝光时间 +void Robertson(vectorexposureImages, vectorexposureTimes) +{ + //auto Robertson_response = createCalibrateRobertson(); + //Mat response; + //Robertson_response->process(exposureImages, response, exposureTimes); + + auto merge_Robertson = createMergeRobertson(); + Mat hdr; + merge_Robertson->process(exposureImages, hdr, exposureTimes); + //由于是在普通的LDR显示器上进行显示,因此我们必须将HDR图像映射到保留大多数细节的8位范围的低动态范围LDR图像。 + //这是进行色调映射的主要目标,伽玛校正值设置为2.2f适用于大多数情况 + Mat ldr; + auto tonemap = createTonemap(2.2f); + tonemap->process(hdr, ldr); + //HDR图像进行色调映射后得到的LDR图像取值范围在 [ 0 , 1 ] ,所以乘255将范围拉伸到 [ 0 , 255 ] + ldr = ldr * 255; + ldr.convertTo(ldr, CV_8UC3); + imshow("Robertson_HDR", hdr); + imshow("Robertson_LDR", ldr); + imwrite("D:\\opencv_c++\\Learning-OpenCV\\高动态(HDR)图像\\Robertson_LDR.png", ldr); + +} + + +#endif /* __OPENCV_HDR_H__ */ diff --git a/app/src/main/cpp/camera2/ndkcamera.cpp b/app/src/main/cpp/camera2/ndkcamera.cpp index dfba86e4..9305fc62 100644 --- a/app/src/main/cpp/camera2/ndkcamera.cpp +++ b/app/src/main/cpp/camera2/ndkcamera.cpp @@ -115,8 +115,7 @@ NdkCamera::~NdkCamera() } } -int NdkCamera::open(const char* cameraId) -{ +int NdkCamera::open(const char* cameraId) { __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "DBG::open %s", cameraId); // camera_facing = _camera_facing; @@ -130,25 +129,23 @@ int NdkCamera::open(const char* cameraId) DisplayDimension foundRes = disp; { - ACameraIdList* camera_id_list = 0; + ACameraIdList *camera_id_list = 0; ACameraManager_getCameraIdList(camera_manager, &camera_id_list); - for (int i = 0; i < camera_id_list->numCameras; ++i) - { - const char* id = camera_id_list->cameraIds[i]; - if (strcmp(id, cameraId) != 0) - { + for (int i = 0; i < camera_id_list->numCameras; ++i) { + const char *id = camera_id_list->cameraIds[i]; + if (strcmp(id, cameraId) != 0) { continue; } - ACameraMetadata* camera_metadata = 0; + ACameraMetadata * camera_metadata = 0; ACameraManager_getCameraCharacteristics(camera_manager, id, &camera_metadata); // query faceing acamera_metadata_enum_android_lens_facing_t facing = ACAMERA_LENS_FACING_FRONT; { - ACameraMetadata_const_entry e = { 0 }; + ACameraMetadata_const_entry e = {0}; ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_LENS_FACING, &e); - facing = (acamera_metadata_enum_android_lens_facing_t)e.data.u8[0]; + facing = (acamera_metadata_enum_android_lens_facing_t) e.data.u8[0]; } camera_facing = facing; @@ -170,18 +167,19 @@ int NdkCamera::open(const char* cameraId) // query orientation int orientation = 0; { - ACameraMetadata_const_entry e = { 0 }; + ACameraMetadata_const_entry e = {0}; ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_ORIENTATION, &e); - orientation = (int)e.data.i32[0]; + orientation = (int) e.data.i32[0]; } camera_orientation = orientation; { - ACameraMetadata_const_entry e = { 0 }; - ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &e); + 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); @@ -208,8 +206,10 @@ int NdkCamera::open(const char* cameraId) } { - ACameraMetadata_const_entry val = { 0 }; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val); + 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) { @@ -228,8 +228,10 @@ int NdkCamera::open(const char* cameraId) } { - ACameraMetadata_const_entry val = { 0 }; - camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val); + 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]; @@ -245,22 +247,17 @@ int NdkCamera::open(const char* cameraId) } { - ACameraMetadata_const_entry e = { 0 }; - ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_CONTROL_AVAILABLE_SCENE_MODES, &e); + 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]) - { + 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]) - { + } 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]) - { + } else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT == e.data.u8[i]) { nightPortraitModeSupported = true; } } @@ -275,15 +272,18 @@ int NdkCamera::open(const char* cameraId) ACameraManager_deleteCameraIdList(camera_id_list); } - if (camera_id.empty() || !foundIt) - { + if (camera_id.empty() || !foundIt) { return 1; } - if (camera_id == "1") - { + // TODO: PATCH!!!! + if (camera_id == "1") { camera_facing = 1; } + if (camera_id == "2") + { + camera_orientation += 180; + } mCameraId = camera_id; @@ -326,7 +326,7 @@ int NdkCamera::open(const char* cameraId) { res = ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request); - int32_t fpsRange[2] = {10,15}; + int32_t fpsRange[2] = {10,30}; res = ACaptureRequest_setEntry_i32(capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,2,fpsRange); bool usingAE = true; @@ -338,7 +338,7 @@ int NdkCamera::open(const char* cameraId) uint8_t aeLockOff = ACAMERA_CONTROL_AE_LOCK_OFF; - ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_LOCK, 1, &aeLockOff); + // 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); @@ -352,11 +352,12 @@ int NdkCamera::open(const char* cameraId) res = ACaptureRequest_setEntry_i64(capture_request, ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime); } - uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO; + // uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_VIDEO; + uint8_t afMode = ACAMERA_CONTROL_AF_MODE_CONTINUOUS_PICTURE; 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); + // 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 @@ -367,14 +368,13 @@ int NdkCamera::open(const char* cameraId) if (nightModeSupported) { uint8_t modeEnabled = 1; // ACAMERA_CONTROL_SCENE_MODE_HDR - res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_NIGHT, 1, &modeEnabled); + // 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 = 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); } diff --git a/app/src/main/cpp/camera2/ndkcamera.h b/app/src/main/cpp/camera2/ndkcamera.h index f96acb41..14e41d1b 100644 --- a/app/src/main/cpp/camera2/ndkcamera.h +++ b/app/src/main/cpp/camera2/ndkcamera.h @@ -73,6 +73,7 @@ public: RangeValue sensitivityRange; + private: ACameraManager* camera_manager; ACameraDevice* camera_device; diff --git a/app/src/main/java/com/xinyingpower/microphoto/FileDownloader.java b/app/src/main/java/com/xinyingpower/microphoto/FileDownloader.java new file mode 100644 index 00000000..114518e3 --- /dev/null +++ b/app/src/main/java/com/xinyingpower/microphoto/FileDownloader.java @@ -0,0 +1,84 @@ +package com.xinyingpower.microphoto; + +import android.text.TextUtils; +import android.util.Log; + +import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; + +public class FileDownloader { + protected void download(String urlString, String filePath) { + File downloadFile = null; + if (TextUtils.isEmpty(urlString)) + return; + HttpURLConnection connection = null; + try { + Thread.currentThread().setPriority(Thread.MIN_PRIORITY); + URL url = new URL(urlString); + connection = (HttpURLConnection) url.openConnection(); + connection.setConnectTimeout(5000); + connection.setReadTimeout(60000); + connection.setDoInput(true); + InputStream is = connection.getInputStream(); + final File temp = new File(filePath); + if (temp.exists()) + temp.delete(); + temp.createNewFile(); + temp.setReadable(true, false); + temp.setWritable(true, false); + downloadFile = temp; + Log.d("download", "url " + urlString + "\n save to " + temp); + OutputStream os = new FileOutputStream(temp); + byte[] buf = new byte[8 * 1024]; + int len; + try { + while ((len = is.read(buf)) != -1) { + os.write(buf, 0, len); + } + os.flush(); + if (os instanceof FileOutputStream) { + ((FileOutputStream) os).getFD().sync(); + } + } finally { + closeSilently(os); + closeSilently(is); + } + Log.d("downloadAPK", "download complete url=" + urlString + ", fileSize= " + temp.length()); +// installPkg(this, temp, pkg); + } catch (Exception e) { + Log.w("downloadAPK", e); + if (downloadFile != null) + downloadFile.delete(); + + } finally { + if (connection != null) + connection.disconnect(); + } + } + + public static final void closeSilently(Object closeable) { + try { + if (closeable != null) { + if (closeable instanceof Closeable) { + ((Closeable) closeable).close(); + } else if (closeable instanceof Socket) { + ((Socket) closeable).close(); + } else if (closeable instanceof ServerSocket) { + ((ServerSocket) closeable).close(); + } else { + throw new IllegalArgumentException("Unknown object to close"); + } + } + } catch (IOException e) { + // ignore + } + } +} diff --git a/app/src/main/java/com/xinyingpower/microphoto/FloatingWindow.java b/app/src/main/java/com/xinyingpower/microphoto/FloatingWindow.java index bee385ea..0bb9e56b 100644 --- a/app/src/main/java/com/xinyingpower/microphoto/FloatingWindow.java +++ b/app/src/main/java/com/xinyingpower/microphoto/FloatingWindow.java @@ -10,6 +10,7 @@ import android.os.IBinder; import android.text.Editable; import android.text.TextWatcher; import android.util.DisplayMetrics; +import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -55,7 +56,8 @@ public class FloatingWindow extends Service { mWindowManager.removeView(mView); } } catch (Exception ex) { - ex.printStackTrace(); + // ex.printStackTrace(); + Log.e("FW", "Exception " + ex.getMessage()); } super.onDestroy(); diff --git a/app/src/main/java/com/xinyingpower/microphoto/MicroPhotoService.java b/app/src/main/java/com/xinyingpower/microphoto/MicroPhotoService.java index 628e21c0..e9d111f4 100644 --- a/app/src/main/java/com/xinyingpower/microphoto/MicroPhotoService.java +++ b/app/src/main/java/com/xinyingpower/microphoto/MicroPhotoService.java @@ -10,6 +10,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.LocationProvider; +import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.PowerManager; import android.os.SystemClock; @@ -24,6 +30,8 @@ import android.util.Log; import android.widget.RemoteViews; import android.widget.Toast; +import com.dev.devapi.api.SysApi; + import java.io.File; import java.lang.reflect.Method; import java.time.LocalDateTime; @@ -71,6 +79,8 @@ public class MicroPhotoService extends Service { private final Map mWakeLocks = new HashMap<>(); private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000 private long mNextHeartbeatTime = 0; + + private PositionManager mPositionManager = null; private final Map mTimers = new HashMap<>(); private static int stateService = STATE_SERVICE.NOT_CONNECTED; public MicroPhotoService() { @@ -619,23 +629,100 @@ public class MicroPhotoService extends Service { String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); String photoFile = "img_" + Integer.toString(channel) + "_" + Integer.toHexString(preset).toUpperCase() + "_" + date + ".jpg"; return photoFile; - } 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; + SysApi.setSystemTime(getApplicationContext(), timeInMillis); } catch (Exception ex) { - int aa = 0; } return true; } + public boolean requestPosition() { + + try { + + if (mLocationManager == null) { + mLocationManager = (LocationManager) getSystemService (Context.LOCATION_SERVICE); + + if (!mLocationManager.isProviderEnabled(GPS_LOCATION_NAME)) { + return false; + } + mLocateType = mLocationManager.GPS_PROVIDER; + } + + Location location = mLocationManager.getLastKnownLocation(mLocateType); + if (location != null) { + updatePosition(mHandler, location.getLongitude(), location.getLatitude(), location.getTime()); + } + // Set Listener + mLocationManager.requestLocationUpdates(mLocateType, 100,0, locationListener); + + return true; + } catch (SecurityException ex) { + } + + return false; + } + public void downloadAndInstall(final String url) { + + final Context context = getApplicationContext(); + final String tempPath = buildAppDir(context) + File.separator + "tmp"; + File file = new File(tempPath); + file.mkdirs(); + final String filePath = tempPath + File.separator + "mp.apk"; + Thread th =new Thread(new Runnable() { + @Override + public void run() { + + PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); + PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "com.xinyingpower.microphoto:Upgrader"); + + FileDownloader fd = new FileDownloader(); + fd.download(url, filePath); + + SysApi.installApk(context, filePath, context.getPackageName(), true); + + wl.release(); + } + }); + th.start(); + } + + public String getPowerInfo() { + StringBuilder sb = new StringBuilder(); + sb.append("CV=" + SysApi.getChargingVoltage()); // ChargeVol + sb.append("&CC=" + SysApi.getChargingCurrent()); // ChargeCurrent + sb.append("&CP="+ SysApi.getChargingPower()); // ChargePower: + sb.append("&CBV="+ SysApi.getChargingBusVoltage()); // ChargeBusVol + sb.append("&BV="+ SysApi.getBatteryVoltage()); // BatVol + sb.append("&BC="+ SysApi.getBatteryCurrent()); // BatCurrent + sb.append("&BP="+ SysApi.getBatteryPower()); // BattaryPower + sb.append("&BBV="+ SysApi.getBatteryBusVoltage()); // BattaryBusVol + + return sb.toString(); + } + + public void reboot() { + + Handler handler = new Handler(); + Runnable runnable = new Runnable() { + @Override + public void run() { + SysApi.reboot(getApplicationContext()); + } + }; + handler.postDelayed(runnable, 400); + } + public void enableGps(boolean enabled) { + SysApi.enableGps(getApplicationContext(), enabled); + } + + public void selectSimCard(int num) { + SysApi.selectSimCard4Data(getApplicationContext(), num); + } + /* TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); // for example value of first element @@ -651,9 +738,62 @@ cellSignalStrengthGsm.getDbm(); 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 void updatePosition(long handler, double lon, double lat, long ts); protected native boolean uninit(long handler); protected long mHandler = 0; - private AlarmReceiver alarmReceiver = null; private ScreenActionReceiver screenactionreceiver = null; + + ////////////////////////GPS//////////////////// + private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER; + private LocationManager mLocationManager; + private String mLocateType; + + private LocationListener locationListener = new LocationListener() { + + @Override + public void onLocationChanged(Location location) { + updatePosition(mHandler, location.getLongitude(), location.getLatitude(), location.getTime()); + // Log.i(TAG, "Time: " + location.getTime()); + // Log.i(TAG, "经度:" + location.getLongitude()); + // Log.i(TAG, "纬度:" + location.getLatitude()); + // Log.i(TAG, "海拔:" + location.getAltitude()); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + switch (status) { + case LocationProvider.AVAILABLE: + // Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为可见状态", Toast.LENGTH_SHORT).show(); + break; + case LocationProvider.OUT_OF_SERVICE: + // Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为服务区外状态", Toast.LENGTH_SHORT).show(); + break; + case LocationProvider.TEMPORARILY_UNAVAILABLE: + // Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为暂停服务状态", Toast.LENGTH_SHORT).show(); + break; + } + } + + /** + * @param provider + */ + @Override + public void onProviderEnabled(String provider) { + // Toast.makeText(MainActivity.this, "onProviderEnabled:方法被触发", Toast.LENGTH_SHORT).show(); + requestPosition(); + } + + /** + * @param provider + */ + @Override + public void onProviderDisabled(String provider) { + + } + }; + + + + ////////////////////////GPS//////////////////// } \ No newline at end of file diff --git a/app/src/main/java/com/xinyingpower/microphoto/PositionManager.java b/app/src/main/java/com/xinyingpower/microphoto/PositionManager.java new file mode 100644 index 00000000..3a50dd47 --- /dev/null +++ b/app/src/main/java/com/xinyingpower/microphoto/PositionManager.java @@ -0,0 +1,32 @@ +package com.xinyingpower.microphoto; + +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.location.LocationProvider; +import android.os.Bundle; + +public class PositionManager { + private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER; + private LocationManager mLocationManager; + private boolean mIsGpsEnabled; + private String mLocateType; + private Context mContext; + + public PositionManager(Context context) { + mContext = context; + + } + + public boolean isGpsEnabled() { + return mIsGpsEnabled; + } + + public void getLocation() { + + } + + + +}