capacitor-signal-strength 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,17 @@
1
- require 'json'
2
-
3
- package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
-
5
- Pod::Spec.new do |s|
6
- s.name = 'CapacitorSignalStrength'
7
- s.version = package['version']
8
- s.summary = package['description']
9
- s.license = package['license']
10
- s.homepage = package['repository']['url']
11
- s.author = package['author']
12
- s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
- s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
- s.ios.deployment_target = '13.0'
15
- s.dependency 'Capacitor'
16
- s.swift_version = '5.1'
17
- end
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapacitorSignalStrength'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '13.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.1'
17
+ end
package/README.md CHANGED
@@ -1,133 +1,72 @@
1
- # capacitor-signal-strength
2
-
3
- Plugin use to get Android device signal strength
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install capacitor-signal-strength
9
- npx cap sync
10
- ```
11
-
12
- ## API
13
-
14
- <docgen-index>
15
-
16
- * [`getdBm()`](#getdbm)
17
- * [`getPercentage(...)`](#getpercentage)
18
- * [`getLevel()`](#getlevel)
19
- * [`checkPermissions()`](#checkpermissions)
20
- * [`requestPermissions()`](#requestpermissions)
21
- * [Interfaces](#interfaces)
22
- * [Type Aliases](#type-aliases)
23
-
24
- </docgen-index>
25
-
26
- <docgen-api>
27
- <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
28
-
29
- ### getdBm()
30
-
31
- ```typescript
32
- getdBm() => Promise<DBm>
33
- ```
34
-
35
- **Returns:** <code>Promise&lt;<a href="#dbm">DBm</a>&gt;</code>
36
-
37
- --------------------
38
-
39
-
40
- ### getPercentage(...)
41
-
42
- ```typescript
43
- getPercentage(options: { connection: ConnectionType; }) => Promise<Percentage>
44
- ```
45
-
46
- | Param | Type |
47
- | ------------- | -------------------------------------------------------------------------- |
48
- | **`options`** | <code>{ connection: <a href="#connectiontype">ConnectionType</a>; }</code> |
49
-
50
- **Returns:** <code>Promise&lt;<a href="#percentage">Percentage</a>&gt;</code>
51
-
52
- --------------------
53
-
54
-
55
- ### getLevel()
56
-
57
- ```typescript
58
- getLevel() => Promise<Level>
59
- ```
60
-
61
- **Returns:** <code>Promise&lt;<a href="#level">Level</a>&gt;</code>
62
-
63
- --------------------
64
-
65
-
66
- ### checkPermissions()
67
-
68
- ```typescript
69
- checkPermissions() => Promise<PermissionStatus>
70
- ```
71
-
72
- **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
73
-
74
- --------------------
75
-
76
-
77
- ### requestPermissions()
78
-
79
- ```typescript
80
- requestPermissions() => Promise<PermissionStatus>
81
- ```
82
-
83
- **Returns:** <code>Promise&lt;<a href="#permissionstatus">PermissionStatus</a>&gt;</code>
84
-
85
- --------------------
86
-
87
-
88
- ### Interfaces
89
-
90
-
91
- #### DBm
92
-
93
- | Prop | Type |
94
- | --------- | ------------------- |
95
- | **`dBm`** | <code>number</code> |
96
-
97
-
98
- #### Percentage
99
-
100
- | Prop | Type |
101
- | ---------------- | ------------------- |
102
- | **`percentage`** | <code>string</code> |
103
-
104
-
105
- #### Level
106
-
107
- | Prop | Type |
108
- | ----------- | ------------------- |
109
- | **`level`** | <code>number</code> |
110
-
111
-
112
- #### PermissionStatus
113
-
114
- | Prop | Type |
115
- | ---------- | ----------------------------------------------------------- |
116
- | **`info`** | <code><a href="#permissionstate">PermissionState</a></code> |
117
-
118
-
119
- ### Type Aliases
120
-
121
-
122
- #### ConnectionType
123
-
124
- The type of network connection that a device might have.
125
-
126
- <code>'wifi' | 'cellular' | 'none' | 'unknown'</code>
127
-
128
-
129
- #### PermissionState
130
-
131
- <code>'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'</code>
132
-
133
- </docgen-api>
1
+ # 📶 Capacitor Signal Strength (Android)
2
+
3
+ A **Capacitor Android-only plugin** to retrieve **cellular signal strength information** such as:
4
+
5
+ - **dBm**
6
+ - **Signal level**
7
+ - **Percentage**
8
+ - **5G / LTE / WCDMA / GSM awareness**
9
+
10
+ Designed with **Capacitor 5 → 8 compatibility** and **correct Android permission handling**.
11
+
12
+ ---
13
+
14
+ ## ✨ Features
15
+
16
+ - ✅ Android only (no web / iOS shims)
17
+ - ✅ Supports **LTE, WCDMA, GSM, CDMA, 5G (NR)**
18
+ - ✅ Returns:
19
+ - Signal strength in **dBm**
20
+ - Normalized **signal level**
21
+ - **Percentage**
22
+ - Uses Capacitor’s **native permission system**
23
+ - ✅ Compatible with **Capacitor 5, 6, 7, 8**
24
+ - ✅ Safe permission lifecycle (no crashes after prompt)
25
+ - ✅ Works with `@capacitor/network` for connection type
26
+
27
+ ---
28
+
29
+ ## ⚠️ Platform Support
30
+
31
+ | Platform | Supported |
32
+ |--------|-----------|
33
+ | Android | ✅ Yes |
34
+ | iOS | ❌ No |
35
+ | Web | ❌ No |
36
+
37
+ ---
38
+
39
+ ## 📦 Installation
40
+
41
+ ```bash
42
+ npm install capacitor-signal-strength
43
+ npx cap sync android
44
+ ```
45
+
46
+ # API Reference
47
+
48
+ ## SignalStrengthPlugin
49
+
50
+ ### Methods
51
+
52
+ - `checkPermissions(): Promise<PermissionStatus>`
53
+ - `requestPermissions(options): Promise<PermissionStatus>`
54
+ - `getdBm(): Promise<{ dBm: number }>`
55
+ - `getLevel(): Promise<{ level: number }>`
56
+ - `getPercentage(connection: ConnectionType): Promise<{ percentage: number }>`
57
+
58
+ ---
59
+
60
+ ## PermissionStatus
61
+
62
+ ```ts
63
+ {
64
+ phone: 'granted' | 'denied' | 'prompt'
65
+ }
66
+ ```
67
+
68
+ ### Compatibility
69
+
70
+ - Capacitor: v5+
71
+ - Android: API 26 (Android 8.0) and above
72
+ - 5G signal metrics are available on Android 11+
@@ -1,58 +1,52 @@
1
- ext {
2
- junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
- androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
4
- androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
5
- androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
6
- }
7
-
8
- buildscript {
9
- repositories {
10
- google()
11
- mavenCentral()
12
- }
13
- dependencies {
14
- classpath 'com.android.tools.build:gradle:8.0.0'
15
- }
16
- }
17
-
18
- apply plugin: 'com.android.library'
19
-
20
- android {
21
- namespace "com.gbvp.androidsignalstrength"
22
- compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 33
23
- defaultConfig {
24
- minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
25
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 33
26
- versionCode 1
27
- versionName "1.0"
28
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
29
- }
30
- buildTypes {
31
- release {
32
- minifyEnabled false
33
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
34
- }
35
- }
36
- lintOptions {
37
- abortOnError false
38
- }
39
- compileOptions {
40
- sourceCompatibility JavaVersion.VERSION_17
41
- targetCompatibility JavaVersion.VERSION_17
42
- }
43
- }
44
-
45
- repositories {
46
- google()
47
- mavenCentral()
48
- }
49
-
50
-
51
- dependencies {
52
- implementation fileTree(dir: 'libs', include: ['*.jar'])
53
- implementation project(':capacitor-android')
54
- implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
55
- testImplementation "junit:junit:$junitVersion"
56
- androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
57
- androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
58
- }
1
+ plugins {
2
+ id 'com.android.library'
3
+ }
4
+
5
+ android {
6
+ namespace "com.gbvp.androidsignalstrength"
7
+
8
+ compileSdk 34
9
+
10
+ defaultConfig {
11
+ minSdk 22
12
+ targetSdk 34
13
+ versionCode 1
14
+ versionName "1.0"
15
+
16
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17
+ }
18
+
19
+ buildTypes {
20
+ release {
21
+ minifyEnabled false
22
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23
+ }
24
+ }
25
+
26
+ compileOptions {
27
+ sourceCompatibility JavaVersion.VERSION_17
28
+ targetCompatibility JavaVersion.VERSION_17
29
+ }
30
+
31
+ lint {
32
+ abortOnError false
33
+ }
34
+ }
35
+
36
+ dependencies {
37
+ implementation fileTree(dir: "libs", include: ["*.jar"])
38
+
39
+ // Capacitor 6 dependency
40
+ implementation project(":capacitor-android")
41
+
42
+ implementation "androidx.appcompat:appcompat:1.6.1"
43
+
44
+ testImplementation "junit:junit:4.13.2"
45
+ androidTestImplementation "androidx.test.ext:junit:1.1.5"
46
+ androidTestImplementation "androidx.test.espresso:espresso-core:3.5.1"
47
+ }
48
+
49
+ repositories {
50
+ google()
51
+ mavenCentral()
52
+ }
@@ -1,6 +1,5 @@
1
- <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
3
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
5
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
3
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
4
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
6
5
  </manifest>
@@ -1,131 +1,124 @@
1
- package com.gbvp.androidsignalstrength;
2
-
3
- import android.annotation.SuppressLint;
4
- import android.content.Context;
5
- import android.location.LocationManager;
6
- import android.os.Build;
7
- import android.telephony.CellInfo;
8
- import android.telephony.CellInfoCdma;
9
- import android.telephony.CellInfoGsm;
10
- import android.telephony.CellInfoLte;
11
- import android.telephony.CellInfoWcdma;
12
- import android.telephony.CellSignalStrengthCdma;
13
- import android.telephony.CellSignalStrengthGsm;
14
- import android.telephony.CellSignalStrengthLte;
15
- import android.telephony.CellSignalStrengthWcdma;
16
- import android.telephony.PhoneStateListener;
17
- import android.telephony.TelephonyManager;
18
-
19
- import androidx.core.location.LocationManagerCompat;
20
-
21
- import com.getcapacitor.JSObject;
22
-
23
- import java.util.List;
24
-
25
- public class SignalStrength {
26
-
27
- class MyPhoneStateListener extends PhoneStateListener {
28
- @Override
29
- public void onSignalStrengthsChanged(android.telephony.SignalStrength signalStrength) {
30
- super.onSignalStrengthsChanged(signalStrength);
31
- asulevel = signalStrength.getGsmSignalStrength();
32
- }
33
- }
34
-
35
- public int asulevel = -1;
36
- public int asulevelmax = 31;
37
- public int dBmlevel = 0;
38
- public String signalLevel;
39
- private Context context;
40
-
41
- public SignalStrength(Context context) {
42
- this.context = context;
43
- }
44
-
45
- @SuppressLint("MissingPermission")
46
- public Boolean isPhoneStateEnabled() {
47
- Boolean phoneStateEnabled = false;
48
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
49
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
50
- phoneStateEnabled = tm.isDataEnabled();
51
- }
52
-
53
- return phoneStateEnabled;
54
- }
55
-
56
- @SuppressLint("MissingPermission")
57
- public Boolean isLocationServicesEnabled() {
58
- LocationManager lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
59
- return LocationManagerCompat.isLocationEnabled(lm);
60
- }
61
-
62
- @SuppressLint("MissingPermission")
63
- public JSObject getInfo(TelephonyManager tm) {
64
- JSObject ret = new JSObject();
65
- List<CellInfo> cellInfoList = tm.getAllCellInfo();
66
- // Checking if list values are not null
67
- if (cellInfoList != null) {
68
- for (final CellInfo info : cellInfoList) {
69
- if (info instanceof CellInfoGsm) {
70
- //GSM Network
71
- CellSignalStrengthGsm cellSignalStrength = ((CellInfoGsm) info).getCellSignalStrength();
72
- ret.put("dBmlevel", cellSignalStrength.getDbm());
73
- ret.put("asulevel", cellSignalStrength.getAsuLevel());
74
- ret.put("signalLevel", cellSignalStrength.getLevel() + "");
75
- ret.put("asulevelmax", 31);
76
- } else if (info instanceof CellInfoCdma) {
77
- //CDMA Network
78
- CellSignalStrengthCdma cellSignalStrength = ((CellInfoCdma) info).getCellSignalStrength();
79
- ret.put("dBmlevel", cellSignalStrength.getDbm());
80
- ret.put("asulevel", cellSignalStrength.getAsuLevel());
81
- ret.put("signalLevel", cellSignalStrength.getLevel() + "");
82
- ret.put("asulevelmax", 97);
83
- } else if (info instanceof CellInfoLte) {
84
- //LTE Network
85
- CellSignalStrengthLte cellSignalStrength = ((CellInfoLte) info).getCellSignalStrength();
86
- ret.put("dBmlevel", cellSignalStrength.getDbm());
87
- ret.put("asulevel", cellSignalStrength.getAsuLevel());
88
- ret.put("signalLevel", cellSignalStrength.getLevel() + "");
89
- ret.put("asulevelmax", 97);
90
- } else if (info instanceof CellInfoWcdma) {
91
- //WCDMA Network
92
- CellSignalStrengthWcdma cellSignalStrength = ((CellInfoWcdma) info).getCellSignalStrength();
93
- ret.put("dBmlevel", cellSignalStrength.getDbm());
94
- ret.put("asulevel", cellSignalStrength.getAsuLevel());
95
- ret.put("signalLevel", cellSignalStrength.getLevel() + "");
96
- ret.put("asulevelmax", 31);
97
- } else {
98
- throw new IllegalArgumentException("Unknown type of cell signal.");
99
- }
100
- }
101
- } else {
102
- //Mostly for Samsung devices, after checking if the list is indeed empty.
103
- try {
104
- MyPhoneStateListener myPhoneStateListener = new SignalStrength.MyPhoneStateListener();
105
- tm.listen(myPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
106
- int cc = 0;
107
- while (asulevel == -1) {
108
- Thread.sleep(200);
109
- if (cc++ >= 5) {
110
- break;
111
- }
112
- }
113
- ret.put("asulevelmax", 31);
114
- ret.put("dBmlevel", -113 + 2 * asulevel);
115
- tm.listen(myPhoneStateListener, PhoneStateListener.LISTEN_NONE);
116
- ret.put("signalLevel", String.format("%.0g%n", 1.0 * asulevel / asulevelmax * 4));
117
- ret.put("asulevel", asulevel);
118
- } catch (Exception e) {
119
- throw new IllegalArgumentException(e);
120
- }
121
- }
122
-
123
- return ret;
124
- }
125
-
126
- @SuppressWarnings("MissingPermission")
127
- public TelephonyManager getPhoneState() {
128
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
129
- return tm;
130
- }
131
- }
1
+ package com.gbvp.androidsignalstrength;
2
+
3
+ import android.annotation.SuppressLint;
4
+ import android.content.Context;
5
+ import android.os.Build;
6
+ import android.telephony.CellInfo;
7
+ import android.telephony.CellInfoCdma;
8
+ import android.telephony.CellInfoGsm;
9
+ import android.telephony.CellInfoLte;
10
+ import android.telephony.CellInfoNr;
11
+ import android.telephony.CellInfoWcdma;
12
+ import android.telephony.CellSignalStrengthCdma;
13
+ import android.telephony.CellSignalStrengthGsm;
14
+ import android.telephony.CellSignalStrengthLte;
15
+ import android.telephony.CellSignalStrengthNr;
16
+ import android.telephony.CellSignalStrengthWcdma;
17
+ import android.telephony.SubscriptionInfo;
18
+ import android.telephony.SubscriptionManager;
19
+ import android.telephony.TelephonyManager;
20
+
21
+ import androidx.annotation.NonNull;
22
+
23
+ import com.getcapacitor.JSObject;
24
+
25
+ import java.util.List;
26
+
27
+ public class SignalStrength {
28
+
29
+ private final Context context;
30
+
31
+ public SignalStrength(@NonNull Context context) {
32
+ this.context = context;
33
+ }
34
+
35
+ @SuppressLint("MissingPermission")
36
+ private Integer getActiveDataSubscriptionId() {
37
+ SubscriptionManager sm = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
38
+
39
+ if (sm == null) return null;
40
+
41
+ SubscriptionInfo active = null;
42
+
43
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
44
+ active = sm.getActiveSubscriptionInfo(SubscriptionManager.getDefaultDataSubscriptionId());
45
+ }
46
+
47
+ return active != null ? active.getSubscriptionId() : null;
48
+ }
49
+
50
+ @SuppressLint("MissingPermission")
51
+ public JSObject getSignalInfo() {
52
+ JSObject ret = new JSObject();
53
+
54
+ TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
55
+ if (tm == null) {
56
+ ret.put("error", "TelephonyManager unavailable");
57
+ return ret;
58
+ }
59
+
60
+ Integer activeId = getActiveDataSubscriptionId();
61
+ if (activeId == null) {
62
+ ret.put("error", "No active data SIM");
63
+ return ret;
64
+ }
65
+
66
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
67
+ tm = tm.createForSubscriptionId(activeId);
68
+ }
69
+
70
+ List<CellInfo> cells = tm.getAllCellInfo();
71
+
72
+ if (cells == null || cells.isEmpty()) {
73
+ ret.put("error", "No cell info available");
74
+ return ret;
75
+ }
76
+
77
+ for (CellInfo info : cells) {
78
+ if (!info.isRegistered()) continue;
79
+
80
+ // --- GSM ---
81
+ if (info instanceof CellInfoGsm) {
82
+ CellSignalStrengthGsm ss = ((CellInfoGsm) info).getCellSignalStrength();
83
+ return makeResponse("GSM", ss.getDbm(), ss.getAsuLevel(), ss.getLevel(), 31);
84
+ }
85
+
86
+ // --- CDMA ---
87
+ if (info instanceof CellInfoCdma) {
88
+ CellSignalStrengthCdma ss = ((CellInfoCdma) info).getCellSignalStrength();
89
+ return makeResponse("CDMA", ss.getDbm(), ss.getAsuLevel(), ss.getLevel(), 97);
90
+ }
91
+
92
+ // --- WCDMA ---
93
+ if (info instanceof CellInfoWcdma) {
94
+ CellSignalStrengthWcdma ss = ((CellInfoWcdma) info).getCellSignalStrength();
95
+ return makeResponse("WCDMA", ss.getDbm(), ss.getAsuLevel(), ss.getLevel(), 31);
96
+ }
97
+
98
+ // --- LTE ---
99
+ if (info instanceof CellInfoLte) {
100
+ CellSignalStrengthLte ss = ((CellInfoLte) info).getCellSignalStrength();
101
+ return makeResponse("LTE", ss.getDbm(), ss.getAsuLevel(), ss.getLevel(), 97);
102
+ }
103
+
104
+ // --- NR / 5G ---
105
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && info instanceof CellInfoNr) {
106
+ CellSignalStrengthNr ss = (CellSignalStrengthNr) ((CellInfoNr) info).getCellSignalStrength();
107
+ return makeResponse("NR", ss.getDbm(), ss.getAsuLevel(), ss.getLevel(), 97);
108
+ }
109
+ }
110
+
111
+ ret.put("error", "No registered cell found");
112
+ return ret;
113
+ }
114
+
115
+ private JSObject makeResponse(String type, int dBm, int asu, int level, int asuMax) {
116
+ JSObject o = new JSObject();
117
+ o.put("type", type);
118
+ o.put("dBm", dBm);
119
+ o.put("asu", asu);
120
+ o.put("level", level);
121
+ o.put("asuMax", asuMax);
122
+ return o;
123
+ }
124
+ }