11package com.omegar.libs.testconnect
22
3+ import android.annotation.SuppressLint
4+ import android.app.Activity
35import android.content.Context
46import android.content.pm.PackageInfo
57import android.content.pm.PackageManager.NameNotFoundException
@@ -10,6 +12,7 @@ import android.net.Uri
1012import android.os.Build
1113import android.os.Build.VERSION
1214import android.os.Build.VERSION_CODES
15+ import android.provider.Settings
1316import android.view.View
1417import com.omegar.libs.testconnect.SocketClient.Callback
1518import kotlinx.coroutines.CoroutineScope
@@ -47,7 +50,26 @@ internal object TestConnector : Callback, CoroutineScope {
4750
4851 private val Context .deviceName: String
4952 get() = Build .MANUFACTURER .replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale .ROOT ) else it.toString() } +
50- " " + Build .MODEL
53+ " " + Build .MODEL +
54+ " Android " + Build .VERSION .RELEASE + " (API " + Build .VERSION .SDK_INT + " )" +
55+ userDeviceName?.let { " - $it " }?.replace(' :' , ' -' ).orEmpty()
56+
57+ private val Context .userDeviceName: String?
58+ get() = try {
59+ (if (VERSION .SDK_INT >= VERSION_CODES .N_MR1 ) {
60+ Settings .Global .getString(contentResolver, Settings .Global .DEVICE_NAME )
61+ } else {
62+ null
63+ }) ? : run {
64+ Settings .System .getString(contentResolver, " device_name" )
65+ } ? : run {
66+ Settings .Secure .getString(contentResolver, " bluetooth_name" )
67+ } ? : run {
68+ Settings .System .getString(contentResolver, " bluetooth_name" )
69+ }
70+ } catch (e: Throwable ) {
71+ null
72+ }
5173
5274 private val Context .appVersion: String
5375 get() {
@@ -63,7 +85,7 @@ internal object TestConnector : Callback, CoroutineScope {
6385 }
6486
6587 fun init (context : Context ) {
66- context.getServerAddress()?.let {serverAddress ->
88+ context.getServerAddress()?.let { serverAddress ->
6789 logCatcher = LogCatcher ()
6890 socketClient = SocketClient (
6991 url = serverAddress,
@@ -111,22 +133,48 @@ internal object TestConnector : Callback, CoroutineScope {
111133 activityCatcher
112134 ?.flow
113135 ?.value
114- ?.window
115- ?.decorView
116- ?.takeScreen()
136+ .getAllViews()
137+ .takeScreen()
117138 ?.let {
118139 socketClient.sendScreenshot(it)
119140 it.recycle()
120141 }
121142 }
122143 }
123144
124- private fun View.takeScreen (): Bitmap ? = runBlocking(Dispatchers .Main ) {
145+ @SuppressLint(" PrivateApi" )
146+ private fun Activity?.getAllViews (): List <View > {
147+ return try {
148+ val wmgClass = Class .forName(" android.view.WindowManagerGlobal" )
149+ val wmgInstance = wmgClass.getMethod(" getInstance" ).invoke(null )
150+ val getViewRootNames = wmgClass.getMethod(" getViewRootNames" )
151+ val getRootView = wmgClass.getMethod(" getRootView" , String ::class .java)
152+ val rootViewNames = getViewRootNames.invoke(wmgInstance) as Array <* >
153+ rootViewNames.mapNotNull { viewName ->
154+ getRootView.invoke(wmgInstance, viewName) as ? View
155+ }
156+ } catch (e: Throwable ) {
157+ e.printStackTrace()
158+ this ?.window?.decorView?.let { listOf (it) } ? : emptyList()
159+ }
160+ }
161+
162+ private fun List<View>.takeScreen (): Bitmap ? = runBlocking(Dispatchers .Main ) {
163+ if (isEmpty()) return @runBlocking null
125164 try {
126- val bitmap = Bitmap .createBitmap(width, height, Bitmap .Config .ARGB_8888 )
165+ val firstView = first()
166+ val bitmap = Bitmap .createBitmap(firstView.width, firstView.height, Bitmap .Config .ARGB_8888 )
127167 val canvas = Canvas (bitmap)
128168 canvas.drawColor(Color .WHITE )
129- draw(canvas)
169+ val locationOfViewInWindow = IntArray (2 )
170+
171+ forEach {
172+ it.getLocationOnScreen(locationOfViewInWindow)
173+ val saveCount = canvas.save()
174+ canvas.translate(locationOfViewInWindow[0 ].toFloat(), locationOfViewInWindow[1 ].toFloat())
175+ it.draw(canvas)
176+ canvas.restoreToCount(saveCount)
177+ }
130178 bitmap
131179 } catch (e: Throwable ) {
132180 e.printStackTrace()
0 commit comments