Compare commits

..

No commits in common. "android" and "1.0" have entirely different histories.
android ... 1.0

41 changed files with 158 additions and 413 deletions

1
.gitattributes vendored Normal file
View file

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

10
.gitignore vendored
View file

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

3
.idea/.gitignore vendored Normal file
View file

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

6
.idea/compiler.xml Normal file
View file

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

View file

@ -0,0 +1,17 @@
<?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>

20
.idea/gradle.xml Normal file
View file

@ -0,0 +1,20 @@
<?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

@ -0,0 +1,6 @@
<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>

34
.idea/misc.xml Normal file
View file

@ -0,0 +1,34 @@
<?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>

6
.idea/vcs.xml Normal file
View file

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

View file

@ -1,12 +1,4 @@
# MobiDL # Disclaimer
## 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.
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>
## Download Using Git LFS for the `.webp` files
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 minSdk 23
targetSdk 31 targetSdk 31
versionCode 1 versionCode 1
versionName "1.2.2" versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -32,12 +32,11 @@ android {
} }
dependencies { dependencies {
implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.5.0' implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3' implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
implementation 'com.github.kittinunf.fuel:fuel:2.3.1' implementation 'com.github.kittinunf.fuel:fuel:2.3.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1'
implementation 'com.google.code.gson:gson:2.8.6' implementation 'com.google.code.gson:gson:2.8.6'
implementation 'androidx.work:work-runtime-ktx:2.7.1'
} }

View file

@ -1,11 +1,7 @@
<?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"
@ -27,16 +23,6 @@
<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>

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View file

