Skip to content

Commit ec30622

Browse files
committed
Second commit, app is now usable
1 parent 0c5402c commit ec30622

24 files changed

Lines changed: 329 additions & 60 deletions

File tree

README.MD

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
1-
# Temperamon
2-
Simple floating window to show some device status controllable via Notification bar, for Android,
3-
sprinkled with my (and some of the contributors) ego.
1+
# FloatStat
2+
Simple, plugin-based floating window to show some device status controllable via Notification bar,
3+
for Android, sprinkled with my (and some of the contributors) ego.
44

55
## Features
66
- **Notification Control** - fast show/hide toggle
7-
- ***Kinda accurate* SoC Temperature reading** - Gives average of all recognized thermal zone state
8-
instead of reading just one. *Well, your phone is just a fist-size slab, average value should be suffice*
9-
- **** -
7+
- **Completely plugin-based** - Even the internal data provider is a plugin that have minimal
8+
ties to the main floating service, See [Plugin Creation](readme/CONTRIBS.MD#plugin) for more info.
9+
- **Simple** - Customizable, just not yet skinnable
10+
11+
### Internal Data
12+
- Network Traffic
13+
- *Kinda Accurate* SoC Temperature, but due to the size nature of a phone, battery temperature might be your best measure
14+
- Battery Temperature
15+
- RAM Usage
16+
- Battery Percentage
17+
1018

1119
## Why?
1220
Have you ever seen this kind of dialog?
13-
![Some annoying ad push notification confirmation dialog](readme/1.jpg)
14-
On some Phone / ROM (e.g My Nokia 6.1 Plus running Android 10), this kind of dialog cannot be
15-
responded when there is a floating window active due to some security concern. When you try to
16-
respond it, it will ask you to deactivate any floating window before you can really respond the
17-
dialog. My last app from other dev offering similar functionality will require me to open it's app
18-
to deactivate the floating window or revoke their permission from Settings, thus making it
19-
inefficient to just respond a dialog. Some app that does offer the notification-based control will
20-
asks you to buy the their "Pro" version or "Pro functionality" IAP, or the worst, The app have ads
21-
that triggered by their floating window that will fully cover the entire screen anytime and
22-
anywhere!
23-
<details>
24-
<summary><i>My complaints and cursing, but nvm.</i></summary>
25-
SHAME ON YOU, THE DEV IMPLEMENTING THE "ANYTIME AND ANYWHERE" ADS! I KNOW YOU NEED MONEY, ME TOO!
26-
JUST DON'T BE GREEDY AND ANNOY YOUR USER! MAY YOU BECAME CONSTANTLY H?RN? UNTIL YOU FIX YOUR APP!
27-
</details>
28-
29-
Well, Sometimes it's worth it to re-invent a new kind of wheel when the existing wheels needs too
21+
22+
![Some example of annoying ad push notification confirmation dialog](1.jpg)
23+
24+
On some Phone / ROM (e.g My Nokia 6.1 Plus running Android 10), this kind of dialog cannot be
25+
responded when there is a floating window active due to some security concern. When you try to
26+
respond it, it will ask you to deactivate any floating window before you can really respond the
27+
dialog.
28+
29+
Well, Sometimes it's worth it to re-invent a new kind of wheel when the existing wheels needs too
3030
much energy to roll over or is designed to work by constantly trampling your toes.
3131

32+
For some more info, See [Why](readme/WHY.MD)
33+
3234
## License
3335
Apache License 2.0, with some file is under Public Domain.

floatstat/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
66
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
7+
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
78
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
89
<application
910
android:allowBackup="true"
@@ -41,7 +42,7 @@
4142
android:exported="false">
4243
<intent-filter>
4344
<action android:name="id.psw.floatstat.action.START_PLUGIN"/>
44-
<category android:name="id.psw.floatstat.category.PLUGIN"/>
45+
<category android:name="id.psw.floatstat.category.DATA_PLUGIN"/>
4546
</intent-filter>
4647
</service>
4748
<provider

floatstat/src/main/java/id/psw/floatstat/App.kt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class App : Application() {
3939
const val PK_THREADED_UPDATE_FREQ = "KeseringanPembaruan"
4040
const val PK_ENABLED_PLUGIN = "TetambahanAktif"
4141
const val PK_DEFAULT_PLUGIN_DISPLAY = "TetambahanTampil"
42+
const val PK_RUN_ON_STARTUP = "MulaiPasHidup"
4243
}
4344

4445

@@ -126,6 +127,7 @@ class App : Application() {
126127
}
127128

128129
val pluginList = arrayListOf<PluginInfo>()
130+
private val displayNames = mutableMapOf<ComponentName, String>()
129131
private val pluginConnector = object : ServiceConnection {
130132
var hasBound = false
131133
private val TAG = "PluginQuery"
@@ -134,8 +136,9 @@ class App : Application() {
134136
if(service != null && name != null){
135137
val asPlugin = IFloatStatDataPlugin.Stub.asInterface(service)
136138
if(pluginList.count { it.name == name } == 0){
137-
Log.d(TAG, "$name -> ${asPlugin.pluginName}")
138-
val vInfo = PluginInfo(asPlugin, name, asPlugin.pluginName)
139+
val pluginDspName = displayNames[name] ?: name.toString() ?: "???"
140+
Log.d(TAG, "$name -> $pluginDspName")
141+
val vInfo = PluginInfo(asPlugin, name, pluginDspName)
139142
asPlugin.dataIds.split(',').forEach {
140143
val dName = asPlugin.getDataName(it)
141144
val dInfo = PluginDataInfo(
@@ -158,21 +161,21 @@ class App : Application() {
158161
}
159162

160163
private fun listPlugins(){
161-
val i = Intent(ACTION_START_PLUGIN)
162-
val pkgs = packageManager.queryIntentServices(i, 0)
164+
val i = Intent(ACTION_START_PLUGIN).addCategory(CATEGORY_PLUGIN)
165+
val dPkg = packageManager.queryIntentServices(i, 0)
163166
if(pluginConnector.hasBound){
164167
unbindService(pluginConnector)
165168
pluginConnector.hasBound = false
166169
}
167170
pluginList.clear()
168171

169-
pkgs.forEach {
172+
dPkg.forEach {
170173
try{
174+
val cName = ComponentName(it.serviceInfo.packageName, it.serviceInfo.name)
171175
val sbi = Intent(ACTION_START_PLUGIN)
172-
.setComponent(ComponentName(it.serviceInfo.packageName, it.serviceInfo.name))
176+
.setComponent(cName)
173177
.putExtra(PluginData.EXTRA_DATA_SENDER, packageName)
174-
175-
178+
displayNames[cName] = it.serviceInfo.loadLabel(packageManager).toString()
176179
if(!bindService(sbi, pluginConnector, BIND_AUTO_CREATE)){
177180
Log.d("App", "Cannot bind ${it.serviceInfo.name}")
178181
}
@@ -183,6 +186,7 @@ class App : Application() {
183186
}
184187

185188
var shouldUpdate = false
189+
var startOnBoot = false
186190

187191
var reReadPreference = false
188192
val activePlugins = arrayListOf<PluginId>()
@@ -220,6 +224,7 @@ class App : Application() {
220224
if(defPlug != null){
221225
defaultPlugin = PluginId(defPlug)
222226
}
227+
startOnBoot = pref.getBoolean(PK_RUN_ON_STARTUP, false)
223228
}
224229

225230
fun savePreferences(){
@@ -229,6 +234,7 @@ class App : Application() {
229234
.putLong(PK_THREADED_UPDATE_FREQ, updateFrequency)
230235
.putString(PK_ENABLED_PLUGIN, activePluginIds.toString())
231236
.putString(PK_DEFAULT_PLUGIN_DISPLAY, defaultPlugin.toString())
237+
.putBoolean(PK_RUN_ON_STARTUP, startOnBoot)
232238
.apply()
233239
}
234240

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package id.psw.floatstat
2+
3+
import android.content.BroadcastReceiver
4+
import android.content.Context
5+
import android.content.Intent
6+
import android.os.Build
7+
8+
class BootStartReceiver : BroadcastReceiver() {
9+
override fun onReceive(context: Context?, intent: Intent?) {
10+
if(context != null){
11+
if(context.app().startOnBoot){
12+
if(intent?.action == Intent.ACTION_BOOT_COMPLETED){
13+
FloatWindowService.startServiceS(context)
14+
}
15+
}
16+
}
17+
}
18+
}

floatstat/src/main/java/id/psw/floatstat/FloatWindowService.kt

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package id.psw.floatstat
22

33
import android.annotation.SuppressLint
44
import android.app.*
5+
import android.content.Context
56
import android.content.Intent
67
import android.content.res.Configuration
78
import android.graphics.*
@@ -37,6 +38,15 @@ class FloatWindowService : Service() {
3738
const val ACTION_CLOSE = "id.psw.temperamon.action.CLOSE"
3839
const val ACTION_EXPAND = "id.psw.temperamon.action.EXPAND"
3940
private const val allowEditor: Boolean = true
41+
42+
fun startServiceS(ctx: Context){
43+
val i = Intent(ctx, FloatWindowService::class.java)
44+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
45+
ctx.startForegroundService(i)
46+
}else{
47+
ctx.startService(i)
48+
}
49+
}
4050
}
4151

4252
private var vMainView : StatusView? = null
@@ -138,19 +148,19 @@ class FloatWindowService : Service() {
138148
val notifFlag = if(sdkAtLeast(Build.VERSION_CODES.M)) PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT else 0
139149

140150
val notif = NotificationCompat.Builder(this, NOTIF_ID)
141-
.setContentTitle("Floating Stats is running")
142-
.setContentText("Expand this notification to control the floating widget")
151+
.setContentTitle(getString(R.string.float_stat_notif_title))
152+
.setContentText(getString(R.string.float_stat_notif_desc))
143153
.setSmallIcon(R.drawable.ic_main_notification)
144154
.setSilent(true)
145155
.setContentIntent(PendingIntent.getService(this, INT_ACTION_EXPAND,
146156
Intent(ACTION_EXPAND), notifFlag))
147-
.addAction(android.R.drawable.ic_menu_view, "Show/Hide",
157+
.addAction(android.R.drawable.ic_menu_view, getString(R.string.float_stat_notif_visibility),
148158
PendingIntent.getService(this, INT_ACTION_VISIBILITY,
149159
Intent(ACTION_VISIBILITY), notifFlag))
150-
.addAction(android.R.drawable.ic_menu_edit, "Edit",
160+
.addAction(android.R.drawable.ic_menu_edit, getString(R.string.float_stat_notif_edit),
151161
PendingIntent.getService(this, INT_ACTION_EDIT,
152162
Intent(ACTION_EDIT), notifFlag))
153-
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Close",
163+
.addAction(android.R.drawable.ic_menu_close_clear_cancel, getString(R.string.float_stat_notif_close),
154164
PendingIntent.getService(this, INT_ACTION_CLOSE,
155165
Intent(ACTION_CLOSE), notifFlag))
156166
.build()
@@ -236,19 +246,25 @@ class FloatWindowService : Service() {
236246
setOnClickListener { btn ->
237247
PopupMenu(context, this).apply {
238248
menuInflater.inflate(R.menu.selector_menu, menu)
249+
menu.findItem(R.id.plugin_selector_bootstart).isChecked = app.startOnBoot
250+
239251
setOnMenuItemClickListener {
240252
when(it.itemId){
241253
R.id.plugin_selector_donate -> { app().openDonateUri() }
242254
R.id.plugin_selector_refresh -> {
243255
editWindow?.cancel()
244256
app().refreshPluginList()
245-
Toast.makeText(app, "Updating Data and Plugin List, The data selector list will re-open after 1 second,", Toast.LENGTH_LONG).show()
257+
Toast.makeText(app, context.getString(R.string.plugin_selector_updating_warning), Toast.LENGTH_LONG).show()
246258
Timer("UpdateWait", false).schedule(1000){
247259
wHandler.post {
248260
openEditWindow()
249261
}
250262
}
251263
}
264+
R.id.plugin_selector_bootstart -> {
265+
app.startOnBoot = !app.startOnBoot
266+
app.savePreferences()
267+
}
252268
}
253269
true
254270
}

floatstat/src/main/java/id/psw/floatstat/InternalStatProviderService.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,14 @@ class InternalStatProviderService : Service() {
216216
override val iconId: Int = IC_UPLINK
217217

218218
override val dataGetter: Long
219-
get() = TrafficStats.getMobileTxBytes()
219+
get() = TrafficStats.getTotalTxBytes()
220220
}
221221

222222
private val dnLinkData = object : IDeltaNetPlugin(){
223223
override val iconId: Int = IC_DOWNLINK
224224

225225
override val dataGetter: Long
226-
get() = TrafficStats.getMobileRxBytes()
226+
get() = TrafficStats.getTotalRxBytes()
227227
}
228228

229229
private val cpuTempData = object : IPlugin(){
@@ -379,10 +379,6 @@ class InternalStatProviderService : Service() {
379379
return sb.toString()
380380
}
381381

382-
override fun getPluginName(): String {
383-
return getString(R.string.internal_plugin_name)
384-
}
385-
386382
override fun getDataName(dataId: String?): String {
387383
return when(dataId) {
388384
DAT_BATTERY_INFO -> getString(R.string.internal_stat_battery_info)

floatstat/src/main/java/id/psw/floatstat/MainActivity.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,7 @@ class MainActivity : Activity() {
3131
}
3232

3333
private fun startWindowService() {
34-
val i = Intent(applicationContext, FloatWindowService::class.java)
35-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
36-
startForegroundService(i)
37-
}else{
38-
startService(i)
39-
}
34+
FloatWindowService.startServiceS(applicationContext)
4035
}
4136

4237
private fun askPermission() {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:height="24dp" android:tint="#FFFFFF"
2+
android:viewportHeight="24" android:viewportWidth="24"
3+
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="@android:color/white" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
5+
</vector>

floatstat/src/main/res/menu/selector_menu.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@
99
android:id="@+id/plugin_selector_donate"
1010
android:icon="@drawable/ic_donation"
1111
android:title="@string/selector_donate" />
12+
<item
13+
android:id="@+id/plugin_selector_bootstart"
14+
android:icon="@drawable/ic_bootstart"
15+
android:checkable="true"
16+
android:title="@string/selector_bootstart" />
1217
</menu>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<string name="app_name">Kondilayang</string>
4+
<string name="svc_name">Layanan Jendela Kondilayang</string>
5+
<string name="err_not_yet_allowed">Aplikasi belum diizinkan untuk berjalan diatas aplikasi lain</string>
6+
<string name="allow_please">Mohon untuk memperbolehkan aplikasi ini untuk berjalan diatas aplikasi lain</string>
7+
<string name="temperamon_start">Memulai Kondilayang, semua kendali ada di Bilah Pemberitahuan, kecuali kalau anda sembunyikan.</string>
8+
<string name="notif_channel_id">Kendali Kondilayang</string>
9+
<string name="internal_plugin_name">Bawaan</string>
10+
<string name="internal_stat_uplink">Kec. Unggah</string>
11+
<string name="internal_stat_downlink">Kec. Unduh</string>
12+
<string name="internal_stat_battery_info">Tingkat Baterai</string>
13+
<string name="internal_stat_ram_usage">P.gunaan RAM</string>
14+
<string name="internal_stat_temp_bat">Suhu Baterai</string>
15+
<string name="internal_stat_temp_cpu">Suhu CPU</string>
16+
<string name="internal_stat_service_name">Pemberi Data Bawaan</string>
17+
<string name="plugin_icon_error">Icon untuk data %1$s dari Pengaya %2$s rusak, atau mungkin tidak sah</string>
18+
<string name="title_plugin_selector">Pengatur Pengaya</string>
19+
<string name="selector_refresh_plugins">Perbarui Pengaya</string>
20+
<string name="selector_donate">Ikut Andil</string>
21+
<string name="svc_name_bootstart">Layanan Automulai Kondilayang</string>
22+
<string name="selector_bootstart">Mulai saat boot</string>
23+
<string name="plugin_selector_updating_warning">Memperbarui daftar pengaya data, pengatur pengaya akan dibuka lagi dalam 1 detik.</string>
24+
<string name="float_stat_notif_title">Kondilayang sedang berjalan</string>
25+
<string name="float_stat_notif_desc">Perluas pemberitahuan ini untuk menampilkan kendali jendela layang</string>
26+
<string name="float_stat_notif_visibility">Tampil/Sembunyi</string>
27+
<string name="float_stat_notif_edit">Ubah</string>
28+
<string name="float_stat_notif_close">Tutup</string>
29+
</resources>

0 commit comments

Comments
 (0)