装置端APP代码

serial
Matthew 2 years ago
parent 9952fcbd8c
commit 96f206c213

@ -45,7 +45,7 @@
<uses-permission
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <!-- 接收短信权限 -->
<uses-permission android:name="android.permission.SEND_SMS" />
@ -69,11 +69,11 @@
android:name="android.permission.SET_TIME_ZONE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REBOOT" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" tools:ignore="ProtectedPermissions" /> <!-- 关机权限 -->
@ -82,10 +82,9 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 添加手机关机的权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <!-- 接收短信权限 -->
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission
android:name="android.permission.DEVICE_POWER"

@ -14,6 +14,8 @@ add_definitions(-DBOOST_ALL_NO_LIB)
project("microphoto")
# include(mars/src/CMakeUtils.txt)
SET(TERM_CORE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../xymp/Core)
SET(JSONCPP_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/jsoncpp)

@ -14,6 +14,28 @@
#include "Camera.h"
#include "Camera2Reader.h"
bool GetJniEnv(JavaVM *vm, JNIEnv **env)
{
bool did_attach_thread = false;
*env = nullptr;
// Check if the current thread is attached to the VM
auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED)
{
if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
did_attach_thread = true;
} else {
// Failed to attach thread. Throw an exception if you want to.
}
} else if (get_env_result == JNI_EVERSION)
{
// Unsupported JNI version. Throw an exception if you want to.
}
return did_attach_thread;
}
// #include "client/linux/handler/exception_handler.h"
// #include "client/linux/handler/minidump_descriptor.h"
@ -85,7 +107,7 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
// const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp
CTermClient& service = CTermClient::GetService();
// CTerminalDevice* device = new CTerminalDevice(vm, pThis);
CPhoneDevice* device = new CPhoneDevice();
CPhoneDevice* device = new CPhoneDevice(vm, pThis);
bool res = service.InitService(appPathStr, cmdidStr, ipStr, (unsigned short)port, "", device);
env->ReleaseStringUTFChars(appPath, appPathStr);
@ -95,11 +117,16 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
return res ? JNI_TRUE : JNI_FALSE;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_takePhoto(
JNIEnv* env,
jobject pThis, jint channel, jint preset, jstring path, jstring fileName) {
jobject pThis, jint channel, jint preset, jstring path, jstring fileName, jboolean sendToCma) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
if (pTerminal == NULL)
{
return JNI_FALSE;
}
if (channel < 1 || channel > 0xFF)
{
@ -107,20 +134,47 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_takePhoto(
}
unsigned char id = (unsigned char)channel - 1;
// env->ReleaseStringUTFChars(fileName, fileNameStr);
// env->ReleaseStringUTFChars(path, pathStr);
Camera2Reader *camera = new Camera2Reader(id);
const char *pathStr = env->GetStringUTFChars(path, 0);
const char *fileNameStr = env->GetStringUTFChars(fileName, 0);
pTerminal->TakeAndSendPhoto(channel, preset, 0);
camera->Open(pathStr, fileNameStr);
env->ReleaseStringUTFChars(fileName, fileNameStr);
env->ReleaseStringUTFChars(path, pathStr);
return JNI_TRUE;
}
camera->start();
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat(
JNIEnv* env,
jobject pThis) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
if (pTerminal == NULL)
{
return JNI_FALSE;
}
pTerminal->SendHeartbeat();
return JNI_TRUE;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout(
JNIEnv* env,
jobject pThis, jlong uid) {
IDevice* dev = CTermClient::GetService().GetDevice();
if (dev == NULL)
{
return JNI_FALSE;
}
CPhoneDevice* phoneDevice = (CPhoneDevice *)dev;
return phoneDevice->FireTimer((IDevice::timer_uid_t)uid) ? JNI_TRUE : JNI_FALSE;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_uninit(
JNIEnv* env,
@ -142,3 +196,65 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getHeartbeatDuration(
return 60000;
}
extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
JNIEnv* env,
jobject pThis) {
CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
if (pTerminal == NULL)
{
return NULL;
}
map<unsigned char, vector<unsigned int>> photoTime;
if (!pTerminal->GetPhotoTime(photoTime) || photoTime.empty())
{
return NULL;
}
size_t numberOfData = photoTime.size() * photoTime.begin()->second.size();
if (numberOfData == 0)
{
return NULL;
}
vector<jlong> dataArray;
dataArray.reserve(numberOfData);
unsigned long val = 0;
jint channel = 0;
for (map<unsigned char, vector<unsigned int>>::const_iterator it = photoTime.cbegin(); it != photoTime.cend(); ++it)
{
if (it->second.empty())
{
continue;
}
channel = (jint)((unsigned short)it->first);
// dataArray.push_back(channel);
// val = (jint)it->second.size();
// dataArray.push_back(val);
for (vector<unsigned int>::const_iterator it2 = it->second.cbegin(); it2 != it->second.cend(); ++it2)
{
val = ((unsigned long)channel << 40);
// preset
val |= ((unsigned long)((*it2) & 0xFF)) << 32;
// time
val |= (unsigned long)(((*it2) & 0xFFFFFF00) >> 8);
dataArray.push_back((jlong)val);
}
}
std::sort(dataArray.begin(), dataArray.end());
jlongArray data = env->NewLongArray(dataArray.size());
if (data == NULL) {
return NULL;
}
env->SetLongArrayRegion(data, 0, dataArray.size(), &dataArray[0]);
return data;
}

@ -19,6 +19,7 @@
#define LOG_TAG "CameraTestHelpers"
#include "PhoneDevice.h"
#include "TermClient.h"
#include <android/log.h>
@ -26,36 +27,129 @@
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
CPhoneDevice::CPhoneDevice()
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
{
m_vm = vm;
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
m_javaService = env->NewGlobalRef(service);
jclass classService = env->GetObjectClass(m_javaService);
mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JI)Z");
mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z");
env->DeleteLocalRef(classService);
if (attached)
{
vm->DetachCurrentThread();
}
m_timerUidFeed = time(NULL);
}
CPhoneDevice::~CPhoneDevice()
{
JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env);
env->DeleteGlobalRef(m_javaService);
if (attached)
{
m_vm->DetachCurrentThread();
}
m_javaService = NULL;
}
void CPhoneDevice::SetListener(IListener* listener)
{
m_listener = listener;
}
IDevice::timer_uid_t CPhoneDevice::registerTimer(unsigned int timerType, unsigned int timeout)
{
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
{
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
m_vm->DetachCurrentThread();
}
if (ret == JNI_TRUE)
{
unsigned long val = timerType;
mTimers.insert(mTimers.end(), std::pair<IDevice::timer_uid_t, unsigned long>(uid, val));
return uid;
}
return 0;
}
bool CPhoneDevice::unregisterTimer(IDevice::timer_uid_t uid)
{
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env);
if (attached)
{
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
m_vm->DetachCurrentThread();
}
if (ret == JNI_TRUE)
{
mTimers.erase(uid);
return true;
}
return false;
}
bool CPhoneDevice::onTimeout(IDevice::timer_uid_t uid, unsigned int timerType, unsigned int times)
bool CPhoneDevice::FireTimer(timer_uid_t uid)
{
std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid);
if (it == mTimers.end())
{
return false;
}
unsigned long timerType = it->second & 0xFFFFFFFF;
unsigned long times = (it->second & 0xFFFFFFFF00000000) >> 32;
times++;
if (timerType != 100)
{
int aa = 0;
}
it->second = timerType | (times << 32);
if (m_listener == NULL)
{
return false;
}
m_listener->OnTimeout(uid, timerType, times);
return true;
}
IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, unsigned int timeout)
{
return registerTimer(timerType, timeout);
}
bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const string& path, bool photo)
bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const string& path)
{
int cameraId = (int)channel - 1;
LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
mPhotoInfo = photoInfo;
mPath = path;
int cameraId = (int)photoInfo.channel - 1;
ACameraIdList *cameraIdList = NULL;
ACameraMetadata *cameraMetadata = NULL;
@ -67,16 +161,19 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
camera_status = ACameraManager_getCameraIdList(cameraManager, &cameraIdList);
if (camera_status != ACAMERA_OK) {
LOGI("Failed to get camera id list (reason: %d)\n", camera_status);
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
if (cameraIdList->numCameras < 1 ) {
LOGI("No camera device detected.\n");
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
if (cameraIdList->numCameras <= cameraId ) {
LOGI("No required camera device %d detected.\n", cameraId);
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@ -125,6 +222,7 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
if (status != AMEDIA_OK)
{
LOGI("AImageReader_new error\n");
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@ -139,6 +237,7 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
if (status != AMEDIA_OK)
{
LOGI("AImageReader_getWindow error\n");
TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@ -157,7 +256,6 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
ACameraCaptureSession_capture(captureSession, NULL, 1, &captureRequest, NULL);
LOGI("Surface is prepared in here.\n");
return true;
}
@ -175,31 +273,28 @@ ACameraCaptureSession_stateCallbacks* CPhoneDevice::GetSessionListener()
void CPhoneDevice::ImageCallback(AImageReader *reader)
{
int32_t format;
AImage *image = nullptr;
media_status_t status = AImageReader_acquireNextImage(reader, &image);
LOGI("ImageCallback\n");
if (status == AMEDIA_OK && image)
{
LOGI("ImageCallback\n");
bool res = WriteFile(image);
AImage_delete(image);
// delete pThis;
TakePhotoCb(res, mPhotoInfo, mPath, time(NULL));
}
}
void CPhoneDevice::OnImageCallback(void *ctx, AImageReader *reader)
{
CPhoneDevice* pThis = reinterpret_cast<CPhoneDevice*>(ctx);
AImage *image = nullptr;
media_status_t status = AImageReader_acquireNextImage(reader, &image);
if (status == AMEDIA_OK && image)
if (pThis != NULL)
{
WriteFile(pThis, image);
AImage_delete(image);
// delete pThis;
pThis->ImageCallback(reader);
}
}
bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
bool CPhoneDevice::WriteFile(AImage *image)
{
int planeCount = 0;
media_status_t status = AImage_getNumberOfPlanes(image, &planeCount);
@ -215,7 +310,7 @@ bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
int len = 0;
AImage_getPlaneData(image, 0, &data, &len);
std::string path = pThis->GetFileName();
std::string path = GetFileName();
bool res = false;
FILE *file = fopen(path.c_str(), "wb");
@ -225,6 +320,8 @@ bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
fclose(file);
LOGE("Capture: %s", path.c_str());
res = true;
}
else
@ -236,16 +333,87 @@ bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
return res;
}
bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
{
return pThis->WriteFile(image);
}
std::string CPhoneDevice::GetFileName() const
{
return mPath;
}
/*
bool CPhoneDevice::SendBroadcastMessage(String16 action, int value)
{
TM_INFO_LOG("sendBroadcastMessage(): Action: %s, Value: %d ", action.string(), value);
sp <IServiceManager> sm = defaultServiceManager();
sp <IBinder> am = sm->getService(String16("activity"));
if (am != NULL) {
Parcel data, reply;
data.writeInterfaceToken(String16("android.app.IActivityManager"));
data.writeStrongBinder(NULL);
// intent begin
data.writeString16(action); // action
data.writeInt32(0); // URI data type
data.writeString16(NULL, 0); // type
data.writeInt32(0); // flags
data.writeString16(NULL, 0); // package name
data.writeString16(NULL, 0); // component name
data.writeInt32(0); // source bound - size
data.writeInt32(0); // categories - size
data.writeInt32(0); // selector - size
data.writeInt32(0); // clipData - size
data.writeInt32(-2); // contentUserHint: -2 -> UserHandle.USER_CURRENT
data.writeInt32(-1); // bundle extras length
data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'
int oldPos = data.dataPosition();
data.writeInt32(1); // size
// data.writeInt32(0); // VAL_STRING, need to remove because of analyze common intent
data.writeString16(String16("type"));
data.writeInt32(1); // VAL_INTEGER
data.writeInt32(value);
int newPos = data.dataPosition();
data.setDataPosition(oldPos - 8);
data.writeInt32(newPos - oldPos); // refill bundle extras length
data.setDataPosition(newPos);
// intent end
data.writeString16(NULL, 0); // resolvedType
data.writeStrongBinder(NULL); // resultTo
data.writeInt32(0); // resultCode
data.writeString16(NULL, 0); // resultData
data.writeInt32(-1); // resultExtras
data.writeString16(NULL, 0); // permission
data.writeInt32(0); // appOp
data.writeInt32(-1); // option
data.writeInt32(1); // serialized: != 0 -> ordered
data.writeInt32(0); // sticky
data.writeInt32(-2); // userId: -2 -> UserHandle.USER_CURRENT
status_t ret = am->transact(IBinder::FIRST_CALL_TRANSACTION + 13, data,
&reply); // BROADCAST_INTENT_TRANSACTION
if (ret == NO_ERROR) {
int exceptionCode = reply.readExceptionCode();
if (exceptionCode) {
TM_INFO_LOG("sendBroadcastMessage(%s) caught exception %d\n",
action.string(), exceptionCode);
return false;
}
} else {
return false;
}
} else {
TM_INFO_LOG("getService() couldn't find activity service!\n");
return false;
}
return true;
}
*/
void CPhoneDevice::camera_device_on_disconnected(void *context, ACameraDevice *device)
{
LOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device));
CPhoneDevice* pThis = (CPhoneDevice*)context;
delete pThis;
// delete pThis;
}
void CPhoneDevice::camera_device_on_error(void *context, ACameraDevice *device, int error)

@ -9,6 +9,9 @@
#include <string.h>
#include <time.h>
#include <map>
#include <atomic>
#include <camera/NdkCameraManager.h>
#include <camera/NdkCameraError.h>
#include <camera/NdkCameraDevice.h>
@ -25,19 +28,23 @@
class CPhoneDevice : public IDevice
{
public:
CPhoneDevice();
~CPhoneDevice();
CPhoneDevice(JavaVM* vm, jobject service);
virtual ~CPhoneDevice();
virtual bool TakePhoto(unsigned char channel, unsigned char preset, const string& path, bool photo);
virtual void SetListener(IListener* listener);
virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout);
virtual bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const string& path);
virtual timer_uid_t registerTimer(unsigned int timerType, unsigned int timeout);
virtual bool unregisterTimer(timer_uid_t uid);
virtual bool onTimeout(timer_uid_t uid, unsigned int timerType, unsigned int times);
virtual bool FireTimer(timer_uid_t uid);
protected:
ACameraCaptureSession_stateCallbacks *GetSessionListener();
std::string GetFileName() const;
bool SendBroadcastMessage(std::string action, int value);
static void camera_device_on_disconnected(void *context, ACameraDevice *device);
static void camera_device_on_error(void *context, ACameraDevice *device, int error);
static void capture_session_on_ready(void *context, ACameraCaptureSession *session);
@ -46,11 +53,35 @@ protected:
void ImageCallback(AImageReader *reader);
static void OnImageCallback(void *ctx, AImageReader *reader);
bool WriteFile(AImage *image);
static bool WriteFile(CPhoneDevice* pThis, AImage *image);
inline bool TakePhotoCb(bool res, const IDevice::PHOTO_INFO& photoInfo, const string& path, time_t photoTime)
{
if (m_listener != NULL)
{
return m_listener->OnPhotoTaken(res, photoInfo, path, photoTime);
}
return false;
}
protected:
JavaVM* m_vm;
jobject m_javaService;
jmethodID mRegisterTimerMid;
jmethodID mUnregisterTimerMid;
std::string mPath;
IDevice::PHOTO_INFO mPhotoInfo;
IListener* m_listener;
atomic_ulong m_timerUidFeed;
std::map<IDevice::timer_uid_t, unsigned long> mTimers;
AImageReader *mAImageReader;
ANativeWindow *theNativeWindow;

@ -4,26 +4,7 @@
typedef jbyteArray (*TakePhotoFunc)(int, int, int, int);
bool GetJniEnv(JavaVM *vm, JNIEnv **env)
{
bool did_attach_thread = false;
*env = nullptr;
// Check if the current thread is attached to the VM
auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED)
{
if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
did_attach_thread = true;
} else {
// Failed to attach thread. Throw an exception if you want to.
}
} else if (get_env_result == JNI_EVERSION)
{
// Unsupported JNI version. Throw an exception if you want to.
}
return did_attach_thread;
}
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
CTerminalDevice::CTerminalDevice(JavaVM* vm, jobject service)
{

@ -58,6 +58,7 @@ public class FloatingWindow extends Service {
WindowManager.LayoutParams mWindowsParams;
private void moveView() {
/*
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int width = (int) (metrics.widthPixels * 1f);
int height = (int) (metrics.heightPixels * 1f);
@ -122,6 +123,8 @@ public class FloatingWindow extends Service {
return false;
}
});
*/
}
private boolean isViewInBounds(View view, int x, int y) {

@ -7,6 +7,7 @@ import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
@ -87,6 +88,31 @@ public class MainActivity extends AppCompatActivity {
});
this.binding.stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, MicroPhotoService.class);
intent.setAction(MicroPhotoService.ACTION_STOP);
MainActivity.this.stopService(intent);
binding.start.setEnabled(true);
binding.stop.setEnabled(false);
}
});
Handler handler=new Handler();
Runnable runnable=new Runnable(){
@Override
public void run() {
binding.start.performClick();
}
};
handler.postDelayed(runnable, 2000);
}
protected void takePhoto()

