Compare commits

...

29 commits
1.0 ... android

Author SHA1 Message Date
49b9eb30ae
No usage of LFS anymore 2022-04-07 14:36:29 +02:00
fb8fdc363c
Add release folder 🌈 2022-04-07 14:33:44 +02:00
49627608b0
Increment version number 2022-04-07 14:24:05 +02:00
Anri
6cdb5c365a Supprimer '.gitattributes' 2022-04-07 14:16:39 +02:00
8efb67cae8
Remove git LFS 2022-04-07 14:10:50 +02:00
ae54ac906f
Remove png from LFS 2022-04-07 14:09:46 +02:00
4f823c5b80
Update dependencies, fixing a crash on Android 12 2022-04-07 13:58:39 +02:00
7fd2ee8c3a
Suppression de fichiers inutiles 2022-04-07 13:42:33 +02:00
1b837b1b15
Upgrade Gradle from 7.0.2 to 7.1.2 2022-04-07 13:06:13 +02:00
1d8ab21c7e Update links 2021-10-29 09:13:22 +02:00
44018f0aaf Merge branch 'android' of gitlab.com:Mylloon/mobilismScrap into android 2021-09-05 12:40:51 +02:00
e945565a97 Remove IDE folder 2021-09-05 12:40:47 +02:00
3d3c219c7a Update README.md 2021-09-04 22:35:37 +00:00
27d02805c1 Better newline 2021-09-04 21:15:41 +02:00
4a9f1ad3ba Better newlines 2021-09-04 21:15:14 +02:00
f6936ee05c Bump from 1.2.0 to 1.2.1 2021-09-04 21:14:44 +02:00
4284123185 Change Background refresh time from 15 minutes to 1 day 2021-09-04 21:14:36 +02:00
d3972142f9 Adding link and requirements 2021-09-04 20:43:50 +02:00
d4e2d5e04a Using Git LFS 2021-09-04 20:43:16 +02:00
1b3cb334ee Adding *PNG 2021-09-04 20:43:10 +02:00
83bd139347 Bump from 1.1.1 to 1.2.0 2021-09-04 20:29:37 +02:00
c5fc622d8c 🆕 Adding Notification support 2021-09-04 20:29:22 +02:00
ce6dca5363 IDE 2021-09-04 20:28:18 +02:00
f0a570e23d Bump from 1.1 to 1.1.1 2021-09-04 00:06:36 +02:00
705880d5de Fix Link Parser 2021-09-04 00:02:55 +02:00
e82ad2c503 Bump from 1.0 to 1.1 2021-09-03 23:37:44 +02:00
d46282db17 💫 Fix Layout bug + Handle Crash bug 2021-09-03 23:37:36 +02:00
391d888908 ⬆ Increase downlaod button size 2021-09-03 23:36:38 +02:00
d2da8710bc IDE 2021-09-03 23:36:02 +02:00
41 changed files with 413 additions and 158 deletions

1
.gitattributes vendored
View file

@ -1 +0,0 @@
*.webp filter=lfs diff=lfs merge=lfs -text

10
.gitignore vendored
View file

@ -1,12 +1,7 @@
*.iml
.gradle
/.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea
.DS_Store
/build
/captures
@ -14,3 +9,4 @@
.cxx
local.properties
*:Zone.Identifier
app/release/

3
.idea/.gitignore vendored
View file

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

View file

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="C:\Users\anri\.android\avd\Mi_Note_10_Lite_API_30.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2021-09-02T10:40:03.136810500Z" />
</component>
</project>

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View file

