第一次提交
6
call_sw/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/build
|
||||
agora-*
|
||||
libagora*
|
||||
libvideo*
|
||||
libudrm3.so
|
||||
/release/
|
||||
73
call_sw/build.gradle
Normal file
@@ -0,0 +1,73 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdk 33
|
||||
namespace = "io.agora.onetoone"
|
||||
|
||||
defaultConfig {
|
||||
ndk.abiFilters 'arm64-v8a', 'armeabi-v7a'
|
||||
minSdk 24
|
||||
targetSdk 33
|
||||
versionCode 1
|
||||
versionName "2.1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
buildConfigField("String", "AG_APP_ID", "\"${project.getProperty("AG_APP_ID")}\"")
|
||||
buildConfigField("String", "AG_APP_CERTIFICATE", "\"${project.getProperty("AG_APP_CERTIFICATE")}\"")
|
||||
buildConfigField "String", "IM_APP_KEY", "\"${IM_APP_KEY}\""
|
||||
}
|
||||
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
pickFirst 'lib/*/libaosl.so'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api 'androidx.core:core-ktx:1.7.0'
|
||||
api 'androidx.appcompat:appcompat:1.4.1'
|
||||
api 'com.google.android.material:material:1.5.0'
|
||||
api 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
api 'androidx.navigation:navigation-fragment-ktx:2.4.1'
|
||||
api 'androidx.navigation:navigation-ui-ktx:2.4.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
// api 'com.squareup.okhttp3:okhttp:3.12.0'
|
||||
api 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||
|
||||
api 'com.github.GrenderG:Toasty:1.5.0'
|
||||
api 'com.orhanobut:logger:2.2.0'
|
||||
|
||||
// rtc
|
||||
api 'io.agora:authentication:1.6.1'
|
||||
api 'commons-codec:commons-codec:1.15'
|
||||
|
||||
// callapi
|
||||
api project(":lib_callapi")
|
||||
api project(":chatkit-ui")
|
||||
|
||||
}
|
||||
21
call_sw/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.agora.onetoone
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("io.agora.callapi", appContext.packageName)
|
||||
}
|
||||
}
|
||||
16
call_sw/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
||||
<application>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
104
call_sw/src/main/java/io/agora/onetoone/http/HttpManager.kt
Normal file
@@ -0,0 +1,104 @@
|
||||
package io.agora.onetoone.http
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import io.agora.onetoone.BuildConfig
|
||||
import okhttp3.*
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import org.json.JSONArray
|
||||
import java.io.IOException
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
object HttpManager {
|
||||
private val TAG = "HttpManager_LOG"
|
||||
private const val mBaseUrl = "https://toolbox.bj2.agoralab.co/v1"
|
||||
private val mClient = OkHttpClient()
|
||||
|
||||
// fun sendPostRequest() {
|
||||
//
|
||||
// val requestBody = RequestBody.create(MediaType.parse("application/json"), "{\"name\":\"John\", \"age\":30}")
|
||||
//
|
||||
// val request = Request.Builder()
|
||||
// .url(mBaseUrl)
|
||||
// .post(requestBody)
|
||||
// .build()
|
||||
//
|
||||
// mClient.newCall(request).enqueue(object : Callback {
|
||||
// override fun onFailure(call: Call, e: IOException) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
//
|
||||
// override fun onResponse(call: Call, response: Response) {
|
||||
// val responseBody = response.body()?.string()
|
||||
// println(responseBody)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 1: RTC Token ; 2: RTM Token
|
||||
fun token007(channelName: String, uid: String, onCompletion: ((String?) -> Unit)?) {
|
||||
val postBody = JSONObject()
|
||||
val types = arrayOf(1,2)
|
||||
val jsonArray = JSONArray(types)
|
||||
try {
|
||||
postBody.put("appId", BuildConfig.AG_APP_ID)
|
||||
postBody.put("appCertificate", BuildConfig.AG_APP_CERTIFICATE)
|
||||
postBody.put("channelName", channelName)
|
||||
postBody.put("expire", 1500) // expire seconds
|
||||
postBody.put("src", "Android")
|
||||
postBody.put("ts", System.currentTimeMillis())
|
||||
postBody.put("types", jsonArray)
|
||||
postBody.put("uid", uid)
|
||||
} catch (e: JSONException) {
|
||||
onCompletion?.invoke(null)
|
||||
}
|
||||
val requestBody = RequestBody.create(null, postBody.toString())
|
||||
val request = Request.Builder()
|
||||
.url("$mBaseUrl/token/generate")
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.post(requestBody)
|
||||
.build()
|
||||
mClient.newCall(request).enqueue(object : Callback {
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val json = response.body?.string() ?: ""
|
||||
val map = parseJson(json)
|
||||
val data = map["data"] as? Map<String, Any>
|
||||
if (data != null) {
|
||||
val token = data["token"] as? String
|
||||
runOnUiThread {
|
||||
onCompletion?.invoke(token)
|
||||
}
|
||||
} else {
|
||||
runOnUiThread {
|
||||
onCompletion?.invoke(null)
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "HTTP response: $json")
|
||||
}
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
Log.d(TAG, "HTTP error")
|
||||
runOnUiThread {
|
||||
onCompletion?.invoke(null)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun runOnUiThread(runnable: Runnable) {
|
||||
if (Thread.currentThread() === Looper.getMainLooper().thread) {
|
||||
runnable.run()
|
||||
} else {
|
||||
Handler(Looper.getMainLooper()).post(runnable)
|
||||
}
|
||||
}
|
||||
|
||||
fun parseJson(json: String): Map<String, Any> {
|
||||
val gson = Gson()
|
||||
val type = object : TypeToken<Map<String, Any>>() {}.type
|
||||
return gson.fromJson(json, type)
|
||||
}
|
||||
|
||||
}
|
||||
28
call_sw/src/main/java/io/agora/onetoone/model/Models.kt
Normal file
@@ -0,0 +1,28 @@
|
||||
package io.agora.onetoone.model
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/** Information carried when joining a room
|
||||
* 加入房间时携带的信息
|
||||
*/
|
||||
data class EnterRoomInfoModel (
|
||||
var isRtm: Boolean = true,
|
||||
var isBrodCaster: Boolean = true,
|
||||
var currentUid: String = "",
|
||||
var showRoomId: String = "",
|
||||
var showUserId: String = "",
|
||||
|
||||
var rtcToken: String = "",
|
||||
var rtmToken: String = "",
|
||||
var showRoomToken: String = "",
|
||||
|
||||
var dimensionsWidth: String = "",
|
||||
var dimensionsHeight: String = "",
|
||||
var frameRate: String = "",
|
||||
var bitrate: String = "0",
|
||||
|
||||
var autoAccept: Boolean = true,
|
||||
var autoJoinRTC: Boolean = false,
|
||||
|
||||
var firstFrameWaittingDisabled: Boolean = false
|
||||
) : Serializable
|
||||
@@ -0,0 +1,191 @@
|
||||
package io.agora.onetoone.signalClient
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import com.hyphenate.EMCallBack
|
||||
import com.hyphenate.EMConnectionListener
|
||||
import com.hyphenate.EMMessageListener
|
||||
import com.hyphenate.chat.EMClient
|
||||
import com.hyphenate.chat.EMMessage
|
||||
import com.hyphenate.chat.EMOptions
|
||||
import com.hyphenate.chat.EMTextMessageBody
|
||||
import com.hyphenate.exceptions.HyphenateException
|
||||
import es.dmoral.toasty.Toasty
|
||||
import io.agora.onetoone.AGError
|
||||
import io.agora.onetoone.R
|
||||
import io.agora.rtm.PublishOptions
|
||||
import io.agora.rtm.RtmConstants
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
|
||||
fun createEasemobSignalClient(context: Context, appKey: String, userId: Int) = CallEasemobSignalClient(context, appKey, userId)
|
||||
|
||||
class CallEasemobSignalClient(
|
||||
private val context: Context,
|
||||
private val appKey: String,
|
||||
private val userId: Int = 0
|
||||
): ISignalClient, EMMessageListener, EMConnectionListener, CallBaseSignalClient() {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "CALL_HY_MSG_MANAGER"
|
||||
}
|
||||
|
||||
init {
|
||||
val options = EMOptions()
|
||||
options.appKey = appKey
|
||||
// Other EMOptions configurations
|
||||
// 其他 EMOptions 配置
|
||||
EMClient.getInstance().init(context, options)
|
||||
// Register message listener
|
||||
// 注册消息监听
|
||||
EMClient.getInstance().chatManager().addMessageListener(this)
|
||||
EMClient.getInstance().addConnectionListener(this)
|
||||
}
|
||||
|
||||
var isConnected: Boolean = false
|
||||
|
||||
private val mHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
fun login(completion: ((success: Boolean) -> Unit)?) {
|
||||
Thread {
|
||||
// Registration
|
||||
// 注册
|
||||
try {
|
||||
// Synchronous method, will block current thread
|
||||
// 同步方法,会阻塞当前线程
|
||||
EMClient.getInstance().createAccount(userId.toString(), userId.toString())
|
||||
|
||||
} catch (e: HyphenateException) {
|
||||
// Failed
|
||||
// 失败
|
||||
Log.e(TAG, "createAccount failed: ${e.message}, code: ${e.errorCode}")
|
||||
}
|
||||
|
||||
// Login
|
||||
// 登陆
|
||||
EMClient.getInstance().login(userId.toString(), userId.toString(), object : EMCallBack {
|
||||
// Login success callback
|
||||
// 登录成功回调
|
||||
override fun onSuccess() {
|
||||
Log.d(TAG, "login success")
|
||||
isConnected = true
|
||||
EMClient.getInstance().chatManager().loadAllConversations()
|
||||
EMClient.getInstance().groupManager().loadAllGroups()
|
||||
completion?.invoke(true)
|
||||
}
|
||||
|
||||
// Login failure callback with error information
|
||||
// 登录失败回调,包含错误信息
|
||||
override fun onError(code: Int, error: String) {
|
||||
Log.e(TAG, "login failed, code:$code, msg:$error")
|
||||
completion?.invoke(false)
|
||||
}
|
||||
|
||||
override fun onProgress(i: Int, s: String) {}
|
||||
})
|
||||
}.start()
|
||||
}
|
||||
|
||||
fun clean() {
|
||||
isConnected = false
|
||||
listeners.clear()
|
||||
EMClient.getInstance().removeConnectionListener(this)
|
||||
EMClient.getInstance().logout(false)
|
||||
}
|
||||
|
||||
override fun sendMessage(
|
||||
userId: String,
|
||||
message: String,
|
||||
completion: ((AGError?) -> Unit)?
|
||||
) {
|
||||
if (userId.isEmpty() || userId == "0") {
|
||||
val errorStr = "sendMessage fail, invalid userId[$userId]"
|
||||
completion?.invoke(AGError(errorStr, -1))
|
||||
return
|
||||
}
|
||||
innerSendMessage(userId, message, completion)
|
||||
}
|
||||
|
||||
private fun innerSendMessage(
|
||||
userId: String,
|
||||
message: String,
|
||||
completion: ((AGError?) -> Unit)?
|
||||
) {
|
||||
if (userId.isEmpty()) {
|
||||
completion?.invoke(AGError("send message fail! roomId is empty", -1))
|
||||
return
|
||||
}
|
||||
val options = PublishOptions()
|
||||
options.setChannelType(RtmConstants.RtmChannelType.USER)
|
||||
val startTime = System.currentTimeMillis()
|
||||
|
||||
// `content` is the text content to send, `toChatUsername` is the recipient's account
|
||||
// `content` 为要发送的文本内容,`toChatUsername` 为对方的账号
|
||||
val msg = EMMessage.createTextSendMessage(message, userId)
|
||||
// Chat type: single chat is EMMessage.ChatType.Chat
|
||||
// 会话类型:单聊为 EMMessage.ChatType.Chat
|
||||
msg.chatType = EMMessage.ChatType.Chat
|
||||
msg.deliverOnlineOnly(true)
|
||||
// When sending a message, you can set an instance of `EMCallBack` to get the message sending status
|
||||
// Can update message display status in this callback, such as message sending failure prompts, etc.
|
||||
// 发送消息时可以设置 `EMCallBack` 的实例,获得消息发送的状态
|
||||
// 可以在该回调中更新消息的显示状态。例如消息发送失败后的提示等等
|
||||
msg.setMessageStatusCallback(object : EMCallBack {
|
||||
override fun onSuccess() {
|
||||
// Message sent successfully
|
||||
// 发送消息成功
|
||||
runOnUiThread { completion?.invoke(null) }
|
||||
}
|
||||
|
||||
override fun onError(code: Int, error: String) {
|
||||
// Message sending failed
|
||||
// 发送消息失败
|
||||
runOnUiThread { completion?.invoke(AGError(error, code)) }
|
||||
}
|
||||
|
||||
override fun onProgress(progress: Int, status: String) {}
|
||||
})
|
||||
// Send message
|
||||
// 发送消息
|
||||
EMClient.getInstance().chatManager().sendMessage(msg)
|
||||
}
|
||||
|
||||
// ---------------- EMMessageListener ----------------
|
||||
override fun onMessageReceived(messages: MutableList<EMMessage>?) {
|
||||
runOnUiThread {
|
||||
messages?.forEach {
|
||||
val body = it.body as EMTextMessageBody
|
||||
listeners.forEach {
|
||||
it.onMessageReceive(body.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- EMConnectionListener ----------------
|
||||
override fun onConnected() {
|
||||
runOnUiThread {
|
||||
Toasty.normal(context, context.getString(R.string.toast_easemob_connected), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
isConnected = true
|
||||
}
|
||||
|
||||
override fun onDisconnected(errorCode: Int) {
|
||||
runOnUiThread {
|
||||
Toasty.normal(context, context.getString(R.string.toast_easemob_disconnected), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
isConnected = false
|
||||
}
|
||||
|
||||
// ---------------- inner private ----------------
|
||||
private fun runOnUiThread(runnable: Runnable) {
|
||||
if (Thread.currentThread() == Looper.getMainLooper().thread) {
|
||||
runnable.run()
|
||||
} else {
|
||||
mHandler.post(runnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
package io.agora.onetoone.utils;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import io.agora.onetoone.R;
|
||||
|
||||
|
||||
public class CircleImageView extends AppCompatImageView {
|
||||
// paint when user press
|
||||
private Paint pressPaint;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
// default bitmap config
|
||||
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
|
||||
private static final int COLORDRAWABLE_DIMENSION = 1;
|
||||
|
||||
// border color
|
||||
private int borderColor;
|
||||
// width of border
|
||||
private int borderWidth;
|
||||
// alpha when pressed
|
||||
private int pressAlpha;
|
||||
// color when pressed
|
||||
private int pressColor;
|
||||
// radius\
|
||||
private int radius;
|
||||
// rectangle or round, 1 is circle, 2 is rectangle
|
||||
private int shapeType;
|
||||
|
||||
public CircleImageView(Context context) {
|
||||
super(context);
|
||||
init(context, null);
|
||||
}
|
||||
|
||||
public CircleImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
//init the value
|
||||
borderWidth = 0;
|
||||
borderColor = 0xddffffff;
|
||||
pressAlpha = 0x42;
|
||||
pressColor = 0x42000000;
|
||||
radius = 16;
|
||||
shapeType = 0;
|
||||
|
||||
// get attribute of EaseImageView
|
||||
if (attrs != null) {
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
|
||||
borderColor = array.getColor(R.styleable.CircleImageView_ease_border_color, borderColor);
|
||||
borderWidth = array.getDimensionPixelOffset(R.styleable.CircleImageView_ease_border_width, borderWidth);
|
||||
pressAlpha = array.getInteger(R.styleable.CircleImageView_ease_press_alpha, pressAlpha);
|
||||
pressColor = array.getColor(R.styleable.CircleImageView_ease_press_color, pressColor);
|
||||
radius = array.getDimensionPixelOffset(R.styleable.CircleImageView_ease_radius, radius);
|
||||
shapeType = array.getInteger(R.styleable.CircleImageView_es_shape_type, shapeType);
|
||||
array.recycle();
|
||||
}
|
||||
|
||||
// set paint when pressed
|
||||
pressPaint = new Paint();
|
||||
pressPaint.setAntiAlias(true);
|
||||
pressPaint.setStyle(Paint.Style.FILL);
|
||||
pressPaint.setColor(pressColor);
|
||||
pressPaint.setAlpha(0);
|
||||
pressPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
setDrawingCacheEnabled(true);
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
|
||||
if (shapeType == 0) {
|
||||
super.onDraw(canvas);
|
||||
return;
|
||||
}
|
||||
Drawable drawable = getDrawable();
|
||||
if (drawable == null) {
|
||||
return;
|
||||
}
|
||||
// the width and height is in xml file
|
||||
if (getWidth() == 0 || getHeight() == 0) {
|
||||
return;
|
||||
}
|
||||
Bitmap bitmap = getBitmapFromDrawable(drawable);
|
||||
drawDrawable(canvas, bitmap);
|
||||
|
||||
if (isClickable()) {
|
||||
drawPress(canvas);
|
||||
}
|
||||
drawBorder(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw Rounded Rectangle
|
||||
*
|
||||
* @param canvas
|
||||
* @param bitmap
|
||||
*/
|
||||
@SuppressLint("WrongConstant")
|
||||
private void drawDrawable(Canvas canvas, Bitmap bitmap) {
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(0xffffffff);
|
||||
paint.setAntiAlias(true); //smooths out the edges of what is being drawn
|
||||
PorterDuffXfermode xfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
|
||||
// set flags
|
||||
int saveFlags = Canvas.ALL_SAVE_FLAG
|
||||
;
|
||||
canvas.saveLayer(0, 0, width, height, null, saveFlags);
|
||||
|
||||
if (shapeType == 1) {
|
||||
canvas.drawCircle(width / 2, height / 2, width / 2 - 1, paint);
|
||||
} else if (shapeType == 2) {
|
||||
RectF rectf = new RectF(1, 1, getWidth() - 1, getHeight() - 1);
|
||||
canvas.drawRoundRect(rectf, radius + 1, radius + 1, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode(xfermode);
|
||||
|
||||
float scaleWidth = ((float) getWidth()) / bitmap.getWidth();
|
||||
float scaleHeight = ((float) getHeight()) / bitmap.getHeight();
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(scaleWidth, scaleHeight);
|
||||
|
||||
//bitmap scale
|
||||
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
|
||||
canvas.drawBitmap(bitmap, 0, 0, paint);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* draw the effect when pressed
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawPress(Canvas canvas) {
|
||||
// check is rectangle or circle
|
||||
if (shapeType == 1) {
|
||||
canvas.drawCircle(width / 2, height / 2, width / 2 - 1, pressPaint);
|
||||
} else if (shapeType == 2) {
|
||||
RectF rectF = new RectF(1, 1, width - 1, height - 1);
|
||||
canvas.drawRoundRect(rectF, radius + 1, radius + 1, pressPaint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* draw customized border
|
||||
*
|
||||
* @param canvas
|
||||
*/
|
||||
private void drawBorder(Canvas canvas) {
|
||||
if (borderWidth > 0) {
|
||||
Paint paint = new Paint();
|
||||
paint.setStrokeWidth(borderWidth);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setColor(borderColor);
|
||||
paint.setAntiAlias(true);
|
||||
// // check is rectangle or circle
|
||||
if (shapeType == 1) {
|
||||
canvas.drawCircle(width / 2, height / 2, (width - borderWidth) / 2, paint);
|
||||
} else if (shapeType == 2) {
|
||||
RectF rectf = new RectF(borderWidth / 2, borderWidth / 2, getWidth() - borderWidth / 2,
|
||||
getHeight() - borderWidth / 2);
|
||||
canvas.drawRoundRect(rectf, radius, radius, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* monitor the size change
|
||||
*
|
||||
* @param w
|
||||
* @param h
|
||||
* @param oldw
|
||||
* @param oldh
|
||||
*/
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* monitor if touched
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
pressPaint.setAlpha(pressAlpha);
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
pressPaint.setAlpha(0);
|
||||
invalidate();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
|
||||
break;
|
||||
default:
|
||||
pressPaint.setAlpha(0);
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param drawable
|
||||
* @return
|
||||
*/
|
||||
private Bitmap getBitmapFromDrawable(Drawable drawable) {
|
||||
if (drawable == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
return ((BitmapDrawable) drawable).getBitmap();
|
||||
}
|
||||
|
||||
Bitmap bitmap;
|
||||
int width = Math.max(drawable.getIntrinsicWidth(), 2);
|
||||
int height = Math.max(drawable.getIntrinsicHeight(), 2);
|
||||
try {
|
||||
bitmap = Bitmap.createBitmap(width, height, BITMAP_CONFIG);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
bitmap = null;
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* set border color
|
||||
*
|
||||
* @param borderColor
|
||||
*/
|
||||
public void setBorderColor(int borderColor) {
|
||||
this.borderColor = borderColor;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* set border width
|
||||
*
|
||||
* @param borderWidth
|
||||
*/
|
||||
public void setBorderWidth(int borderWidth) {
|
||||
this.borderWidth = borderWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* set alpha when pressed
|
||||
*
|
||||
* @param pressAlpha
|
||||
*/
|
||||
public void setPressAlpha(int pressAlpha) {
|
||||
this.pressAlpha = pressAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* set color when pressed
|
||||
*
|
||||
* @param pressColor
|
||||
*/
|
||||
public void setPressColor(int pressColor) {
|
||||
this.pressColor = pressColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* set radius
|
||||
*
|
||||
* @param radius
|
||||
*/
|
||||
public void setRadius(int radius) {
|
||||
this.radius = radius;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* set shape,1 is circle, 2 is rectangle
|
||||
*
|
||||
* @param shapeType
|
||||
*/
|
||||
public void setShapeType(int shapeType) {
|
||||
this.shapeType = shapeType;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
33
call_sw/src/main/java/io/agora/onetoone/utils/KeyCenter.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
package io.agora.onetoone.utils
|
||||
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import io.agora.media.RtcTokenBuilder
|
||||
import io.agora.onetoone.BuildConfig
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* @author create by zhangwei03
|
||||
*/
|
||||
object KeyCenter {
|
||||
|
||||
private const val TAG = "KeyCenter"
|
||||
|
||||
var rtcUid: Int = Random(System.nanoTime()).nextInt(10000) + 1000000;
|
||||
|
||||
fun getRtcToken(channelId: String, uid: Int): String {
|
||||
var rtcToken: String = ""
|
||||
if (TextUtils.isEmpty(BuildConfig.AG_APP_CERTIFICATE)) {
|
||||
return rtcToken
|
||||
}
|
||||
try {
|
||||
rtcToken = RtcTokenBuilder().buildTokenWithUid(
|
||||
BuildConfig.AG_APP_ID, BuildConfig.AG_APP_CERTIFICATE, channelId, uid,
|
||||
RtcTokenBuilder.Role.Role_Publisher, 0
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "rtc token build error:${e.message}")
|
||||
}
|
||||
return rtcToken
|
||||
}
|
||||
}
|
||||
173
call_sw/src/main/java/io/agora/onetoone/utils/Ov1Logger.kt
Normal file
@@ -0,0 +1,173 @@
|
||||
package io.agora.onetoone.utils
|
||||
|
||||
import android.os.*
|
||||
import com.netease.yunxin.kit.corekit.im.IMKitClient.getApplicationContext
|
||||
import com.orhanobut.logger.*
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
object Ov1Logger {
|
||||
|
||||
private val entLogger = EntLogger(EntLogger.Config("Ov1"))
|
||||
|
||||
@JvmStatic
|
||||
fun d(tag: String, message: String, vararg args: Any) {
|
||||
entLogger.d(tag, message, args)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun w(tag: String, message: String, vararg args: Any) {
|
||||
entLogger.w(tag, message, args)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun e(tag: String, message: String, vararg args: Any) {
|
||||
entLogger.e(tag, message, args)
|
||||
}
|
||||
}
|
||||
|
||||
class EntLogger(private val config: Config) {
|
||||
|
||||
companion object {
|
||||
private val LogFolder = getApplicationContext().getExternalFilesDir("")!!.absolutePath
|
||||
private val LogFileWriteThread by lazy {
|
||||
HandlerThread("AndroidFileLogger.$LogFolder").apply {
|
||||
start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Config(
|
||||
val sceneName: String,
|
||||
val fileSize: Int = 2 * 1024 * 1024, // 2M, unit in bytes
|
||||
val fileName: String = "agora_${sceneName}_${SimpleDateFormat("yyyy-MM-DD", Locale.US).format(Date())}_log".lowercase()
|
||||
)
|
||||
|
||||
private val dataFormat = SimpleDateFormat("HH:mm:ss.SSS", Locale.US)
|
||||
|
||||
init {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Logger.addLogAdapter(
|
||||
object: AndroidLogAdapter(
|
||||
PrettyFormatStrategy.newBuilder()
|
||||
.showThreadInfo(true) // (Optional) Whether to show thread info or not. Default true
|
||||
.methodCount(1) // (Optional) How many method line to show. Default 2
|
||||
.methodOffset(2) // (Optional) Hides internal method calls up to offset. Default 5
|
||||
.logStrategy(LogcatLogStrategy()) // (Optional) Changes the log strategy to print out. Default LogCat
|
||||
.tag(config.sceneName) // (Optional) Global tag for every log. Default PRETTY_LOGGER
|
||||
.build()
|
||||
){
|
||||
override fun isLoggable(priority: Int, tag: String?): Boolean {
|
||||
return tag == config.sceneName
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Logger.addLogAdapter(
|
||||
object: DiskLogAdapter(
|
||||
CsvFormatStrategy
|
||||
.newBuilder()
|
||||
.logStrategy(DiskLogStrategy(WriteHandler()))
|
||||
.tag(config.sceneName)
|
||||
.build()
|
||||
){
|
||||
override fun isLoggable(priority: Int, tag: String?): Boolean {
|
||||
return tag == config.sceneName
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun i(tag: String? = null, message: String, vararg args: Any) {
|
||||
Logger.t(config.sceneName).i(formatMessage("INFO", tag, message), args)
|
||||
}
|
||||
|
||||
fun w(tag: String? = null, message: String, vararg args: Any) {
|
||||
Logger.t(config.sceneName).w(formatMessage("Warn", tag, message), args)
|
||||
}
|
||||
|
||||
fun d(tag: String? = null, message: String, vararg args: Any) {
|
||||
Logger.t(config.sceneName).d(formatMessage("Debug", tag, message), args)
|
||||
}
|
||||
|
||||
fun e(tag: String? = null, message: String, vararg args: Any) {
|
||||
Logger.t(config.sceneName).e(formatMessage("Error", tag, message), args)
|
||||
}
|
||||
|
||||
fun e(tag: String? = null, throwable: Throwable, message: String, vararg args: Any) {
|
||||
Logger.t(config.sceneName).e(throwable, formatMessage("Error", tag, message), args)
|
||||
}
|
||||
|
||||
private fun formatMessage(level: String, tag: String?, message: String): String {
|
||||
val sb = StringBuilder("[Agora][${level}][${config.sceneName}]")
|
||||
tag?.let { sb.append("[${tag}]"); }
|
||||
sb.append(" : (${dataFormat.format(Date())}) : $message")
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
private inner class WriteHandler : Handler(LogFileWriteThread.looper) {
|
||||
|
||||
override fun handleMessage(msg: Message) {
|
||||
val content = msg.obj as String
|
||||
var fileWriter: FileWriter? = null
|
||||
val logFile = getLogFile(LogFolder, config.fileName)
|
||||
try {
|
||||
fileWriter = FileWriter(logFile, true)
|
||||
writeLog(fileWriter, content)
|
||||
fileWriter.flush()
|
||||
fileWriter.close()
|
||||
} catch (e: IOException) {
|
||||
if (fileWriter != null) {
|
||||
try {
|
||||
fileWriter.flush()
|
||||
fileWriter.close()
|
||||
} catch (e1: IOException) { /* fail silently */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun writeLog(fileWriter: FileWriter, content: String) {
|
||||
var writeContent = content
|
||||
val agoraTag = writeContent.indexOf("[Agora]")
|
||||
if (agoraTag > 0) {
|
||||
writeContent = writeContent.substring(agoraTag)
|
||||
}
|
||||
fileWriter.append(writeContent)
|
||||
}
|
||||
|
||||
private fun getLogFile(folderName: String, fileName: String): File {
|
||||
val folder = File(folderName)
|
||||
if (!folder.exists()) {
|
||||
folder.mkdirs()
|
||||
}
|
||||
var newFileCount = 0
|
||||
var newFile: File
|
||||
var existingFile: File? = null
|
||||
newFile = File(folder, getLogFileFullName(fileName, newFileCount))
|
||||
while (newFile.exists()) {
|
||||
existingFile = newFile
|
||||
newFileCount++
|
||||
newFile = File(folder, getLogFileFullName(fileName, newFileCount))
|
||||
}
|
||||
if (existingFile != null && existingFile.length() < config.fileSize) {
|
||||
return existingFile
|
||||
} else {
|
||||
return newFile
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLogFileFullName(fileName: String, count: Int) : String{
|
||||
if(count == 0){
|
||||
return "${fileName}.txt"
|
||||
}
|
||||
return "${fileName}_${count}.txt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
144
call_sw/src/main/java/io/agora/onetoone/utils/PermissionHelp.kt
Normal file
@@ -0,0 +1,144 @@
|
||||
package io.agora.onetoone.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
|
||||
class PermissionHelp constructor(val activity: ComponentActivity) {
|
||||
|
||||
private var granted: (() -> Unit)? = null
|
||||
private var unGranted: (() -> Unit)? = null
|
||||
private val requestPermissionLauncher =
|
||||
activity.registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
|
||||
val granted = granted
|
||||
val unGranted = unGranted
|
||||
this.granted = null
|
||||
this.unGranted = null
|
||||
|
||||
if (isGranted) {
|
||||
granted?.invoke()
|
||||
} else {
|
||||
unGranted?.invoke()
|
||||
}
|
||||
}
|
||||
private val appSettingLauncher =
|
||||
activity.registerForActivityResult(object : ActivityResultContract<String, Boolean>() {
|
||||
private var input: String? = null
|
||||
|
||||
override fun createIntent(context: Context, input: String): Intent {
|
||||
this.input = input
|
||||
return Intent().apply {
|
||||
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
data = Uri.parse("package:" + context.packageName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
|
||||
return ContextCompat.checkSelfPermission(
|
||||
activity,
|
||||
input ?: ""
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
}) { isGranted ->
|
||||
val granted = granted
|
||||
val unGranted = unGranted
|
||||
this.granted = null
|
||||
this.unGranted = null
|
||||
|
||||
if (isGranted) {
|
||||
granted?.invoke()
|
||||
} else {
|
||||
unGranted?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check camera and microphone permissions
|
||||
*
|
||||
* @param force If true, will redirect to the system app permission settings page if the permission is denied
|
||||
*/
|
||||
fun checkCameraAndMicPerms(granted: () -> Unit, unGranted: () -> Unit, force: Boolean = false) {
|
||||
checkCameraPerm({
|
||||
checkMicPerm(granted, unGranted, force)
|
||||
}, unGranted, force)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check microphone permission
|
||||
*
|
||||
* @param force If true, will redirect to the system app permission settings page if the permission is denied
|
||||
*/
|
||||
fun checkMicPerm(granted: () -> Unit, unGranted: () -> Unit, force: Boolean = false) {
|
||||
checkPermission(Manifest.permission.RECORD_AUDIO, granted, force, unGranted)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check camera permission
|
||||
*
|
||||
* @param force If true, will redirect to the system app permission settings page if the permission is denied
|
||||
*/
|
||||
fun checkCameraPerm(granted: () -> Unit, unGranted: () -> Unit, force: Boolean = false) {
|
||||
checkPermission(Manifest.permission.CAMERA, granted, force, unGranted)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check external storage permission
|
||||
*
|
||||
* @param force If true, will redirect to the system app permission settings page if the permission is denied
|
||||
*/
|
||||
fun checkStoragePerm(granted: () -> Unit, unGranted: () -> Unit, force: Boolean = false) {
|
||||
checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, {
|
||||
checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE, granted, force, unGranted)
|
||||
}, force, unGranted)
|
||||
}
|
||||
|
||||
private fun checkPermission(perm: String, granted: () -> Unit, force: Boolean, unGranted: () -> Unit) {
|
||||
when {
|
||||
ContextCompat.checkSelfPermission(
|
||||
activity,
|
||||
perm
|
||||
) == PackageManager.PERMISSION_GRANTED -> {
|
||||
// You can use the API that requires the permission.
|
||||
granted.invoke()
|
||||
}
|
||||
activity.shouldShowRequestPermissionRationale(perm) -> {
|
||||
// In an educational UI, explain to the user why your app requires this
|
||||
// permission for a specific feature to behave as expected, and what
|
||||
// features are disabled if it's declined. In this UI, include a
|
||||
// "cancel" or "no thanks" button that lets the user continue
|
||||
// using your app without granting the permission.
|
||||
// showInContextUI(...)
|
||||
if (force) {
|
||||
launchAppSetting(perm, granted, unGranted)
|
||||
} else {
|
||||
unGranted.invoke()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
// You can directly ask for the permission.
|
||||
// The registered ActivityResultCallback gets the result of this request.
|
||||
launchPermissionRequest(perm, granted, unGranted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchPermissionRequest(perm: String, granted: () -> Unit, unGranted: () -> Unit) {
|
||||
this.granted = granted
|
||||
this.unGranted = unGranted
|
||||
requestPermissionLauncher.launch(perm)
|
||||
}
|
||||
|
||||
private fun launchAppSetting(perm: String, granted: () -> Unit, unGranted: () -> Unit) {
|
||||
this.granted = granted
|
||||
this.unGranted = unGranted
|
||||
appSettingLauncher.launch(perm)
|
||||
}
|
||||
}
|
||||
133
call_sw/src/main/java/io/agora/onetoone/utils/SPUtil.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package io.agora.onetoone.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.Editor;
|
||||
|
||||
import com.netease.yunxin.kit.corekit.im.IMKitClient;
|
||||
|
||||
public class SPUtil {
|
||||
private final static String PREFERENCES_NAME = "PREF_ONE_TO_ONE";
|
||||
|
||||
private SPUtil() {
|
||||
}
|
||||
|
||||
private static final class MInstanceHolder {
|
||||
static final SharedPreferences mInstance = IMKitClient.getApplicationContext().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the SharedPreferences instance object
|
||||
*/
|
||||
private static SharedPreferences getSharedPreference() {
|
||||
return MInstanceHolder.mInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a Boolean value!
|
||||
*/
|
||||
public static boolean putBoolean(String key, Boolean value) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.putBoolean(key, value);
|
||||
return editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an int value!
|
||||
*/
|
||||
public static boolean putInt(String key, int value) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.putInt(key, value);
|
||||
return editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a float value!
|
||||
*/
|
||||
public static boolean putFloat(String key, float value) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.putFloat(key, value);
|
||||
return editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a long value!
|
||||
*/
|
||||
public static boolean putLong(String key, long value) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.putLong(key, value);
|
||||
return editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a String value!
|
||||
*/
|
||||
public static boolean putString(String key, String value) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.putString(key, value);
|
||||
return editor.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the String value
|
||||
*/
|
||||
public static String getString(String key, String defValue) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
return sharedPreference.getString(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the int value
|
||||
*/
|
||||
public static int getInt(String key, int defValue) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
return sharedPreference.getInt(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the float value
|
||||
*/
|
||||
public static float getFloat(String key, Float defValue) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
return sharedPreference.getFloat(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the boolean value
|
||||
*/
|
||||
public static boolean getBoolean(String key, Boolean defValue) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
return sharedPreference.getBoolean(key, defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the long value
|
||||
*/
|
||||
public static long getLong(String key, long defValue) {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
return sharedPreference.getLong(key, defValue);
|
||||
}
|
||||
|
||||
public static void removeKey(String key) {
|
||||
try {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.remove(key);
|
||||
editor.apply();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
SharedPreferences sharedPreference = getSharedPreference();
|
||||
Editor editor = sharedPreference.edit();
|
||||
editor.clear();
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
30
call_sw/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
BIN
call_sw/src/main/res/drawable-xxhdpi/app_icon_back.png
Normal file
|
After Width: | Height: | Size: 203 B |
BIN
call_sw/src/main/res/drawable-xxhdpi/app_icon_close.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
call_sw/src/main/res/drawable-xxhdpi/app_icon_exit.png
Normal file
|
After Width: | Height: | Size: 644 B |
BIN
call_sw/src/main/res/drawable-xxhdpi/app_icon_switch.png
Normal file
|
After Width: | Height: | Size: 815 B |
8
call_sw/src/main/res/drawable/bottom_light_dialog_bg.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/white" />
|
||||
<corners
|
||||
android:topLeftRadius="20dp"
|
||||
android:topRightRadius="20dp" />
|
||||
</shape>
|
||||
11
call_sw/src/main/res/drawable/default_room_bg.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="#A1ADEA"
|
||||
android:startColor="#C2A1EA"
|
||||
android:useLevel="false"/>
|
||||
|
||||
</shape>
|
||||
170
call_sw/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
6
call_sw/src/main/res/drawable/statistic_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#CC151325" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
184
call_sw/src/main/res/layout/activity_pure1v1_living.xml
Normal file
@@ -0,0 +1,184 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/default_room_bg"
|
||||
tools:context=".LivingActivity">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/vertical40"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.4" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/vCenter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black_50"/>
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/horizontal20"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0.2" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tvTargetUid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/pure_1v1_target_uid"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="#CCFFFFFF"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/horizontal20" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/etTargetUid"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:hint="@string/pure_1v1_target_uid_hint"
|
||||
android:singleLine="true"
|
||||
android:imeOptions="actionDone|flagNoExtractUi"
|
||||
android:textColor="@color/white"
|
||||
android:textColorHint="#99FFFFFF"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tvTargetUid"
|
||||
app:layout_constraintStart_toEndOf="@id/tvTargetUid"
|
||||
app:layout_constraintTop_toTopOf="@id/tvTargetUid" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/vertical50"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/vLeft"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintDimensionRatio="1.31:2"
|
||||
app:layout_constraintEnd_toEndOf="@id/vertical50"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/horizontal20" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/vRight"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@android:color/white"
|
||||
app:layout_constraintDimensionRatio="1.31:2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@id/vertical50"
|
||||
app:layout_constraintTop_toTopOf="@id/horizontal20" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvCurrentId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="25dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/pure_1v1_current_uid" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/btnQuitChannel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/app_icon_exit"
|
||||
android:text="@string/app_quit_channel"
|
||||
app:layout_constraintBottom_toBottomOf="@id/tvCurrentId"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tvCurrentId" />
|
||||
|
||||
<include
|
||||
android:id="@+id/statisticLayout"
|
||||
layout="@layout/layout_statistic"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintStart_toStartOf="@id/vertical40"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tvCurrentId" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnCall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:text="@string/pure_1v1_invite"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnHangUp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:text="@string/pure_1v1_hangup"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnAudio"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:text="@string/pure_1v1_audio_off"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btnHangUp"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnVideo"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/pure_1v1_video_off"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btnAudio"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="11sp"
|
||||
android:textColor="@color/white"
|
||||
android:text=""
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/vLeft"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
324
call_sw/src/main/res/layout/activity_pure1v1_living1.xml
Normal file
@@ -0,0 +1,324 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/default_room_bg">
|
||||
<RelativeLayout
|
||||
android:id="@+id/calll_wait_ry"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<io.agora.onetoone.utils.CircleImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginTop="148dp"
|
||||
app:es_shape_type="round"
|
||||
android:id="@+id/user_iv"
|
||||
android:src="@mipmap/ic_launcher_round"
|
||||
app:ease_border_width="1dp"
|
||||
app:ease_border_color="@color/white"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/etTargetUid"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"
|
||||
android:layout_below="@id/user_iv"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:hint="@string/pure_1v1_target_uid_hint"
|
||||
android:singleLine="true"
|
||||
android:background="@null"
|
||||
android:enabled="false"
|
||||
android:imeOptions="actionDone|flagNoExtractUi"
|
||||
android:textColor="@color/white"
|
||||
android:textColorHint="#99FFFFFF"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="等待接听..."
|
||||
android:layout_below="@id/etTargetUid"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/kaiqimaikefeng"
|
||||
android:text="开启麦克风"
|
||||
android:id="@+id/btnAudio"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/guanduan_img"
|
||||
android:text="取消"
|
||||
android:id="@+id/btnQuitChannel"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/kaiqiyangshengqi"
|
||||
android:text="开启扬声器"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/calll_wait_in_ry"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<io.agora.onetoone.utils.CircleImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginTop="148dp"
|
||||
app:es_shape_type="round"
|
||||
android:id="@+id/user_iv1"
|
||||
android:src="@mipmap/ic_launcher_round"
|
||||
app:ease_border_width="1dp"
|
||||
app:ease_border_color="@color/white"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/etTargetUid2"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_below="@id/user_iv1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:hint="@string/pure_1v1_target_uid_hint"
|
||||
android:singleLine="true"
|
||||
android:gravity="center"
|
||||
android:background="@null"
|
||||
android:imeOptions="actionDone|flagNoExtractUi"
|
||||
android:textColor="@color/white"
|
||||
android:textColorHint="#99FFFFFF"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="等待接听..."
|
||||
android:layout_below="@id/etTargetUid2"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/guanduan_img"
|
||||
android:text="拒绝"
|
||||
android:id="@+id/btnGuaduan"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/jietong_img"
|
||||
android:text="接听"
|
||||
android:id="@+id/btnJieTong"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
<RelativeLayout
|
||||
android:id="@+id/video_ry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/default_room_bg"
|
||||
android:visibility="gone"
|
||||
>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/vLeft"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/vRight"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="192dp"
|
||||
android:layout_marginTop="98dp"
|
||||
android:background="@android:color/white"
|
||||
android:layout_marginStart="15dp"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/kaiqimaikefeng"
|
||||
android:text="开启麦克风"
|
||||
android:id="@+id/btnAudio1"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/yangshengqi_img"
|
||||
android:text="开启扬声器"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnVideo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/kaiqiyangshengqi"
|
||||
android:text="@string/pure_1v1_video_off"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_weight="1"
|
||||
android:drawablePadding="10dp"
|
||||
android:drawableTop="@mipmap/guanduan_img"
|
||||
android:text="取消"
|
||||
android:id="@+id/btnHangUp"
|
||||
android:textColor="#ffffffff"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvCurrentId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="25dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/pure_1v1_current_uid" />
|
||||
|
||||
<include
|
||||
android:id="@+id/statisticLayout"
|
||||
layout="@layout/layout_statistic"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/tvCurrentId" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btnCall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:text="@string/pure_1v1_invite"
|
||||
android:visibility="gone"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="11sp"
|
||||
android:textColor="@color/white"
|
||||
android:text=""
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
232
call_sw/src/main/res/layout/dialog_debug.xml
Normal file
@@ -0,0 +1,232 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:paddingBottom="24dp"
|
||||
android:background="@drawable/bottom_light_dialog_bg"
|
||||
tools:theme="@style/Theme.MaterialComponents"
|
||||
android:fitsSystemWindows="false">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/vertical50"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/ivBack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="16dp"
|
||||
android:src="@drawable/app_icon_back"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debugging_title"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ivBack"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/ivBack" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tvSure"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="12dp"
|
||||
android:text="@string/app_confirm"
|
||||
android:textColor="#009FFF"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/ivBack"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/ivBack" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layoutResolution"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/ivBack">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debug_encode_dimensions"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/etResolutionWidth"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="numberDecimal"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/tvResolutionX"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="1920" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tvResolutionX"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debug_x"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/etResolutionHeight"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/etResolutionHeight"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="numberDecimal"
|
||||
android:singleLine="true"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="1080" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/color_deliver"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layoutFrameRate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/layoutResolution">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debug_encode_frame_rate"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/etFps"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="numberDecimal"
|
||||
android:singleLine="true"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/tvFps"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="60" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tvFps"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debug_frame_rate"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/color_deliver"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/layoutBitrate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/layoutFrameRate">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debug_encode_bitrate"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/etBitrate"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="numberDecimal"
|
||||
android:singleLine="true"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/tvBitrate"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="6000" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tvBitrate"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_debug_bitrate"
|
||||
android:textColor="#303553"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@color/color_deliver"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
86
call_sw/src/main/res/layout/layout_statistic.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/statistic_bg"
|
||||
android:paddingHorizontal="20dp"
|
||||
android:paddingVertical="10dp">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/tvStatistic"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableEnd="@drawable/app_icon_switch"
|
||||
android:drawablePadding="2dp"
|
||||
android:text="@string/app_statistic"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/tlStatistic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvStatistic"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TableRow >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvEncodeDimensions"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
android:paddingVertical="3dp"
|
||||
tools:text="@string/app_statistic_dimensions" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvEncodeFrameRate"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
android:paddingVertical="3dp"
|
||||
tools:text="@string/app_statistic_frame_rate" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvEncodeBitrate"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
android:paddingVertical="3dp"
|
||||
tools:text="@string/app_statistic_bitrate" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvLocalUid"
|
||||
android:layout_weight="1"
|
||||
android:paddingVertical="3dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
tools:text="@string/app_local_uid" />
|
||||
</TableRow>
|
||||
|
||||
<TableRow >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPkChannels"
|
||||
android:layout_weight="1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"
|
||||
android:paddingVertical="3dp"
|
||||
tools:text="@string/app_pk_channels" />
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
6
call_sw/src/main/res/layout/layout_video_one.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/video_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/black_50"/>
|
||||
9
call_sw/src/main/res/layout/layout_video_two.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/video_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
5
call_sw/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
6
call_sw/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
call_sw/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
call_sw/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
call_sw/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
call_sw/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
call_sw/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
call_sw/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/guanduan_img.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/jietong_img.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/kaiqimaikefeng.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/kaiqiyangshengqi.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
call_sw/src/main/res/mipmap-xxhdpi/yangshengqi_img.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
call_sw/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
call_sw/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
3
call_sw/src/main/res/values-land/dimens.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">48dp</dimen>
|
||||
</resources>
|
||||
16
call_sw/src/main/res/values-night/themes.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.OneToOne" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_200</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/black</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
</resources>
|
||||
3
call_sw/src/main/res/values-w1240dp/dimens.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">200dp</dimen>
|
||||
</resources>
|
||||
3
call_sw/src/main/res/values-w600dp/dimens.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">48dp</dimen>
|
||||
</resources>
|
||||
106
call_sw/src/main/res/values-zh/strings.xml
Normal file
@@ -0,0 +1,106 @@
|
||||
<resources>
|
||||
<string name="app_name">遇聊</string>
|
||||
<string name="app_channel_name">频 道 号</string>
|
||||
<string name="app_role">角  色</string>
|
||||
<string name="app_input_channel">输入直播频道名</string>
|
||||
<string name="app_input_title_local_uid">当前的用户id</string>
|
||||
<string name="app_input_local_uid">输入当前的用uid</string>
|
||||
<string name="app_role_broadcaster">主播</string>
|
||||
<string name="app_role_audience">观众</string>
|
||||
<string name="app_join_channel">加入频道</string>
|
||||
<string name="app_debugging">Debug页面</string>
|
||||
<string name="app_debugging_title">开发者模式设置</string>
|
||||
<string name="app_debug_encode_dimensions">编码分辨率</string>
|
||||
<string name="app_debug_encode_frame_rate">编码帧率</string>
|
||||
<string name="app_debug_encode_bitrate">码率</string>
|
||||
<string name="app_debug_x">x</string>
|
||||
<string name="app_debug_frame_rate">fps</string>
|
||||
<string name="app_debug_bitrate">kbps</string>
|
||||
<string name="app_confirm">确认</string>
|
||||
<string name="app_pk_channel">对端频道</string>
|
||||
<string name="app_update_pk_channel">更新对端频道号</string>
|
||||
<string name="app_quit_channel">退出</string>
|
||||
<string name="app_statistic">实时数据</string>
|
||||
<string name="app_statistic_dimensions">编码分辨率: %s</string>
|
||||
<string name="app_statistic_frame_rate">编码帧率: %s fps</string>
|
||||
<string name="app_statistic_bitrate">编码码率: %s Kbps</string>
|
||||
<string name="app_pk_channels">对端频道:%s</string>
|
||||
<string name="app_local_uid">UID:%s</string>
|
||||
<string name="app_main_channel_empty">加入的频道不能为空</string>
|
||||
|
||||
<!-- Radio Buttons -->
|
||||
<string name="radio_rtm_show_1v1">RTM秀转场1V1</string>
|
||||
<string name="radio_rtm_pure_1v1">RTM纯1V1</string>
|
||||
<string name="radio_easemob_show_1v1">环信秀转场1V1</string>
|
||||
<string name="radio_easemob_pure_1v1">环信纯1V1</string>
|
||||
|
||||
<!-- Input Fields -->
|
||||
<string name="input_broadcaster_id">主播id</string>
|
||||
<string name="input_broadcaster_id_hint">输入主播id</string>
|
||||
|
||||
<!-- Checkboxes -->
|
||||
<string name="checkbox_auto_accept">收到呼叫自动接受</string>
|
||||
<string name="checkbox_first_frame">音视频首帧与接通相关</string>
|
||||
<string name="checkbox_join_rtc">提前加入RTC频道</string>
|
||||
|
||||
<!-- Toast Messages -->
|
||||
<string name="toast_no_im_app_key">未配置IM_APP_KEY</string>
|
||||
<string name="toast_user_id_empty">用户id不能为空</string>
|
||||
<string name="toast_local_user_id_number">本地用户的id需要是纯数字</string>
|
||||
<string name="toast_both_user_id_number">本地和远端用户的id需要是纯数字</string>
|
||||
<string name="toast_get_token_failed">get token failed</string>
|
||||
|
||||
<!-- Button Text -->
|
||||
<string name="btn_create_show_to_1v1">创建秀场转1v1</string>
|
||||
<string name="btn_join_show_to_1v1">加入秀场转1v1</string>
|
||||
<string name="btn_enter_pure_1v1">进入纯1v1</string>
|
||||
|
||||
<!-- Channel -->
|
||||
<string name="app_current_channel">当前频道: %s</string>
|
||||
<string name="label_current_user_id">当前用户id:%1$s</string>
|
||||
|
||||
<!-- Call Type Dialog -->
|
||||
<string name="call_type_dialog_title">通话类型选择</string>
|
||||
<string name="call_type_dialog_message">选择音频或视频通话</string>
|
||||
<string name="call_type_audio">音频</string>
|
||||
<string name="call_type_video">视频</string>
|
||||
|
||||
<!-- Alert Dialog -->
|
||||
<string name="alert_title">提示</string>
|
||||
<string name="alert_calling_user">呼叫用户 %d 中</string>
|
||||
<string name="alert_cancel">取消</string>
|
||||
<string name="alert_incoming_call">用户 %1$d 邀请您1对1通话</string>
|
||||
<string name="alert_accept">同意</string>
|
||||
<string name="alert_reject">拒绝</string>
|
||||
|
||||
<!-- Toast Messages -->
|
||||
<string name="toast_no_permission">没给权限😯</string>
|
||||
<string name="toast_call_api_initializing">CallAPi初始化中</string>
|
||||
<string name="toast_no_target_user">无目标用户</string>
|
||||
<string name="toast_rtm_connected">rtm已连接</string>
|
||||
<string name="toast_rtm_disconnected">rtm已断开</string>
|
||||
<string name="toast_easemob_connected">环信已连接</string>
|
||||
<string name="toast_easemob_disconnected">环信已断开</string>
|
||||
<string name="toast_rtm_not_logged_in">rtm未登录或连接异常</string>
|
||||
<string name="toast_easemob_not_logged_in">环信未登录或连接异常</string>
|
||||
<string name="toast_call_started">通话开始%s</string>
|
||||
<string name="toast_call_ended">通话结束</string>
|
||||
<string name="toast_call_rejected">通话被拒绝</string>
|
||||
<string name="toast_no_answer">无应答</string>
|
||||
<string name="toast_user_busy">用户正忙</string>
|
||||
|
||||
<!-- Call Status -->
|
||||
<string name="call_status_start">通话开始,\nRTC 频道号: %1$s,\n主叫用户id: %2$d,\n当前用户id: %3$d,\n开始时间戳: %4$d ms</string>
|
||||
<string name="call_status_end">通话结束,\nRTC 频道号: %1$s,\n挂断用户id: %2$d,\n当前用户id: %3$d,\n结束时间戳: %4$d ms,\n通话时长: %5$d ms</string>
|
||||
|
||||
<!-- Pure 1v1 Activity -->
|
||||
<string name="pure_1v1_target_uid">目标用户uid</string>
|
||||
<string name="pure_1v1_target_uid_hint">输入目标用户uid</string>
|
||||
<string name="pure_1v1_current_uid">当前用户id</string>
|
||||
<string name="pure_1v1_invite">邀请</string>
|
||||
<string name="pure_1v1_hangup">挂断</string>
|
||||
<string name="pure_1v1_video_on">开启视频</string>
|
||||
<string name="pure_1v1_video_off">关闭视频</string>
|
||||
<string name="pure_1v1_audio_on">开启音频</string>
|
||||
<string name="pure_1v1_audio_off">关闭音频</string>
|
||||
</resources>
|
||||
29
call_sw/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF7800FF</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="color_deliver">#EFEFEF</color>
|
||||
<color name="black_10">#1A000000</color>
|
||||
<color name="black_15">#26000000</color>
|
||||
<color name="black_20">#33000000</color>
|
||||
<color name="black_25">#40000000</color>
|
||||
<color name="black_30">#4D000000</color>
|
||||
<color name="black_35">#59000000</color>
|
||||
<color name="black_40">#66000000</color>
|
||||
<color name="black_45">#73000000</color>
|
||||
<color name="black_50">#80000000</color>
|
||||
<color name="black_55">#8C000000</color>
|
||||
<color name="black_60">#99000000</color>
|
||||
<color name="black_65">#A6000000</color>
|
||||
<color name="black_70">#B3000000</color>
|
||||
<color name="black_75">#BF000000</color>
|
||||
<color name="black_80">#CC000000</color>
|
||||
<color name="black_85">#D9000000</color>
|
||||
<color name="black_90">#E6000000</color>
|
||||
<color name="black_95">#F2000000</color>
|
||||
</resources>
|
||||
3
call_sw/src/main/res/values/dimens.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
||||
106
call_sw/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,106 @@
|
||||
<resources>
|
||||
<string name="app_name">OneToOne</string>
|
||||
<string name="app_channel_name">Channel Number</string>
|
||||
<string name="app_role">Role</string>
|
||||
<string name="app_input_channel">Enter Live Channel Name</string>
|
||||
<string name="app_input_title_local_uid">Current User ID</string>
|
||||
<string name="app_input_local_uid">Enter Current User UID</string>
|
||||
<string name="app_role_broadcaster">Broadcaster</string>
|
||||
<string name="app_role_audience">Audience</string>
|
||||
<string name="app_join_channel">Join Channel</string>
|
||||
<string name="app_debugging">Debug Page</string>
|
||||
<string name="app_debugging_title">Developer Mode Settings</string>
|
||||
<string name="app_debug_encode_dimensions">Encoding Resolution</string>
|
||||
<string name="app_debug_encode_frame_rate">Encoding Frame Rate</string>
|
||||
<string name="app_debug_encode_bitrate">Bitrate</string>
|
||||
<string name="app_debug_x">x</string>
|
||||
<string name="app_debug_frame_rate">fps</string>
|
||||
<string name="app_debug_bitrate">kbps</string>
|
||||
<string name="app_confirm">Confirm</string>
|
||||
<string name="app_pk_channel">Peer Channel</string>
|
||||
<string name="app_update_pk_channel">Update Peer Channel Number</string>
|
||||
<string name="app_quit_channel">Exit</string>
|
||||
<string name="app_statistic">Real-time Data</string>
|
||||
<string name="app_statistic_dimensions">Encoding Resolution: %s</string>
|
||||
<string name="app_statistic_frame_rate">Encoding Frame Rate: %s fps</string>
|
||||
<string name="app_statistic_bitrate">Encoding Bitrate: %s Kbps</string>
|
||||
<string name="app_pk_channels">Peer Channel: %s</string>
|
||||
<string name="app_local_uid">UID: %s</string>
|
||||
<string name="app_main_channel_empty">Joined channel cannot be empty</string>
|
||||
|
||||
<!-- Radio Buttons -->
|
||||
<string name="radio_rtm_show_1v1">RTM Show to 1v1</string>
|
||||
<string name="radio_rtm_pure_1v1">RTM Pure 1v1</string>
|
||||
<string name="radio_easemob_show_1v1">Easemob Show to 1v1</string>
|
||||
<string name="radio_easemob_pure_1v1">Easemob Pure 1v1</string>
|
||||
|
||||
<!-- Input Fields -->
|
||||
<string name="input_broadcaster_id">Broadcaster ID</string>
|
||||
<string name="input_broadcaster_id_hint">Enter broadcaster ID</string>
|
||||
|
||||
<!-- Checkboxes -->
|
||||
<string name="checkbox_auto_accept">Auto accept incoming calls</string>
|
||||
<string name="checkbox_first_frame">First frame related to connection</string>
|
||||
<string name="checkbox_join_rtc">Join RTC channel in advance</string>
|
||||
|
||||
<!-- Toast Messages -->
|
||||
<string name="toast_no_im_app_key">IM_APP_KEY not configured</string>
|
||||
<string name="toast_user_id_empty">User ID cannot be empty</string>
|
||||
<string name="toast_local_user_id_number">Local user ID must be numeric</string>
|
||||
<string name="toast_both_user_id_number">Both local and remote user IDs must be numeric</string>
|
||||
<string name="toast_get_token_failed">Get token failed</string>
|
||||
|
||||
<!-- Button Text -->
|
||||
<string name="btn_create_show_to_1v1">Create Show to 1v1</string>
|
||||
<string name="btn_join_show_to_1v1">Join Show to 1v1</string>
|
||||
<string name="btn_enter_pure_1v1">Enter Pure 1v1</string>
|
||||
|
||||
<!-- Channel -->
|
||||
<string name="app_current_channel">Current Channel: %s</string>
|
||||
<string name="label_current_user_id">Current User ID: %1$s</string>
|
||||
|
||||
<!-- Call Type Dialog -->
|
||||
<string name="call_type_dialog_title">Call Type Selection</string>
|
||||
<string name="call_type_dialog_message">Select audio or video call</string>
|
||||
<string name="call_type_audio">Audio</string>
|
||||
<string name="call_type_video">Video</string>
|
||||
|
||||
<!-- Alert Dialog -->
|
||||
<string name="alert_title">Notice</string>
|
||||
<string name="alert_calling_user">Calling user %d</string>
|
||||
<string name="alert_cancel">Cancel</string>
|
||||
<string name="alert_incoming_call">User %1$d invites you to 1-on-1 call</string>
|
||||
<string name="alert_accept">Accept</string>
|
||||
<string name="alert_reject">Reject</string>
|
||||
|
||||
<!-- Toast Messages -->
|
||||
<string name="toast_no_permission">No permission granted 😯</string>
|
||||
<string name="toast_call_api_initializing">CallAPI Initializing</string>
|
||||
<string name="toast_no_target_user">No Target User</string>
|
||||
<string name="toast_rtm_connected">RTM connected</string>
|
||||
<string name="toast_rtm_disconnected">RTM disconnected</string>
|
||||
<string name="toast_easemob_connected">Easemob Client Connected</string>
|
||||
<string name="toast_easemob_disconnected">Easemob Client Disconnected</string>
|
||||
<string name="toast_rtm_not_logged_in">RTM not logged in or connection abnormal</string>
|
||||
<string name="toast_easemob_not_logged_in">Easemob not logged in or connection abnormal</string>
|
||||
<string name="toast_call_started">Call started %s</string>
|
||||
<string name="toast_call_ended">Call ended</string>
|
||||
<string name="toast_call_rejected">Call rejected</string>
|
||||
<string name="toast_no_answer">No answer</string>
|
||||
<string name="toast_user_busy">User is busy</string>
|
||||
|
||||
<!-- Call Status -->
|
||||
<string name="call_status_start">Call started,\nRTC Channel: %1$s,\nCaller ID: %2$d,\nCurrent User ID: %3$d,\nStart Timestamp: %4$d ms</string>
|
||||
<string name="call_status_end">Call ended,\nRTC Channel: %1$s,\nHangup User ID: %2$d,\nCurrent User ID: %3$d,\nEnd Timestamp: %4$d ms,\nDuration: %5$d ms</string>
|
||||
|
||||
<!-- Pure 1v1 Activity -->
|
||||
<string name="pure_1v1_target_uid">Target User ID</string>
|
||||
<string name="pure_1v1_target_uid_hint">Enter target user ID</string>
|
||||
<string name="pure_1v1_current_uid">Current User ID</string>
|
||||
<string name="pure_1v1_invite">Invite 1v1</string>
|
||||
<string name="pure_1v1_hangup">Hangup 1v1</string>
|
||||
<string name="pure_1v1_video_on">Video On</string>
|
||||
<string name="pure_1v1_video_off">Video Off</string>
|
||||
<string name="pure_1v1_audio_on">Audio On</string>
|
||||
<string name="pure_1v1_audio_off">Audio Off</string>
|
||||
</resources>
|
||||
40
call_sw/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Theme.OneToOne" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||
<!-- Primary brand color. -->
|
||||
<item name="colorPrimary">@color/purple_500</item>
|
||||
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||
<item name="colorOnPrimary">@color/white</item>
|
||||
<!-- Secondary brand color. -->
|
||||
<item name="colorSecondary">@color/teal_200</item>
|
||||
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.OneToOne.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.OneToOne.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="Theme.OneToOne.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
|
||||
|
||||
<declare-styleable name="CircleImageView">
|
||||
<attr name="ease_border_color" format="color" />
|
||||
<attr name="ease_border_width" format="dimension" />
|
||||
<attr name="ease_press_alpha" format="integer" />
|
||||
<attr name="ease_press_color" format="color" />
|
||||
<attr name="ease_radius" format="dimension" />
|
||||
<attr name="es_shape_type" format="enum">
|
||||
<enum name="none" value="0" />
|
||||
<enum name="round" value="1" />
|
||||
<enum name="rectangle" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
13
call_sw/src/main/res/xml/backup_rules.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample backup rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/guide/topics/data/autobackup
|
||||
for details.
|
||||
Note: This file is ignored for devices older that API 31
|
||||
See https://developer.android.com/about/versions/12/backup-restore
|
||||
-->
|
||||
<full-backup-content>
|
||||
<!--
|
||||
<include domain="sharedpref" path="."/>
|
||||
<exclude domain="sharedpref" path="device.xml"/>
|
||||
-->
|
||||
</full-backup-content>
|
||||
19
call_sw/src/main/res/xml/data_extraction_rules.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
Sample data extraction rules file; uncomment and customize as necessary.
|
||||
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
|
||||
for details.
|
||||
-->
|
||||
<data-extraction-rules>
|
||||
<cloud-backup>
|
||||
<!-- TODO: Use <include> and <exclude> to control what is backed up.
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
-->
|
||||
</cloud-backup>
|
||||
<!--
|
||||
<device-transfer>
|
||||
<include .../>
|
||||
<exclude .../>
|
||||
</device-transfer>
|
||||
-->
|
||||
</data-extraction-rules>
|
||||
17
call_sw/src/test/java/io/agora/onetoone/ExampleUnitTest.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package io.agora.onetoone
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||