@ -30,8 +30,18 @@ import com.dowse.camera.client.DSCameraManager;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MicroPhotoService extends Service {
@ -55,6 +65,19 @@ public class MicroPhotoService extends Service {
private static String ACTION_HEARTBEAT = "ACT_HB";
private static String ACTION_TAKE_PHOTO = "ACT_TP";
private static String ACTION_TIMEOUT = "ACT_TIMEOUT";
private static String EXTRA_PARAM_CHANNEL = "Channel";
private static String EXTRA_PARAM_SCHEDULES = "Schedules";
private static String EXTRA_PARAM_SCHEDULE = "Schedule_";
private static String EXTRA_PARAM_PRESET = "Preset";
private static String EXTRA_PARAM_TIME = "Time";
// private static String EXTRA_PARAM_FILENAME = "FileName";
private static String EXTRA_PARAM_TIMER_UID = "TimerUid";
// private static String EXTRA_PARAM_TIMER_TYPE = "TimerType";
private static String EXTRA_PARAM_TIMEOUT = "Timeout";
private final static String FOREGROUND_CHANNEL_ID = "foreground_channel_id";
@ -63,20 +86,15 @@ public class MicroPhotoService extends Service {
public static final int NOT_CONNECTED = 0;
}
private static String mDesc = "";
private AlarmManager mAlarmManager;
private NotificationManager mNotificationManager;
private Handler handler;
private int count = 0;
private int mHeartbeatDuration = 300000; // 5m: 5 * 60 * 1000
private long mNextHeartbeatTime = 0;
private Map<Long, PendingIntent> mTimers = new HashMap<>();
private static int stateService = STATE_SERVICE.NOT_CONNECTED;
public MicroPhotoService() {
}
@Override
@ -92,7 +110,31 @@ public class MicroPhotoService extends Service {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
stateService = STATE_SERVICE.NOT_CONNECTED;
alarmReceiver = new AlarmReceiver(this);
// 注册广播接受者
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO);
intentFilter.addAction(ACTION_TIMEOUT);
registerReceiver( alarmReceiver, intentFilter);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
while (true) {
AlarmManager.AlarmClockInfo aci = alarmManager.getNextAlarmClock();
if (aci == null) {
break;
}
if (aci.getShowIntent().isBroadcast()) {
// alarmManager.cancel(aci.getShowIntent());
}
}
// alarmManager.cancel();
boolean res = false;
/*
res = DSCameraManager.getInstace().init();
ChannelPicParam picParam = new ChannelPicParam();
picParam.setColor(1);
@ -100,8 +142,13 @@ public class MicroPhotoService extends Service {
picParam.setHeight(1080);
picParam.setCompress_radio(40);
DSCameraManager.getInstace().setPicParam(1, picParam);
*/
// Environment.getExternalStoragePublicDirectory(String)
File path = getApplicationContext().getFilesDir();
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/");
if (!path.exists()) {
path.mkdirs();
}
// File path = getApplicationContext().getFilesDir();
String appPath = path.getAbsolutePath();
Log.i("XYMP", "AppPath=" + appPath);
String ip = "180.166.218.222";
@ -109,14 +156,203 @@ public class MicroPhotoService extends Service {
String cmdid = "XYDEV100230100012";
init(appPath, ip, port, cmdid);
alarmReceiver = new AlarmReceiver(this);
// registerHeartbeatTimer(getHeartbeatDuration());
// 注册广播接受者
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO);
registerReceiver( alarmReceiver, intentFilter);
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();
}
public static class AlarmReceiver extends BroadcastReceiver {
private MicroPhotoService mService;
public AlarmReceiver(MicroPhotoService service) {
mService = service;
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(TextUtils.equals(ACTION_HEARTBEAT, action)){
Log.i(TAG, "receiver ACTION=" + action);
mService.sendHeartbeat();
mService.registerHeartbeatTimer();
}
else if(TextUtils.equals(ACTION_TAKE_PHOTO, action)) {
long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0);
int cnt = intent.getIntExtra(EXTRA_PARAM_SCHEDULES, 0);
if (cnt > 0) {
for (int idx = 0; idx < cnt; idx++) {
long val = intent.getLongExtra(EXTRA_PARAM_SCHEDULE + idx, 0);
int channel = (int)((val & 0xFF0000000000L) >> 40);
int preset = (int)((val & 0xFF00000000L) >> 32);
mService.takePhoto(channel, preset, mService.buildPhotoDir(channel), mService.buildPhotoFileName(channel, preset, ts), true);
}
}
// Register Next Photo Timer
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;
mService.registerCaptureSchedule(startTime, baseTime);
}
else if(TextUtils.equals(ACTION_TIMEOUT, action)) {
long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0);
Log.i(TAG, "Timeout:" + uid);
mService.fireTimeout(uid);
int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0);
Long uidObj = Long.valueOf(uid);
PendingIntent pendingIntent = mService.mTimers.get(uidObj);
if (pendingIntent != null) {
mService.registerTimer(pendingIntent, uid, timeout);
}
}
}
}
private void updateHeartbeatDuration(int duration) {
mHeartbeatDuration = duration;
}
private void registerHeartbeatTimer() {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_HEARTBEAT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + mHeartbeatDuration, pendingIntent);
mNextHeartbeatTime = System.currentTimeMillis() + mHeartbeatDuration;
// alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent);
}
private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List<Long> schedules) {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TAKE_PHOTO);
int cnt = schedules.size();
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULES, cnt);
for (int idx = 0; idx < cnt; idx++) {
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue());
}
alarmIntent.putExtra(EXTRA_PARAM_TIME, ts);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
}
registerHeartbeatTimer(getHeartbeatDuration());
// private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>();
public boolean registerTimer(long uid, int timeout) {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TIMEOUT);
alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid);
alarmIntent.putExtra(EXTRA_PARAM_TIMEOUT, timeout);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mTimers.put(Long.valueOf(uid), pendingIntent);
return registerTimer(pendingIntent, uid, timeout);
}
public boolean registerTimer(PendingIntent pendingIntent, long uid, int timeout) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + timeout, pendingIntent);
Log.i(TAG, "RegTimer:" + uid + " timeout=" + timeout);
return true;
}
public boolean unregisterTimer(long uid) {
Long uidObj = Long.valueOf(uid);
PendingIntent pendingIntent = mTimers.get(uidObj);
if (pendingIntent != null) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
mTimers.remove(uidObj);
Log.i(TAG, "UnregTimer:" + uid);
}
return true;
}
private boolean registerCaptureSchedule(long startTime, long baseTime) {
long[] photoTimeData = getPhotoTimeData();
if (photoTimeData == null) {
return false;
}
int cnt = photoTimeData.length;
int idx = 0;
short channel = 0;
short preset = 0;
int ts = 0;
long val = 0L;
// int maxDuration = mHeartbeatDuration * 2 / 1000;
int maxDuration = 35 * 60 * 1000 + 1000;
int currentTs = 0;
List<Long> schedules = new ArrayList<>();
while (true) {
val = photoTimeData[idx++];
ts = (int)(val & 0xFFFFFFFFL);
if (ts < baseTime) {
continue;
}
if ((ts - baseTime) > maxDuration) {
break;
}
if (currentTs == 0) {
currentTs = ts;
channel = (short)((val & 0xFF0000000000L) >> 40);
preset = (short)((val & 0xFF00000000L) >> 32);
schedules.add(Long.valueOf(val));
} else if (ts > currentTs) {
break;
} else {
schedules.add(Long.valueOf(val));
}
}
if (!schedules.isEmpty()) {
Date date = new Date((startTime + ts) * 1000);
Log.d(TAG, "Register Photo Time: " + date.toString() + " BaseTime=" + baseTime + " ts=" + ts + " startTime=" + startTime);
registerPhotoTimer(channel, preset, currentTs, (currentTs - baseTime) * 1000, schedules);
}
return true;
}
@Override
@ -151,7 +387,6 @@ public class MicroPhotoService extends Service {
return START_NOT_STICKY;
}
private void connect() {
// after 10 seconds its connected
new android.os.Handler().postDelayed(
@ -273,8 +508,8 @@ public class MicroPhotoService extends Service {
super.onDestroy();
}
private String buildPhotoDir(int channel) {
File path = new File(Environment.getExternalStorageDirectory(), "com.xinyingpower.com/photos/");
public String buildPhotoDir(int channel) {
File path = new File(Environment.getExternalStorageDirectory(), "com.xyp.mp/photos/");
if (!path.exists() && !path.mkdirs()) {
return null;
@ -286,74 +521,22 @@ public class MicroPhotoService extends Service {
return p;
}
private String buildPhotoFileName(int channel, int preset) {
private String buildPhotoFileName(int channel, int preset, long ts) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
String photoFile = "img_" + Integer.toString(channel) + "_" + Integer.toHexString(preset).toUpperCase() + "_" + date + ".jpg";
return photoFile;
}
public static class AlarmReceiver extends BroadcastReceiver {
private MicroPhotoService mService;
public AlarmReceiver(MicroPhotoService service) {
mService = service;
}
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(TextUtils.equals(ACTION_HEARTBEAT, action)){
Log.i(TAG, "receiver ACTION=" + action);
mService.registerHeartbeatTimer(mService.getHeartbeatDuration());
}
}
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 获取广播事件
String action = intent.getAction();
if(TextUtils.equals(ACTION_HEARTBEAT, action)){
Log.i(TAG, "receiver ACTION");
registerHeartbeatTimer(getHeartbeatDuration());
}
}
};
private void registerHeartbeatTimer(long timeout){
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_HEARTBEAT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + timeout, pendingIntent);
// alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent);
}
private void registerPhotoTimer(long ts){
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TAKE_PHOTO);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, ts, pendingIntent);
}
protected native boolean init(String appPath, String ip, int port, String cmdid);
protected native long getHeartbeatDuration();
protected native boolean takePhoto(int channel, int preset, String path, String fileName);
protected native long[] getPhotoTimeData();
protected native boolean takePhoto(int channel, int preset, String path, String fileName, boolean sendToCma);
protected native boolean sendHeartbeat();
protected native boolean fireTimeout(long uid);
protected native boolean uninit();
protected long mHandler = 0;
private AlarmReceiver alarmReceiver = null;

Loading…
Cancel
Save