diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 6268e16c..5d27265f 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -25,6 +25,7 @@ add_definitions(-DTERMINAL_CLIENT) add_definitions(-DKEEP_FRAME_TYPE_ON_REVERSE) add_definitions(-DBOOST_ALL_NO_LIB) add_definitions(-DASIO_STANDALONE) +add_definitions(-DUSING_XY_EXTENSION) # add_definitions(-DUSING_BREAK_PAD) diff --git a/app/src/main/cpp/MicroPhoto.cpp b/app/src/main/cpp/MicroPhoto.cpp index 51f0ec1a..15a6da53 100644 --- a/app/src/main/cpp/MicroPhoto.cpp +++ b/app/src/main/cpp/MicroPhoto.cpp @@ -215,7 +215,7 @@ Java_com_xypower_mpapp_MicroPhotoService_init( extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_notifyToTakePhoto( JNIEnv* env, - jobject pThis, jlong handler, jint channel, jint preset, jlong scheduleTime, jboolean sendToCma) { + jobject pThis, jlong handler, jint channel, jint preset, jlong scheduleTime, jboolean photoOrVideo) { if (channel < 1 || channel > 0xFF) { @@ -227,7 +227,8 @@ Java_com_xypower_mpapp_MicroPhotoService_notifyToTakePhoto( return JNI_FALSE; } - std::thread th(&Runner::RequestCapture, pTerminal, (unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime); + unsigned char type = photoOrVideo ? 0 : 1; + std::thread th(&Runner::RequestCapture, pTerminal, (unsigned int)channel, (unsigned int)preset, type, (unsigned long)scheduleTime); th.detach(); // pTerminal->RequestCapture((unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime); @@ -452,3 +453,28 @@ Java_com_xypower_mpapp_MicroPhotoService_getNextScheduleItem( return data; } */ + + +extern "C" JNIEXPORT void JNICALL +Java_com_xypower_mpapp_MicroPhotoService_recordingFinished( + JNIEnv* env, + jobject pThis, jlong handler, jboolean result, jstring path, jlong videoId) { + + CTerminal* pTerminal = reinterpret_cast(handler); + if (pTerminal == NULL) + { + return; + } + + IDevice* dev = pTerminal->GetDevice(); + if (dev != NULL) + { + const char *pathStr = env->GetStringUTFChars(path, 0); + + // camera->Open(pathStr, fileNameStr); + unsigned long photoId = videoId; + ((CPhoneDevice *)dev)->OnVideoReady(result != JNI_FALSE, pathStr, photoId); + + env->ReleaseStringUTFChars(path, pathStr); + } +} \ No newline at end of file diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index 63418c72..e7418285 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -177,6 +177,7 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service, const std::string& appPa mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V"); mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z"); mUpdateTimeMid = env->GetMethodID(classService, "updateTime", "(J)Z"); + mStartRecordingMid = env->GetMethodID(classService, "startRecording", "(IJIIII)V"); mRequestWakelockMid = env->GetMethodID(classService, "requestWakelock", "(Ljava/lang/String;J)V"); mReleaseWakelockMid = env->GetMethodID(classService, "releaseWakelock", "(Ljava/lang/String;)V"); @@ -643,7 +644,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector< mCamera = NULL; } - ALOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset); + ALOGI("TAKE_PHOTO: CH=%u PR=%u PHOTOID=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset, photoInfo.photoId); mPhotoInfo = photoInfo; mPath = path; mOsds = osds; @@ -673,23 +674,32 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector< } TurnOnCameraPower(env); - if (didAttachThread) - { - m_vm->DetachCurrentThread(); - } - mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height, params); - if (mCamera->open(to_string(mPhotoInfo.cameraId)) == 0) + res = true; + if (mPhotoInfo.mediaType == 0) { + mCamera = new CPhoneCamera(this, photoInfo.width, photoInfo.height, params); + if (mCamera->open(to_string(mPhotoInfo.cameraId)) == 0) + { + } + else + { + delete mCamera; + mCamera = NULL; + res = false; + } } else { - delete mCamera; - mCamera = NULL; - return false; + env->CallVoidMethod(m_javaService, mStartRecordingMid, mPhotoInfo.cameraId, (unsigned long)mPhotoInfo.photoId, mPhotoInfo.duration, mPhotoInfo.width, mPhotoInfo.height, mPhotoInfo.duration); } - return true; + if (didAttachThread) + { + m_vm->DetachCurrentThread(); + } + + return res; } bool CPhoneDevice::CloseCamera() @@ -707,10 +717,12 @@ bool CPhoneDevice::CloseCamera() void CPhoneDevice::CloseCamera2(CPhoneDevice::CPhoneCamera* camera, bool turnOffOtg) { - // std::this_thread::sleep_for(std::chrono::milliseconds(16)); - camera->close(); - delete camera; + if (camera != NULL) + { + camera->close(); + delete camera; + } // GpioControl::EnableGpio(CMD_SET_CAM_3V3_EN_STATE, true); JNIEnv* env = NULL; @@ -791,6 +803,9 @@ bool CPhoneDevice::OnImageReady(cv::Mat& mat) int aa = 0; return false; } + + mat = cv::imread("/sdcard/com.xypower.mpapp/ai1.jpg"); + mPhotoInfo.photoTime = time(NULL); int baseline = 0; cv::Size textSize, textSize2; @@ -941,6 +956,26 @@ bool CPhoneDevice::OnImageReady(cv::Mat& mat) return res; } +bool CPhoneDevice::OnVideoReady(bool result, const char* path, unsigned int photoId) +{ + mPhotoInfo.photoTime = time(NULL); + + CPhoneCamera* pCamera = NULL; + std::vector objs; + std::string fullPath = mPath + CTerminal::BuildPhotoFileName(mPhotoInfo); + if (result) + { + std::rename(path, fullPath.c_str()); + } + TakePhotoCb(result, mPhotoInfo, fullPath, time(NULL), objs); + + bool turnOffOtg = (mPhotoInfo.usbCamera != 0); + std::thread closeThread(&CPhoneDevice::CloseCamera2, this, pCamera, turnOffOtg); + closeThread.detach(); + + return result; +} + void CPhoneDevice::onError(const std::string& msg) { // XFLOG(XFLOG_SEVERITY_ERROR, "Failed to Take Photo: %s", msg.c_str()); diff --git a/app/src/main/cpp/PhoneDevice.h b/app/src/main/cpp/PhoneDevice.h index c8349203..6b35a687 100644 --- a/app/src/main/cpp/PhoneDevice.h +++ b/app/src/main/cpp/PhoneDevice.h @@ -187,6 +187,8 @@ public: bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector& items); void UpdatePosition(double lon, double lat, time_t ts); + bool OnVideoReady(bool result, const char* path, unsigned int photoId); + protected: std::string GetFileName() const; @@ -218,6 +220,7 @@ protected: void QueryPowerInfo(std::map& powerInfo); std::string QueryCpuTemperature(); + bool OnImageReady(cv::Mat& mat); void onError(const std::string& msg); @@ -240,6 +243,7 @@ protected: jmethodID mRegisterHeartbeatMid; jmethodID mUnregisterTimerMid; jmethodID mUpdateTimeMid; + jmethodID mStartRecordingMid; jmethodID mRequestWakelockMid; jmethodID mReleaseWakelockMid; diff --git a/app/src/main/java/com/xypower/mpapp/MainActivity.java b/app/src/main/java/com/xypower/mpapp/MainActivity.java index 5dd13607..734a1e53 100644 --- a/app/src/main/java/com/xypower/mpapp/MainActivity.java +++ b/app/src/main/java/com/xypower/mpapp/MainActivity.java @@ -269,25 +269,50 @@ public class MainActivity extends AppCompatActivity { this.binding.takePhotoBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - MicroPhotoService.takePhoto(MainActivity.this.getApplicationContext(), 1, 255, true); + MicroPhotoService.takePhoto(view.getContext(), 1, 255, true); } }); this.binding.takePhotoBtn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - MicroPhotoService.takePhoto(MainActivity.this, 2, 255, true); + MicroPhotoService.takePhoto(view.getContext(), 2, 255, true); } }); this.binding.takePhotoBtn3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - MicroPhotoService.takePhoto(MainActivity.this, 3, 255, true); + MicroPhotoService.takePhoto(view.getContext(), 3, 255, true); } }); this.binding.takePhotoBtn4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - MicroPhotoService.takePhoto(MainActivity.this, 4, 255, true); + MicroPhotoService.takePhoto(view.getContext(), 4, 255, true); + } + }); + + this.binding.takeVideoBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + MicroPhotoService.takePhoto(view.getContext(), 1, 255, false); + } + }); + this.binding.takeVideoBtn2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + MicroPhotoService.takePhoto(view.getContext(), 2, 255, false); + } + }); + this.binding.takeVideoBtn3.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + MicroPhotoService.takePhoto(view.getContext(), 3, 255, false); + } + }); + this.binding.takeVideoBtn4.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + MicroPhotoService.takePhoto(view.getContext(), 4, 255, false); } }); diff --git a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java index 8700d890..4600b9a0 100644 --- a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java +++ b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java @@ -85,14 +85,15 @@ public class MicroPhotoService extends Service { // public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 0; public static final String ACTION_MSG_BROADCAST = "ACT_MSG_BROADCAST"; - public static final String ACTION_START = "ACT_START"; - public static final String ACTION_STOP = "ACT_STOP"; - public static final String ACTION_MAIN = "ACT_MAIN"; - private static final String ACTION_HEARTBEAT = "ACT_HB"; - private static final String ACTION_TAKE_PHOTO = "ACT_TP"; - private static final String ACTION_TAKE_PHOTO_MANUALLY = "ACT_TP_M"; - private static final String ACTION_HEARTBEAT_MANUALLY = "ACT_HB_M"; - private static final String ACTION_TIMEOUT = "ACT_TIMEOUT"; + public static final String ACTION_START = "com.xypower.mpapp.ACT_START"; + public static final String ACTION_STOP = "com.xypower.mpapp.ACT_STOP"; + public static final String ACTION_MAIN = "com.xypower.mpapp.ACT_MAIN"; + private static final String ACTION_HEARTBEAT = "com.xypower.mpapp.ACT_HB"; + private static final String ACTION_TAKE_PHOTO = "com.xypower.mpapp.ACT_TP"; + private static final String ACTION_TAKE_PHOTO_MANUALLY = "com.xypower.mpapp.ACT_TP_M"; + private static final String ACTION_HEARTBEAT_MANUALLY = "com.xypower.mpapp.ACT_HB_M"; + private static final String ACTION_TIMEOUT = "com.xypower.mpapp.ACT_TIMEOUT"; + public static final String ACTION_VIDEO_FINISHED = "com.xypower.mpapp.ACT_V_FINISHED"; private static final String EXTRA_PARAM_CHANNEL = "Channel"; private static final String EXTRA_PARAM_PRESET = "Preset"; private static final String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo"; @@ -161,6 +162,7 @@ public class MicroPhotoService extends Service { intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY); intentFilter.addAction(ACTION_HEARTBEAT_MANUALLY); intentFilter.addAction(ACTION_MSG_BROADCAST); + intentFilter.addAction(ACTION_VIDEO_FINISHED); registerReceiver(mAlarmReceiver, intentFilter); // IntentFilter intentFilter2 = new IntentFilter(ACTION_MSG_BROADCAST); @@ -281,9 +283,10 @@ public class MicroPhotoService extends Service { int channel = (int) ((val & 0xFF0000L) >> 16); int preset = (int) ((val & 0xFF00L) >> 8); + boolean photoOrVideo = ((val & 0xFFL) == 0); Log.i(TAG, "PhotoTimer Fired: CH=" + channel + " PR=" + preset); - mService.notifyToTakePhoto(mService.mNativeHandle, channel, preset, ts, true); + mService.notifyToTakePhoto(mService.mNativeHandle, channel, preset, ts, photoOrVideo); } } @@ -340,6 +343,13 @@ public class MicroPhotoService extends Service { if (what == MSG_WHAT_SENDING_HB) { mService.sendHeartbeat(mService.mNativeHandle); } + } else if (TextUtils.equals(ACTION_VIDEO_FINISHED, action)) { + boolean result = intent.getBooleanExtra("result", false); + String path = intent.getStringExtra("path"); + long videoId = intent.getLongExtra("videoId", 0); + Log.i(TAG, "Recording received(" + Long.toString(videoId) + "):" + path); + + mService.recordingFinished(mService.mNativeHandle, result, path, videoId); } } } @@ -397,6 +407,20 @@ public class MicroPhotoService extends Service { registerPhotoTimer(this.getApplicationContext(), channel, preset, ts, timeout, schedules); } + public void startRecording(int cameraId, long videoId, int duration, int width, int height, int quality) { + Context context = getApplicationContext(); + Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.xypower.mvapp"); + intent.putExtra("cameraId", cameraId); + intent.putExtra("videoId", videoId); + intent.putExtra("duration", duration); + intent.putExtra("width", width); + intent.putExtra("height", height); + intent.putExtra("quality", quality); + + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + context.startActivity(intent); + } + // private HashMap mTimers = new HashMap(); public boolean registerTimer(long uid, int timeout, long times) { @@ -536,6 +560,8 @@ public class MicroPhotoService extends Service { long val = 0; val |= ((long)channel << 16); val |= ((long)preset << 8); + val |= photoOrVideo ? 0L : 1L; + schedules.add(Long.valueOf(val)); registerPhotoTimer(context, channel, preset, 0, 0, schedules); @@ -997,12 +1023,12 @@ cellSignalStrengthGsm.getDbm(); protected native long getHeartbeatDuration(long handler); protected native long[] getPhotoTimeData(long handler); // protected native long[] getNextScheduleItem(long handler); - protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, boolean sendToCma); + protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, boolean photoOrVideo); 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 native void recordingFinished(long handler, boolean result, String path, long videoId); ////////////////////////GPS//////////////////// private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER; diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml index 65a7685a..4e1ead39 100644 --- a/app/src/main/res/layout-land/activity_main.xml +++ b/app/src/main/res/layout-land/activity_main.xml @@ -238,6 +238,47 @@ app:layout_constraintStart_toEndOf="@+id/takePhotoBtn3" app:layout_constraintTop_toTopOf="@+id/takePhotoBtn" /> +