RemoteSharedLibraryManager.kt (4869B) - raw


      1 package me.rhunk.snapenhance
      2 
      3 import android.annotation.SuppressLint
      4 import android.app.Notification
      5 import android.app.NotificationChannel
      6 import android.app.NotificationManager
      7 import android.app.PendingIntent
      8 import android.content.Intent
      9 import android.os.Build
     10 import androidx.core.net.toUri
     11 import me.rhunk.snapenhance.common.BuildConfig
     12 import me.rhunk.snapenhance.common.bridge.InternalFileHandleType
     13 import okhttp3.OkHttpClient
     14 import okhttp3.Request
     15 import java.io.File
     16 
     17 class RemoteSharedLibraryManager(
     18     private val remoteSideContext: RemoteSideContext
     19 ) {
     20     private val okHttpClient = OkHttpClient()
     21 
     22     private fun getVersion(): String? {
     23         return runCatching {
     24             okHttpClient.newCall(
     25                 Request.Builder()
     26                     .url("${BuildConfig.SIF_ENDPOINT}/version")
     27                     .build()
     28             ).execute().use { response ->
     29                 if (!response.isSuccessful) {
     30                     return null
     31                 }
     32                 response.body.string()
     33             }
     34         }.getOrNull()
     35     }
     36 
     37     private fun downloadLatest(outputFile: File): Boolean {
     38         val abi = Build.SUPPORTED_ABIS.firstOrNull() ?: return false
     39         val request = Request.Builder()
     40             .url("${BuildConfig.SIF_ENDPOINT}/$abi.so")
     41             .build()
     42         runCatching {
     43             okHttpClient.newCall(request).execute().use { response ->
     44                 if (!response.isSuccessful) {
     45                     return false
     46                 }
     47                 response.body.byteStream().use { input ->
     48                     outputFile.outputStream().use { output ->
     49                         input.copyTo(output)
     50                     }
     51                 }
     52                 return true
     53             }
     54         }.onFailure {
     55             remoteSideContext.log.error("Failed to download latest sif", it)
     56         }
     57         return false
     58     }
     59 
     60     @SuppressLint("ApplySharedPref")
     61     fun init() {
     62         val libraryFile = InternalFileHandleType.SIF.resolve(remoteSideContext.androidContext)
     63         val currentVersion = remoteSideContext.sharedPreferences.getString("sif", null)?.trim()
     64         if (currentVersion == null || currentVersion == "false") {
     65             libraryFile.takeIf { it.exists() }?.delete()
     66             remoteSideContext.log.info("sif can't be loaded due to user preference")
     67             return
     68         }
     69         val latestVersion = getVersion()?.trim() ?: run {
     70             throw Exception("Failed to get latest sif version")
     71         }
     72 
     73         if (currentVersion == latestVersion) {
     74             remoteSideContext.log.info("sif is up to date ($currentVersion)")
     75             return
     76         }
     77 
     78         remoteSideContext.log.info("Updating sif from $currentVersion to $latestVersion")
     79         if (downloadLatest(libraryFile)) {
     80             remoteSideContext.sharedPreferences.edit().putString("sif", latestVersion).commit()
     81             remoteSideContext.shortToast("SIF updated to $latestVersion!")
     82 
     83             if (currentVersion.isNotEmpty()) {
     84                 val notificationManager = remoteSideContext.androidContext.getSystemService(NotificationManager::class.java)
     85                 val channelId = "sif_update"
     86 
     87                 notificationManager.createNotificationChannel(
     88                     NotificationChannel(
     89                         channelId,
     90                         "SIF Updates",
     91                         NotificationManager.IMPORTANCE_DEFAULT
     92                     )
     93                 )
     94 
     95                 notificationManager.notify(
     96                     System.nanoTime().toInt(),
     97                     Notification.Builder(remoteSideContext.androidContext, channelId)
     98                         .setContentTitle("SnapEnhance")
     99                         .setContentText("Security Features have been updated to version $latestVersion")
    100                         .setSmallIcon(android.R.drawable.stat_sys_download_done)
    101                         .setContentIntent(PendingIntent.getActivity(
    102                             remoteSideContext.androidContext,
    103                             0,
    104                             Intent().apply {
    105                                 action = Intent.ACTION_VIEW
    106                                 data = "https://github.com/SnapEnhance/resources".toUri()
    107                                 flags = Intent.FLAG_ACTIVITY_NEW_TASK
    108                             },
    109                             PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    110                         )).build()
    111                 )
    112             }
    113 
    114             // force restart snapchat
    115             runCatching {
    116                 remoteSideContext.config.configStateListener?.takeIf { it.asBinder().pingBinder() }?.onRestartRequired()
    117             }
    118         } else {
    119             remoteSideContext.log.warn("Failed to download latest sif")
    120             throw Exception("Failed to download latest sif")
    121         }
    122     }
    123 }