마이크 볼륨 설정 추가
@ -9,8 +9,8 @@ android {
|
||||
applicationId = 'kr.co.rito.ritosip'
|
||||
minSdkVersion 29
|
||||
targetSdkVersion 35
|
||||
versionCode = 100
|
||||
versionName = '1.0.0'
|
||||
versionCode = 104
|
||||
versionName = '1.0.4'
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cFlags '-DHAVE_INTTYPES_H -lstdc++'
|
||||
@ -45,6 +45,7 @@ android {
|
||||
// minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
|
||||
'proguard-rules.pro'
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
}
|
||||
android.applicationVariants.all { variant ->
|
||||
|
@ -23,7 +23,7 @@
|
||||
android:maxSdkVersion="32" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28"
|
||||
android:maxSdkVersion="32"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
|
@ -29,6 +29,7 @@ module vp8.so
|
||||
module vp9.so
|
||||
module av1.so
|
||||
module snapshot.so
|
||||
module fakevideo.so
|
||||
module stun.so
|
||||
module turn.so
|
||||
module ice.so
|
||||
@ -37,11 +38,13 @@ module dtls_srtp.so
|
||||
module gzrtp.so
|
||||
module uuid.so
|
||||
module vumeter.so
|
||||
module webrtc_aecm.so
|
||||
module_app account.so
|
||||
module_app debug_cmd.so
|
||||
module_app mwi.so
|
||||
avcodec_h264enc h264_mediacodec
|
||||
video_fps 30
|
||||
mic_volume 20
|
||||
evdev_device /dev/input/event0
|
||||
opus_samplerate 48000
|
||||
opus_stereo no
|
||||
|
@ -1785,6 +1785,18 @@ JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Api_call_1set_1video_1source
|
||||
return err;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Api_call_1set_1video_1fake(
|
||||
JNIEnv *env, jobject obj, jlong call)
|
||||
{
|
||||
(void)env;
|
||||
(void)obj;
|
||||
int err;
|
||||
re_thread_enter();
|
||||
err = video_set_source(call_video((struct call *)call), "fakevideo", NULL);
|
||||
re_thread_leave();
|
||||
return err;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_com_tutpro_baresip_plus_Api_call_1destroy(
|
||||
JNIEnv *env, jobject obj, jlong call)
|
||||
{
|
||||
@ -1808,6 +1820,36 @@ JNIEXPORT jint JNICALL Java_com_tutpro_baresip_plus_Api_cmd_1exec(
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_tutpro_baresip_plus_Api_set_1audio_1source(JNIEnv *env, jobject obj)
|
||||
{
|
||||
(void)obj;
|
||||
struct list *aucodecl = baresip_ausrcl();
|
||||
struct le *le;
|
||||
char codec_buf[256];
|
||||
char *start = &(codec_buf[0]);
|
||||
unsigned int left = sizeof codec_buf;
|
||||
int len;
|
||||
for (le = list_head(aucodecl); le != NULL; le = le->next) {
|
||||
const struct ausrc *ac = le->data;
|
||||
if (start == &(codec_buf[0]))
|
||||
len = re_snprintf(start, left, "<%s>", ac->name);
|
||||
else
|
||||
len = re_snprintf(start, left, ",<%s>", ac->name);
|
||||
if (len == -1) {
|
||||
LOGE("failed to print codec to buffer\n");
|
||||
codec_buf[0] = '\0';
|
||||
return (*env)->NewStringUTF(env, codec_buf);
|
||||
}
|
||||
start = start + len;
|
||||
left = left - len;
|
||||
}
|
||||
*start = '\0';
|
||||
return (*env)->NewStringUTF(env, codec_buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_com_tutpro_baresip_plus_Api_audio_1codecs(JNIEnv *env, jobject obj)
|
||||
{
|
||||
(void)obj;
|
||||
|
@ -98,6 +98,7 @@ object Api {
|
||||
external fun call_state(callp: Long): Int
|
||||
external fun call_has_video(callp: Long): Boolean
|
||||
external fun call_set_video_source(callp: Long, front: Boolean): Int
|
||||
external fun call_set_video_fake(callp: Long): Int // added by ritoseo
|
||||
external fun call_set_video_direction(callp: Long, dir: Int)
|
||||
external fun call_set_video_mute(callp: Long, mute: Boolean) // added by ritoseo
|
||||
external fun call_set_media_direction(callp: Long, adir: Int, vdir: Int)
|
||||
@ -113,6 +114,7 @@ object Api {
|
||||
|
||||
external fun message_send(uap: Long, peer_uri: String, message: String, time: String): Int
|
||||
|
||||
external fun set_audio_source(): String
|
||||
external fun audio_codecs(): String
|
||||
external fun video_codecs(): String
|
||||
|
||||
|
@ -35,14 +35,12 @@ import android.telecom.TelecomManager
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.util.JsonReader
|
||||
import android.util.Size
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.RemoteViews
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.Keep
|
||||
import androidx.annotation.StringRes
|
||||
@ -63,11 +61,8 @@ import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.InetAddress
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.time.Clock
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.util.*
|
||||
import kotlin.concurrent.schedule
|
||||
@ -269,7 +264,6 @@ class BaresipService: Service() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sipReqeustReceiver = object : BroadcastReceiver() {
|
||||
fun sendContactList() {
|
||||
val resArr : JSONArray = JSONArray()
|
||||
@ -570,11 +564,17 @@ class BaresipService: Service() {
|
||||
if(param != null) {
|
||||
val json = JSONObject(param)
|
||||
val device_name = json.getString("device_name")
|
||||
val mic_volume = json.getString("mic_volume")
|
||||
val display_type = json.getString("display_type")
|
||||
|
||||
Config.replaceVariable("device_name", device_name)
|
||||
BaresipService.deviceName = device_name
|
||||
|
||||
val mic_volume_int = mic_volume.toInt()
|
||||
if(mic_volume_int >= 0 && mic_volume_int <= 24) {
|
||||
Utils.setMicVolumeByMix(mic_volume_int)
|
||||
}
|
||||
|
||||
Config.replaceVariable("far_view_display_id", display_type)
|
||||
BaresipService.farViewDisplayId = display_type.toInt()
|
||||
Config.save()
|
||||
@ -759,14 +759,28 @@ class BaresipService: Service() {
|
||||
}
|
||||
|
||||
val scope = CoroutineScope(Dispatchers.Default)
|
||||
var captureCount = 0
|
||||
var captureCount : Long = 0
|
||||
var running = true
|
||||
|
||||
val job = scope.launch {
|
||||
println("camera capture manager is running...")
|
||||
Utils.deleteFiles("/mnt/obb", "jpg")
|
||||
var updateDate = LocalDateTime.now()
|
||||
var cameraState = -1
|
||||
while (running) {
|
||||
|
||||
// var devices = am.getDevices(AudioManager.GET_DEVICES_INPUTS)
|
||||
// for (device in devices) {
|
||||
// var typeName = "모름 ${device.type}"
|
||||
// if(device.type == AudioDeviceInfo.TYPE_USB_HEADSET) {
|
||||
// typeName = "USB헤드셋(${device.id})"
|
||||
// } else if(device.type == AudioDeviceInfo.TYPE_BUILTIN_MIC) {
|
||||
// typeName = "내장마이크(${device.id})"
|
||||
// }
|
||||
// println("[입력장치] ${typeName} : ${device.productName}")
|
||||
// }
|
||||
updateAudioSourceDevice(applicationContext)
|
||||
|
||||
if(File("/mnt/obb/camera_near.rgb565.done").exists() && !File("/mnt/obb/camera_near.jpg").exists()) {
|
||||
try {
|
||||
val nearBuf = Utils.readFileToByteBuffer("/mnt/obb/camera_near.rgb565")
|
||||
@ -970,25 +984,88 @@ class BaresipService: Service() {
|
||||
|
||||
val camera1 = Utils.checkCameraConnection(0)
|
||||
val camera2 = Utils.checkCameraConnection(1)
|
||||
val prevCamera1 = Utils.propertyGet("sys.ritosip.camera1.status")
|
||||
Utils.propertySet("sys.ritosip.camera1.status", camera1)
|
||||
//call.setVideoSource(!BaresipService.cameraFront)
|
||||
val prevCamera2 = Utils.propertyGet("sys.ritosip.camera2.status")
|
||||
Utils.propertySet("sys.ritosip.camera2.status", camera2)
|
||||
if(camera2 != prevCamera2) {
|
||||
if(camera1 != "plugin" && camera2 != "plugin" && cameraState != 0) {
|
||||
if(uas.size > 0) {
|
||||
val ua = uas[0]
|
||||
val call = ua.currentCall()
|
||||
|
||||
if(call != null) {
|
||||
if(camera2 == "plugin") {
|
||||
BaresipService.cameraFront = false; // Contents Input
|
||||
call.setVideoSource(false)
|
||||
} else {
|
||||
BaresipService.cameraFront = true; // Camera Input
|
||||
call.setVideoFake()
|
||||
cameraState = 0
|
||||
}
|
||||
}
|
||||
} else if(camera1 == "plugin" && camera2 != "plugin" && (cameraState == 0 || cameraState == 2)) {
|
||||
if(uas.size > 0) {
|
||||
val ua = uas[0]
|
||||
val call = ua.currentCall()
|
||||
|
||||
if(call != null) {
|
||||
Log.d(TAG, "RITO camera1 detect!")
|
||||
//val process = Runtime.getRuntime().exec("ritosysc shell-order=killall android.hardware.camera.provider@2.4-service android.hardware.camera.provider@2.4-external-service cameraserver android.hardware.tv.input@1.0-service")
|
||||
if(cameraState == 0) {
|
||||
val process = Runtime.getRuntime()
|
||||
.exec("ritosysc shell-order=killall cameraserver")
|
||||
process.waitFor()
|
||||
process.destroy()
|
||||
delay(1500) // 1초마다 실행
|
||||
}
|
||||
BaresipService.cameraFront = true;
|
||||
call.setVideoSource(true)
|
||||
cameraState = 1
|
||||
//delay(3000) // 1초마다 실행
|
||||
}
|
||||
}
|
||||
} else if(camera2 == "plugin" && cameraState != 2) {
|
||||
if(uas.size > 0) {
|
||||
val ua = uas[0]
|
||||
val call = ua.currentCall()
|
||||
|
||||
if(call != null) {
|
||||
Log.d(TAG, "RITO camera2 detect!")
|
||||
//val process = Runtime.getRuntime().exec("ritosysc shell-order=killall android.hardware.camera.provider@2.4-service android.hardware.camera.provider@2.4-external-service cameraserver android.hardware.tv.input@1.0-service")
|
||||
// val process = Runtime.getRuntime().exec("ritosysc shell-order=killall cameraserver")
|
||||
// process.waitFor()
|
||||
// process.destroy()
|
||||
// delay(1500) // 1초마다 실행
|
||||
BaresipService.cameraFront = false;
|
||||
call.setVideoSource(false)
|
||||
cameraState = 2
|
||||
//delay(3000) // 1초마다 실행
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if(camera2 != prevCamera2) {
|
||||
// if(uas.size > 0) {
|
||||
// val ua = uas[0]
|
||||
// val call = ua.currentCall()
|
||||
//
|
||||
// if(call != null) {
|
||||
// cameraState = 2
|
||||
// if(camera2 == "plugin") {
|
||||
// BaresipService.cameraFront = false; // Contents Input
|
||||
// call.setVideoSource(false)
|
||||
// } else {
|
||||
// BaresipService.cameraFront = true; // Camera Input
|
||||
// call.setVideoSource(true)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if(uas.size > 0) {
|
||||
val ua = uas[0]
|
||||
val call = ua.currentCall()
|
||||
|
||||
if(call == null) {
|
||||
cameraState = -1
|
||||
}
|
||||
} else {
|
||||
cameraState = -1
|
||||
}
|
||||
|
||||
if(BaresipService.cameraFront) {
|
||||
@ -1000,15 +1077,17 @@ class BaresipService: Service() {
|
||||
val usbMicExist = Utils.checkUsbMicrophone()
|
||||
if(usbMicExist) {
|
||||
Utils.propertySet("sys.ritosip.usb.microphone", "connected")
|
||||
if(audioInputDevice == "usb") {
|
||||
Utils.propertySet("sys.rito.audio.input.device", "usb")
|
||||
} else {
|
||||
Utils.propertySet("sys.rito.audio.input.device", "codec")
|
||||
}
|
||||
// if(audioInputDevice == "usb") {
|
||||
// Utils.propertySet("sys.rito.audio.input.device", "usb")
|
||||
// } else {
|
||||
// Utils.propertySet("sys.rito.audio.input.device", "codec")
|
||||
// }
|
||||
} else {
|
||||
Utils.propertySet("sys.ritosip.usb.microphone", "disconnected")
|
||||
}
|
||||
|
||||
Utils.setAudioSourceDevice(audioInputDevice)
|
||||
|
||||
delay(100) // 1초마다 실행
|
||||
|
||||
val now = LocalDateTime.now()
|
||||
@ -1051,7 +1130,7 @@ class BaresipService: Service() {
|
||||
if (farFilePath.length > 0)
|
||||
Utils.propertySet("sys.ritosip.far_screen_file", farFilePath)
|
||||
} else {
|
||||
Utils.propertySet("sys.ritosip.near_screen_file", "")
|
||||
//Utils.propertySet("sys.ritosip.near_screen_file", "")
|
||||
Utils.propertySet("sys.ritosip.far_screen_file", "")
|
||||
}
|
||||
}
|
||||
@ -1068,6 +1147,54 @@ class BaresipService: Service() {
|
||||
Utils.propertySet("sys.ritosip.display_split_mode", BaresipService.displaySplitMode.toString())
|
||||
Utils.propertySet("sys.ritosip.sip.total_duration", BaresipService.totalDurationSeconds.toString())
|
||||
|
||||
// Call 중이 아닌 경우 Local Camera 화면 캡쳐
|
||||
val camera1 = Utils.checkCameraConnection(0)
|
||||
if(cameraState == -1) {
|
||||
if(camera1 == "plugin") {
|
||||
//Utils.runShellOrderSuper("killall -9 v4l2-ctl")
|
||||
Utils.runShellOrderSuper("timeout 2s v4l2-ctl --device=/dev/video20 --stream-mmap=3 --stream-to=/mnt/obb/camera.rgb888 --stream-count=1 && chmod 666 /mnt/obb/camera.rgb888")
|
||||
|
||||
try {
|
||||
val nearBuf = Utils.readFileToByteBuffer("/mnt/obb/camera.rgb888")
|
||||
var bufSize = nearBuf.capacity()
|
||||
var width : Int = 1280
|
||||
var height : Int = 720
|
||||
if(bufSize == 1280 * 720 * 3) {
|
||||
width = 1280
|
||||
height = 720
|
||||
} else if(bufSize == 1920 * 1080 * 3) {
|
||||
width = 1920
|
||||
height = 1080
|
||||
}
|
||||
|
||||
if(bufSize > 0) {
|
||||
var nearFilePath = "/mnt/obb/near_$captureCount.jpg"
|
||||
Utils.saveRGB888AsJPG(
|
||||
applicationContext,
|
||||
nearBuf,
|
||||
width,
|
||||
height,
|
||||
nearFilePath
|
||||
)
|
||||
|
||||
val destFile = File(nearFilePath)
|
||||
destFile.setReadable(true, false)
|
||||
Utils.propertySet("sys.ritosip.near_screen_file", nearFilePath)
|
||||
}
|
||||
} catch(e : Exception) {
|
||||
//e.printStackTrace()
|
||||
}
|
||||
} else {
|
||||
var nearFilePath = "/mnt/obb/near_$captureCount.jpg"
|
||||
Utils.saveDrawableAsJpg(applicationContext, R.drawable.nocamera, nearFilePath)
|
||||
|
||||
val destFile = File(nearFilePath)
|
||||
destFile.setReadable(true, false)
|
||||
Utils.propertySet("sys.ritosip.near_screen_file", nearFilePath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
captureCount++
|
||||
delay(100)
|
||||
|
||||
@ -1161,7 +1288,7 @@ class BaresipService: Service() {
|
||||
CallHistoryNew.save()
|
||||
}
|
||||
|
||||
val value = Utils.readNumberFromFile("/sdcard/Documents/sip_total_duration")
|
||||
val value = Utils.readNumberFromFile("/sdcard/Documents/sip_total_duration.txt")
|
||||
if(value != null) {
|
||||
BaresipService.totalDurationSeconds = value
|
||||
}
|
||||
@ -1225,6 +1352,8 @@ class BaresipService: Service() {
|
||||
|
||||
applyTransportConfiguration()
|
||||
|
||||
Utils.setMicVolumeByMix(BaresipService.micVolume)
|
||||
|
||||
}
|
||||
|
||||
"Start Content Observer" -> {
|
||||
@ -1826,7 +1955,9 @@ class BaresipService: Service() {
|
||||
/* Added by ritoseo */
|
||||
val duration = call.duration()
|
||||
BaresipService.totalDurationSeconds += duration
|
||||
Utils.saveNumberToFile("/sdcard/Documents/sip_total_duration", BaresipService.totalDurationSeconds)
|
||||
Utils.saveNumberToFile("/sdcard/Documents/sip_total_duration.txt", BaresipService.totalDurationSeconds)
|
||||
//Utils.saveNumberToFile(File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "sip_total_duration").absolutePath, BaresipService.totalDurationSeconds)
|
||||
|
||||
/* ---------------- */
|
||||
|
||||
if (!Utils.isVisible()) {
|
||||
@ -2267,11 +2398,15 @@ class BaresipService: Service() {
|
||||
}
|
||||
|
||||
private fun setCallVolume() {
|
||||
println("Call volume setting!")
|
||||
callVolume = 0
|
||||
if (callVolume != 0)
|
||||
for (streamType in listOf(AudioManager.STREAM_MUSIC, AudioManager.STREAM_VOICE_CALL)) {
|
||||
origVolume[streamType] = am.getStreamVolume(streamType)
|
||||
val maxVolume = am.getStreamMaxVolume(streamType)
|
||||
am.setStreamVolume(streamType, (callVolume * 0.1 * maxVolume).roundToInt(), 0)
|
||||
println("Orig/new/max $streamType volume is " +
|
||||
"${origVolume[streamType]}/${am.getStreamVolume(streamType)}/$maxVolume")
|
||||
Log.d(TAG, "Orig/new/max $streamType volume is " +
|
||||
"${origVolume[streamType]}/${am.getStreamVolume(streamType)}/$maxVolume")
|
||||
}
|
||||
@ -2548,6 +2683,26 @@ class BaresipService: Service() {
|
||||
var nearViewDisplayId = 2
|
||||
var farViewLayout : Rect = Rect(0, 0, 1920, 1080)
|
||||
var nearViewLayout : Rect = Rect(0, 0, 1920, 1080)
|
||||
var audioDeviceUsbId = -1
|
||||
var audioDeviceCodecId = -1
|
||||
var micVolume = 20
|
||||
|
||||
fun updateAudioSourceDevice(ctx: Context) {
|
||||
val am = ctx.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
var devices = am.getDevices(AudioManager.GET_DEVICES_INPUTS)
|
||||
var usbId = -1
|
||||
var codecId = -1
|
||||
for (device in devices) {
|
||||
if(device.type == AudioDeviceInfo.TYPE_USB_HEADSET) {
|
||||
usbId = device.id
|
||||
} else if(device.type == AudioDeviceInfo.TYPE_BUILTIN_MIC) {
|
||||
codecId = device.id
|
||||
}
|
||||
}
|
||||
|
||||
audioDeviceUsbId = usbId
|
||||
audioDeviceCodecId = codecId
|
||||
}
|
||||
|
||||
fun requestAudioFocus(ctx: Context): Boolean {
|
||||
Log.d(TAG, "Requesting audio focus")
|
||||
|
@ -46,6 +46,10 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
|
||||
return Api.call_set_video_source(callp, front)
|
||||
}
|
||||
|
||||
fun setVideoFake(): Int {
|
||||
return Api.call_set_video_fake(callp)
|
||||
}
|
||||
|
||||
fun hold(): Boolean {
|
||||
return Api.call_hold(callp, true) == 0
|
||||
}
|
||||
|
@ -211,6 +211,14 @@ object Config {
|
||||
*/
|
||||
|
||||
/* Added by ritoseo */
|
||||
val micVolume = previousVariable("mic_volume")
|
||||
if (micVolume != "") {
|
||||
config = "${config}mic_volume $micVolume\n"
|
||||
BaresipService.micVolume = micVolume.toInt()
|
||||
} else {
|
||||
config = "${config}mic_volume ${BaresipService.micVolume}\n"
|
||||
}
|
||||
|
||||
for (size in defaultSizes)
|
||||
videoSizes.add(size.toString())
|
||||
/********************/
|
||||
@ -225,12 +233,15 @@ object Config {
|
||||
Size(videoSize.substringBefore("x").toInt(),
|
||||
videoSize.substringAfter("x").toInt())
|
||||
}
|
||||
|
||||
BaresipService.videoSize = Size(1280, 720)
|
||||
|
||||
//BaresipService.videoSize = Size(640, 480)
|
||||
config = "${config}video_size " +
|
||||
"${BaresipService.videoSize.width}x${BaresipService.videoSize.height}\n"
|
||||
|
||||
/* Added by ritoseo */
|
||||
config = "${config}video_bitrate 60000000\n"
|
||||
config = "${config}video_bitrate 100000000\n"
|
||||
config = "${config}rtp_video_tos 184\n"
|
||||
config = "${config}rtp_bandwidth 512-8192\n"
|
||||
/********************/
|
||||
|
@ -11,6 +11,7 @@ import android.content.*
|
||||
import android.content.Intent.ACTION_CALL
|
||||
import android.content.Intent.ACTION_DIAL
|
||||
import android.content.Intent.ACTION_VIEW
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
@ -19,10 +20,8 @@ import android.media.AudioManager
|
||||
import android.media.MediaActionSound
|
||||
import android.net.Uri
|
||||
import android.os.*
|
||||
import android.os.StrictMode.VmPolicy
|
||||
import android.provider.DocumentsContract
|
||||
import android.provider.MediaStore
|
||||
import android.provider.MediaStore.Audio.Radio
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.util.TypedValue
|
||||
@ -48,14 +47,18 @@ import androidx.lifecycle.Observer
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tutpro.baresip.plus.Utils.getAppVersion
|
||||
import com.tutpro.baresip.plus.Utils.showSnackBar
|
||||
import com.tutpro.baresip.plus.databinding.ActivityMainBinding
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
@ -138,6 +141,11 @@ class MainActivity : AppCompatActivity() {
|
||||
private lateinit var callStartButton: AppCompatButton
|
||||
private lateinit var callHistoryButton: AppCompatButton
|
||||
private lateinit var settingButton: AppCompatButton
|
||||
private lateinit var layoutButton: AppCompatButton
|
||||
private lateinit var serverButton: AppCompatButton
|
||||
private lateinit var volumeButton: AppCompatButton
|
||||
private lateinit var networkButton: AppCompatButton
|
||||
private lateinit var backwardButton: AppCompatButton
|
||||
|
||||
private var callHandler: Handler = Handler(Looper.getMainLooper())
|
||||
private var callRunnable: Runnable? = null
|
||||
@ -191,6 +199,9 @@ class MainActivity : AppCompatActivity() {
|
||||
lateinit var navUpList : HashMap<View, View>
|
||||
lateinit var navDownList : HashMap<View, View>
|
||||
|
||||
lateinit var navUpServerList : HashMap<View, View>
|
||||
lateinit var navDownServerList : HashMap<View, View>
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
if(!isKeyboardVisible) {
|
||||
val currentFocusView = currentFocus
|
||||
@ -214,6 +225,24 @@ class MainActivity : AppCompatActivity() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if(navUpServerList.contains(currentFocusView)) {
|
||||
val view = navUpServerList.get(currentFocusView)!!
|
||||
if(view.isVisible) {
|
||||
view.requestFocus()
|
||||
return false
|
||||
} else {
|
||||
if(currentFocusView == binding.btnApply) {
|
||||
binding.radioDhcp.requestFocus()
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(currentFocusView == binding.aorSpinner) {
|
||||
callStartButton.requestFocus()
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event.keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
|
||||
if(navDownList.contains(currentFocusView)) {
|
||||
@ -223,12 +252,22 @@ class MainActivity : AppCompatActivity() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if(navDownServerList.contains(currentFocusView)) {
|
||||
val view = navDownServerList.get(currentFocusView)!!
|
||||
if(view.isVisible) {
|
||||
view.requestFocus()
|
||||
return false
|
||||
}
|
||||
}
|
||||
} else if(event.keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
if(currentFocusView == binding.editIp ||
|
||||
currentFocusView == binding.editGateway ||
|
||||
currentFocusView == binding.editNetmask ||
|
||||
currentFocusView == binding.editDns) {
|
||||
currentFocusView == binding.editDns ||
|
||||
currentFocusView == binding.editDisplayName ||
|
||||
currentFocusView == binding.editSipId ||
|
||||
currentFocusView == binding.editSipPassword
|
||||
) {
|
||||
if(imm.isActive) {
|
||||
imm.showSoftInput(currentFocusView, InputMethodManager.SHOW_IMPLICIT)
|
||||
imm.restartInput(currentFocusView)
|
||||
@ -242,6 +281,9 @@ class MainActivity : AppCompatActivity() {
|
||||
if(navUpList.contains(currentFocusView) || navDownList.contains(currentFocusView)) {
|
||||
found = true
|
||||
}
|
||||
if(navUpServerList.contains(currentFocusView) || navDownServerList.contains(currentFocusView)) {
|
||||
found = true
|
||||
}
|
||||
|
||||
if(found) {
|
||||
return true
|
||||
@ -253,6 +295,12 @@ class MainActivity : AppCompatActivity() {
|
||||
currentFocusView == binding.editDns) {
|
||||
return true
|
||||
}
|
||||
|
||||
if(currentFocusView == binding.editDisplayName ||
|
||||
currentFocusView == binding.editSipId ||
|
||||
currentFocusView == binding.editSipPassword) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -389,6 +437,8 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
setupKeyboardVisibilityListener()
|
||||
|
||||
Utils.propertySet("sys.ritosip.version", getAppVersion(this))
|
||||
|
||||
// Must be done after view has been created
|
||||
this.setShowWhenLocked(true)
|
||||
this.setTurnScreenOn( true)
|
||||
@ -453,10 +503,213 @@ class MainActivity : AppCompatActivity() {
|
||||
// binding.baseButtonLayout.visibility = View.INVISIBLE
|
||||
// binding.mainActivityLayout.visibility = View.INVISIBLE
|
||||
// binding.defaultLayout.visibility = View.INVISIBLE
|
||||
|
||||
// binding.networkSettingLayout.visibility = View.VISIBLE
|
||||
// binding.radioDhcp.requestFocus()
|
||||
|
||||
binding.settingLayout.visibility = View.VISIBLE
|
||||
binding.dialogButtonLayout.requestFocus()
|
||||
}
|
||||
|
||||
networkButton = binding.dialogButtonNetwork
|
||||
networkButton.setOnClickListener {
|
||||
binding.networkSettingLayout.bringToFront()
|
||||
binding.networkSettingLayout.visibility = View.VISIBLE
|
||||
binding.radioDhcp.requestFocus()
|
||||
}
|
||||
|
||||
layoutButton = binding.dialogButtonLayout
|
||||
layoutButton.setOnClickListener {
|
||||
binding.layoutSettingLayout.bringToFront()
|
||||
binding.layoutSettingLayout.visibility = View.VISIBLE
|
||||
var splitMode = Utils.propertyGet("sys.ritosip.display_split_mode")
|
||||
if(splitMode == "2") {
|
||||
binding.layoutType2.requestFocus()
|
||||
} else if(splitMode == "3") {
|
||||
binding.layoutType3.requestFocus()
|
||||
} else if(splitMode == "4") {
|
||||
binding.layoutType4.requestFocus()
|
||||
} else if(splitMode == "5") {
|
||||
binding.layoutType5.requestFocus()
|
||||
} else if(splitMode == "6") {
|
||||
binding.layoutType6.requestFocus()
|
||||
} else if(splitMode == "7") {
|
||||
binding.layoutType7.requestFocus()
|
||||
} else if(splitMode == "8") {
|
||||
binding.layoutType8.requestFocus()
|
||||
} else if(splitMode == "9") {
|
||||
binding.layoutType9.requestFocus()
|
||||
} else if(splitMode == "10") {
|
||||
binding.layoutType10.requestFocus()
|
||||
} else {
|
||||
binding.layoutType1.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
binding.layoutType1.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout1\"}")
|
||||
}
|
||||
binding.layoutType2.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout2\"}")
|
||||
}
|
||||
binding.layoutType3.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout3\"}")
|
||||
}
|
||||
binding.layoutType4.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout4\"}")
|
||||
}
|
||||
binding.layoutType5.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout5\"}")
|
||||
}
|
||||
binding.layoutType6.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout6\"}")
|
||||
}
|
||||
|
||||
binding.layoutType7.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout7\"}")
|
||||
}
|
||||
binding.layoutType8.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout8\"}")
|
||||
}
|
||||
binding.layoutType9.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout9\"}")
|
||||
}
|
||||
binding.layoutType10.setOnClickListener {
|
||||
sendSettingByBroadcast("layout_setting", "{\"layout\":\"layout10\"}")
|
||||
}
|
||||
|
||||
|
||||
binding.dialogButtonLayoutInCall.setOnClickListener {
|
||||
binding.layoutSettingLayout.bringToFront()
|
||||
binding.layoutSettingLayout.visibility = View.VISIBLE
|
||||
var splitMode = Utils.propertyGet("sys.ritosip.display_split_mode")
|
||||
if(splitMode == "2") {
|
||||
binding.layoutType2.requestFocus()
|
||||
} else if(splitMode == "3") {
|
||||
binding.layoutType3.requestFocus()
|
||||
} else if(splitMode == "4") {
|
||||
binding.layoutType4.requestFocus()
|
||||
} else if(splitMode == "5") {
|
||||
binding.layoutType5.requestFocus()
|
||||
} else if(splitMode == "6") {
|
||||
binding.layoutType6.requestFocus()
|
||||
} else if(splitMode == "7") {
|
||||
binding.layoutType7.requestFocus()
|
||||
} else if(splitMode == "8") {
|
||||
binding.layoutType8.requestFocus()
|
||||
} else if(splitMode == "9") {
|
||||
binding.layoutType9.requestFocus()
|
||||
} else if(splitMode == "10") {
|
||||
binding.layoutType10.requestFocus()
|
||||
} else {
|
||||
binding.layoutType1.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
serverButton = binding.dialogButtonServer
|
||||
serverButton.setOnClickListener {
|
||||
binding.serverSettingLayout.bringToFront()
|
||||
binding.serverSettingLayout.visibility = View.VISIBLE
|
||||
binding.editDisplayName.setText(Utils.propertyGet("sys.ritosip.account.display_name"))
|
||||
binding.editSipId.setText(Utils.propertyGet("sys.ritosip.account.account_name"))
|
||||
binding.editSipServer.setText(Utils.propertyGet("sys.ritosip.account.server_address"))
|
||||
var transport = Utils.propertyGet("sys.ritosip.account.prefer_transport")
|
||||
if(transport == "tcp") {
|
||||
binding.radioTransportTcp.isChecked = true
|
||||
} else if(transport == "tls") {
|
||||
binding.radioTransportTls.isChecked = true
|
||||
} else {
|
||||
binding.radioTransportUdp.isChecked = true
|
||||
}
|
||||
var encryption = Utils.propertyGet("sys.ritosip.account.media_encryption")
|
||||
if(encryption == "srtp") {
|
||||
binding.radioEncryptSrtp.isChecked = true
|
||||
} else {
|
||||
binding.radioEncryptNone.isChecked = true
|
||||
}
|
||||
binding.editDisplayName.requestFocus()
|
||||
}
|
||||
|
||||
volumeButton = binding.dialogButtonVolume
|
||||
volumeButton.setOnClickListener {
|
||||
binding.volumeSettingLayout.bringToFront()
|
||||
binding.volumeSettingLayout.visibility = View.VISIBLE
|
||||
binding.seekbarMicVolume.requestFocus()
|
||||
|
||||
binding.seekbarMicVolume.progress = BaresipService.micVolume
|
||||
val currentValue = binding.seekbarMicVolume.progress
|
||||
binding.textMicVolume.setText(currentValue.toString())
|
||||
}
|
||||
|
||||
binding.dialogButtonVolumeInCall.setOnClickListener {
|
||||
binding.volumeSettingLayout.bringToFront()
|
||||
binding.volumeSettingLayout.visibility = View.VISIBLE
|
||||
binding.seekbarMicVolume.requestFocus()
|
||||
|
||||
binding.seekbarMicVolume.progress = BaresipService.micVolume
|
||||
val currentValue = binding.seekbarMicVolume.progress
|
||||
binding.textMicVolume.setText(currentValue.toString())
|
||||
}
|
||||
|
||||
binding.seekbarMicVolume.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
// progress: 현재 값
|
||||
// fromUser: 사용자가 직접 움직였는지 여부
|
||||
val currentValue = progress
|
||||
println("현재 값: $currentValue")
|
||||
binding.textMicVolume.setText(currentValue.toString())
|
||||
Utils.setMicVolumeByMix(currentValue)
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||
// 터치 시작 시 호출
|
||||
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
// 터치 끝날 때 호출
|
||||
}
|
||||
})
|
||||
|
||||
binding.btnDoneVolume.setOnClickListener {
|
||||
binding.volumeSettingLayout.visibility = View.INVISIBLE
|
||||
if(binding.settingLayout.visibility == View.VISIBLE) {
|
||||
binding.dialogButtonVolume.requestFocus()
|
||||
} else if(binding.settingLayoutInCall.visibility == View.VISIBLE) {
|
||||
binding.dialogButtonVolumeInCall.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
backwardButton = binding.dialogButtonBackward
|
||||
backwardButton.setOnClickListener {
|
||||
if(binding.settingLayout.visibility == View.VISIBLE) {
|
||||
binding.settingLayout.visibility = View.INVISIBLE
|
||||
binding.settingBtn.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
binding.dialogButtonHangUp.setOnClickListener {
|
||||
if(binding.settingLayoutInCall.visibility == View.VISIBLE) {
|
||||
hangupButton.performClick()
|
||||
binding.settingLayoutInCall.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
binding.dialogButtonBackwardInCall.setOnClickListener {
|
||||
if(binding.settingLayoutInCall.visibility == View.VISIBLE) {
|
||||
binding.settingLayoutInCall.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
binding.layoutBackward.setOnClickListener {
|
||||
binding.layoutSettingLayout.visibility = View.INVISIBLE
|
||||
if(binding.settingLayout.visibility == View.VISIBLE) {
|
||||
binding.dialogButtonLayout.requestFocus()
|
||||
} else if(binding.settingLayoutInCall.visibility == View.VISIBLE) {
|
||||
binding.dialogButtonLayoutInCall.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BaresipService.supportedCameras = Utils.supportedCameras(applicationContext).isNotEmpty()
|
||||
|
||||
@ -530,12 +783,87 @@ class MainActivity : AppCompatActivity() {
|
||||
showCustomToast(applicationContext, "STATIC 적용되었습니다.")
|
||||
binding.networkSettingLayout.visibility = View.INVISIBLE
|
||||
}
|
||||
binding.dialogButtonNetwork.requestFocus()
|
||||
}
|
||||
|
||||
|
||||
binding.btnCancel.setOnClickListener { _ ->
|
||||
binding.networkSettingLayout.visibility = View.INVISIBLE
|
||||
binding.dialogButtonNetwork.requestFocus()
|
||||
}
|
||||
|
||||
|
||||
binding.btnApplyServer.setOnClickListener { _ ->
|
||||
showCustomToast(applicationContext, "적용되었습니다.")
|
||||
var param : JSONObject = JSONObject()
|
||||
param.put("display_name", binding.editDisplayName.text)
|
||||
param.put("account_name", binding.editSipId.text)
|
||||
var password = binding.editSipPassword.text.toString()
|
||||
if(password.isEmpty()) {
|
||||
if (File(filesDir.absolutePath + "/accounts").exists()) {
|
||||
val accounts = String(
|
||||
Utils.getFileContents(filesDir.absolutePath + "/accounts")!!,
|
||||
Charsets.UTF_8
|
||||
).lines().toMutableList()
|
||||
|
||||
password = getPassword(accounts)
|
||||
}
|
||||
}
|
||||
param.put("password", password)
|
||||
param.put("server_address", binding.editSipServer.text)
|
||||
var transport = "udp"
|
||||
if(binding.radioTransportTcp.isChecked) {
|
||||
transport = "tcp"
|
||||
} else if(binding.radioTransportTls.isChecked) {
|
||||
transport = "tls"
|
||||
}
|
||||
param.put("transport", transport)
|
||||
var encrypt = "none"
|
||||
if(binding.radioEncryptSrtp.isChecked) {
|
||||
encrypt = "srtpo"
|
||||
}
|
||||
param.put("media_encryption", encrypt)
|
||||
println("PARAM >> " + param.toString())
|
||||
sendSettingByBroadcast("set_account", param.toString())
|
||||
binding.serverSettingLayout.visibility = View.INVISIBLE
|
||||
binding.dialogButtonServer.requestFocus()
|
||||
}
|
||||
|
||||
binding.btnCancelServer.setOnClickListener { _ ->
|
||||
binding.serverSettingLayout.visibility = View.INVISIBLE
|
||||
binding.dialogButtonServer.requestFocus()
|
||||
}
|
||||
|
||||
navUpServerList = HashMap<View, View>()
|
||||
navDownServerList = HashMap<View, View>()
|
||||
|
||||
navUpServerList.put(binding.editDisplayName, binding.btnApplyServer)
|
||||
navUpServerList.put(binding.editSipId, binding.editDisplayName)
|
||||
navUpServerList.put(binding.editSipPassword, binding.editSipId)
|
||||
navUpServerList.put(binding.editSipServer, binding.editSipPassword)
|
||||
navUpServerList.put(binding.radioTransportUdp, binding.editSipServer)
|
||||
navUpServerList.put(binding.radioTransportTcp, binding.editSipServer)
|
||||
navUpServerList.put(binding.radioTransportTls, binding.editSipServer)
|
||||
navUpServerList.put(binding.radioEncryptNone, binding.radioTransportUdp)
|
||||
navUpServerList.put(binding.radioEncryptSrtp, binding.radioTransportUdp)
|
||||
navUpServerList.put(binding.btnApplyServer, binding.radioEncryptNone)
|
||||
navUpServerList.put(binding.btnCancelServer, binding.radioEncryptNone)
|
||||
//navUpList.put(binding.btnApply, binding.radioDhcp)
|
||||
|
||||
navDownServerList.put(binding.editDisplayName, binding.editSipId)
|
||||
navDownServerList.put(binding.editSipId, binding.editSipPassword)
|
||||
navDownServerList.put(binding.editSipPassword, binding.editSipServer)
|
||||
navDownServerList.put(binding.editSipServer, binding.radioTransportUdp)
|
||||
navDownServerList.put(binding.radioTransportUdp, binding.radioEncryptNone)
|
||||
navDownServerList.put(binding.radioTransportTcp, binding.radioEncryptNone)
|
||||
navDownServerList.put(binding.radioTransportTls, binding.radioEncryptNone)
|
||||
navDownServerList.put(binding.radioEncryptNone, binding.btnApplyServer)
|
||||
navDownServerList.put(binding.radioEncryptSrtp, binding.btnApplyServer)
|
||||
navDownServerList.put(binding.btnApplyServer, binding.editDisplayName)
|
||||
navDownServerList.put(binding.btnCancelServer, binding.editDisplayName)
|
||||
|
||||
|
||||
|
||||
updateFieldsVisibility()
|
||||
|
||||
val radioGroup = findViewById<RadioGroup>(R.id.radioGroup)
|
||||
@ -1179,11 +1507,12 @@ class MainActivity : AppCompatActivity() {
|
||||
else
|
||||
getString(R.string.audio_permissions)
|
||||
) { requestPermissionsLauncher.launch(permissions) }
|
||||
else
|
||||
startBaresip()
|
||||
// else
|
||||
// startBaresip()
|
||||
}
|
||||
}
|
||||
|
||||
startBaresip()
|
||||
addVideoLayoutViews()
|
||||
|
||||
if (!BaresipService.isServiceRunning) {
|
||||
@ -1192,7 +1521,7 @@ class MainActivity : AppCompatActivity() {
|
||||
Utils.getFileContents(filesDir.absolutePath + "/accounts")!!,
|
||||
Charsets.UTF_8
|
||||
).lines().toMutableList()
|
||||
askPasswords(accounts)
|
||||
//askPasswords(accounts)
|
||||
} else {
|
||||
// Baresip is started for the first time
|
||||
requestPermissionsLauncher.launch(permissions)
|
||||
@ -1201,6 +1530,14 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
} // OnCreate
|
||||
|
||||
fun sendSettingByBroadcast(req : String, param : String) {
|
||||
val responseIntent = Intent("kr.co.rito.ritosip.REQUEST")
|
||||
responseIntent.putExtra("request", req)
|
||||
responseIntent.putExtra("param", param)
|
||||
responseIntent.setPackage("kr.co.rito.ritosip");
|
||||
sendBroadcast(responseIntent)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
Log.d(TAG, "Main onStart")
|
||||
@ -2055,6 +2392,7 @@ class MainActivity : AppCompatActivity() {
|
||||
hangupButton.performClick()
|
||||
}
|
||||
videoLayout.addView(hb)
|
||||
hb.visibility = View.INVISIBLE // by ritoseo
|
||||
|
||||
// Info Button
|
||||
val ib = ImageButton(this)
|
||||
@ -2354,13 +2692,50 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
when (event?.scanCode) {
|
||||
SCANCODE_OPTION -> {
|
||||
val dialog = findViewById<FrameLayout>(R.id.dialogLayout)
|
||||
// val dialog = findViewById<FrameLayout>(R.id.dialogLayout)
|
||||
// if(dialog.isVisible) {
|
||||
// dialog.visibility = View.INVISIBLE
|
||||
// } else {
|
||||
// dialog.visibility = View.VISIBLE
|
||||
// findViewById<AppCompatButton>(R.id.dialogButtonImg1).requestFocus()
|
||||
// }
|
||||
|
||||
// val dialog = findViewById<FrameLayout>(R.id.settingLayout)
|
||||
// if (dialog.isVisible) {
|
||||
// dialog.visibility = View.INVISIBLE
|
||||
// } else {
|
||||
// dialog.bringToFront()
|
||||
// dialog.visibility = View.VISIBLE
|
||||
// findViewById<AppCompatButton>(R.id.dialogButtonLayout).requestFocus()
|
||||
// }
|
||||
if(binding.layoutSettingLayout.visibility == View.VISIBLE ||
|
||||
binding.networkSettingLayout.visibility == View.VISIBLE ||
|
||||
binding.serverSettingLayout.visibility == View.VISIBLE ||
|
||||
binding.volumeSettingLayout.visibility == View.VISIBLE)
|
||||
return true
|
||||
|
||||
if (Call.inCall()) {
|
||||
val dialog = findViewById<FrameLayout>(R.id.settingLayoutInCall)
|
||||
if (dialog.isVisible) {
|
||||
dialog.visibility = View.INVISIBLE
|
||||
println("settingLayoutInCall 비활성화")
|
||||
} else {
|
||||
dialog.bringToFront()
|
||||
dialog.visibility = View.VISIBLE
|
||||
findViewById<AppCompatButton>(R.id.dialogButtonLayoutInCall).requestFocus()
|
||||
println("settingLayoutInCall 활성화")
|
||||
}
|
||||
} else {
|
||||
val dialog = findViewById<FrameLayout>(R.id.settingLayout)
|
||||
if (dialog.isVisible) {
|
||||
dialog.visibility = View.INVISIBLE
|
||||
} else {
|
||||
dialog.bringToFront()
|
||||
dialog.visibility = View.VISIBLE
|
||||
findViewById<AppCompatButton>(R.id.dialogButtonImg1).requestFocus()
|
||||
findViewById<AppCompatButton>(R.id.dialogButtonLayout).requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
// val dialog = findViewById<FrameLayout>(R.id.dialogBase)
|
||||
// val customButton = LayoutInflater.from(this).inflate(R.layout.image_button, null)
|
||||
// dialog.addView(customButton)
|
||||
@ -3097,6 +3472,19 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPassword(accounts: MutableList<String>) : String {
|
||||
if (accounts.isNotEmpty()) {
|
||||
val account = accounts.removeAt(0)
|
||||
val params = account.substringAfter(">")
|
||||
if ((Utils.paramValue(params, "auth_user") != "") &&
|
||||
(Utils.paramValue(params, "auth_pass") != "")) {
|
||||
return Utils.paramValue(params, "auth_pass").trim('"')
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
private fun askPasswords(accounts: MutableList<String>) {
|
||||
if (accounts.isNotEmpty()) {
|
||||
val account = accounts.removeAt(0)
|
||||
@ -3315,8 +3703,8 @@ class MainActivity : AppCompatActivity() {
|
||||
callVideoButton.visibility = View.INVISIBLE
|
||||
callVideoButton.isEnabled = false
|
||||
switchVideoLayout(true)
|
||||
hangupButton.visibility = View.VISIBLE
|
||||
hangupButton.isEnabled = true
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
hangupButton.isEnabled = false
|
||||
if (Build.VERSION.SDK_INT < 31) {
|
||||
Log.d(TAG, "Setting audio mode to MODE_IN_COMMUNICATION")
|
||||
am.mode = AudioManager.MODE_IN_COMMUNICATION
|
||||
@ -3470,7 +3858,10 @@ class MainActivity : AppCompatActivity() {
|
||||
//callVideoButton.visibility = View.VISIBLE
|
||||
callVideoButton.visibility = View.INVISIBLE // modified by ritoseo
|
||||
callVideoButton.isEnabled = true
|
||||
|
||||
binding.callBackground.visibility = View.GONE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
binding.callBackground.visibility = View.GONE
|
||||
answerButton.visibility = View.INVISIBLE
|
||||
answerVideoButton.visibility = View.INVISIBLE
|
||||
rejectButton.visibility = View.INVISIBLE
|
||||
@ -3501,8 +3892,10 @@ class MainActivity : AppCompatActivity() {
|
||||
securityButton.visibility = View.INVISIBLE
|
||||
diverter.visibility = View.GONE
|
||||
callButton.visibility = View.INVISIBLE
|
||||
hangupButton.visibility = View.VISIBLE
|
||||
hangupButton.isEnabled = true
|
||||
|
||||
binding.callBackground.visibility = View.VISIBLE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
hangupButton.isEnabled = false
|
||||
answerButton.visibility = View.INVISIBLE
|
||||
answerVideoButton.visibility = View.INVISIBLE
|
||||
rejectButton.visibility = View.INVISIBLE
|
||||
@ -3528,6 +3921,8 @@ class MainActivity : AppCompatActivity() {
|
||||
callButton.visibility = View.INVISIBLE
|
||||
callVideoButton.visibility = View.INVISIBLE
|
||||
switchVideoLayout(true)
|
||||
|
||||
binding.callBackground.visibility = View.GONE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
answerButton.visibility = View.VISIBLE
|
||||
answerButton.isEnabled = true
|
||||
@ -3603,8 +3998,9 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
switchVideoLayout(true)
|
||||
|
||||
hangupButton.visibility = View.VISIBLE
|
||||
hangupButton.isEnabled = true
|
||||
binding.callBackground.visibility = View.VISIBLE
|
||||
hangupButton.visibility = View.INVISIBLE
|
||||
hangupButton.isEnabled = false
|
||||
answerButton.visibility = View.INVISIBLE
|
||||
answerVideoButton.visibility = View.INVISIBLE
|
||||
rejectButton.visibility = View.INVISIBLE
|
||||
|
@ -14,6 +14,8 @@ import android.graphics.Bitmap.createScaledBitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.hardware.camera2.CameraAccessException
|
||||
import android.hardware.camera2.CameraCharacteristics
|
||||
import android.hardware.camera2.CameraManager
|
||||
@ -49,6 +51,9 @@ import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.*
|
||||
import java.lang.reflect.Method
|
||||
import java.net.Inet4Address
|
||||
@ -1175,6 +1180,62 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
fun rgb888ToBitmap(rgbData: ByteArray, width: Int, height: Int): Bitmap? {
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
val pixels = IntArray(width * height)
|
||||
for (i in pixels.indices) {
|
||||
val b = rgbData[i * 3].toInt() and 0xFF
|
||||
val g = rgbData[i * 3 + 1].toInt() and 0xFF
|
||||
val r = rgbData[i * 3 + 2].toInt() and 0xFF
|
||||
pixels[i] = 0xFF shl 24 or (r shl 16) or (g shl 8) or b
|
||||
}
|
||||
bitmap.setPixels(pixels, 0, width, 0, 0, width, height)
|
||||
return bitmap
|
||||
}
|
||||
fun saveRGB888AsJPG(context: Context, rgb565Data: ByteBuffer, width: Int, height: Int, fileName: String) {
|
||||
// RGB565 포맷의 빈 Bitmap 생성
|
||||
val bitmap = rgb888ToBitmap(rgb565Data.array(), width, height)
|
||||
if(bitmap == null)
|
||||
return
|
||||
|
||||
try {
|
||||
// 저장할 파일 경로 설정
|
||||
val file = File(fileName)
|
||||
|
||||
try {
|
||||
FileOutputStream(file).use { fos ->
|
||||
// Bitmap을 JPG 형식으로 저장 (품질 90%)
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos)
|
||||
fos.flush()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
} catch(e: java.lang.Exception) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun saveDrawableAsJpg(context: Context, drawableResId: Int, filename: String): Boolean {
|
||||
val drawable: Drawable? = ContextCompat.getDrawable(context, drawableResId)
|
||||
if (drawable == null || drawable !is BitmapDrawable) {
|
||||
return false
|
||||
}
|
||||
|
||||
val bitmap: Bitmap = drawable.bitmap
|
||||
|
||||
val file = File(filename)
|
||||
return try {
|
||||
FileOutputStream(file).use { out ->
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
|
||||
}
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun copyFile(sourcePath: String, destinationPath: String): Boolean {
|
||||
return try {
|
||||
FileInputStream(sourcePath).use { input ->
|
||||
@ -1259,7 +1320,7 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
fun setAudioSourceDevice(dev : String) {
|
||||
fun setAudioSourceDeviceV1(dev : String) {
|
||||
propertySet("sys.rito.audio.input.device", dev)
|
||||
//val process = Runtime.getRuntime().exec("ritosysc shell-order=killall audioserver")
|
||||
val process = Runtime.getRuntime().exec("ritosysc shell-order=killall android.hardware.audio.service")
|
||||
@ -1267,6 +1328,22 @@ object Utils {
|
||||
process.destroy()
|
||||
}
|
||||
|
||||
fun setAudioSourceDevice(dev : String) {
|
||||
propertySet("sys.ritosip.audio.input.device", dev)
|
||||
if(dev == "usb") {
|
||||
if(BaresipService.audioDeviceUsbId == -1) {
|
||||
propertySet("sys.ritosip.audio.source", BaresipService.audioDeviceCodecId.toString())
|
||||
propertySet("sys.ritosip.audio.source.volume", "0")
|
||||
} else {
|
||||
propertySet("sys.ritosip.audio.source", BaresipService.audioDeviceUsbId.toString())
|
||||
propertySet("sys.ritosip.audio.source.volume", "100")
|
||||
}
|
||||
} else if(dev == "codec") {
|
||||
propertySet("sys.ritosip.audio.source", BaresipService.audioDeviceCodecId.toString())
|
||||
propertySet("sys.ritosip.audio.source.volume", "100")
|
||||
}
|
||||
}
|
||||
|
||||
fun checkNetworkIpType() {
|
||||
val process = Runtime.getRuntime().exec("ritosysc shell-order=rm /mnt/obb/ip_static;grep STATIC /data/misc/ethernet/ipconfig.txt && touch /mnt/obb/ip_static")
|
||||
process.waitFor()
|
||||
@ -1279,6 +1356,28 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
fun runShellOrder(order : String) {
|
||||
val process = Runtime.getRuntime().exec(order)
|
||||
process.waitFor()
|
||||
process.destroy()
|
||||
}
|
||||
|
||||
fun setMicVolumeByMix(volume : Int) {
|
||||
CoroutineScope(Dispatchers.Default).launch {
|
||||
Utils.runShellOrderSuper("tinymix -D 3 \"Mic Capture Volume\" ${volume}")
|
||||
BaresipService.micVolume = volume
|
||||
Config.replaceVariable("mic_volume", volume.toString())
|
||||
Config.save()
|
||||
propertySet("sys.ritosip.mic.volume", volume.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun runShellOrderSuper(order : String) {
|
||||
val process = Runtime.getRuntime().exec("ritosysc shell-order=" + order)
|
||||
process.waitFor()
|
||||
process.destroy()
|
||||
}
|
||||
|
||||
fun save(dev : String) {
|
||||
propertySet("sys.rito.audio.input.device", dev)
|
||||
//val process = Runtime.getRuntime().exec("ritosysc shell-order=killall audioserver")
|
||||
@ -1315,7 +1414,17 @@ object Utils {
|
||||
val file = File("/d/hdmirx/status") // 파일 경로 설정
|
||||
file.bufferedReader().use { reader ->
|
||||
val line = reader.readLine() // 첫 번째 줄 읽기
|
||||
return line.split(":")[1].trim()
|
||||
val plugStatus = line.split(":")[1].trim()
|
||||
if(plugStatus == "plugin") {
|
||||
val line2 = reader.readLine() // 두 번째 줄 읽기
|
||||
val lockStatus = line2.split(":")[1].trim().startsWith("Lock")
|
||||
|
||||
if (lockStatus) {
|
||||
return "plugin"
|
||||
}
|
||||
}
|
||||
|
||||
return "plugout"
|
||||
}
|
||||
} else if(idx == 1) {
|
||||
val file = File("/sys/module/lt6911uxc/parameters/status") // 파일 경로 설정
|
||||
@ -1334,13 +1443,21 @@ object Utils {
|
||||
fun saveNumberToFile(path: String, number: Int) {
|
||||
val file = File(path)
|
||||
try {
|
||||
//println("파일 존재 여부: ${file.exists()}, 디렉토리 여부: ${file.isDirectory}, 파일 여부: ${file.isFile}")
|
||||
if(!file.exists()) {
|
||||
file.createNewFile()
|
||||
}
|
||||
|
||||
file.writeText(number.toString())
|
||||
|
||||
Log.d("FileSave", "숫자 저장 완료: $number")
|
||||
|
||||
RandomAccessFile(path, "rw").use { raf ->
|
||||
raf.fd.sync() // eMMC에 확실히 기록
|
||||
raf.close()
|
||||
}
|
||||
|
||||
file.setWritable(true, false)
|
||||
} catch (e: IOException) {
|
||||
Log.e("FileSave", "파일 저장 실패 : " + e.toString())
|
||||
}
|
||||
|
BIN
app/src/main/res/drawable/backward.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
24
app/src/main/res/drawable/bg_button_selector_2.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="2dp" android:color="#FFFFFF" />
|
||||
<solid android:color="#0098FF" /> <!-- 포커스 배경 (주황색 강조) -->
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="2dp" android:color="#FFFFFF" />
|
||||
<solid android:color="#26A7FF" /> <!-- 포커스 배경 (주황색 강조) -->
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:width="2dp" android:color="#88FFFFFF" />
|
||||
<solid android:color="#c2c2c2" /> <!-- 포커스 배경 (회색) -->
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
5
app/src/main/res/drawable/hangup_big.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="128dp" android:width="128dp"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@color/colorTrafficRed" android:pathData="M12,9c-1.6,0 -3.15,0.25 -4.6,0.72v3.1c0,0.39 -0.23,0.74 -0.56,0.9 -0.98,0.49 -1.87,1.12 -2.66,1.85 -0.18,0.18 -0.43,0.28 -0.7,0.28 -0.28,0 -0.53,-0.11 -0.71,-0.29L0.29,13.08c-0.18,-0.17 -0.29,-0.42 -0.29,-0.7 0,-0.28 0.11,-0.53 0.29,-0.71C3.34,8.78 7.46,7 12,7s8.66,1.78 11.71,4.67c0.18,0.18 0.29,0.43 0.29,0.71 0,0.28 -0.11,0.53 -0.29,0.71l-2.48,2.48c-0.18,0.18 -0.43,0.29 -0.71,0.29 -0.27,0 -0.52,-0.11 -0.7,-0.28 -0.79,-0.74 -1.69,-1.36 -2.67,-1.85 -0.33,-0.16 -0.56,-0.5 -0.56,-0.9v-3.1C15.15,9.25 13.6,9 12,9z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/layout.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable/layout1.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable/layout10.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable/layout2.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable/layout3.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable/layout4.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable/layout5.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable/layout6.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/drawable/layout7.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable/layout8.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/layout9.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable/network.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
app/src/main/res/drawable/nocamera.png
Normal file
After Width: | Height: | Size: 924 KiB |
BIN
app/src/main/res/drawable/server.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
app/src/main/res/drawable/volume.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
@ -19,6 +19,15 @@
|
||||
app:srcCompat="@drawable/osvc_splash" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/callBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/colorBlack"
|
||||
android:visibility="gone">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/defaultLayout"
|
||||
android:layout_width="match_parent"
|
||||
@ -662,6 +671,228 @@
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/settingLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginHorizontal="60px"
|
||||
android:layout_marginVertical="150px"
|
||||
android:background="@drawable/custom_border"
|
||||
android:visibility="invisible">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonLayout"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="90px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/layout"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:nextFocusLeft="@id/dialogButtonBackward"
|
||||
android:nextFocusRight="@id/dialogButtonServer"
|
||||
android:nextFocusUp="@id/dialogButtonLayout"
|
||||
android:nextFocusDown="@id/dialogButtonLayout"
|
||||
android:text="레이아웃설정"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonServer"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="432px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/server"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="서버설정"
|
||||
android:nextFocusLeft="@id/dialogButtonLayout"
|
||||
android:nextFocusRight="@id/dialogButtonNetwork"
|
||||
android:nextFocusUp="@id/dialogButtonServer"
|
||||
android:nextFocusDown="@id/dialogButtonServer"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonNetwork"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="774px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/network"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="네트워크설정"
|
||||
android:nextFocusLeft="@id/dialogButtonServer"
|
||||
android:nextFocusRight="@id/dialogButtonVolume"
|
||||
android:nextFocusUp="@id/dialogButtonNetwork"
|
||||
android:nextFocusDown="@id/dialogButtonNetwork"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonVolume"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="1116px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/volume"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="볼륨설정"
|
||||
android:nextFocusLeft="@id/dialogButtonNetwork"
|
||||
android:nextFocusRight="@id/dialogButtonBackward"
|
||||
android:nextFocusUp="@id/dialogButtonVolume"
|
||||
android:nextFocusDown="@id/dialogButtonVolume"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonBackward"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="1458px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/backward"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="돌아가기"
|
||||
android:nextFocusLeft="@id/dialogButtonVolume"
|
||||
android:nextFocusRight="@id/dialogButtonLayout"
|
||||
android:nextFocusUp="@id/dialogButtonBackward"
|
||||
android:nextFocusDown="@id/dialogButtonBackward"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/settingLayoutInCall"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginHorizontal="150px"
|
||||
android:layout_marginVertical="150px"
|
||||
android:background="@drawable/custom_border"
|
||||
android:visibility="invisible">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonLayoutInCall"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="100px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/layout"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:nextFocusLeft="@id/dialogButtonBackwardInCall"
|
||||
android:nextFocusRight="@id/dialogButtonHangUp"
|
||||
android:nextFocusUp="@id/dialogButtonLayoutInCall"
|
||||
android:nextFocusDown="@id/dialogButtonLayoutInCall"
|
||||
android:text="레이아웃설정"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonHangUp"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="480px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/hangup_big"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="통화종료"
|
||||
android:nextFocusLeft="@id/dialogButtonLayoutInCall"
|
||||
android:nextFocusRight="@id/dialogButtonVolumeInCall"
|
||||
android:nextFocusUp="@id/dialogButtonHangUp"
|
||||
android:nextFocusDown="@id/dialogButtonHangUp"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonVolumeInCall"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="860px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/volume"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="볼륨설정"
|
||||
android:nextFocusLeft="@id/dialogButtonHangUp"
|
||||
android:nextFocusRight="@id/dialogButtonBackwardInCall"
|
||||
android:nextFocusUp="@id/dialogButtonVolumeInCall"
|
||||
android:nextFocusDown="@id/dialogButtonVolumeInCall"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/dialogButtonBackwardInCall"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="1240px"
|
||||
android:layout_marginTop="250px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/backward"
|
||||
android:drawablePadding="25px"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="돌아가기"
|
||||
android:nextFocusLeft="@id/dialogButtonVolumeInCall"
|
||||
android:nextFocusRight="@id/dialogButtonLayoutInCall"
|
||||
android:nextFocusUp="@id/dialogButtonBackwardInCall"
|
||||
android:nextFocusDown="@id/dialogButtonBackwardInCall"
|
||||
android:textColor="@color/colorWhite"
|
||||
android:textSize="30sp"
|
||||
android:textStyle="bold" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/networkSettingLayout"
|
||||
android:layout_width="match_parent"
|
||||
@ -761,6 +992,8 @@
|
||||
android:layout_margin="16dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:nextFocusLeft="@id/btnApply"
|
||||
android:nextFocusRight="@id/btnCancel"
|
||||
android:text="적용하기"
|
||||
android:textSize="24sp" />
|
||||
|
||||
@ -771,10 +1004,549 @@
|
||||
android:layout_margin="16dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:nextFocusLeft="@id/btnApply"
|
||||
android:nextFocusRight="@id/btnCancel"
|
||||
android:text="취소하기"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/serverSettingLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/custom_border"
|
||||
android:visibility="invisible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="서버 설정"
|
||||
android:textSize="34sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="표시명"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editDisplayName"
|
||||
android:layout_width="1000px"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="인증 사용자명"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSipId"
|
||||
android:layout_width="1000px"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="phone"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="인증 암호"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSipPassword"
|
||||
android:layout_width="1000px"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SIP 서버주소"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editSipServer"
|
||||
android:layout_width="1000px"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="트랜스포트"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/radioGroupTransport"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radioTransportUdp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingRight="15dp"
|
||||
android:nextFocusUp="@id/editSipServer"
|
||||
android:text="UDP"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radioTransportTcp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingRight="15dp"
|
||||
android:nextFocusUp="@id/editSipServer"
|
||||
android:text="TCP"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radioTransportTls"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingRight="15dp"
|
||||
android:nextFocusUp="@id/editSipServer"
|
||||
android:text="TLS"
|
||||
android:textSize="24sp" />
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="미디어 암호화"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/radioGroupEncrypt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radioEncryptNone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingRight="15dp"
|
||||
android:nextFocusDown="@id/btnApplyServer"
|
||||
android:text="사용안함"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radioEncryptSrtp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:paddingRight="15dp"
|
||||
android:nextFocusDown="@id/btnApplyServer"
|
||||
android:text="SRTP"
|
||||
android:textSize="24sp" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnApplyServer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:nextFocusUp="@id/radioEncryptNone"
|
||||
android:nextFocusLeft="@id/btnApplyServer"
|
||||
android:nextFocusRight="@id/btnCancelServer"
|
||||
android:text="적용하기"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCancelServer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:nextFocusUp="@id/radioEncryptNone"
|
||||
android:nextFocusLeft="@id/btnApplyServer"
|
||||
android:nextFocusRight="@id/btnCancelServer"
|
||||
android:text="취소하기"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/volumeSettingLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/custom_border"
|
||||
android:visibility="invisible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="볼륨 설정"
|
||||
android:textSize="34sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:layout_width="200px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="마이크볼륨"
|
||||
android:textSize="24sp"
|
||||
/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbarMicVolume"
|
||||
android:layout_width="600px"
|
||||
android:max="24"
|
||||
android:layout_height="wrap_content"
|
||||
android:nextFocusUp="@id/seekbarMicVolume"
|
||||
android:nextFocusLeft="@id/seekbarMicVolume"
|
||||
android:nextFocusRight="@id/seekbarMicVolume"
|
||||
android:textSize="24sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textMicVolume"
|
||||
android:layout_width="200px"
|
||||
android:layout_marginLeft="30px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text=""
|
||||
android:textSize="36sp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnDoneVolume"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp"
|
||||
android:nextFocusUp="@id/seekbarMicVolume"
|
||||
android:nextFocusLeft="@id/btnDoneVolume"
|
||||
android:nextFocusRight="@id/btnDoneVolume"
|
||||
android:nextFocusDown="@id/btnDoneVolume"
|
||||
android:text="돌아가기"
|
||||
android:textSize="24sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/layoutSettingLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/custom_border"
|
||||
android:visibility="invisible">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="레이아웃 설정"
|
||||
android:textSize="34sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType1"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="155px"
|
||||
android:layout_marginTop="140px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout1"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType10"
|
||||
android:nextFocusRight="@id/layoutType2"
|
||||
android:nextFocusUp="@id/layoutBackward"
|
||||
android:nextFocusDown="@id/layoutType6" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType2"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="495px"
|
||||
android:layout_marginTop="140px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout2"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType1"
|
||||
android:nextFocusRight="@id/layoutType3"
|
||||
android:nextFocusUp="@id/layoutBackward"
|
||||
android:nextFocusDown="@id/layoutType7" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType3"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="835px"
|
||||
android:layout_marginTop="140px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout3"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType2"
|
||||
android:nextFocusRight="@id/layoutType4"
|
||||
android:nextFocusUp="@id/layoutBackward"
|
||||
android:nextFocusDown="@id/layoutType8" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType4"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="1175px"
|
||||
android:layout_marginTop="140px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout4"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType3"
|
||||
android:nextFocusRight="@id/layoutType5"
|
||||
android:nextFocusUp="@id/layoutBackward"
|
||||
android:nextFocusDown="@id/layoutType9" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType5"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="1515px"
|
||||
android:layout_marginTop="140px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout5"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType4"
|
||||
android:nextFocusRight="@id/layoutType6"
|
||||
android:nextFocusUp="@id/layoutBackward"
|
||||
android:nextFocusDown="@id/layoutType10" />
|
||||
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType6"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="155px"
|
||||
android:layout_marginTop="420px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout6"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType5"
|
||||
android:nextFocusRight="@id/layoutType7"
|
||||
android:nextFocusUp="@id/layoutType1"
|
||||
android:nextFocusDown="@id/layoutBackward" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType7"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="495px"
|
||||
android:layout_marginTop="420px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout7"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType6"
|
||||
android:nextFocusRight="@id/layoutType8"
|
||||
android:nextFocusUp="@id/layoutType2"
|
||||
android:nextFocusDown="@id/layoutBackward" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType8"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="835px"
|
||||
android:layout_marginTop="420px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout8"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType7"
|
||||
android:nextFocusRight="@id/layoutType9"
|
||||
android:nextFocusUp="@id/layoutType3"
|
||||
android:nextFocusDown="@id/layoutBackward" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType9"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="1175px"
|
||||
android:layout_marginTop="420px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout9"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType8"
|
||||
android:nextFocusRight="@id/layoutType10"
|
||||
android:nextFocusUp="@id/layoutType4"
|
||||
android:nextFocusDown="@id/layoutBackward" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutType10"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="1515px"
|
||||
android:layout_marginTop="420px"
|
||||
android:background="@drawable/bg_button_selector_2"
|
||||
android:drawableTop="@drawable/layout10"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutType9"
|
||||
android:nextFocusRight="@id/layoutType1"
|
||||
android:nextFocusUp="@id/layoutType5"
|
||||
android:nextFocusDown="@id/layoutBackward" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/layoutBackward"
|
||||
android:layout_width="250px"
|
||||
android:layout_height="210px"
|
||||
android:layout_marginLeft="835px"
|
||||
android:layout_marginTop="780px"
|
||||
android:background="@drawable/bg_button_selector"
|
||||
android:drawableTop="@drawable/backward"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:gravity="center"
|
||||
android:padding="32dp"
|
||||
android:nextFocusLeft="@id/layoutBackward"
|
||||
android:nextFocusRight="@id/layoutBackward"
|
||||
android:nextFocusUp="@id/layoutType8"
|
||||
android:nextFocusDown="@id/layoutType3" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|