@ -4,7 +4,6 @@ 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
@ -17,73 +16,18 @@ 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 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() { 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
@ -91,8 +35,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 sharedPref: SharedPreferences? = null // first run detection private var prefs: SharedPreferences? = null // first run detection
private val sharedPrefName = "com.mylloon.MobiDL" // shared pref name private val sharedPref = "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
@ -118,54 +62,15 @@ 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(sharedPrefName, MODE_PRIVATE) val sharedPref = context.getSharedPreferences(sharedPref, 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)
sharedPref = getSharedPreferences(sharedPrefName, MODE_PRIVATE) prefs = getSharedPreferences("com.mylloon.MobiDL", 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
@ -221,7 +126,6 @@ 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()
@ -231,7 +135,6 @@ 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>() {
@ -258,30 +161,20 @@ 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.config)} ${button?.text} ?") builder.setTitle("${getString(R.string.remove)} ${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 appInstalled = isItAnInstalledApp(button?.text.toString())
if (appInstalled != null) {
val checkedItems = booleanArrayOf( val checkedItems = booleanArrayOf(
checkedItemListOfApps[button?.text.toString()] == true false // get this info from the app files somewhere
) )
builder.setMultiChoiceItems( builder.setMultiChoiceItems(
arrayOf(getString(R.string.updateCheck)), arrayOf(getString(R.string.updateCheck)),
checkedItems checkedItems
) { _, _, isChecked -> ) { _, _, isChecked ->
checkedItemListOfApps[button?.text.toString()] = isChecked println("Update for ${button?.text.toString()}: " + if (isChecked) "enabled" else "disabled" + "")
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()
@ -310,8 +203,11 @@ 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
sharedPref!!.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply() val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
sharedPref.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply()
recyclerView.adapter = Adapter(valuesRecyclerView) recyclerView.adapter = Adapter(valuesRecyclerView)
} }
recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.layoutManager = LinearLayoutManager(this)
@ -321,8 +217,11 @@ 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
sharedPref!!.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply() val sharedPref = context.getSharedPreferences(sharedPref, MODE_PRIVATE)
sharedPref.edit().putStringSet("apps", valuesRecyclerView.toSet()).apply()
recyclerView.adapter = Adapter(valuesRecyclerView) recyclerView.adapter = Adapter(valuesRecyclerView)
} }
@ -348,21 +247,6 @@ 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,
@ -525,28 +409,16 @@ class MainActivity : AppCompatActivity() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun showAppInfoPage() { private fun showAppInfoPage() {
val link = appMobilismInfos!!["link"]
if (link != null) {
val infoApp: MutableMap<String, String?>
var links: MutableMap<String, List<String>> = mutableMapOf()
var errorHappen = false
runBlocking {
infoApp = Scraper().parseInfos(link)
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 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 if (!settingsButtonVisible) toggleSettingsButtonVisibility() // check if the settings button isn't already showed and show it if necessary
inAppInfo = true inAppInfo = true
val link = appMobilismInfos!!["link"]
if (link != null) {
val infoApp: MutableMap<String, String?>
val links: MutableMap<String, List<String>>
runBlocking {
infoApp = Scraper().parseInfos(link)
links = Scraper().parseDownloadLinks(infoApp["downloadLinks"]!!)
} }
class Adapter(private val values: List<String>) : class Adapter(private val values: List<String>) :
RecyclerView.Adapter<Adapter.ViewHolder>() { RecyclerView.Adapter<Adapter.ViewHolder>() {
@ -584,26 +456,16 @@ 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.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) findViewById<TextView>(R.id.textViewAppChangelogs).text = infoApp["changelogs"]
changelogs.text = infoApp["changelogs"]
changelogs.movementMethod = ScrollingMovementMethod()
val listDownloads = mutableListOf<String>() val listDownloads = mutableListOf<String>()
for (arch in links.keys) {
val recyclerViewAppDownloads: RecyclerView = val recyclerViewAppDownloads: RecyclerView =
findViewById(R.id.recyclerViewAppDownloads) // get recyclerview findViewById(R.id.recyclerViewAppDownloads) // get recyclerview
recyclerViewAppDownloads.layoutManager = LinearLayoutManager(this) recyclerViewAppDownloads.layoutManager = LinearLayoutManager(this)
val displayMetrics = DisplayMetrics()
recyclerViewAppDownloads.layoutParams.height = displayMetrics.heightPixels / 3
for (arch in links.keys) {
for ((count, _) in links[arch]!!.withIndex()) { for ((count, _) in links[arch]!!.withIndex()) {
listDownloads += "$arch - ${count + 1}" listDownloads += "$arch - ${count + 1}"
} }
@ -645,9 +507,9 @@ class MainActivity : AppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (sharedPref!!.getBoolean("firstrun", true)) { if (prefs!!.getBoolean("firstrun", true)) {
Credentials().generateKey() // Generate RSA keys Credentials().generateKey() // Generate RSA keys
sharedPref!!.edit().putBoolean("firstrun", false) prefs!!.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".
} }
} }

View file

@ -1,169 +0,0 @@
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." "No changelog found."
} }
elements["downloadLinks"] = try { elements["downloadLinks"] = try {
htmlPage = htmlPage.replace(Regex("Download Instructions:</span>(.*?)?<br />"), htmlPage = htmlPage.replace(Regex("Download Instructions:</span>(.*?)?<br /><s"),
"Download Instructions:</span><br />") "Download Instructions:</span><br /><s")
var tmp = var tmp =
Regex("""Download Instructions:</span> ?<br />(.*|[\s\S]*)<br /><br />Trouble downloading|</a></div>""").findAll( Regex("""Download Instructions:</span> ?<br />(.*|[\s\S]*)<br /><br />Trouble downloading|</a></div>""").findAll(
htmlPage) htmlPage)

View file

@ -1,5 +0,0 @@
<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

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

View file

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

View file

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

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 130 B

View file

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

View file

@ -13,20 +13,11 @@
<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>
@ -49,5 +40,4 @@
<!-- App Infos --> <!-- App Infos -->
<string name="changelogs">Changelogs</string> <string name="changelogs">Changelogs</string>
<string name="downloads">Downloads</string> <string name="downloads">Downloads</string>
<string name="noLinkFound">No link found</string>
</resources> </resources>

View file

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

View file

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