@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AndroidElementNotAllowed" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View file

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable-v24/ic_launcher_foreground.xml" value="0.3402777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable/ic_launcher_background.xml" value="0.3402777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable/ic_launcher_foreground_test.xml" value="0.3402777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable/ic_plus.xml" value="0.20337837837837838" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable/ic_return.xml" value="0.3402777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable/ic_settings.xml" value="0.3402777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/drawable/shadow.xml" value="0.3277777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/activity_app_infos.xml" value="0.33" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/activity_app_list.xml" value="0.3015625" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/activity_login.xml" value="0.25" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/activity_main.xml" value="0.22" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/activity_settings.xml" value="0.25" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/activity_showInfos.xml" value="0.2171875" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/list_item_view.xml" value="0.29739583333333336" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/list_item_view_app_download.xml" value="0.228125" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/layout/list_item_view_app_list.xml" value="0.25729166666666664" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/menu/menu_main.xml" value="0.33" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.3402777777777778" />
<entry key="..\:/Users/anri/AndroidStudioProjects/MobiDL/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml" value="0.3402777777777778" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -1,4 +1,12 @@
# Disclaimer
This branch corresponds to the scraper written in Kotlin *for Android*, check [this branch](https://gitlab.com/Mylloon/mobilismScrap/-/tree/python) for the one written in Python.
# MobiDL
## Disclaimer
This branch corresponds to the scraper written in Kotlin *for Android*, check [this branch](https://git.kennel.ml/Anri/mobilismScrap/src/branch/python) for the one written in Python.<br>
Using Git LFS for the `.webp` files
## Download
You can download the app in the [release page](https://git.kennel.ml/Anri/mobilismScrap/releases).
Application compatible with Android 12.
### Requirements
Minimum: Android 6.0 (Marshmallow) <br>
Recommended: Android 8.0 (Oreo)

View file

@ -11,7 +11,7 @@ android {
minSdk 23
targetSdk 31
versionCode 1
versionName "1.0"
versionName "1.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@ -32,11 +32,12 @@ android {
}
dependencies {
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.github.kittinunf.fuel:fuel:2.3.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
}

View file

@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.mylloon.mobidl" >
<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
android:allowBackup="true"
@ -23,6 +27,16 @@
<meta-data
android:name="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>
</manifest>

View file

@ -0,0 +1,4 @@
{
"tiktok": "musically",
"twitch livestream multiplayer": "twitch"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

View file

@ -4,6 +4,7 @@ package com.mylloon.mobidl
import android.Manifest
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
@ -16,18 +17,73 @@ import android.os.Looper
import android.text.Editable
import android.text.InputType
import android.text.TextWatcher
import android.text.method.ScrollingMovementMethod
import android.util.DisplayMetrics
import android.view.*
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.*
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.*
import java.util.*
import java.util.concurrent.ExecutionException
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>(1, TimeUnit.DAYS)
.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() {
private var settingsButton: Menu? = null // before starting the app there is no settings button
@ -35,8 +91,8 @@ class MainActivity : AppCompatActivity() {
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 inAppInfo: Boolean = false // by default your not in app info page
private var prefs: SharedPreferences? = null // first run detection
private val sharedPref = "com.mylloon.MobiDL" // shared pref name
private var sharedPref: SharedPreferences? = null // first run detection
private val sharedPrefName = "com.mylloon.MobiDL" // shared pref name
private var timeOfLastToast: Long = System.currentTimeMillis() - 2000
private var listInfos: MutableList<Map<String, String?>>? = null
private var appMobilismInfos: Map<String, String?>? = null
@ -62,15 +118,54 @@ class MainActivity : AppCompatActivity() {
val context = applicationContext() // get app context
// 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)
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
super.onCreate(savedInstanceState)
prefs = getSharedPreferences("com.mylloon.MobiDL", MODE_PRIVATE)
sharedPref = getSharedPreferences(sharedPrefName, MODE_PRIVATE)
try {
if (Credentials().get(0) == null) { // test if credentials have already been registered
@ -126,6 +221,7 @@ class MainActivity : AppCompatActivity() {
private fun mainPage(toDelete: String? = null) {
if (toDelete == null) {
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
Handler(Looper.getMainLooper()).postDelayed({
toggleSettingsButtonVisibility()
@ -135,6 +231,7 @@ class MainActivity : AppCompatActivity() {
val user = Credentials().get(0).toString()
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 checkedItemListOfApps = getValuesAppNeedToBeUpdated()
class Adapter(private val values: List<String>) :
RecyclerView.Adapter<Adapter.ViewHolder>() {
@ -161,20 +258,30 @@ class MainActivity : AppCompatActivity() {
button?.setOnLongClickListener {
val builder: AlertDialog.Builder =
AlertDialog.Builder(instance)
builder.setTitle("${getString(R.string.remove)} ${button?.text} ?")
builder.setTitle("${getString(R.string.config)} ${button?.text} ?")
builder.setPositiveButton(R.string.remove) { _, _ ->
instance?.mainPage(
button?.text.toString()
)
checkedItemListOfApps[button?.text.toString()] = false
storeValuesAppNeedToBeUpdated(checkedItemListOfApps)
}
val checkedItems = booleanArrayOf(
false // get this info from the app files somewhere
)
builder.setMultiChoiceItems(
arrayOf(getString(R.string.updateCheck)),
checkedItems
) { _, _, isChecked ->
println("Update for ${button?.text.toString()}: " + if (isChecked) "enabled" else "disabled" + "")
val appInstalled = isItAnInstalledApp(button?.text.toString())
if (appInstalled != null) {
val checkedItems = booleanArrayOf(
checkedItemListOfApps[button?.text.toString()] == true
)
builder.setMultiChoiceItems(
arrayOf(getString(R.string.updateCheck)),
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.show()
@ -203,11 +310,8 @@ class MainActivity : AppCompatActivity() {
if (toDelete != null) {
valuesRecyclerView.remove(toDelete)
val context = applicationContext() // get app context
// 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.layoutManager = LinearLayoutManager(this)
@ -217,11 +321,8 @@ class MainActivity : AppCompatActivity() {
fun addApp(app: String) {
valuesRecyclerView.add(app)
val context = applicationContext() // get app context
// 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)
}
@ -247,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(
user: String,
password: String,
@ -409,16 +525,28 @@ class MainActivity : AppCompatActivity() {
@SuppressLint("SetTextI18n")
private fun showAppInfoPage() {
setContentView(R.layout.activity_app_infos) // display app info detailed page
if (!settingsButtonVisible) toggleSettingsButtonVisibility() // check if the settings button isn't already showed and show it if necessary
inAppInfo = true
val link = appMobilismInfos!!["link"]
if (link != null) {
val infoApp: MutableMap<String, String?>
val links: MutableMap<String, List<String>>
var links: MutableMap<String, List<String>> = mutableMapOf()
var errorHappen = false
runBlocking {
infoApp = Scraper().parseInfos(link)
links = Scraper().parseDownloadLinks(infoApp["downloadLinks"]!!)
try {
links = Scraper().parseDownloadLinks(infoApp["downloadLinks"]!!)
} catch (e: Exception) {
Toast.makeText(
instance,
"${getString(R.string.noLinkFound)}...",
Toast.LENGTH_SHORT
).show()
errorHappen = true
}
}
if (errorHappen) return else {
setContentView(R.layout.activity_app_infos) // display app info detailed page
if (!settingsButtonVisible) toggleSettingsButtonVisibility() // check if the settings button isn't already showed and show it if necessary
inAppInfo = true
}
class Adapter(private val values: List<String>) :
RecyclerView.Adapter<Adapter.ViewHolder>() {
@ -456,16 +584,26 @@ class MainActivity : AppCompatActivity() {
}
}
}
findViewById<TextView>(R.id.textViewAppName).text = appMobilismInfos!!["title"]
val title = findViewById<TextView>(R.id.textViewAppName)
title.text = appMobilismInfos!!["title"]
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.textViewAppDate).text = appMobilismInfos!!["date"]
findViewById<TextView>(R.id.textViewAppChangelogs).text = infoApp["changelogs"]
val changelogs = findViewById<TextView>(R.id.textViewAppChangelogs)
changelogs.text = infoApp["changelogs"]
changelogs.movementMethod = ScrollingMovementMethod()
val listDownloads = mutableListOf<String>()
val recyclerViewAppDownloads: RecyclerView =
findViewById(R.id.recyclerViewAppDownloads) // get recyclerview
recyclerViewAppDownloads.layoutManager = LinearLayoutManager(this)
val displayMetrics = DisplayMetrics()
recyclerViewAppDownloads.layoutParams.height = displayMetrics.heightPixels / 3
for (arch in links.keys) {
val recyclerViewAppDownloads: RecyclerView =
findViewById(R.id.recyclerViewAppDownloads) // get recyclerview
recyclerViewAppDownloads.layoutManager = LinearLayoutManager(this)
for ((count, _) in links[arch]!!.withIndex()) {
listDownloads += "$arch - ${count + 1}"
}
@ -507,9 +645,9 @@ class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
if (prefs!!.getBoolean("firstrun", true)) {
if (sharedPref!!.getBoolean("firstrun", true)) {
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".
}
}

View 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
}
}
}
}

View file

@ -196,8 +196,8 @@ class Scraper(
"No changelog found."
}
elements["downloadLinks"] = try {
htmlPage = htmlPage.replace(Regex("Download Instructions:</span>(.*?)?<br /><s"),
"Download Instructions:</span><br /><s")
htmlPage = htmlPage.replace(Regex("Download Instructions:</span>(.*?)?<br />"),
"Download Instructions:</span><br />")
var tmp =
Regex("""Download Instructions:</span> ?<br />(.*|[\s\S]*)<br /><br />Trouble downloading|</a></div>""").findAll(
htmlPage)

View 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>

View file

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:19994ee5e957b8d8f6a2fbef8e00b35d608d3e4d7a68911e67ca07047f5cf6ba
size 3360

View file

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c24a8e75ece7af2ac1671c9882d635c2986eaf5172984e7fcb77576bfe398865
size 5042

View file

@ -57,10 +57,11 @@
<TextView
android:id="@+id/textViewAppChangelogs"
android:layout_width="334dp"
android:layout_height="wrap_content"
android:layout_width="337dp"
android:layout_height="183dp"
android:layout_marginTop="12dp"
android:fontFamily="monospace"
android:scrollbars="vertical"
android:textAlignment="viewStart"
android:textSize="16sp"
android:textStyle="italic"
@ -83,14 +84,14 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerViewAppDownloads"
android:layout_width="334dp"
android:layout_height="524dp"
android:layout_width="350dp"
android:layout_height="262dp"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.493"
app:layout_constraintHorizontal_bias="0.491"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewAppDownloadsTitle"
app:layout_constraintVertical_bias="0.125" />
app:layout_constraintVertical_bias="0.036" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -3,7 +3,7 @@
android:id="@+id/linear_layout_app_list"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_height="70dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:paddingStart="5dp"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 B

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -31,4 +31,12 @@
<string name="noURL">Aucune URL n\'a été trouvé pour ce post</string>
<string name="changelogs">Changements</string>
<string name="downloads">Téléchargements</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>

View file

@ -13,11 +13,20 @@
<string name="newAppDialogTitle">New app name</string>
<string name="validate">Validate</string>
<string name="remove">Remove</string>
<string name="config">Config</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="notConnected">You are not logged in, redirection to the login page</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 -->
<string name="titleSettings">Settings</string>
<string name="changeCredentials">Change credentials</string>
@ -40,4 +49,5 @@
<!-- App Infos -->
<string name="changelogs">Changelogs</string>
<string name="downloads">Downloads</string>
<string name="noLinkFound">No link found</string>
</resources>

View file

@ -5,7 +5,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30"
// NOTE: Do not place your application dependencies here; they belong

View file

@ -1,6 +1,6 @@
#Wed Aug 25 01:29:46 CEST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME