Compare commits

..

25 commits
1.1 ... 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
39 changed files with 375 additions and 143 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 *.iml
.gradle /.gradle
/local.properties /local.properties
/.idea/caches /.idea
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store .DS_Store
/build /build
/captures /captures
@ -14,3 +9,4 @@
.cxx .cxx
local.properties local.properties
*:Zone.Identifier *: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-03T21:19:00.040945900Z" />
</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.5" />
<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.75" />
<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 # MobiDL
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. ## 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 minSdk 23
targetSdk 31 targetSdk 31
versionCode 1 versionCode 1
versionName "1.1" versionName "1.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
@ -32,11 +32,12 @@ android {
} }
dependencies { dependencies {
implementation 'androidx.core:core-ktx:1.6.0' implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.4.0' implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
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,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>

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.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>(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
@ -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".
} }
} }

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

@ -197,7 +197,7 @@ class Scraper(
} }
elements["downloadLinks"] = try { elements["downloadLinks"] = try {
htmlPage = htmlPage.replace(Regex("Download Instructions:</span>(.*?)?<br />"), htmlPage = htmlPage.replace(Regex("Download Instructions:</span>(.*?)?<br />"),
"Download Instructions:</span><br /><s") "Download Instructions:</span><br />")
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

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

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

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

View file

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

View file

@ -5,7 +5,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { 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" 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.0.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME