mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	inapp updater and intent and dubbedanime
This commit is contained in:
		
							parent
							
								
									d12a8894ae
								
							
						
					
					
						commit
						1886fcd80e
					
				
					 13 changed files with 438 additions and 20 deletions
				
			
		|  | @ -30,11 +30,24 @@ | |||
|                 android:supportsPictureInPicture="true"> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.MAIN"/> | ||||
| 
 | ||||
|                 <category android:name="android.intent.category.LAUNCHER"/> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.VIEW"/> | ||||
| 
 | ||||
|                 <category android:name="android.intent.category.BROWSABLE"/> | ||||
|                 <category android:name="android.intent.category.DEFAULT"/> | ||||
| 
 | ||||
|                 <data android:scheme="https" android:host="bestdubbedanime.com" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="tenshi.moe" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="www.wcostream.com" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="wcostream.cc" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="hdm.to" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="lookmovie.io" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="trailers.to" android:pathPrefix="/"/> | ||||
|                 <data android:scheme="https" android:host="www.vmovee.watch" android:pathPrefix="/"/> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
| 
 | ||||
|         <receiver | ||||
|                 android:name=".receivers.VideoDownloadRestartReceiver" | ||||
|  |  | |||
|  | @ -5,10 +5,7 @@ import androidx.preference.PreferenceManager | |||
| import com.fasterxml.jackson.databind.DeserializationFeature | ||||
| import com.fasterxml.jackson.databind.json.JsonMapper | ||||
| import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||
| import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider | ||||
| import com.lagradost.cloudstream3.animeproviders.TenshiProvider | ||||
| import com.lagradost.cloudstream3.animeproviders.WatchCartoonOnlineProvider | ||||
| import com.lagradost.cloudstream3.animeproviders.WcoProvider | ||||
| import com.lagradost.cloudstream3.animeproviders.* | ||||
| import com.lagradost.cloudstream3.movieproviders.HDMProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.TrailersToProvider | ||||
| import com.lagradost.cloudstream3.movieproviders.VMoveeProvider | ||||
|  | @ -25,6 +22,8 @@ val mapper = JsonMapper.builder().addModule(KotlinModule()) | |||
| object APIHolder { | ||||
|     val unixTime: Long | ||||
|         get() = System.currentTimeMillis() / 1000L | ||||
|     val unixTimeMS: Long | ||||
|         get() = System.currentTimeMillis() | ||||
| 
 | ||||
|     private const val defProvider = 0 | ||||
| 
 | ||||
|  | @ -117,11 +116,11 @@ abstract class MainAPI { | |||
|         return null | ||||
|     } | ||||
| 
 | ||||
|     open fun search(query: String): ArrayList<SearchResponse>? { | ||||
|     open fun search(query: String): List<SearchResponse>? { | ||||
|         return null | ||||
|     } | ||||
| 
 | ||||
|     open fun quickSearch(query: String): ArrayList<SearchResponse>? { | ||||
|     open fun quickSearch(query: String): List<SearchResponse>? { | ||||
|         return null | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,8 +32,10 @@ import com.lagradost.cloudstream3.utils.DataStore.getKey | |||
| import com.lagradost.cloudstream3.utils.DataStore.removeKey | ||||
| import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos | ||||
| import com.lagradost.cloudstream3.utils.Event | ||||
| import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate | ||||
| import kotlinx.android.synthetic.main.activity_main.* | ||||
| import kotlinx.android.synthetic.main.fragment_result.* | ||||
| import kotlin.concurrent.thread | ||||
| 
 | ||||
| const val VLC_PACKAGE = "org.videolan.vlc" | ||||
| const val VLC_INTENT_ACTION_RESULT = "org.videolan.vlc.player.result" | ||||
|  | @ -295,6 +297,10 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener { | |||
|             createISO() | ||||
|         }*/ | ||||
|         handleAppIntent(intent) | ||||
| 
 | ||||
|         thread { | ||||
|             runAutoUpdate() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty | |||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.unixTime | ||||
| import com.lagradost.cloudstream3.APIHolder.unixTimeMS | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -17,6 +18,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         get() = "DubbedAnime" | ||||
|     override val hasQuickSearch: Boolean | ||||
|         get() = true | ||||
|     override val hasMainPage: Boolean | ||||
|         get() = true | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf( | ||||
|  | @ -57,6 +60,67 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         @JsonProperty("tags") val tags: String,*/ | ||||
|     ) | ||||
| 
 | ||||
|     private fun parseDocumentTrending(url: String): List<SearchResponse> { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         return document.select("li > a").map { | ||||
|             val href = fixUrl(it.attr("href")) | ||||
|             val title = it.selectFirst("> div > div.cittx").text() | ||||
|             val poster = fixUrl(it.selectFirst("> div > div.imghddde > img").attr("src")) | ||||
|             AnimeSearchResponse( | ||||
|                 title, | ||||
|                 href, | ||||
|                 this.name, | ||||
|                 TvType.Anime, | ||||
|                 poster, | ||||
|                 null, | ||||
|                 null, | ||||
|                 EnumSet.of(DubStatus.Dubbed), | ||||
|                 null, | ||||
|                 null | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun parseDocument(url: String, trimEpisode: Boolean = false): List<SearchResponse> { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         return document.select("a.grid__link").map { | ||||
|             val href = fixUrl(it.attr("href")) | ||||
|             val title = it.selectFirst("> div.gridtitlek").text() | ||||
|             val poster = fixUrl(it.selectFirst("> img.grid__img").attr("src")) | ||||
|             AnimeSearchResponse( | ||||
|                 title, | ||||
|                 if (trimEpisode) href.removeRange(href.lastIndexOf('/'), href.length) else href, | ||||
|                 this.name, | ||||
|                 TvType.Anime, | ||||
|                 poster, | ||||
|                 null, | ||||
|                 null, | ||||
|                 EnumSet.of(DubStatus.Dubbed), | ||||
|                 null, | ||||
|                 null | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun getMainPage(): HomePageResponse { | ||||
|         val trendingUrl = "$mainUrl/xz/trending.php?_=$unixTimeMS" | ||||
|         val lastEpisodeUrl = "$mainUrl/xz/epgrid.php?p=1&_=$unixTimeMS" | ||||
|         val recentlyAddedUrl = "$mainUrl/xz/gridgrabrecent.php?p=1&_=$unixTimeMS" | ||||
|         //val allUrl = "$mainUrl/xz/gridgrab.php?p=1&limit=12&_=$unixTimeMS" | ||||
| 
 | ||||
|         val listItems = listOf( | ||||
|             HomePageList("Trending", parseDocumentTrending(trendingUrl)), | ||||
|             HomePageList("Recently Added", parseDocument(recentlyAddedUrl)), | ||||
|             HomePageList("Recent Releases", parseDocument(lastEpisodeUrl, true)), | ||||
|            // HomePageList("All", parseDocument(allUrl)) | ||||
|         ) | ||||
| 
 | ||||
|         return HomePageResponse(listItems) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     private fun getAnimeEpisode(slug: String, isMovie: Boolean): EpisodeInfo { | ||||
|         val url = | ||||
|             mainUrl + (if (isMovie) "/movies/jsonMovie" else "/xz/v3/jsonEpi") + ".php?slug=$slug&_=$unixTime" | ||||
|  | @ -76,8 +140,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         return href.replace("$mainUrl/", "") | ||||
|     } | ||||
| 
 | ||||
|     override fun quickSearch(query: String): ArrayList<SearchResponse> { | ||||
|         val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=${unixTime}" | ||||
|     override fun quickSearch(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=$unixTime" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val items = document.select("div.grid__item > a") | ||||
|  | @ -111,7 +175,7 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         return returnValue | ||||
|     } | ||||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/search/$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|  | @ -188,9 +252,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val slug = url.replace("$mainUrl/","") | ||||
|         if (getIsMovie(slug)) { | ||||
|             val realSlug = slug.replace("movies/", "") | ||||
|         if (getIsMovie(url)) { | ||||
|             val realSlug = url.replace("movies/", "") | ||||
|             val episode = getAnimeEpisode(realSlug, true) | ||||
|             val poster = episode.previewImg ?: episode.wideImg | ||||
|             return MovieLoadResponse( | ||||
|  | @ -205,7 +268,7 @@ class DubbedAnimeProvider : MainAPI() { | |||
|                 null | ||||
|             ) | ||||
|         } else { | ||||
|             val response = khttp.get("$mainUrl/$slug") | ||||
|             val response = khttp.get(url) | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             val title = document.selectFirst("h4").text() | ||||
|             val descriptHeader = document.selectFirst("div.animeDescript") | ||||
|  | @ -220,7 +283,18 @@ class DubbedAnimeProvider : MainAPI() { | |||
| 
 | ||||
|             val img = fixUrl(document.select("div.fkimgs > img").attr("src")) | ||||
|             return AnimeLoadResponse( | ||||
|                 null, null, title, "$mainUrl/$slug", this.name, TvType.Anime, img, year, ArrayList(episodes), null, null, descript, | ||||
|                 null, | ||||
|                 null, | ||||
|                 title, | ||||
|                 url, | ||||
|                 this.name, | ||||
|                 TvType.Anime, | ||||
|                 img, | ||||
|                 year, | ||||
|                 ArrayList(episodes), | ||||
|                 null, | ||||
|                 null, | ||||
|                 descript, | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -18,8 +18,7 @@ class APIRepository(val api: MainAPI) { | |||
| 
 | ||||
|     suspend fun load(url: String): Resource<LoadResponse> { | ||||
|         return safeApiCall { | ||||
|             // remove suffix for some slugs to handle correctly | ||||
|             api.load(url.removeSuffix("/")) ?: throw ErrorLoadingException() | ||||
|             api.load(api.fixUrl(url)) ?: throw ErrorLoadingException() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -30,7 +29,7 @@ class APIRepository(val api: MainAPI) { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     suspend fun quickSearch(query: String): Resource<ArrayList<SearchResponse>> { | ||||
|     suspend fun quickSearch(query: String): Resource<List<SearchResponse>> { | ||||
|         return safeApiCall { | ||||
|             api.quickSearch(query) ?: throw ErrorLoadingException() | ||||
|         } | ||||
|  |  | |||
|  | @ -122,7 +122,12 @@ class HomeFragment : Fragment() { | |||
|             val MAX_BREAK_COUNT = 10 | ||||
| 
 | ||||
|             while (random?.posterUrl == null) { | ||||
|                 random = home.items.random().list.random() | ||||
|                 try { | ||||
|                     random = home.items.random().list.random() | ||||
|                 } catch (e : Exception) { | ||||
|                     // probs Collection is empty. | ||||
|                 } | ||||
| 
 | ||||
|                 breakCount++ | ||||
|                 if (breakCount > MAX_BREAK_COUNT) { | ||||
|                     break | ||||
|  |  | |||
|  | @ -1,16 +1,30 @@ | |||
| package com.lagradost.cloudstream3.ui.settings | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.widget.Toast | ||||
| import androidx.preference.Preference | ||||
| import androidx.preference.PreferenceFragmentCompat | ||||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment | ||||
| import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate | ||||
| import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard | ||||
| import kotlin.concurrent.thread | ||||
| 
 | ||||
| class SettingsFragment : PreferenceFragmentCompat() { | ||||
|     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { | ||||
|         hideKeyboard() | ||||
|         setPreferencesFromResource(R.xml.settings, rootKey) | ||||
|         val updatePrefrence = findPreference<Preference>(getString(R.string.manual_check_update_key))!! | ||||
|         updatePrefrence.setOnPreferenceClickListener { | ||||
|             thread { | ||||
|                 if (!requireActivity().runAutoUpdate(false)) { | ||||
|                     activity?.runOnUiThread { | ||||
|                         Toast.makeText(this.context, "No Update Found", Toast.LENGTH_SHORT).show() | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return@setOnPreferenceClickListener true | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onPreferenceTreeClick(preference: Preference?): Boolean { | ||||
|  |  | |||
|  | @ -0,0 +1,283 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import android.app.Activity | ||||
| import android.content.Intent | ||||
| import android.net.Uri | ||||
| import android.os.Build | ||||
| import android.widget.Toast | ||||
| import androidx.appcompat.app.AlertDialog | ||||
| import androidx.core.app.NotificationManagerCompat | ||||
| import androidx.core.content.FileProvider | ||||
| import androidx.preference.PreferenceManager | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.databind.DeserializationFeature | ||||
| import com.fasterxml.jackson.databind.json.JsonMapper | ||||
| import com.fasterxml.jackson.module.kotlin.KotlinModule | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.BuildConfig | ||||
| import com.lagradost.cloudstream3.R | ||||
| import java.io.* | ||||
| import java.net.URL | ||||
| import java.net.URLConnection | ||||
| import kotlin.concurrent.thread | ||||
| 
 | ||||
| const val UPDATE_TIME = 1000 | ||||
| 
 | ||||
| class InAppUpdater { | ||||
|     companion object { | ||||
|         // === IN APP UPDATER === | ||||
|         data class GithubAsset( | ||||
|             @JsonProperty("name") val name: String, | ||||
|             @JsonProperty("size") val size: Int, // Size bytes | ||||
|             @JsonProperty("browser_download_url") val browser_download_url: String, // download link | ||||
|             @JsonProperty("content_type") val content_type: String, // application/vnd.android.package-archive | ||||
|         ) | ||||
| 
 | ||||
|         data class GithubRelease( | ||||
|             @JsonProperty("tag_name") val tag_name: String, // Version code | ||||
|             @JsonProperty("body") val body: String, // Desc | ||||
|             @JsonProperty("assets") val assets: List<GithubAsset>, | ||||
|             @JsonProperty("target_commitish") val target_commitish: String, // branch | ||||
|         ) | ||||
| 
 | ||||
|         data class Update( | ||||
|             @JsonProperty("shouldUpdate") val shouldUpdate: Boolean, | ||||
|             @JsonProperty("updateURL") val updateURL: String?, | ||||
|             @JsonProperty("updateVersion") val updateVersion: String?, | ||||
|             @JsonProperty("changelog") val changelog: String?, | ||||
|         ) | ||||
| 
 | ||||
|         private val mapper = JsonMapper.builder().addModule(KotlinModule()) | ||||
|             .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build() | ||||
| 
 | ||||
|         private fun Activity.getAppUpdate(): Update { | ||||
|             try { | ||||
|                 val url = "https://api.github.com/repos/LagradOst/CloudStream-3/releases" | ||||
|                 val headers = mapOf("Accept" to "application/vnd.github.v3+json") | ||||
|                 val response = | ||||
|                     mapper.readValue<List<GithubRelease>>(khttp.get(url, headers = headers).text) | ||||
| 
 | ||||
|                 val versionRegex = Regex("""(.*?((\d)\.(\d)\.(\d)).*\.apk)""") | ||||
| 
 | ||||
|                 /* | ||||
|                 val releases = response.map { it.assets }.flatten() | ||||
|                     .filter { it.content_type == "application/vnd.android.package-archive" } | ||||
|                 val found = | ||||
|                     releases.sortedWith(compareBy { | ||||
|                         versionRegex.find(it.name)?.groupValues?.get(2) | ||||
|                     }).toList().lastOrNull()*/ | ||||
|                 val found = | ||||
|                     response.sortedWith(compareBy { release -> | ||||
|                         release.assets.filter { it.content_type == "application/vnd.android.package-archive" } | ||||
|                             .getOrNull(0)?.name?.let { it1 -> | ||||
|                                 versionRegex.find( | ||||
|                                     it1 | ||||
|                                 )?.groupValues?.get(2) | ||||
|                             } | ||||
|                     }).toList().lastOrNull() | ||||
|                 val foundAsset = found?.assets?.getOrNull(0) | ||||
|                 val currentVersion = packageName?.let { | ||||
|                     packageManager.getPackageInfo(it, | ||||
|                         0) | ||||
|                 } | ||||
| 
 | ||||
|                 val foundVersion = foundAsset?.name?.let { versionRegex.find(it) } | ||||
|                 val shouldUpdate = if (found != null && foundAsset?.browser_download_url != "" && foundVersion != null) currentVersion?.versionName?.compareTo( | ||||
|                     foundVersion.groupValues[2] | ||||
|                 )!! < 0 else false | ||||
|                 return if (foundVersion != null) { | ||||
|                     Update(shouldUpdate, foundAsset.browser_download_url, foundVersion.groupValues[2], found.body) | ||||
|                 } else { | ||||
|                     Update(false, null, null, null) | ||||
|                 } | ||||
| 
 | ||||
|             } catch (e: Exception) { | ||||
|                 println(e) | ||||
|                 return Update(false, null, null, null) | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private fun Activity.downloadUpdate(url: String): Boolean { | ||||
|             println("DOWNLOAD UPDATE $url") | ||||
|             var fullResume = false // IF FULL RESUME | ||||
|             try { | ||||
|                 // =================== DOWNLOAD POSTERS AND SETUP PATH =================== | ||||
|                 val path = filesDir.toString() + | ||||
|                         "/Download/apk/update.apk" | ||||
| 
 | ||||
|                 // =================== MAKE DIRS =================== | ||||
|                 val rFile = File(path) | ||||
|                 try { | ||||
|                     rFile.parentFile?.mkdirs() | ||||
|                 } catch (_ex: Exception) { | ||||
|                     println("FAILED:::$_ex") | ||||
|                 } | ||||
|                 val url = url.replace(" ", "%20") | ||||
| 
 | ||||
|                 val _url = URL(url) | ||||
| 
 | ||||
|                 val connection: URLConnection = _url.openConnection() | ||||
| 
 | ||||
|                 var bytesRead = 0L | ||||
| 
 | ||||
|                 // =================== STORAGE =================== | ||||
|                 try { | ||||
|                     if (!rFile.exists()) { | ||||
|                         rFile.createNewFile() | ||||
|                     } else { | ||||
|                         rFile.delete() | ||||
|                         rFile.createNewFile() | ||||
|                     } | ||||
|                 } catch (e: Exception) { | ||||
|                     println(e) | ||||
|                     runOnUiThread { | ||||
|                         Toast.makeText(this, "Permission error", Toast.LENGTH_SHORT).show() | ||||
|                     } | ||||
|                     return false | ||||
|                 } | ||||
| 
 | ||||
|                 // =================== CONNECTION =================== | ||||
|                 connection.setRequestProperty("Accept-Encoding", "identity") | ||||
|                 connection.connectTimeout = 10000 | ||||
|                 var clen = 0 | ||||
|                 try { | ||||
|                     connection.connect() | ||||
|                     clen = connection.contentLength | ||||
|                     println("CONTENTN LENGTH: $clen") | ||||
|                 } catch (_ex: Exception) { | ||||
|                     println("CONNECT:::$_ex") | ||||
|                     _ex.printStackTrace() | ||||
|                 } | ||||
| 
 | ||||
|                 // =================== VALIDATE =================== | ||||
|                 if (clen < 5000000) { // min of 5 MB | ||||
|                     clen = 0 | ||||
|                 } | ||||
|                 if (clen <= 0) { // TO SMALL OR INVALID | ||||
|                     //showNot(0, 0, 0, DownloadType.IsFailed, info) | ||||
|                     return false | ||||
|                 } | ||||
| 
 | ||||
|                 // =================== SETUP VARIABLES =================== | ||||
|                 //val bytesTotal: Long = (clen + bytesRead.toInt()).toLong() | ||||
|                 val input: InputStream = BufferedInputStream(connection.inputStream) | ||||
|                 val output: OutputStream = FileOutputStream(rFile, false) | ||||
|                 var bytesPerSec = 0L | ||||
|                 val buffer = ByteArray(1024) | ||||
|                 var count: Int | ||||
|                 //var lastUpdate = System.currentTimeMillis() | ||||
| 
 | ||||
|                 while (true) { | ||||
|                     try { | ||||
|                         count = input.read(buffer) | ||||
|                         if (count < 0) break | ||||
| 
 | ||||
|                         bytesRead += count | ||||
|                         bytesPerSec += count | ||||
|                         output.write(buffer, 0, count) | ||||
|                     } catch (_ex: Exception) { | ||||
|                         println("CONNECT TRUE:::$_ex") | ||||
|                         _ex.printStackTrace() | ||||
|                         fullResume = true | ||||
|                         break | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (fullResume) { // IF FULL RESUME DELETE CURRENT AND DONT SHOW DONE | ||||
|                     with(NotificationManagerCompat.from(this)) { | ||||
|                         cancel(-1) | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 output.flush() | ||||
|                 output.close() | ||||
|                 input.close() | ||||
| 
 | ||||
|                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { | ||||
|                     val contentUri = FileProvider.getUriForFile( | ||||
|                         this, | ||||
|                         BuildConfig.APPLICATION_ID + ".provider", | ||||
|                         rFile | ||||
|                     ) | ||||
|                     val install = Intent(Intent.ACTION_VIEW) | ||||
|                     install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) | ||||
|                     install.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) | ||||
|                     install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true) | ||||
|                     install.data = contentUri | ||||
|                     startActivity(install) | ||||
|                     return true | ||||
|                 } else { | ||||
|                     val apkUri = Uri.fromFile(rFile) | ||||
|                     val install = Intent(Intent.ACTION_VIEW) | ||||
|                     install.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP | ||||
|                     install.setDataAndType( | ||||
|                         apkUri, | ||||
|                         "application/vnd.android.package-archive" | ||||
|                     ) | ||||
|                     startActivity(install) | ||||
|                     return true | ||||
|                 } | ||||
| 
 | ||||
|             } catch (_ex: Exception) { | ||||
|                 println("FATAL EX DOWNLOADING:::$_ex") | ||||
|                 return false | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         fun Activity.runAutoUpdate(checkAutoUpdate: Boolean = true): Boolean { | ||||
|             val settingsManager = PreferenceManager.getDefaultSharedPreferences(this) | ||||
| 
 | ||||
|             if (!checkAutoUpdate || settingsManager.getBoolean(getString(R.string.auto_update_key), true) | ||||
|             ) { | ||||
|                 val update = getAppUpdate() | ||||
|                 if (update.shouldUpdate && update.updateURL != null) { | ||||
|                     runOnUiThread { | ||||
|                         val currentVersion = packageName?.let { | ||||
|                             packageManager.getPackageInfo(it, | ||||
|                                 0) | ||||
|                         } | ||||
| 
 | ||||
|                         val builder: AlertDialog.Builder = AlertDialog.Builder(this) | ||||
|                         builder.setTitle("New update found!\n${currentVersion?.versionName} -> ${update.updateVersion}") | ||||
|                         builder.setMessage("${update.changelog}") | ||||
| 
 | ||||
|                         val context = this | ||||
|                         builder.apply { | ||||
|                             setPositiveButton("Update") { _, _ -> | ||||
|                                 Toast.makeText(context, "Download started", Toast.LENGTH_LONG).show() | ||||
|                                 thread { | ||||
|                                     val downloadStatus = context.downloadUpdate(update.updateURL) | ||||
|                                     if (!downloadStatus) { | ||||
|                                         runOnUiThread { | ||||
|                                             Toast.makeText(context, | ||||
|                                                 "Download Failed", | ||||
|                                                 Toast.LENGTH_LONG).show() | ||||
|                                         } | ||||
|                                     } /*else { | ||||
|                                         activity.runOnUiThread { | ||||
|                                             Toast.makeText(localContext, | ||||
|                                                 "Downloaded APK", | ||||
|                                                 Toast.LENGTH_LONG).show() | ||||
|                                         } | ||||
|                                     }*/ | ||||
|                                 } | ||||
|                             } | ||||
| 
 | ||||
|                             setNegativeButton("Cancel") { _, _ -> } | ||||
| 
 | ||||
|                             if(checkAutoUpdate) { | ||||
|                                 setNeutralButton("Don't show again") { _, _ -> | ||||
|                                     settingsManager.edit().putBoolean("auto_update", false).apply() | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         builder.show() | ||||
|                     } | ||||
|                     return true | ||||
|                 } | ||||
|                 return false | ||||
|             } | ||||
|             return false | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| <vector android:height="24dp" android:tint="#FFFFFF" | ||||
|     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="M7.58,4.08L6.15,2.65C3.75,4.48 2.17,7.3 2.03,10.5h2c0.15,-2.65 1.51,-4.97 3.55,-6.42zM19.97,10.5h2c-0.15,-3.2 -1.73,-6.02 -4.12,-7.85l-1.42,1.43c2.02,1.45 3.39,3.77 3.54,6.42zM18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2v-5zM12,22c0.14,0 0.27,-0.01 0.4,-0.04 0.65,-0.14 1.18,-0.58 1.44,-1.18 0.1,-0.24 0.15,-0.5 0.15,-0.78h-4c0.01,1.1 0.9,2 2.01,2z"/> | ||||
| </vector> | ||||
|  | @ -0,0 +1,5 @@ | |||
| <vector android:height="24dp" android:tint="#FFFFFF" | ||||
|     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="M17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19L7,19L7,5h10v14zM16,13h-3L13,8h-2v5L8,13l4,4 4,-4z"/> | ||||
| </vector> | ||||
|  | @ -87,6 +87,7 @@ | |||
|                         android:id="@+id/home_main_poster" | ||||
|                         tools:src="@drawable/example_poster" | ||||
|                         android:layout_gravity="center" | ||||
|                         android:scaleType="centerCrop" | ||||
|                         android:layout_width="150dp" | ||||
|                         android:layout_height="212dp" | ||||
|                         android:contentDescription="@string/home_main_poster"> | ||||
|  |  | |||
|  | @ -83,4 +83,6 @@ | |||
|     <string name="subs_font">Font</string> | ||||
|     <string name="search_provider_text_providers">Search using providers</string> | ||||
|     <string name="search_provider_text_types">Search using types</string> | ||||
|     <string name="auto_update_key">auto_update</string> | ||||
|     <string name="manual_check_update_key">manual_check_update</string> | ||||
| </resources> | ||||
|  | @ -84,6 +84,18 @@ | |||
|                 android:summaryOff="Only sends data on crashes" | ||||
|                 android:summaryOn="Sends no data" | ||||
|                 android:defaultValue="false"/> | ||||
|         <SwitchPreference | ||||
|                 app:key="@string/auto_update_key" | ||||
|                 android:title="Show app updates" | ||||
|                 android:summary="Automatically search for new updates on start" | ||||
|                 app:defaultValue="true" | ||||
|                 android:icon="@drawable/ic_baseline_notifications_active_24" | ||||
|         /> | ||||
|         <Preference | ||||
|                 android:title="Check for Update" | ||||
|                 app:key="@string/manual_check_update_key" | ||||
|                 app:icon="@drawable/ic_baseline_system_update_24" | ||||
|         /> | ||||
|         <Preference | ||||
|                 android:title="Github" | ||||
|                 android:icon="@drawable/ic_github_logo" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue