🆕 Adding Notification support
This commit is contained in:
parent
ce6dca5363
commit
c5fc622d8c
7 changed files with 352 additions and 26 deletions
|
@ -1,7 +1,11 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.mylloon.mobidl" >
|
package="com.mylloon.mobidl" >
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
|
tools:ignore="QueryAllPackagesPermission" />
|
||||||
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -23,6 +27,16 @@
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="preloaded_fonts"
|
android:name="preloaded_fonts"
|
||||||
android:resource="@array/preloaded_fonts" />
|
android:resource="@array/preloaded_fonts" />
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name="BootReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
4
app/src/main/assets/appNames.json
Normal file
4
app/src/main/assets/appNames.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"tiktok": "musically",
|
||||||
|
"twitch livestream multiplayer": "twitch"
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ package com.mylloon.mobidl
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.AlertDialog
|
import android.app.AlertDialog
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
@ -16,20 +17,73 @@ import android.os.Looper
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.text.method.ScrollingMovementMethod
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.work.*
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import android.text.method.ScrollingMovementMethod
|
import java.util.concurrent.ExecutionException
|
||||||
import android.util.DisplayMetrics
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
private fun isWorkScheduled(context: Context): Boolean {
|
||||||
|
val instance = WorkManager.getInstance(context)
|
||||||
|
val statuses = instance.getWorkInfosByTag("com.mylloon.mobidl.BackgroundUpdateCheck")
|
||||||
|
return try {
|
||||||
|
var running = false
|
||||||
|
val workInfoList = statuses.get()
|
||||||
|
for (workInfo in workInfoList) {
|
||||||
|
val state = workInfo.state
|
||||||
|
running = (state == WorkInfo.State.RUNNING) or (state == WorkInfo.State.ENQUEUED)
|
||||||
|
}
|
||||||
|
running
|
||||||
|
} catch (e: ExecutionException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
println("No job already running")
|
||||||
|
false
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
println("No job already running")
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun newJob(context: Context) {
|
||||||
|
val myConstraints = Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(NetworkType.CONNECTED) //checks whether device should have Network Connection
|
||||||
|
.build()
|
||||||
|
val job = PeriodicWorkRequestBuilder<BackgroundUpdateCheck>(15, TimeUnit.MINUTES)
|
||||||
|
.setConstraints(myConstraints)
|
||||||
|
.build()
|
||||||
|
WorkManager.getInstance(context).enqueue(job)
|
||||||
|
}
|
||||||
|
|
||||||
|
class BootReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (!isWorkScheduled(context)) {
|
||||||
|
println("Create a update check job in background...")
|
||||||
|
when (intent.action) {
|
||||||
|
Intent.ACTION_DATE_CHANGED -> {
|
||||||
|
newJob(context)
|
||||||
|
}
|
||||||
|
Intent.ACTION_BOOT_COMPLETED -> {
|
||||||
|
val sharedPref = context.getSharedPreferences("com.mylloon.MobiDL",
|
||||||
|
AppCompatActivity.MODE_PRIVATE)
|
||||||
|
sharedPref.edit().putInt("notifID", 0).apply()
|
||||||
|
newJob(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private var settingsButton: Menu? = null // before starting the app there is no settings button
|
private var settingsButton: Menu? = null // before starting the app there is no settings button
|
||||||
|
@ -37,8 +91,8 @@ class MainActivity : AppCompatActivity() {
|
||||||
private var inSettings: Boolean = false // by default your not in settings page
|
private var inSettings: Boolean = false // by default your not in settings page
|
||||||
private var inAppList: Boolean = false // by default your not in app list page
|
private var inAppList: Boolean = false // by default your not in app list page
|
||||||
private var inAppInfo: Boolean = false // by default your not in app info page
|
private var inAppInfo: Boolean = false // by default your not in app info page
|
||||||
private var prefs: SharedPreferences? = null // first run detection
|
private var sharedPref: SharedPreferences? = null // first run detection
|
||||||
private val sharedPref = "com.mylloon.MobiDL" // shared pref name
|
private val sharedPrefName = "com.mylloon.MobiDL" // shared pref name
|
||||||
private var timeOfLastToast: Long = System.currentTimeMillis() - 2000
|
private var timeOfLastToast: Long = System.currentTimeMillis() - 2000
|
||||||
private var listInfos: MutableList<Map<String, String?>>? = null
|
private var listInfos: MutableList<Map<String, String?>>? = null
|
||||||
private var appMobilismInfos: Map<String, String?>? = null
|
private var appMobilismInfos: Map<String, String?>? = null
|
||||||
|
@ -64,15 +118,54 @@ class MainActivity : AppCompatActivity() {
|
||||||
val context = applicationContext() // get app context
|
val context = applicationContext() // get app context
|
||||||
|
|
||||||
// read apps from the app preference
|
// read apps from the app preference
|
||||||
val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
|
val sharedPref = context.getSharedPreferences(sharedPrefName, MODE_PRIVATE)
|
||||||
val data: Set<String>? = sharedPref.getStringSet("apps", null)
|
val data: Set<String>? = sharedPref.getStringSet("apps", null)
|
||||||
|
|
||||||
return data?.toMutableList() ?: mutableListOf()
|
return data?.toMutableList() ?: mutableListOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getValuesAppNeedToBeUpdated(): MutableMap<String, Boolean> { // list of the apps (from the storage if exists)
|
||||||
|
val context = applicationContext() // get app context
|
||||||
|
|
||||||
|
// read apps from the app preference
|
||||||
|
val sharedPref = context.getSharedPreferences(sharedPrefName, MODE_PRIVATE)
|
||||||
|
val dataApp: Set<String>? = sharedPref.getStringSet("appsUpdate", null)
|
||||||
|
val dataBool: Set<String>? = sharedPref.getStringSet("boolUpdate", null)
|
||||||
|
val dataAppList = dataApp?.toList()
|
||||||
|
val dataBoolList = dataBool?.toList()
|
||||||
|
|
||||||
|
val finalMap = mutableMapOf<String, Boolean>()
|
||||||
|
if ((dataAppList != null) and (dataBoolList != null)) {
|
||||||
|
for (i in dataAppList!!.indices) {
|
||||||
|
if (i in dataBoolList!!.indices) {
|
||||||
|
finalMap[dataAppList[i]] =
|
||||||
|
dataBoolList[i].substring(i.toString().length).toBoolean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun storeValuesAppNeedToBeUpdated(updateApps: MutableMap<String, Boolean>) {
|
||||||
|
val updateAppsName: Set<String> = updateApps.keys
|
||||||
|
val updateAppsBool: MutableCollection<Boolean> = updateApps.values
|
||||||
|
val updateAppsBoolList: List<Boolean> = updateAppsBool.toList()
|
||||||
|
val updateAppsBoolSet: MutableList<String> = mutableListOf()
|
||||||
|
for (i in updateAppsBoolList.indices) {
|
||||||
|
updateAppsBoolSet.add(i.toString() + updateAppsBoolList[i].toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
with(applicationContext().getSharedPreferences(sharedPrefName, MODE_PRIVATE).edit()) {
|
||||||
|
this?.putStringSet("appsUpdate", updateAppsName)
|
||||||
|
this?.putStringSet("boolUpdate", updateAppsBoolSet.toSet())
|
||||||
|
this?.apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) { // Main function
|
override fun onCreate(savedInstanceState: Bundle?) { // Main function
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
prefs = getSharedPreferences("com.mylloon.MobiDL", MODE_PRIVATE)
|
sharedPref = getSharedPreferences(sharedPrefName, MODE_PRIVATE)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (Credentials().get(0) == null) { // test if credentials have already been registered
|
if (Credentials().get(0) == null) { // test if credentials have already been registered
|
||||||
|
@ -128,6 +221,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
private fun mainPage(toDelete: String? = null) {
|
private fun mainPage(toDelete: String? = null) {
|
||||||
if (toDelete == null) {
|
if (toDelete == null) {
|
||||||
setContentView(R.layout.activity_main) // display main page
|
setContentView(R.layout.activity_main) // display main page
|
||||||
|
if (!isWorkScheduled(applicationContext)) newJob(applicationContext) // run background job if not already running
|
||||||
if (!settingsButtonVisible) { // check if the settings button isn't already showed
|
if (!settingsButtonVisible) { // check if the settings button isn't already showed
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
toggleSettingsButtonVisibility()
|
toggleSettingsButtonVisibility()
|
||||||
|
@ -137,6 +231,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
val user = Credentials().get(0).toString()
|
val user = Credentials().get(0).toString()
|
||||||
this.title = "${getString(R.string.app_name)} (${getString(R.string.connected_as)} $user)"
|
this.title = "${getString(R.string.app_name)} (${getString(R.string.connected_as)} $user)"
|
||||||
val valuesRecyclerView = getValuesRecyclerView() // list of all the element in the main page
|
val valuesRecyclerView = getValuesRecyclerView() // list of all the element in the main page
|
||||||
|
val checkedItemListOfApps = getValuesAppNeedToBeUpdated()
|
||||||
|
|
||||||
class Adapter(private val values: List<String>) :
|
class Adapter(private val values: List<String>) :
|
||||||
RecyclerView.Adapter<Adapter.ViewHolder>() {
|
RecyclerView.Adapter<Adapter.ViewHolder>() {
|
||||||
|
@ -163,20 +258,30 @@ class MainActivity : AppCompatActivity() {
|
||||||
button?.setOnLongClickListener {
|
button?.setOnLongClickListener {
|
||||||
val builder: AlertDialog.Builder =
|
val builder: AlertDialog.Builder =
|
||||||
AlertDialog.Builder(instance)
|
AlertDialog.Builder(instance)
|
||||||
builder.setTitle("${getString(R.string.remove)} ${button?.text} ?")
|
builder.setTitle("${getString(R.string.config)} ${button?.text} ?")
|
||||||
builder.setPositiveButton(R.string.remove) { _, _ ->
|
builder.setPositiveButton(R.string.remove) { _, _ ->
|
||||||
instance?.mainPage(
|
instance?.mainPage(
|
||||||
button?.text.toString()
|
button?.text.toString()
|
||||||
)
|
)
|
||||||
|
checkedItemListOfApps[button?.text.toString()] = false
|
||||||
|
storeValuesAppNeedToBeUpdated(checkedItemListOfApps)
|
||||||
}
|
}
|
||||||
val checkedItems = booleanArrayOf(
|
val appInstalled = isItAnInstalledApp(button?.text.toString())
|
||||||
false // get this info from the app files somewhere
|
if (appInstalled != null) {
|
||||||
)
|
val checkedItems = booleanArrayOf(
|
||||||
builder.setMultiChoiceItems(
|
checkedItemListOfApps[button?.text.toString()] == true
|
||||||
arrayOf(getString(R.string.updateCheck)),
|
)
|
||||||
checkedItems
|
builder.setMultiChoiceItems(
|
||||||
) { _, _, isChecked ->
|
arrayOf(getString(R.string.updateCheck)),
|
||||||
println("Update for ${button?.text.toString()}: " + if (isChecked) "enabled" else "disabled" + "")
|
checkedItems
|
||||||
|
) { _, _, isChecked ->
|
||||||
|
checkedItemListOfApps[button?.text.toString()] = isChecked
|
||||||
|
storeValuesAppNeedToBeUpdated(checkedItemListOfApps)
|
||||||
|
}
|
||||||
|
builder.setNegativeButton(R.string.forceUpdate) { _, _ ->
|
||||||
|
Notif().work(applicationContext,
|
||||||
|
button?.text.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
builder.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.cancel() }
|
builder.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.cancel() }
|
||||||
builder.show()
|
builder.show()
|
||||||
|
@ -205,11 +310,8 @@ class MainActivity : AppCompatActivity() {
|
||||||
if (toDelete != null) {
|
if (toDelete != null) {
|
||||||
valuesRecyclerView.remove(toDelete)
|
valuesRecyclerView.remove(toDelete)
|
||||||
|
|
||||||
val context = applicationContext() // get app context
|
|
||||||
|
|
||||||
// read apps from the app preference
|
// read apps from the app preference
|
||||||
val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
|
sharedPref!!.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply()
|
||||||
sharedPref.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply()
|
|
||||||
recyclerView.adapter = Adapter(valuesRecyclerView)
|
recyclerView.adapter = Adapter(valuesRecyclerView)
|
||||||
}
|
}
|
||||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
recyclerView.layoutManager = LinearLayoutManager(this)
|
||||||
|
@ -219,11 +321,8 @@ class MainActivity : AppCompatActivity() {
|
||||||
fun addApp(app: String) {
|
fun addApp(app: String) {
|
||||||
valuesRecyclerView.add(app)
|
valuesRecyclerView.add(app)
|
||||||
|
|
||||||
val context = applicationContext() // get app context
|
|
||||||
|
|
||||||
// read apps from the app preference
|
// read apps from the app preference
|
||||||
val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
|
sharedPref!!.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply()
|
||||||
sharedPref.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply()
|
|
||||||
recyclerView.adapter = Adapter(valuesRecyclerView)
|
recyclerView.adapter = Adapter(valuesRecyclerView)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -249,6 +348,21 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isItAnInstalledApp(app: String): String? {
|
||||||
|
var appName = app
|
||||||
|
val registeredAnswered: Map<String, String> = Gson().fromJson(
|
||||||
|
assets.open("appNames.json").bufferedReader()
|
||||||
|
.use { it.readText() },
|
||||||
|
object : TypeToken<Map<String, String>>() {}.type
|
||||||
|
)
|
||||||
|
for ((key, value) in registeredAnswered) appName =
|
||||||
|
if (Regex(appName.lowercase()).containsMatchIn(key)) value else appName.lowercase()
|
||||||
|
for (packageInfo in packageManager.getInstalledPackages(PackageManager.GET_META_DATA)) {
|
||||||
|
if (Regex(appName).containsMatchIn(packageInfo.packageName)) return packageInfo.versionName
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun callScrapper(
|
private fun callScrapper(
|
||||||
user: String,
|
user: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
@ -470,9 +584,13 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val title = findViewById<TextView>(R.id.textViewAppName)
|
val title = findViewById<TextView>(R.id.textViewAppName)
|
||||||
title.text = appMobilismInfos!!["title"]
|
title.text = appMobilismInfos!!["title"]
|
||||||
title.setOnClickListener { startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://forum.mobilism.org$link"))) }
|
title.setOnClickListener {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW,
|
||||||
|
Uri.parse("https://forum.mobilism.org$link")))
|
||||||
|
}
|
||||||
findViewById<TextView>(R.id.textViewAppAuthor).text = appMobilismInfos!!["author"]
|
findViewById<TextView>(R.id.textViewAppAuthor).text = appMobilismInfos!!["author"]
|
||||||
findViewById<TextView>(R.id.textViewAppDate).text = appMobilismInfos!!["date"]
|
findViewById<TextView>(R.id.textViewAppDate).text = appMobilismInfos!!["date"]
|
||||||
val changelogs = findViewById<TextView>(R.id.textViewAppChangelogs)
|
val changelogs = findViewById<TextView>(R.id.textViewAppChangelogs)
|
||||||
|
@ -527,9 +645,9 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (prefs!!.getBoolean("firstrun", true)) {
|
if (sharedPref!!.getBoolean("firstrun", true)) {
|
||||||
Credentials().generateKey() // Generate RSA keys
|
Credentials().generateKey() // Generate RSA keys
|
||||||
prefs!!.edit().putBoolean("firstrun", false)
|
sharedPref!!.edit().putBoolean("firstrun", false)
|
||||||
.apply() // first run done, now the next ones won't be "first".
|
.apply() // first run done, now the next ones won't be "first".
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
169
app/src/main/java/com/mylloon/mobidl/Notification.kt
Normal file
169
app/src/main/java/com/mylloon/mobidl/Notification.kt
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
package com.mylloon.mobidl
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Notification
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.work.Worker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
|
||||||
|
var sharedPrefName = "com.mylloon.MobiDL" // shared pref name
|
||||||
|
|
||||||
|
class BackgroundUpdateCheck(appContext: Context, workerParams: WorkerParameters) :
|
||||||
|
Worker(appContext, workerParams) {
|
||||||
|
private val ctx = appContext
|
||||||
|
|
||||||
|
override fun doWork(): Result {
|
||||||
|
fun getValuesAppNeedToBeUpdated(): MutableMap<String, Boolean> { // list of the apps (from the storage if exists)
|
||||||
|
val context = MainActivity.applicationContext() // get app context
|
||||||
|
|
||||||
|
// read apps from the app preference
|
||||||
|
val sharedPref = context.getSharedPreferences(sharedPrefName,
|
||||||
|
AppCompatActivity.MODE_PRIVATE)
|
||||||
|
val dataApp: Set<String>? = sharedPref.getStringSet("appsUpdate", null)
|
||||||
|
val dataBool: Set<String>? = sharedPref.getStringSet("boolUpdate", null)
|
||||||
|
val dataAppList = dataApp?.toList()
|
||||||
|
val dataBoolList = dataBool?.toList()
|
||||||
|
|
||||||
|
val finalMap = mutableMapOf<String, Boolean>()
|
||||||
|
if ((dataAppList != null) and (dataBoolList != null)) {
|
||||||
|
for (i in dataAppList!!.indices) {
|
||||||
|
if (i in dataBoolList!!.indices) {
|
||||||
|
finalMap[dataAppList[i]] =
|
||||||
|
dataBoolList[i].substring(i.toString().length).toBoolean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalMap
|
||||||
|
}
|
||||||
|
val apps = getValuesAppNeedToBeUpdated()
|
||||||
|
for (app in apps.keys) {
|
||||||
|
if (apps[app] == true) {
|
||||||
|
println("Checking update for $app...")
|
||||||
|
Notif().work(ctx, app)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println("Update check: Done.")
|
||||||
|
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Notif {
|
||||||
|
private lateinit var notificationManager: NotificationManager
|
||||||
|
private lateinit var notificationChannel: NotificationChannel
|
||||||
|
private lateinit var builder: Notification.Builder
|
||||||
|
private val channelId = "i.apps.notifications"
|
||||||
|
private val description = R.string.descriptionNotification
|
||||||
|
|
||||||
|
@SuppressLint("UnspecifiedImmutableFlag")
|
||||||
|
fun newNotification(
|
||||||
|
context: Context,
|
||||||
|
notificationID: Int,
|
||||||
|
appName: String,
|
||||||
|
version: String,
|
||||||
|
url: String,
|
||||||
|
) {
|
||||||
|
notificationManager = context.getSystemService(NotificationManager::class.java)
|
||||||
|
val pendingIntent = PendingIntent.getActivity(context,
|
||||||
|
notificationID,
|
||||||
|
Intent(Intent.ACTION_VIEW, Uri.parse(url)),
|
||||||
|
(PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // checking if android version is greater than oreo(API 26) or not
|
||||||
|
notificationChannel = NotificationChannel(channelId,
|
||||||
|
context.getString(description),
|
||||||
|
NotificationManager.IMPORTANCE_LOW)
|
||||||
|
notificationChannel.enableLights(true)
|
||||||
|
notificationChannel.lightColor = Color.GREEN
|
||||||
|
notificationChannel.enableVibration(false)
|
||||||
|
notificationManager.createNotificationChannel(notificationChannel)
|
||||||
|
|
||||||
|
builder = Notification.Builder(context, channelId)
|
||||||
|
.setContentTitle("${context.getString(R.string.newUpdateTitleNotification)} $appName")
|
||||||
|
.setContentText("${context.getString(R.string.newUpdateVersionNotification)} $version ${
|
||||||
|
context.getString(R.string.newUpdateAvailableNotification)
|
||||||
|
}")
|
||||||
|
.setSmallIcon(R.drawable.download)
|
||||||
|
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher))
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
} else {
|
||||||
|
builder = Notification.Builder(context)
|
||||||
|
.setContentTitle("${context.getString(R.string.newUpdateTitleNotification)} $appName")
|
||||||
|
.setContentText("${context.getString(R.string.newUpdateVersionNotification)} $version ${
|
||||||
|
context.getString(R.string.newUpdateAvailableNotification)
|
||||||
|
}")
|
||||||
|
.setSmallIcon(R.drawable.download)
|
||||||
|
.setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher))
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
}
|
||||||
|
notificationManager.notify(notificationID, builder.build())
|
||||||
|
val sharedPref =
|
||||||
|
context.getSharedPreferences(sharedPrefName, AppCompatActivity.MODE_PRIVATE)
|
||||||
|
sharedPref.edit().putInt("notifID", notificationID + 1).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun work(context: Context, app: String) {
|
||||||
|
var appName = app
|
||||||
|
val registeredAnswered: Map<String, String> = Gson().fromJson(
|
||||||
|
context.assets.open("appNames.json").bufferedReader()
|
||||||
|
.use { it.readText() },
|
||||||
|
object : TypeToken<Map<String, String>>() {}.type
|
||||||
|
)
|
||||||
|
for ((key, value) in registeredAnswered) appName =
|
||||||
|
if (Regex(appName.lowercase()).containsMatchIn(key)) value else appName.lowercase()
|
||||||
|
var installedAppVersion: String? = null
|
||||||
|
for (packageInfo in context.packageManager.getInstalledPackages(PackageManager.GET_META_DATA)) {
|
||||||
|
if (Regex(appName).containsMatchIn(packageInfo.packageName)) installedAppVersion =
|
||||||
|
packageInfo.versionName
|
||||||
|
}
|
||||||
|
if (installedAppVersion == null) return
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
val res =
|
||||||
|
Scraper(Credentials().get(0), Credentials().get(1), app).search() ?: return
|
||||||
|
if (res[0].containsKey("gotResults")) {
|
||||||
|
var latestVersion = res[1]["title"]!!
|
||||||
|
latestVersion = Regex("""(?<=v?)\d+\.\d+(\.\d+)?""").findAll(latestVersion)
|
||||||
|
.map { it.groupValues[0] }.toList()[0]
|
||||||
|
val arrayInstalledVersion: MutableList<String> =
|
||||||
|
installedAppVersion.split(".") as MutableList<String>
|
||||||
|
val arrayLatestVersion: MutableList<String> =
|
||||||
|
latestVersion.split(".") as MutableList<String>
|
||||||
|
while (arrayInstalledVersion.size > arrayLatestVersion.size) arrayLatestVersion.add(
|
||||||
|
"0")
|
||||||
|
while (arrayInstalledVersion.size < arrayLatestVersion.size) arrayInstalledVersion.add(
|
||||||
|
"0")
|
||||||
|
var needUpdate = false
|
||||||
|
for (i in arrayInstalledVersion.indices) {
|
||||||
|
if (arrayLatestVersion[i].toInt() > arrayInstalledVersion[i].toInt()) needUpdate =
|
||||||
|
true
|
||||||
|
}
|
||||||
|
if (needUpdate) {
|
||||||
|
val sharedPref = context.getSharedPreferences(sharedPrefName,
|
||||||
|
AppCompatActivity.MODE_PRIVATE)
|
||||||
|
return newNotification(context,
|
||||||
|
sharedPref.getInt("notifID", 0),
|
||||||
|
app,
|
||||||
|
latestVersion,
|
||||||
|
"https://forum.mobilism.org${res[1]["link"]}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
app/src/main/res/drawable/download.xml
Normal file
5
app/src/main/res/drawable/download.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#8E44AD"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z"/>
|
||||||
|
</vector>
|
|
@ -32,4 +32,11 @@
|
||||||
<string name="changelogs">Changements</string>
|
<string name="changelogs">Changements</string>
|
||||||
<string name="downloads">Téléchargements</string>
|
<string name="downloads">Téléchargements</string>
|
||||||
<string name="noLinkFound">Aucun lien trouvé</string>
|
<string name="noLinkFound">Aucun lien trouvé</string>
|
||||||
|
<string name="descriptionNotification">Mise à jour des applications</string>
|
||||||
|
<string name="newUpdateTitleNotification">Nouvelle version pour</string>
|
||||||
|
<string name="newUpdateVersionNotification">Version</string>
|
||||||
|
<string name="newUpdateAvailableNotification">disponible</string>
|
||||||
|
<string name="forceUpdate">Force recherche de MàJ</string>
|
||||||
|
<string name="rename">Renommer</string>
|
||||||
|
<string name="config">Configurer</string>
|
||||||
</resources>
|
</resources>
|
|
@ -13,11 +13,20 @@
|
||||||
<string name="newAppDialogTitle">New app name</string>
|
<string name="newAppDialogTitle">New app name</string>
|
||||||
<string name="validate">Validate</string>
|
<string name="validate">Validate</string>
|
||||||
<string name="remove">Remove</string>
|
<string name="remove">Remove</string>
|
||||||
|
<string name="config">Config</string>
|
||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
|
<string name="forceUpdate">Force update search</string>
|
||||||
|
<string name="rename">Rename</string>
|
||||||
<string name="updateCheck">Update check</string>
|
<string name="updateCheck">Update check</string>
|
||||||
<string name="notConnected">You are not logged in, redirection to the login page</string>
|
<string name="notConnected">You are not logged in, redirection to the login page</string>
|
||||||
<string name="dropBro">drop bro</string>
|
<string name="dropBro">drop bro</string>
|
||||||
|
|
||||||
|
<!-- Notifications -->
|
||||||
|
<string name="descriptionNotification">Application Update</string>
|
||||||
|
<string name="newUpdateTitleNotification">New version for</string>
|
||||||
|
<string name="newUpdateVersionNotification">Version</string>
|
||||||
|
<string name="newUpdateAvailableNotification">available</string>
|
||||||
|
|
||||||
<!-- Settings page -->
|
<!-- Settings page -->
|
||||||
<string name="titleSettings">Settings</string>
|
<string name="titleSettings">Settings</string>
|
||||||
<string name="changeCredentials">Change credentials</string>
|
<string name="changeCredentials">Change credentials</string>
|
||||||
|
|
Reference in a new issue