Compare commits
4 Commits
Author | SHA1 | Date |
---|---|---|
|
f3021f7588 | |
|
f6d877403f | |
|
6052a5e728 | |
|
6044cda511 |
|
@ -13,3 +13,7 @@
|
|||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
.idea
|
||||
.idea/*
|
||||
.gitignore
|
||||
.idea/*
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="resolveExternalAnnotations" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
549
.idea/other.xml
549
.idea/other.xml
|
@ -1,549 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="direct_access_persist.xml">
|
||||
<option name="deviceSelectionList">
|
||||
<list>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="27" />
|
||||
<option name="brand" value="DOCOMO" />
|
||||
<option name="codename" value="F01L" />
|
||||
<option name="id" value="F01L" />
|
||||
<option name="manufacturer" value="FUJITSU" />
|
||||
<option name="name" value="F-01L" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1280" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="OnePlus" />
|
||||
<option name="codename" value="OP5552L1" />
|
||||
<option name="id" value="OP5552L1" />
|
||||
<option name="manufacturer" value="OnePlus" />
|
||||
<option name="name" value="CPH2415" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2412" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="OPPO" />
|
||||
<option name="codename" value="OP573DL1" />
|
||||
<option name="id" value="OP573DL1" />
|
||||
<option name="manufacturer" value="OPPO" />
|
||||
<option name="name" value="CPH2557" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="28" />
|
||||
<option name="brand" value="DOCOMO" />
|
||||
<option name="codename" value="SH-01L" />
|
||||
<option name="id" value="SH-01L" />
|
||||
<option name="manufacturer" value="SHARP" />
|
||||
<option name="name" value="AQUOS sense2 SH-01L" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2160" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="Lenovo" />
|
||||
<option name="codename" value="TB370FU" />
|
||||
<option name="id" value="TB370FU" />
|
||||
<option name="manufacturer" value="Lenovo" />
|
||||
<option name="name" value="Tab P12" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1840" />
|
||||
<option name="screenY" value="2944" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a15" />
|
||||
<option name="id" value="a15" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A15" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a35x" />
|
||||
<option name="id" value="a35x" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="A35" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="31" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="a51" />
|
||||
<option name="id" value="a51" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy A51" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="akita" />
|
||||
<option name="id" value="akita" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="arcfox" />
|
||||
<option name="id" value="arcfox" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="razr plus 2024" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="1272" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="austin" />
|
||||
<option name="id" value="austin" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g 5G (2022)" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="b0q" />
|
||||
<option name="id" value="b0q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S22 Ultra" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3088" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="32" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="bluejay" />
|
||||
<option name="id" value="bluejay" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 6a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="caiman" />
|
||||
<option name="id" value="caiman" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="960" />
|
||||
<option name="screenY" value="2142" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="comet" />
|
||||
<option name="id" value="comet" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro Fold" />
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="2076" />
|
||||
<option name="screenY" value="2152" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="29" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="crownqlteue" />
|
||||
<option name="id" value="crownqlteue" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Note9" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2220" />
|
||||
<option name="screenY" value="1080" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="dm2q" />
|
||||
<option name="id" value="dm2q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="S23 Plus" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="dm3q" />
|
||||
<option name="id" value="dm3q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S23 Ultra" />
|
||||
<option name="screenDensity" value="600" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3088" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="e1q" />
|
||||
<option name="id" value="e1q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S24" />
|
||||
<option name="screenDensity" value="480" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="e3q" />
|
||||
<option name="id" value="e3q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S24 Ultra" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="3120" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="eos" />
|
||||
<option name="id" value="eos" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Eos" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="384" />
|
||||
<option name="screenY" value="384" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="felix" />
|
||||
<option name="id" value="felix" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Fold" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2208" />
|
||||
<option name="screenY" value="1840" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="felix" />
|
||||
<option name="id" value="felix" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Fold" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2208" />
|
||||
<option name="screenY" value="1840" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="felix_camera" />
|
||||
<option name="id" value="felix_camera" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Fold (Camera-enabled)" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="2208" />
|
||||
<option name="screenY" value="1840" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="fogona" />
|
||||
<option name="id" value="fogona" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g play - 2024" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="g0q" />
|
||||
<option name="id" value="g0q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S906U1" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gta9pwifi" />
|
||||
<option name="id" value="gta9pwifi" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-X210" />
|
||||
<option name="screenDensity" value="240" />
|
||||
<option name="screenX" value="1200" />
|
||||
<option name="screenY" value="1920" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts7xllite" />
|
||||
<option name="id" value="gts7xllite" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-T738U" />
|
||||
<option name="screenDensity" value="340" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts8uwifi" />
|
||||
<option name="id" value="gts8uwifi" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Tab S8 Ultra" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="1848" />
|
||||
<option name="screenY" value="2960" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts8wifi" />
|
||||
<option name="id" value="gts8wifi" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Tab S8" />
|
||||
<option name="screenDensity" value="274" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="gts9fe" />
|
||||
<option name="id" value="gts9fe" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Tab S9 FE 5G" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="1440" />
|
||||
<option name="screenY" value="2304" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="husky" />
|
||||
<option name="id" value="husky" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8 Pro" />
|
||||
<option name="screenDensity" value="390" />
|
||||
<option name="screenX" value="1008" />
|
||||
<option name="screenY" value="2244" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="java" />
|
||||
<option name="id" value="java" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="G20" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="komodo" />
|
||||
<option name="id" value="komodo" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9 Pro XL" />
|
||||
<option name="screenDensity" value="360" />
|
||||
<option name="screenX" value="1008" />
|
||||
<option name="screenY" value="2244" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="lynx" />
|
||||
<option name="id" value="lynx" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 7a" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="motorola" />
|
||||
<option name="codename" value="maui" />
|
||||
<option name="id" value="maui" />
|
||||
<option name="manufacturer" value="Motorola" />
|
||||
<option name="name" value="moto g play - 2023" />
|
||||
<option name="screenDensity" value="280" />
|
||||
<option name="screenX" value="720" />
|
||||
<option name="screenY" value="1600" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="o1q" />
|
||||
<option name="id" value="o1q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21" />
|
||||
<option name="screenDensity" value="421" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="31" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="oriole" />
|
||||
<option name="id" value="oriole" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 6" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="panther" />
|
||||
<option name="id" value="panther" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 7" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="q5q" />
|
||||
<option name="id" value="q5q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Z Fold5" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1812" />
|
||||
<option name="screenY" value="2176" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="q6q" />
|
||||
<option name="id" value="q6q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy Z Fold6" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1856" />
|
||||
<option name="screenY" value="2160" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="r11" />
|
||||
<option name="id" value="r11" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Watch" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="384" />
|
||||
<option name="screenY" value="384" />
|
||||
<option name="type" value="WEAR_OS" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="r11q" />
|
||||
<option name="id" value="r11q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="SM-S711U" />
|
||||
<option name="screenDensity" value="450" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="30" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="redfin" />
|
||||
<option name="id" value="redfin" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 5" />
|
||||
<option name="screenDensity" value="440" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2340" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="shiba" />
|
||||
<option name="id" value="shiba" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 8" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="samsung" />
|
||||
<option name="codename" value="t2q" />
|
||||
<option name="id" value="t2q" />
|
||||
<option name="manufacturer" value="Samsung" />
|
||||
<option name="name" value="Galaxy S21 Plus" />
|
||||
<option name="screenDensity" value="394" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2400" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="33" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tangorpro" />
|
||||
<option name="id" value="tangorpro" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel Tablet" />
|
||||
<option name="screenDensity" value="320" />
|
||||
<option name="screenX" value="1600" />
|
||||
<option name="screenY" value="2560" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="34" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
</PersistentDeviceSelectionData>
|
||||
<PersistentDeviceSelectionData>
|
||||
<option name="api" value="35" />
|
||||
<option name="brand" value="google" />
|
||||
<option name="codename" value="tokay" />
|
||||
<option name="id" value="tokay" />
|
||||
<option name="manufacturer" value="Google" />
|
||||
<option name="name" value="Pixel 9" />
|
||||
<option name="screenDensity" value="420" />
|
||||
<option name="screenX" value="1080" />
|
||||
<option name="screenY" value="2424" />
|
||||
</PersistentDeviceSelectionData>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
|
@ -1,333 +1,336 @@
|
|||
package com.example.mrtcdemo
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import cn.migu.tsg.MRTCEngine
|
||||
import cn.migu.tsg.MRTCAdapter
|
||||
import cn.migu.tsg.MRTCVideoFrame
|
||||
import cn.migu.tsg.OnMRTCSDKListener
|
||||
import cn.migu.tsg.RoomListener
|
||||
import com.example.mrtcdemo.ui.theme.MRTCDemoTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
// 权限请求回调
|
||||
private val permissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
) { permissions ->
|
||||
if (permissions.all { it.value }) {
|
||||
// 所有权限已授予,开始加载SDK
|
||||
} else {
|
||||
// 处理权限被拒绝的情况
|
||||
showToast("权限被拒绝,功能将受限")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
// 请求必要权限
|
||||
requestPermissions()
|
||||
|
||||
setContent {
|
||||
MRTCDemoTheme {
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||
Greeting(
|
||||
name = "Android",
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestPermissions() {
|
||||
permissionLauncher.launch(
|
||||
arrayOf(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.INTERNET,
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var applicationId_ = "1357389261426393088"
|
||||
var mAppSecrectKey_ = "gytr3qrrznsgac2lbdchfg0l4ltqx4x3nf4my0yt1dbx7riz1gnnsnhblrlc2j4o1lx4vdu495lifv8s7jyrmfxtq9lif9rusxnur5smdn5cjopstxp5dim7p52xrezp"
|
||||
var domain_ = "rtc.migu.cn"
|
||||
var mPort_ = 34443
|
||||
var srcUserId_ = "srcUser12"
|
||||
var destUserId_ = "destUser12"
|
||||
|
||||
var srcDisplayName_ = "srcDisplayName12"
|
||||
var destDisplayName_ = "destDisplayName12"
|
||||
var srcRoomId_ = "srcRoom12"
|
||||
var destRoomId_ = srcRoomId_
|
||||
var srcChannelIndex_ = 46
|
||||
var destChannelIndex_ = 47
|
||||
var sampleRate_ = 16000
|
||||
var channelNum_ = 1
|
||||
var isOnRoom_ = false
|
||||
var isOnConsumer_ = false
|
||||
|
||||
|
||||
private val audioListener_ = object : MRTCAdapter.MRTCAudioProcessListener {
|
||||
override fun onReceiveRawAudioFrame(streamId: String, userId: String, frame: MRTCAdapter.MRTCAudioFrame) {
|
||||
// 在这里处理原始音频帧
|
||||
println("MRTCDEBUG ==================================")
|
||||
println("MRTCDEBUG streamId=$streamId, userId=$userId")
|
||||
println("MRTCDEBUG frame, channel=${frame.channel}, length=${frame.length}, sampleRate=${frame.sampleRate}")
|
||||
println(frame.audioBuffer)
|
||||
}
|
||||
}
|
||||
private val sdkListener_ = object : OnMRTCSDKListener {
|
||||
override fun onRoom(type: Int, roomInfo: MRTCAdapter.MRTCRoomInfo) {
|
||||
println("MRTCDEBUG 房间状态变化: type=$type, roomId=${roomInfo.roomId}")
|
||||
println("MRTCDEBUG RTCContext::onRoom()")
|
||||
isOnRoom_ = true
|
||||
}
|
||||
|
||||
override fun onRTMRoom(p0: Int, p1: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onProducer(p0: Int, p1: MRTCAdapter.MRTCProducerInfo?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onConsumer(msgId: Int, roomId: String?, peerId: String?, p3: Any?) {
|
||||
println("MRTCDEBUG onConsumer, msgId:$msgId, roomId:$roomId, peerId:$peerId")
|
||||
isOnConsumer_ = true
|
||||
MRTCEngine.getDefault().registerSoundLevelListener(MRTCAdapter.MRTCAudioSourceType.TYPE_AUDIO_SOURCE_CUSTOM,
|
||||
roomId, peerId, srcChannelIndex_)
|
||||
var ret = MRTCEngine.getDefault().muteAudio(roomId, peerId, MRTCAdapter.MRTCAudioSourceType.TYPE_AUDIO_SOURCE_CUSTOM.type,
|
||||
false, srcChannelIndex_)
|
||||
if (ret != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().muteAudio() failed, ret:$ret")
|
||||
return
|
||||
}
|
||||
println("MRTCDEBUG init recv succ")
|
||||
|
||||
}
|
||||
|
||||
override fun callBackMessage(code: Int, msg: String) {
|
||||
println("MRTCDEBUG callBackMessage: [$code] $msg")
|
||||
}
|
||||
|
||||
override fun onCustomData(p0: MRTCAdapter.MRTCCustomData?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onDataProducer(p0: Int, p1: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onDataConsumer(p0: Int, p1: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onMessager(p0: String?, p1: String?, p2: String?, p3: String?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onRender(p0: String?, p1: String?, p2: Int, p3: Int, p4: MRTCVideoFrame?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onScreenShot(p0: Bitmap?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onLocalAudioStats(p0: MRTCAdapter.MRTCLocalAudioStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onLocalVideoStats(p0: MRTCAdapter.MRTCLocalVideoStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onRemoteAudioStats(p0: MRTCAdapter.MRTCRemoteAudioStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onRemoteVideoStats(p0: MRTCAdapter.MRTCRemoteVideoStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onSoundLevelUpdate(p0: String?, p1: String?, p2: Int, p3: Int, p4: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
private fun initMRTCEngine() : Boolean {
|
||||
println("MRTCDEBUG initMRTCEngine=======================")
|
||||
|
||||
val config = MRTCAdapter.Config().apply {
|
||||
// 设置必要参数(根据SDK文档补充)
|
||||
applicationId = applicationId_
|
||||
mAppSecrectKey = mAppSecrectKey_
|
||||
domain = domain_
|
||||
mPort = mPort_
|
||||
}
|
||||
|
||||
var ret1 = MRTCEngine.getDefault().init(config, this)
|
||||
if (ret1 != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().init() failed, ret:$ret1")
|
||||
return false
|
||||
}
|
||||
var roomListener = RoomListener()
|
||||
roomListener.setOnDorySDKListener(sdkListener_)
|
||||
MRTCEngine.getDefault().setUserInfo(srcUserId_,srcDisplayName_,srcRoomId_)
|
||||
var loginConfig = MRTCAdapter.LoginConfigParams().apply {
|
||||
mAppId = applicationId_
|
||||
mAppSecrectKey = mAppSecrectKey_
|
||||
}
|
||||
var ret2 = MRTCEngine.getDefault().joinRoom(loginConfig)
|
||||
if (ret2 != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().joinRoom() failed, ret:$ret2")
|
||||
return false
|
||||
}
|
||||
|
||||
MRTCEngine.getDefault().registerListener(MRTCAdapter.MRTCListenerType.TYPE_LISTENER_ROOM)
|
||||
MRTCEngine.getDefault().registerListener(MRTCAdapter.MRTCListenerType.TYPE_LISTENER_CONSUMER)
|
||||
|
||||
MRTCEngine.getDefault().registerReceivedMicAudioFrameListener(audioListener_)
|
||||
println("MRTCDEBUG init succ")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun initSendMRTCEngine() : Boolean {
|
||||
while (!isOnRoom_)
|
||||
{
|
||||
println("MRTCDEBUG wait for OnRoom")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
|
||||
println("MRTCDEBUG initSendMRTCEngine=======================")
|
||||
val option = MRTCAdapter.MRTCAudioOption().apply {
|
||||
// 修改需要自定义的参数
|
||||
sampleRate = sampleRate_
|
||||
channel = 1 // 改为立体声
|
||||
channelIndex = destChannelIndex_
|
||||
echoCancellation = true // 开启回声消除
|
||||
}
|
||||
var ret = MRTCEngine.getDefault().startCustomAudio(option)
|
||||
if (ret != 0) {
|
||||
println("MRTCDEBUG startCustomAudio fail, ret:$ret")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG init send succ")
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
private fun initRecvMRTCEngine() : Boolean {
|
||||
println("MRTCDEBUG initRecvMRTCEngine=======================")
|
||||
while (!isOnConsumer_)
|
||||
{
|
||||
println("MRTCDEBUG wait for OnConsumer")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
private fun sendCustomAudioData(data :ByteArray, dataLength :Int) : Boolean {
|
||||
while(!isOnRoom_) {
|
||||
println("MRTCDEBUG wait for room and multi room before send")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
if (data == null) {
|
||||
println("MRTCDEBUG customData is null")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG sendAudioData=======================")
|
||||
MRTCEngine.getDefault().sendCustomAudioData(data, sampleRate_, channelNum_, dataLength)
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun showToast(message: String) {
|
||||
// 实现Toast显示
|
||||
println("MRTCDEBUG showToast: $message")
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
val isSDKReady = remember { mutableStateOf(false) }
|
||||
var ret1 = initMRTCEngine()
|
||||
if (!ret1) {
|
||||
println("MRTCDEBUG init fail, ret:$ret1")
|
||||
return
|
||||
}
|
||||
var ret2 = initSendMRTCEngine()
|
||||
if (!ret2) {
|
||||
println("MRTCDEBUG initSend fail, ret:$ret2")
|
||||
return
|
||||
}
|
||||
var ret3 = initRecvMRTCEngine()
|
||||
if (!ret3) {
|
||||
println("MRTCDEBUG initRecv fail, ret:$ret3")
|
||||
return
|
||||
}
|
||||
|
||||
val data: ByteArray = "Hello".toByteArray(Charsets.UTF_8)
|
||||
val dataLength: Int = data.size
|
||||
for (i in 1..100) {
|
||||
println("MRTCDEBUG 第${i}次循环")
|
||||
// 执行您的业务逻辑
|
||||
|
||||
var ret4 = sendCustomAudioData(data, dataLength)
|
||||
if (!ret4) {
|
||||
println("MRTCDEBUG send fail, ret:$ret3")
|
||||
return
|
||||
}
|
||||
Thread.sleep(3000)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 监听SDK状态
|
||||
LaunchedEffect(Unit) {
|
||||
// 这里可以添加SDK状态监听逻辑
|
||||
}
|
||||
|
||||
Text(
|
||||
text = if (isSDKReady.value) "Hello $name! (SDK Ready)" else "Loading SDK1...",
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
println("MRTCDEBUG GreetingPreview")
|
||||
MRTCDemoTheme {
|
||||
Greeting("Android")
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.example.mrtcdemo
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import cn.migu.tsg.MRTCEngine
|
||||
import cn.migu.tsg.MRTCAdapter
|
||||
import cn.migu.tsg.MRTCVideoFrame
|
||||
import cn.migu.tsg.OnMRTCSDKListener
|
||||
import cn.migu.tsg.RoomListener
|
||||
import com.example.mrtcdemo.ui.theme.MRTCDemoTheme
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
// 权限请求回调
|
||||
private val permissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
) { permissions ->
|
||||
if (permissions.all { it.value }) {
|
||||
// 所有权限已授予,开始加载SDK
|
||||
} else {
|
||||
// 处理权限被拒绝的情况
|
||||
showToast("权限被拒绝,功能将受限")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
// 请求必要权限
|
||||
requestPermissions()
|
||||
|
||||
setContent {
|
||||
MRTCDemoTheme {
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||
Greeting(
|
||||
name = "Android",
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestPermissions() {
|
||||
permissionLauncher.launch(
|
||||
arrayOf(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.INTERNET,
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var applicationId_ = "1357389261426393088"
|
||||
var mAppSecrectKey_ = "gytr3qrrznsgac2lbdchfg0l4ltqx4x3nf4my0yt1dbx7riz1gnnsnhblrlc2j4o1lx4vdu495lifv8s7jyrmfxtq9lif9rusxnur5smdn5cjopstxp5dim7p52xrezp"
|
||||
var domain_ = "rtc.migu.cn"
|
||||
var mPort_ = 34443
|
||||
var srcUserId_ = "srcUser12"
|
||||
var destUserId_ = "destUser12"
|
||||
|
||||
var srcDisplayName_ = "srcDisplayName12"
|
||||
var destDisplayName_ = "destDisplayName12"
|
||||
var srcRoomId_ = "srcRoom12"
|
||||
var destRoomId_ = srcRoomId_
|
||||
var srcChannelIndex_ = 46
|
||||
var destChannelIndex_ = 47
|
||||
var sampleRate_ = 16000
|
||||
var channelNum_ = 1
|
||||
var isOnRoom_ = false
|
||||
var isOnConsumer_ = false
|
||||
|
||||
|
||||
private val audioListener_ = object : MRTCAdapter.MRTCAudioProcessListener {
|
||||
override fun onReceiveRawAudioFrame(streamId: String, userId: String, frame: MRTCAdapter.MRTCAudioFrame) {
|
||||
// 在这里处理原始音频帧
|
||||
println("MRTCDEBUG ==================================")
|
||||
println("MRTCDEBUG streamId=$streamId, userId=$userId")
|
||||
println("MRTCDEBUG frame, channel=${frame.channel}, length=${frame.length}, sampleRate=${frame.sampleRate}")
|
||||
println(frame.audioBuffer.toString())
|
||||
}
|
||||
}
|
||||
private val sdkListener_ = object : OnMRTCSDKListener {
|
||||
override fun onRoom(type: Int, roomInfo: MRTCAdapter.MRTCRoomInfo) {
|
||||
println("MRTCDEBUG 房间状态变化: type=$type, roomId=${roomInfo.roomId}")
|
||||
println("MRTCDEBUG RTCContext::onRoom()")
|
||||
isOnRoom_ = true
|
||||
}
|
||||
|
||||
override fun onRTMRoom(p0: Int, p1: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onProducer(p0: Int, p1: MRTCAdapter.MRTCProducerInfo?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onConsumer(msgId: Int, roomId: String?, peerId: String?, p3: Any?) {
|
||||
println("MRTCDEBUG onConsumer, msgId:$msgId, roomId:$roomId, peerId:$peerId")
|
||||
isOnConsumer_ = true
|
||||
MRTCEngine.getDefault().registerSoundLevelListener(MRTCAdapter.MRTCAudioSourceType.TYPE_AUDIO_SOURCE_CUSTOM,
|
||||
roomId, peerId, srcChannelIndex_)
|
||||
var ret = MRTCEngine.getDefault().muteAudio(roomId, peerId, MRTCAdapter.MRTCAudioSourceType.TYPE_AUDIO_SOURCE_CUSTOM.type,
|
||||
false, srcChannelIndex_)
|
||||
if (ret != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().muteAudio() failed, ret:$ret")
|
||||
return
|
||||
}
|
||||
println("MRTCDEBUG init recv succ")
|
||||
|
||||
}
|
||||
|
||||
override fun callBackMessage(code: Int, msg: String) {
|
||||
println("MRTCDEBUG callBackMessage: [$code] $msg")
|
||||
}
|
||||
|
||||
override fun onCustomData(p0: MRTCAdapter.MRTCCustomData?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onDataProducer(p0: Int, p1: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onDataConsumer(p0: Int, p1: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onMessager(p0: String?, p1: String?, p2: String?, p3: String?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onRender(p0: String?, p1: String?, p2: Int, p3: Int, p4: MRTCVideoFrame?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onScreenShot(p0: Bitmap?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onLocalAudioStats(p0: MRTCAdapter.MRTCLocalAudioStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onLocalVideoStats(p0: MRTCAdapter.MRTCLocalVideoStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onRemoteAudioStats(p0: MRTCAdapter.MRTCRemoteAudioStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onRemoteVideoStats(p0: MRTCAdapter.MRTCRemoteVideoStats?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun onSoundLevelUpdate(p0: String?, p1: String?, p2: Int, p3: Int, p4: Int) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
private fun initMRTCEngine() : Boolean {
|
||||
println("MRTCDEBUG initMRTCEngine=======================")
|
||||
|
||||
val config = MRTCAdapter.Config().apply {
|
||||
// 设置必要参数(根据SDK文档补充)
|
||||
applicationId = applicationId_
|
||||
mAppSecrectKey = mAppSecrectKey_
|
||||
domain = domain_
|
||||
mPort = mPort_
|
||||
}
|
||||
|
||||
RoomListener().setOnDorySDKListener(sdkListener_)
|
||||
|
||||
val ret1 = MRTCEngine.getDefault().init(config, this)
|
||||
if (ret1 != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().init() failed, ret:$ret1")
|
||||
return false
|
||||
}
|
||||
|
||||
MRTCEngine.getDefault().registerListener(MRTCAdapter.MRTCListenerType.TYPE_LISTENER_ROOM)
|
||||
MRTCEngine.getDefault().registerListener(MRTCAdapter.MRTCListenerType.TYPE_LISTENER_CONSUMER)
|
||||
MRTCEngine.getDefault().registerReceivedMicAudioFrameListener(audioListener_)
|
||||
|
||||
MRTCEngine.getDefault().setUserInfo(srcUserId_,srcDisplayName_,srcRoomId_)
|
||||
val loginConfig = MRTCAdapter.LoginConfigParams().apply {
|
||||
mAppId = applicationId_
|
||||
mAppSecrectKey = mAppSecrectKey_
|
||||
}
|
||||
val ret2 = MRTCEngine.getDefault().joinRoom(loginConfig)
|
||||
if (ret2 != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().joinRoom() failed, ret:$ret2")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG init succ")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun initSendMRTCEngine() : Boolean {
|
||||
while (!isOnRoom_)
|
||||
{
|
||||
println("MRTCDEBUG wait for OnRoom")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
|
||||
println("MRTCDEBUG initSendMRTCEngine=======================")
|
||||
val option = MRTCAdapter.MRTCAudioOption().apply {
|
||||
// 修改需要自定义的参数
|
||||
sampleRate = sampleRate_
|
||||
channel = 1 // 改为立体声
|
||||
channelIndex = destChannelIndex_
|
||||
echoCancellation = true // 开启回声消除
|
||||
}
|
||||
var ret = MRTCEngine.getDefault().startCustomAudio(option)
|
||||
if (ret != 0) {
|
||||
println("MRTCDEBUG startCustomAudio fail, ret:$ret")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG init send succ")
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
private fun initRecvMRTCEngine() : Boolean {
|
||||
println("MRTCDEBUG initRecvMRTCEngine=======================")
|
||||
while (!isOnConsumer_)
|
||||
{
|
||||
println("MRTCDEBUG wait for OnConsumer")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
private fun sendCustomAudioData(data :ByteArray, dataLength :Int) : Boolean {
|
||||
while(!isOnRoom_) {
|
||||
println("MRTCDEBUG wait for room and multi room before send")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
if (data == null) {
|
||||
println("MRTCDEBUG customData is null")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG sendAudioData=======================")
|
||||
MRTCEngine.getDefault().sendCustomAudioData(data, sampleRate_, channelNum_, dataLength)
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun showToast(message: String) {
|
||||
// 实现Toast显示
|
||||
println("MRTCDEBUG showToast: $message")
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
val isSDKReady = remember { mutableStateOf(false) }
|
||||
var ret1 = initMRTCEngine()
|
||||
if (!ret1) {
|
||||
println("MRTCDEBUG init fail, ret:$ret1")
|
||||
return
|
||||
}
|
||||
thread {
|
||||
var ret2 = initSendMRTCEngine()
|
||||
if (!ret2) {
|
||||
println("MRTCDEBUG initSend fail, ret:$ret2")
|
||||
}
|
||||
thread {
|
||||
var ret3 = initRecvMRTCEngine()
|
||||
if (!ret3) {
|
||||
println("MRTCDEBUG initRecv fail, ret:$ret3")
|
||||
}
|
||||
}
|
||||
|
||||
val data: ByteArray = "Hello".toByteArray(Charsets.UTF_8)
|
||||
val dataLength: Int = data.size
|
||||
for (i in 1..100) {
|
||||
println("MRTCDEBUG 第${i}次循环")
|
||||
// 执行您的业务逻辑
|
||||
|
||||
var ret4 = sendCustomAudioData(data, dataLength)
|
||||
if (!ret4) {
|
||||
println("MRTCDEBUG send fail, ret:$ret4")
|
||||
}
|
||||
Thread.sleep(3000)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 监听SDK状态
|
||||
LaunchedEffect(Unit) {
|
||||
// 这里可以添加SDK状态监听逻辑
|
||||
}
|
||||
|
||||
Text(
|
||||
text = if (isSDKReady.value) "Hello $name! (SDK Ready)" else "Loading SDK1...",
|
||||
modifier = modifier
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
println("MRTCDEBUG GreetingPreview")
|
||||
MRTCDemoTheme {
|
||||
Greeting("Android")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,331 @@
|
|||
package com.example.mrtcdemo
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.res.AssetManager
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import cn.migu.tsg.MRTCEngine
|
||||
import cn.migu.tsg.MRTCAdapter
|
||||
import cn.migu.tsg.MRTCVideoFrame
|
||||
import cn.migu.tsg.OnMRTCSDKListener
|
||||
import cn.migu.tsg.RoomListener
|
||||
import com.example.mrtcdemo.ui.theme.MRTCDemoTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
// 权限请求回调
|
||||
private val permissionLauncher = registerForActivityResult(
|
||||
ActivityResultContracts.RequestMultiplePermissions()
|
||||
) { permissions ->
|
||||
if (permissions.all { it.value }) {
|
||||
// 所有权限已授予,开始加载SDK
|
||||
} else {
|
||||
// 处理权限被拒绝的情况
|
||||
showToast("权限被拒绝,功能将受限")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
// 请求必要权限
|
||||
requestPermissions()
|
||||
|
||||
setContent {
|
||||
MRTCDemoTheme {
|
||||
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
|
||||
Greeting(
|
||||
name = "Android",
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestPermissions() {
|
||||
permissionLauncher.launch(
|
||||
arrayOf(
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
||||
Manifest.permission.WRITE_EXTERNAL_STORAGE,
|
||||
Manifest.permission.INTERNET,
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
var applicationId_ = "1357389261426393088"
|
||||
var mAppSecrectKey_ = "gytr3qrrznsgac2lbdchfg0l4ltqx4x3nf4my0yt1dbx7riz1gnnsnhblrlc2j4o1lx4vdu495lifv8s7jyrmfxtq9lif9rusxnur5smdn5cjopstxp5dim7p52xrezp"
|
||||
var domain_ = "rtc.migu.cn"
|
||||
var mPort_ = 34443
|
||||
var srcUserId_ = "srcUser12"
|
||||
var destUserId_ = "destUser12"
|
||||
|
||||
var srcDisplayName_ = "srcDisplayName12"
|
||||
var destDisplayName_ = "destDisplayName12"
|
||||
var srcRoomId_ = "srcRoom12"
|
||||
var destRoomId_ = srcRoomId_
|
||||
var srcChannelIndex_ = 46
|
||||
var destChannelIndex_ = 47
|
||||
var sampleRate_ = 16000
|
||||
var channelNum_ = 1
|
||||
var isOnRoom_ = false
|
||||
var isOnConsumer_ = false
|
||||
|
||||
|
||||
private val audioListener_ = object : MRTCAdapter.MRTCAudioProcessListener {
|
||||
override fun onReceiveRawAudioFrame(streamId: String, userId: String, frame: MRTCAdapter.MRTCAudioFrame) {
|
||||
// 在这里处理原始音频帧
|
||||
println("MRTCDEBUG ==================================")
|
||||
println("MRTCDEBUG streamId=$streamId, userId=$userId")
|
||||
println("MRTCDEBUG frame, channel=${frame.channel}, length=${frame.length}, sampleRate=${frame.sampleRate}")
|
||||
println(frame.audioBuffer)
|
||||
}
|
||||
}
|
||||
private val sdkListener_ = object : OnMRTCSDKListener {
|
||||
override fun onRoom(type: Int, roomInfo: MRTCAdapter.MRTCRoomInfo) {
|
||||
println("MRTCDEBUG 房间状态变化: type=$type, roomId=${roomInfo.roomId}")
|
||||
println("MRTCDEBUG RTCContext::onRoom()")
|
||||
isOnRoom_ = true
|
||||
}
|
||||
|
||||
override fun onRTMRoom(p0: Int, p1: Int) {
|
||||
println("MRTCDEBUG onRTMRoom()")
|
||||
}
|
||||
|
||||
override fun onProducer(p0: Int, p1: MRTCAdapter.MRTCProducerInfo?) {
|
||||
println("MRTCDEBUG onProducer()")
|
||||
}
|
||||
|
||||
override fun onConsumer(msgId: Int, roomId: String?, peerId: String?, p3: Any?) {
|
||||
println("MRTCDEBUG onConsumer, msgId:$msgId, roomId:$roomId, peerId:$peerId")
|
||||
isOnConsumer_ = true
|
||||
MRTCEngine.getDefault().registerSoundLevelListener(MRTCAdapter.MRTCAudioSourceType.TYPE_AUDIO_SOURCE_CUSTOM,
|
||||
roomId, peerId, srcChannelIndex_)
|
||||
var ret = MRTCEngine.getDefault().muteAudio(roomId, peerId, MRTCAdapter.MRTCAudioSourceType.TYPE_AUDIO_SOURCE_CUSTOM.type,
|
||||
false, srcChannelIndex_)
|
||||
if (ret != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().muteAudio() failed, ret:$ret")
|
||||
return
|
||||
}
|
||||
println("MRTCDEBUG init recv succ")
|
||||
|
||||
}
|
||||
|
||||
override fun callBackMessage(code: Int, msg: String) {
|
||||
println("MRTCDEBUG callBackMessage: [$code] $msg")
|
||||
}
|
||||
|
||||
override fun onCustomData(p0: MRTCAdapter.MRTCCustomData?) {
|
||||
println("MRTCDEBUG onCustomData()")
|
||||
}
|
||||
|
||||
override fun onDataProducer(p0: Int, p1: Int) {
|
||||
println("MRTCDEBUG onDataProducer()")
|
||||
}
|
||||
|
||||
override fun onDataConsumer(p0: Int, p1: Int) {
|
||||
println("MRTCDEBUG onDataConsumer()")
|
||||
}
|
||||
|
||||
override fun onMessager(p0: String?, p1: String?, p2: String?, p3: String?) {
|
||||
println("MRTCDEBUG onMessager()")
|
||||
}
|
||||
|
||||
override fun onRender(p0: String?, p1: String?, p2: Int, p3: Int, p4: MRTCVideoFrame?) {
|
||||
println("MRTCDEBUG onRender()")
|
||||
}
|
||||
|
||||
override fun onScreenShot(p0: Bitmap?) {
|
||||
println("MRTCDEBUG onScreenShot()")
|
||||
}
|
||||
|
||||
override fun onLocalAudioStats(p0: MRTCAdapter.MRTCLocalAudioStats?) {
|
||||
println("MRTCDEBUG onLocalAudioStats()")
|
||||
}
|
||||
|
||||
override fun onLocalVideoStats(p0: MRTCAdapter.MRTCLocalVideoStats?) {
|
||||
println("MRTCDEBUG onLocalVideoStats()")
|
||||
}
|
||||
|
||||
override fun onRemoteAudioStats(p0: MRTCAdapter.MRTCRemoteAudioStats?) {
|
||||
println("MRTCDEBUG onRemoteAudioStats()")
|
||||
}
|
||||
|
||||
override fun onRemoteVideoStats(p0: MRTCAdapter.MRTCRemoteVideoStats?) {
|
||||
println("MRTCDEBUG onRemoteVideoStats()")
|
||||
}
|
||||
|
||||
override fun onSoundLevelUpdate(p0: String?, p1: String?, p2: Int, p3: Int, p4: Int) {
|
||||
println("MRTCDEBUG onSoundLevelUpdate()")
|
||||
}
|
||||
}
|
||||
|
||||
private fun initMRTCEngine() : Boolean {
|
||||
println("MRTCDEBUG initMRTCEngine=======================")
|
||||
|
||||
val config = MRTCAdapter.Config().apply {
|
||||
applicationId = applicationId_
|
||||
mAppSecrectKey = mAppSecrectKey_
|
||||
domain = domain_
|
||||
mPort = mPort_
|
||||
}
|
||||
var roomListener = RoomListener()
|
||||
roomListener.setOnDorySDKListener(sdkListener_)
|
||||
//MRTCEngine.setSDKLogDirectory("/Users/wangjiyu/StudioProjects/Log")
|
||||
var ret1 = MRTCEngine.getDefault().init(config, this)
|
||||
if (ret1 != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().init() failed, ret:$ret1")
|
||||
return false
|
||||
}
|
||||
MRTCEngine.getDefault().setUserInfo(srcUserId_,srcDisplayName_,srcRoomId_)
|
||||
var loginConfig = MRTCAdapter.LoginConfigParams().apply {
|
||||
mAppId = applicationId_
|
||||
mAppSecrectKey = mAppSecrectKey_
|
||||
}
|
||||
MRTCEngine.getDefault().registerListener(MRTCAdapter.MRTCListenerType.TYPE_LISTENER_ROOM)
|
||||
MRTCEngine.getDefault().registerListener(MRTCAdapter.MRTCListenerType.TYPE_LISTENER_CONSUMER)
|
||||
var ret2 = MRTCEngine.getDefault().joinRoom(loginConfig)
|
||||
if (ret2 != 0) {
|
||||
println("MRTCDEBUG RTCContext::instance().joinRoom() failed, ret:$ret2")
|
||||
return false
|
||||
}
|
||||
MRTCEngine.getDefault().registerReceivedMicAudioFrameListener(audioListener_)
|
||||
println("MRTCDEBUG init succ")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun initSendMRTCEngine() : Boolean {
|
||||
while (!isOnRoom_)
|
||||
{
|
||||
println("MRTCDEBUG wait for OnRoom")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
|
||||
println("MRTCDEBUG initSendMRTCEngine=======================")
|
||||
val option = MRTCAdapter.MRTCAudioOption().apply {
|
||||
// 修改需要自定义的参数
|
||||
sampleRate = sampleRate_
|
||||
channel = 1 // 改为立体声
|
||||
channelIndex = destChannelIndex_
|
||||
echoCancellation = true // 开启回声消除
|
||||
}
|
||||
var ret = MRTCEngine.getDefault().startCustomAudio(option)
|
||||
if (ret != 0) {
|
||||
println("MRTCDEBUG startCustomAudio fail, ret:$ret")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG init send succ")
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
private fun initRecvMRTCEngine() : Boolean {
|
||||
println("MRTCDEBUG initRecvMRTCEngine=======================")
|
||||
while (!isOnConsumer_)
|
||||
{
|
||||
println("MRTCDEBUG wait for OnConsumer")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
private fun sendCustomAudioData(data :ByteArray, dataLength :Int) : Boolean {
|
||||
while(!isOnRoom_) {
|
||||
println("MRTCDEBUG wait for room and multi room before send")
|
||||
Thread.sleep(3000)
|
||||
}
|
||||
if (data == null) {
|
||||
println("MRTCDEBUG customData is null")
|
||||
return false
|
||||
}
|
||||
println("MRTCDEBUG sendAudioData=======================")
|
||||
MRTCEngine.getDefault().sendCustomAudioData(data, sampleRate_, channelNum_, dataLength)
|
||||
return true
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun showToast(message: String) {
|
||||
// 实现Toast显示
|
||||
println("MRTCDEBUG showToast: $message")
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Greeting(name: String, modifier: Modifier = Modifier) {
|
||||
val context = LocalContext.current
|
||||
val isSDKReady = remember { mutableStateOf(false) }
|
||||
var ret1 = initMRTCEngine()
|
||||
if (!ret1) {
|
||||
println("MRTCDEBUG init fail, ret:$ret1")
|
||||
return
|
||||
}
|
||||
var ret2 = initSendMRTCEngine()
|
||||
if (!ret2) {
|
||||
println("MRTCDEBUG initSend fail, ret:$ret2")
|
||||
return
|
||||
}
|
||||
var ret3 = initRecvMRTCEngine()
|
||||
if (!ret3) {
|
||||
println("MRTCDEBUG initRecv fail, ret:$ret3")
|
||||
return
|
||||
}
|
||||
|
||||
val data: ByteArray = "Hello".toByteArray(Charsets.UTF_8)
|
||||
val dataLength: Int = data.size
|
||||
for (i in 1..100) {
|
||||
println("MRTCDEBUG 第${i}次循环")
|
||||
// 执行您的业务逻辑
|
||||
|
||||
var ret4 = sendCustomAudioData(data, dataLength)
|
||||
if (!ret4) {
|
||||
println("MRTCDEBUG send fail, ret:$ret3")
|
||||
return
|
||||
}
|
||||
Thread.sleep(3000)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 监听SDK状态
|
||||
LaunchedEffect(Unit) {
|
||||
// 这里可以添加SDK状态监听逻辑
|
||||
}
|
||||
|
||||
Text(
|
||||
text = if (isSDKReady.value) "Hello $name! (SDK Ready)" else "Loading SDK1...",
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun GreetingPreview() {
|
||||
println("MRTCDEBUG GreetingPreview")
|
||||
MRTCDemoTheme {
|
||||
Greeting("Android")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue