diff options
| author | bt <bt@rctt.net> | 2026-05-03 03:27:18 +0200 |
|---|---|---|
| committer | bt <bt@rctt.net> | 2026-05-03 03:27:18 +0200 |
| commit | 2937bc975848e7979287e7067f4fff10bbfe4988 (patch) | |
| tree | f8ec8ea8f638977b75919879a5a76eb7333a264b | |
| parent | cde732059b237af7b147d58c43e4f5b03b9fbddd (diff) | |
| download | netmon-2937bc975848e7979287e7067f4fff10bbfe4988.tar.gz netmon-2937bc975848e7979287e7067f4fff10bbfe4988.zip | |
Basic current cell info view
| -rw-r--r-- | .idea/.gitignore | 3 | ||||
| -rw-r--r-- | .idea/AndroidProjectSystem.xml | 6 | ||||
| -rw-r--r-- | .idea/compiler.xml | 6 | ||||
| -rw-r--r-- | .idea/deploymentTargetSelector.xml | 18 | ||||
| -rw-r--r-- | .idea/deviceManager.xml | 13 | ||||
| -rw-r--r-- | .idea/dictionaries/project.xml | 8 | ||||
| -rw-r--r-- | .idea/gradle.xml | 17 | ||||
| -rw-r--r-- | .idea/misc.xml | 10 | ||||
| -rw-r--r-- | .idea/runConfigurations.xml | 17 | ||||
| -rw-r--r-- | .idea/vcs.xml | 6 | ||||
| -rw-r--r-- | app/build.gradle.kts | 8 | ||||
| -rw-r--r-- | app/src/main/AndroidManifest.xml | 11 | ||||
| -rw-r--r-- | app/src/main/java/net/rctt/netmon/MainActivity.kt | 104 | ||||
| -rw-r--r-- | app/src/main/res/layout/activity_main.xml | 63 | ||||
| -rw-r--r-- | app/src/main/res/values-land/dimens.xml | 3 | ||||
| -rw-r--r-- | app/src/main/res/values-w1240dp/dimens.xml | 3 | ||||
| -rw-r--r-- | app/src/main/res/values-w600dp/dimens.xml | 3 | ||||
| -rw-r--r-- | app/src/main/res/values-w820dp/dimens.xml | 6 | ||||
| -rw-r--r-- | app/src/main/res/values/dimens.xml | 8 | ||||
| -rw-r--r-- | app/src/main/res/values/strings.xml | 3 | ||||
| -rw-r--r-- | app/src/main/res/values/themes.xml | 9 | ||||
| -rw-r--r-- | gradle/libs.versions.toml | 6 |
22 files changed, 315 insertions, 16 deletions
diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="AndroidProjectSystem"> + <option name="providerId" value="com.android.tools.idea.GradleProjectSystem" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="CompilerConfiguration"> + <bytecodeTargetLevel target="21" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..df74897 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="deploymentTargetSelector"> + <selectionStates> + <SelectionState runConfigName="app"> + <option name="selectionMode" value="DROPDOWN" /> + <DropdownSelection timestamp="2026-05-03T01:02:55.812002Z"> + <Target type="DEFAULT_BOOT"> + <handle> + <DeviceId pluginId="PhysicalDevice" identifier="serial=47111JEKB06200" /> + </handle> + </Target> + </DropdownSelection> + <DialogSelection /> + </SelectionState> + </selectionStates> + </component> +</project>
\ No newline at end of file diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml new file mode 100644 index 0000000..91f9558 --- /dev/null +++ b/.idea/deviceManager.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="DeviceTable"> + <option name="columnSorters"> + <list> + <ColumnSorterState> + <option name="column" value="Name" /> + <option name="order" value="ASCENDING" /> + </ColumnSorterState> + </list> + </option> + </component> +</project>
\ No newline at end of file diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml new file mode 100644 index 0000000..ffb84f9 --- /dev/null +++ b/.idea/dictionaries/project.xml @@ -0,0 +1,8 @@ +<component name="ProjectDictionaryState"> + <dictionary name="project"> + <words> + <w>tdscdma</w> + <w>wcdma</w> + </words> + </dictionary> +</component>
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..cdbc250 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="GradleSettings"> + <option name="linkedExternalProjectsSettings"> + <GradleProjectSettings> + <option name="testRunner" value="CHOOSE_PER_TEST" /> + <option name="externalProjectPath" value="$PROJECT_DIR$" /> + <option name="modules"> + <set> + <option value="$PROJECT_DIR$" /> + <option value="$PROJECT_DIR$/app" /> + </set> + </option> + </GradleProjectSettings> + </option> + </component> +</project>
\ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ExternalStorageConfigurationManager" enabled="true" /> + <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> + <output url="file://$PROJECT_DIR$/build/classes" /> + </component> + <component name="ProjectType"> + <option name="id" value="Android" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="RunConfigurationProducerService"> + <option name="ignoredProducers"> + <set> + <option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" /> + <option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" /> + <option value="com.intellij.execution.junit.PatternConfigurationProducer" /> + <option value="com.intellij.execution.junit.TestInClassConfigurationProducer" /> + <option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" /> + <option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" /> + <option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" /> + <option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" /> + </set> + </option> + </component> +</project>
\ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="$PROJECT_DIR$" vcs="Git" /> + </component> +</project>
\ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 98e6f42..21281d3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,7 +12,7 @@ android { defaultConfig { applicationId = "net.rctt.netmon" - minSdk = 26 + minSdk = 29 targetSdk = 36 versionCode = 1 versionName = "1.0" @@ -33,6 +33,9 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } + buildFeatures { + viewBinding = true + } } dependencies { @@ -41,6 +44,9 @@ dependencies { implementation(libs.material) implementation(libs.androidx.activity) implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.lifecycle.livedata.ktx) + implementation(libs.androidx.lifecycle.viewmodel.ktx) + implementation(libs.androidx.cardview) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 87305ab..d036883 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" > +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + + <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <application android:allowBackup="true" @@ -10,13 +12,12 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/Theme.Netmon" > + android:theme="@style/Theme.Netmon"> <activity android:name=".MainActivity" - android:exported="true" > + android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> diff --git a/app/src/main/java/net/rctt/netmon/MainActivity.kt b/app/src/main/java/net/rctt/netmon/MainActivity.kt index 53c6f05..7111922 100644 --- a/app/src/main/java/net/rctt/netmon/MainActivity.kt +++ b/app/src/main/java/net/rctt/netmon/MainActivity.kt @@ -1,12 +1,34 @@ package net.rctt.netmon +import android.Manifest +import android.annotation.SuppressLint import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.telephony.CellInfoGsm +import android.telephony.CellInfoLte +import android.telephony.CellInfoNr +import android.telephony.CellInfoTdscdma +import android.telephony.CellInfoWcdma +import android.telephony.TelephonyManager +import android.util.Log +import android.widget.LinearLayout +import android.widget.TextView import androidx.activity.enableEdgeToEdge +import androidx.annotation.RequiresPermission import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat +import java.text.SimpleDateFormat +import java.util.Date class MainActivity : AppCompatActivity() { + lateinit var statusView: LinearLayout + lateinit var cellView: LinearLayout + + lateinit var tel: TelephonyManager + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -16,5 +38,87 @@ class MainActivity : AppCompatActivity() { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } + + statusView = findViewById(R.id.statusView) + cellView = findViewById(R.id.cellView) + + val pLoc = ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_FINE_LOCATION) + if (pLoc == -1) { + log("Location permission required") + } else { + log("Ready") + tel = getSystemService(TELEPHONY_SERVICE) as TelephonyManager + + val mainHandler = Handler(Looper.getMainLooper()) + + mainHandler.post(object : Runnable { + @RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION) + override fun run() { + refresh() + mainHandler.postDelayed(this, 1000) + } + }) + } + } + + @RequiresPermission(Manifest.permission.ACCESS_FINE_LOCATION) + fun refresh() { + log("refreshing") + + val cellList = tel.allCellInfo + cellView.removeAllViews() + for (cell in cellList) { + when (cell) { + is CellInfoGsm -> { + logDetected("GSM") + } + is CellInfoLte -> { + val id = cell.cellIdentity + if (id.ci == 2147483647) { + continue + } + + logDetected("LTE") + logCell("CID: ${id.ci}") + logCell("PCI: ${id.pci}") + logCell("TAC: ${id.tac}") + logCell("EARFCN ${id.earfcn}") + logCell("BANDWIDTH: ${id.bandwidth}") + logCell("RSRP: ${cell.cellSignalStrength.rsrp}") + logCell("DBM: ${cell.cellSignalStrength.dbm}") + logCell("STATUS: ${cell.cellConnectionStatus}") + logCell("") + } + is CellInfoNr -> { + logDetected("NR") + } + is CellInfoTdscdma -> { + logDetected("TDSCDMA") + } + is CellInfoWcdma -> { + logDetected("WCDMA") + } + } + } + } + + @SuppressLint("SimpleDateFormat", "SetTextI18n") + fun log(text: String) { + val sdf = SimpleDateFormat("hh:mm:ss") + val date = sdf.format(Date()) + val msg = TextView(this) + msg.text = "$date $text" + statusView.addView(msg) + } + + fun logDetected(text: String) { + log("detected $text cell") + } + + fun logCell(text: String) { + val msg = TextView(this) + msg.text = text + cellView.addView(msg) + Log.d("NETMON", text) } }
\ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 25a2ae6..e7c0e2c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,13 +7,56 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Hello World!" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - - </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" > + + <TextView + android:id="@+id/haederCell" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Cell Info" + android:textSize="20sp" /> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="400dp"> + + <LinearLayout + android:id="@+id/cellView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" /> + </ScrollView> + + <View + android:id="@+id/divider" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?android:attr/listDivider" /> + + <TextView + android:id="@+id/headerStatus" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Status" + android:textSize="20sp" /> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + android:id="@+id/statusView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"/> + </ScrollView> + </LinearLayout> + +</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">48dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml new file mode 100644 index 0000000..d73f4a3 --- /dev/null +++ b/app/src/main/res/values-w1240dp/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">200dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -0,0 +1,3 @@ +<resources> + <dimen name="fab_margin">48dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..9309de9 --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ +<resources> + <!-- Example customization of dimensions originally defined in res/values/dimens.xml + (such as screen margins) for screens with more than 820dp of available width. This + would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> + <dimen name="activity_horizontal_margin">64dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..0a87b6e --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,8 @@ +<resources> + <!-- Default screen margins, per the Android Design guidelines. --> + <dimen name="activity_horizontal_margin">16dp</dimen> + <dimen name="activity_vertical_margin">16dp</dimen> + <dimen name="appbar_padding">16dp</dimen> + <dimen name="fab_margin">16dp</dimen> + <dimen name="appbar_padding_top">8dp</dimen> +</resources>
\ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1d0121e..2c29dfa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,6 @@ <resources> <string name="app_name">netmon</string> + <string name="title_activity_main2">MainActivity2</string> + <string name="tab_text_1">Tab 1</string> + <string name="tab_text_2">Tab 2</string> </resources>
\ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 9b8da79..8c1e2ef 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -6,4 +6,13 @@ </style> <style name="Theme.Netmon" parent="Base.Theme.Netmon" /> + + <style name="Theme.Netmon.NoActionBar"> + <item name="windowActionBar">false</item> + <item name="windowNoTitle">true</item> + </style> + + <style name="Theme.Netmon.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> + + <style name="Theme.Netmon.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> </resources>
\ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 486d16b..20de420 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,9 @@ appcompat = "1.7.1" material = "1.13.0" activity = "1.13.0" constraintlayout = "2.2.1" +lifecycleLivedataKtx = "2.10.0" +lifecycleViewmodelKtx = "2.10.0" +cardview = "1.0.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -18,6 +21,9 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version material = { group = "com.google.android.material", name = "material", version.ref = "material" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } +androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" } +androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" } +androidx-cardview = { group = "androidx.cardview", name = "cardview", version.ref = "cardview" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } |
