카메라2번 연결 시 자동 절체 컨텐츠 재생 처리
해제시 1번 카메라 절체 처리
This commit is contained in:
parent
5827b1eb7d
commit
936d804d1d
@ -18,7 +18,7 @@ video_source avformat,android_camera,1
|
|||||||
videnc_format yuv420p
|
videnc_format yuv420p
|
||||||
audio_jitter_buffer_type adaptive
|
audio_jitter_buffer_type adaptive
|
||||||
audio_jitter_buffer_delay 0-20
|
audio_jitter_buffer_delay 0-20
|
||||||
video_jitter_buffer_type adaptive
|
video_jitter_buffer_type off
|
||||||
video_jitter_buffer_delay 1-100
|
video_jitter_buffer_delay 1-100
|
||||||
rtp_stats yes
|
rtp_stats yes
|
||||||
rtp_timeout 60
|
rtp_timeout 60
|
||||||
|
@ -116,7 +116,7 @@ add_library(lib_baresip STATIC IMPORTED)
|
|||||||
set_target_properties(lib_baresip PROPERTIES IMPORTED_LOCATION
|
set_target_properties(lib_baresip PROPERTIES IMPORTED_LOCATION
|
||||||
${distribution_DIR}/baresip/lib/${ANDROID_ABI}/libbaresip.a)
|
${distribution_DIR}/baresip/lib/${ANDROID_ABI}/libbaresip.a)
|
||||||
|
|
||||||
add_library(baresip SHARED baresip.c vidisp.c)
|
add_library(baresip SHARED baresip.c vidisp.c serial.c)
|
||||||
|
|
||||||
#set(CMAKE_SHARED_LINKER_FLAGS
|
#set(CMAKE_SHARED_LINKER_FLAGS
|
||||||
# "${CMAKE_SHARED_LINKER_FLAGS} -u AImageReader_new")
|
# "${CMAKE_SHARED_LINKER_FLAGS} -u AImageReader_new")
|
||||||
|
119
app/src/main/cpp/serial.c
Normal file
119
app/src/main/cpp/serial.c
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <jni.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// Created by ritos on 2025-03-10.
|
||||||
|
//
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// 설명 : 시리얼포트를 연다.
|
||||||
|
// 주의 : RTS/CTS 를 제어하지 않는다.
|
||||||
|
// 시리얼포트를 열고 이전의 포트설정상태를 저장하지 않았다.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
int open_serial(const char *dev_name, int baud, int vtime, int vmin )
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct termios newtio;
|
||||||
|
// 시리얼포트를 연다.
|
||||||
|
fd = open( dev_name, O_RDWR | O_NOCTTY | O_NONBLOCK );
|
||||||
|
if ( fd < 0 )
|
||||||
|
{
|
||||||
|
// 화일 열기 실패
|
||||||
|
printf( "Device OPEN FAIL %s\n", dev_name );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// 시리얼 포트 환경을 설정한다.
|
||||||
|
memset(&newtio, 0, sizeof(newtio));
|
||||||
|
newtio.c_iflag = IGNPAR; // non-parity
|
||||||
|
newtio.c_oflag = 0;
|
||||||
|
newtio.c_cflag = CS8 | CLOCAL | CREAD; // NO-rts/cts
|
||||||
|
|
||||||
|
switch( baud )
|
||||||
|
{
|
||||||
|
case 115200 : newtio.c_cflag |= B115200; break;
|
||||||
|
case 57600 : newtio.c_cflag |= B57600; break;
|
||||||
|
case 38400 : newtio.c_cflag |= B38400; break;
|
||||||
|
case 19200 : newtio.c_cflag |= B19200; break;
|
||||||
|
case 9600 : newtio.c_cflag |= B9600; break;
|
||||||
|
case 4800 : newtio.c_cflag |= B4800; break;
|
||||||
|
case 2400 : newtio.c_cflag |= B2400; break;
|
||||||
|
default : newtio.c_cflag |= B115200; break;
|
||||||
|
}
|
||||||
|
//set input mode (non-canonical, no echo,.....)
|
||||||
|
newtio.c_lflag = 0;
|
||||||
|
newtio.c_cc[VTIME] = vtime; // timeout 0.1초 단위
|
||||||
|
newtio.c_cc[VMIN] = vmin; // 최소 n 문자 받을 때까진 대기
|
||||||
|
tcflush ( fd, TCIFLUSH );
|
||||||
|
tcsetattr( fd, TCSANOW, &newtio );
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// 설명 : 시리얼포트를 닫는다.
|
||||||
|
// 주의 :
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void close_serial( int fd )
|
||||||
|
{
|
||||||
|
close( fd );
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Utils_openSerial(JNIEnv *env, jobject thiz, jstring strDev, jint baudrate)
|
||||||
|
{
|
||||||
|
(void)env;
|
||||||
|
(void)thiz;
|
||||||
|
const char *pType;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
pType = (*env)->GetStringUTFChars(env, strDev, NULL);
|
||||||
|
result = open_serial(pType, baudrate, 100, 1);
|
||||||
|
(*env)->ReleaseStringUTFChars(env, strDev, pType);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Utils_readSerial(JNIEnv *env, jobject thiz, jint devHandle, jbyteArray buffer, jint size)
|
||||||
|
{
|
||||||
|
(void)env;
|
||||||
|
(void)thiz;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
jbyte *pBuffer = (*env)->GetByteArrayElements(env, buffer, NULL);
|
||||||
|
result = read( devHandle, (char *)pBuffer, size );
|
||||||
|
(*env)->ReleaseByteArrayElements(env, buffer, pBuffer, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Utils_writeSerial(JNIEnv *env, jobject thiz, jint devHandle, jbyteArray buffer, jint size)
|
||||||
|
{
|
||||||
|
(void)env;
|
||||||
|
(void)thiz;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
jbyte *pBuffer = (*env)->GetByteArrayElements(env, buffer, NULL);
|
||||||
|
result = write( devHandle, (char *)pBuffer, size );
|
||||||
|
(*env)->ReleaseByteArrayElements(env, buffer, pBuffer, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Utils_closeSerial(JNIEnv *env, jobject thiz, jint devHandle)
|
||||||
|
{
|
||||||
|
(void)env;
|
||||||
|
(void)thiz;
|
||||||
|
close_serial(devHandle);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
@ -73,6 +73,27 @@ static void renderer_destroy(struct vidisp_st *st)
|
|||||||
gst = NULL;
|
gst = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void renderer_destroy_self(struct vidisp_st *st)
|
||||||
|
{
|
||||||
|
LOGD("At renderer_destroy_self() on thread %li\n", (long)pthread_self());
|
||||||
|
|
||||||
|
if (st->display != EGL_NO_DISPLAY) {
|
||||||
|
eglMakeCurrent(st->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
if (st->surface != EGL_NO_SURFACE) {
|
||||||
|
eglDestroySurface(st->display, st->surface);
|
||||||
|
st->surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
if (st->context != EGL_NO_CONTEXT) {
|
||||||
|
eglDestroyContext(st->display, st->context);
|
||||||
|
st->context = EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
eglTerminate(st->display);
|
||||||
|
st->display = EGL_NO_DISPLAY;
|
||||||
|
}
|
||||||
|
eglReleaseThread();
|
||||||
|
gst_self = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void destructor(void *arg)
|
static void destructor(void *arg)
|
||||||
{
|
{
|
||||||
struct vidisp_st *st = arg;
|
struct vidisp_st *st = arg;
|
||||||
@ -81,6 +102,14 @@ static void destructor(void *arg)
|
|||||||
mem_deref(st->vf);
|
mem_deref(st->vf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destructor_self(void *arg)
|
||||||
|
{
|
||||||
|
struct vidisp_st *st = arg;
|
||||||
|
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
mem_deref(st->vf);
|
||||||
|
}
|
||||||
|
|
||||||
static int context_initialize(struct vidisp_st *st)
|
static int context_initialize(struct vidisp_st *st)
|
||||||
{
|
{
|
||||||
const EGLint attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
|
const EGLint attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
|
||||||
@ -166,6 +195,93 @@ static int context_initialize(struct vidisp_st *st)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int context_initialize_self(struct vidisp_st *st)
|
||||||
|
{
|
||||||
|
const EGLint attribs[] = {EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8,
|
||||||
|
EGL_RED_SIZE, 8, EGL_NONE};
|
||||||
|
|
||||||
|
EGLDisplay display;
|
||||||
|
EGLConfig config;
|
||||||
|
EGLint numConfigs;
|
||||||
|
EGLint format;
|
||||||
|
EGLSurface surface;
|
||||||
|
EGLContext context;
|
||||||
|
|
||||||
|
if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {
|
||||||
|
LOGW("eglGetDisplay() returned error %d\n", eglGetError());
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
if (!eglInitialize(display, NULL, NULL)) {
|
||||||
|
LOGW("eglInitialize() returned error %d\n", eglGetError());
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) {
|
||||||
|
LOGW("eglChooseConfig() returned error %d\n", eglGetError());
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
|
||||||
|
LOGW("eglGetConfigAttrib() returned error %d\n", eglGetError());
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
ANativeWindow_setBuffersGeometry(st->window, 0, 0, format);
|
||||||
|
|
||||||
|
if (!(surface = eglCreateWindowSurface(display, config, st->window, NULL))) {
|
||||||
|
LOGW("eglCreateWindowSurface() returned error %s\n", egl_error(eglGetError()));
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
|
||||||
|
LOGW("eglBindApi failed with error %s\n", egl_error(eglGetError()));
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL))) {
|
||||||
|
LOGW("eglCreateContext() returned error %d\n", eglGetError());
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(display, surface, surface, context)) {
|
||||||
|
LOGW("eglMakeCurrent() returned error %d\n", eglGetError());
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglQuerySurface(display, surface, EGL_WIDTH, &st->width)
|
||||||
|
|| !eglQuerySurface(display, surface, EGL_HEIGHT, &st->height)) {
|
||||||
|
LOGW("eglQuerySurface() returned error %d\n", eglGetError());
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
return eglGetError();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGD("RenderSelf buffer w/h = %d/%d", st->width, st->height);
|
||||||
|
|
||||||
|
st->display = display;
|
||||||
|
st->surface = surface;
|
||||||
|
st->context = context;
|
||||||
|
|
||||||
|
glDisable(GL_DITHER);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
resize = false;
|
||||||
|
resize_self = false;
|
||||||
|
|
||||||
|
LOGD("Rendered contextSelf initialized");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int opengles_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm,
|
int opengles_alloc(struct vidisp_st **stp, const struct vidisp *vd, struct vidisp_prm *prm,
|
||||||
const char *dev, vidisp_resize_h *resizeh, void *arg)
|
const char *dev, vidisp_resize_h *resizeh, void *arg)
|
||||||
{
|
{
|
||||||
@ -217,9 +333,9 @@ int opengles_alloc_self(struct vidisp_st **stp, const struct vidisp *vd, struct
|
|||||||
LOGD("At opengles_alloc_self() on thread %li\n", (long)pthread_self());
|
LOGD("At opengles_alloc_self() on thread %li\n", (long)pthread_self());
|
||||||
|
|
||||||
if (gst_self)
|
if (gst_self)
|
||||||
renderer_destroy(gst_self);
|
renderer_destroy_self(gst_self);
|
||||||
|
|
||||||
gst_self = mem_zalloc(sizeof(*gst_self), destructor);
|
gst_self = mem_zalloc(sizeof(*gst_self), destructor_self);
|
||||||
if (!gst_self)
|
if (!gst_self)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
@ -612,11 +728,11 @@ static int opengles_render_self(struct vidisp_st *st)
|
|||||||
|
|
||||||
err = texture_init(st);
|
err = texture_init(st);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGW("opengles_render_self: failed to initialize texture\n");
|
LOGW("[SELF] opengles_render_self: failed to initialize texture\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGD("video frame width/height = %d/%d\n", st->vf->size.w, st->vf->size.h);
|
LOGD("[SELF] video frame width/height = %d/%d\n", st->vf->size.w, st->vf->size.h);
|
||||||
|
|
||||||
#if 1 // 원본 이미지 원본 크기를 View 에 매핑. 작으면 가운데로, 크면 Crop 발생
|
#if 1 // 원본 이미지 원본 크기를 View 에 매핑. 작으면 가운데로, 크면 Crop 발생
|
||||||
frame_width_self = st->vf->size.w;
|
frame_width_self = st->vf->size.w;
|
||||||
@ -729,22 +845,22 @@ int opengles_display_self(
|
|||||||
|
|
||||||
/* This is hack to make sure that context is initialised on the same thread */
|
/* This is hack to make sure that context is initialised on the same thread */
|
||||||
if (!st->context) {
|
if (!st->context) {
|
||||||
err = context_initialize(st);
|
err = context_initialize_self(st);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGW("Renderer context init failed with error %d\n", err);
|
LOGW("[SELF] Renderer context init failed with error %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!st->vf) {
|
if (!st->vf) {
|
||||||
if (frame->size.w & 3) {
|
if (frame->size.w & 3) {
|
||||||
LOGW("opengles_display: frame width must be multiple of 4\n");
|
LOGW("[SELF] opengles_display: frame width must be multiple of 4\n");
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = vidframe_alloc(&st->vf, VID_FMT_RGB565, &frame->size);
|
err = vidframe_alloc(&st->vf, VID_FMT_RGB565, &frame->size);
|
||||||
if (err) {
|
if (err) {
|
||||||
LOGW("opengles_display: vidframe_alloc failed: %d\n", err);
|
LOGW("[SELF] opengles_display: vidframe_alloc failed: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -754,8 +870,16 @@ int opengles_display_self(
|
|||||||
opengles_render_self(st);
|
opengles_render_self(st);
|
||||||
|
|
||||||
err = eglSwapBuffers(st->display, st->surface);
|
err = eglSwapBuffers(st->display, st->surface);
|
||||||
if (!err)
|
if (!err) {
|
||||||
LOGW("eglSwapBuffers() returned error %s\n", egl_error(eglGetError()));
|
LOGW("[SELF] eglSwapBuffers() returned error %s\n", egl_error(eglGetError()));
|
||||||
|
renderer_destroy_self(st);
|
||||||
|
mem_deref(st->vf);
|
||||||
|
|
||||||
|
err = context_initialize_self(st);
|
||||||
|
err = vidframe_alloc(&st->vf, VID_FMT_RGB565, &frame->size);
|
||||||
|
glDeleteTextures(1, &st->texture_id);
|
||||||
|
st->texture_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -808,20 +932,20 @@ JNIEXPORT void JNICALL Java_com_tutpro_baresip_plus_VideoView_set_1surfaceSelf(
|
|||||||
{
|
{
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
||||||
LOGD("At set_surface() on thread %li\n", (long)pthread_self());
|
LOGD("[SELF] At set_surface() on thread %li\n", (long)pthread_self());
|
||||||
|
|
||||||
if (surface != 0) {
|
if (surface != 0) {
|
||||||
window_self = ANativeWindow_fromSurface(env, surface);
|
window_self = ANativeWindow_fromSurface(env, surface);
|
||||||
w = ANativeWindow_getWidth(window_self);
|
w = ANativeWindow_getWidth(window_self);
|
||||||
h = ANativeWindow_getHeight(window_self);
|
h = ANativeWindow_getHeight(window_self);
|
||||||
if ((w != window_width_self) || (h != window_height_self)) {
|
if ((w != window_width_self) || (h != window_height_self)) {
|
||||||
LOGI("Got new windowSelf %p with w/h = %d/%d", window_self, w, h);
|
LOGI("[SELF] Got new windowSelf %p with w/h = %d/%d", window_self, w, h);
|
||||||
window_width_self = w;
|
window_width_self = w;
|
||||||
window_height_self = h;
|
window_height_self = h;
|
||||||
resize_self = true;
|
resize_self = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOGI("Releasing windowSelf");
|
LOGI("[SELF] Releasing windowSelf");
|
||||||
ANativeWindow_release(window_self);
|
ANativeWindow_release(window_self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,10 +216,10 @@ object Config {
|
|||||||
|
|
||||||
val videoSize = previousVariable("video_size")
|
val videoSize = previousVariable("video_size")
|
||||||
BaresipService.videoSize = if (videoSize !in videoSizes) {
|
BaresipService.videoSize = if (videoSize !in videoSizes) {
|
||||||
if ("1280x720" in videoSizes)
|
if ("1920x1080" in videoSizes)
|
||||||
Size(1280, 720)
|
Size(1920, 1080)
|
||||||
else
|
else
|
||||||
Size(640, 480)
|
Size(1280, 720)
|
||||||
} else {
|
} else {
|
||||||
Size(videoSize.substringBefore("x").toInt(),
|
Size(videoSize.substringBefore("x").toInt(),
|
||||||
videoSize.substringAfter("x").toInt())
|
videoSize.substringAfter("x").toInt())
|
||||||
|
@ -13,12 +13,12 @@ import android.content.Intent.ACTION_DIAL
|
|||||||
import android.content.Intent.ACTION_VIEW
|
import android.content.Intent.ACTION_VIEW
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.media.MediaActionSound
|
import android.media.MediaActionSound
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.*
|
import android.os.*
|
||||||
|
import android.os.StrictMode.VmPolicy
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
@ -46,7 +46,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.tutpro.baresip.plus.Utils.showSnackBar
|
import com.tutpro.baresip.plus.Utils.showSnackBar
|
||||||
import com.tutpro.baresip.plus.databinding.ActivityMainBinding
|
import com.tutpro.baresip.plus.databinding.ActivityMainBinding
|
||||||
import org.w3c.dom.Text
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@ -54,6 +53,7 @@ import java.time.format.DateTimeFormatter
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
class SecondScreenPresentation(context: Context, display: Display) : Presentation(context, display) {
|
class SecondScreenPresentation(context: Context, display: Display) : Presentation(context, display) {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -159,6 +159,18 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// if (BuildConfig.DEBUG) {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// StrictMode.setVmPolicy(
|
||||||
|
// VmPolicy.Builder()
|
||||||
|
// .detectLeakedClosableObjects() // ✨ close() 호출 누락 감지
|
||||||
|
// .penaltyLog() // Logcat에 로그 출력
|
||||||
|
// .penaltyDeath() // 앱 크래시 (원인 추적 용이)
|
||||||
|
// .build()
|
||||||
|
// )
|
||||||
|
|
||||||
enableEdgeToEdge()
|
enableEdgeToEdge()
|
||||||
|
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||||
@ -2671,6 +2683,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (atStartup)
|
if (atStartup)
|
||||||
moveTaskToBack(true)
|
moveTaskToBack(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun backup(password: String) {
|
private fun backup(password: String) {
|
||||||
|
@ -608,6 +608,7 @@ object Utils {
|
|||||||
|
|
||||||
RandomAccessFile(filePath, "rw").use { raf ->
|
RandomAccessFile(filePath, "rw").use { raf ->
|
||||||
raf.fd.sync() // eMMC에 확실히 기록
|
raf.fd.sync() // eMMC에 확실히 기록
|
||||||
|
raf.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e: IOException) {
|
catch (e: IOException) {
|
||||||
@ -1185,6 +1186,9 @@ object Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
output.fd.sync()
|
output.fd.sync()
|
||||||
|
output.close()
|
||||||
|
|
||||||
|
input.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,5 +1355,9 @@ object Utils {
|
|||||||
).joinToString(".")
|
).joinToString(".")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
external fun openSerial(strDev: String, baudrate: Int): Int // by ritoseo
|
||||||
|
external fun readSerial(devHandle:Int, buffer: ByteArray, size: Int): Int // by ritoseo
|
||||||
|
external fun writeSerial(devHandle:Int, buffer: ByteArray, size: Int): Int // by ritoseo
|
||||||
|
external fun closeSerial(devHandle: Int): Int // by ritoseo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user