mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-11-04 09:13:00 +00:00 
			
		
		
		
	Convert NewVersionWorker to Kotlin
This commit is contained in:
		@@ -1,175 +0,0 @@
 | 
			
		||||
package org.schabi.newpipe;
 | 
			
		||||
 | 
			
		||||
import android.app.PendingIntent;
 | 
			
		||||
import android.content.Context;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.content.SharedPreferences;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.util.Log;
 | 
			
		||||
 | 
			
		||||
import androidx.annotation.NonNull;
 | 
			
		||||
import androidx.core.app.NotificationCompat;
 | 
			
		||||
import androidx.core.app.NotificationManagerCompat;
 | 
			
		||||
import androidx.preference.PreferenceManager;
 | 
			
		||||
import androidx.work.OneTimeWorkRequest;
 | 
			
		||||
import androidx.work.WorkManager;
 | 
			
		||||
import androidx.work.WorkRequest;
 | 
			
		||||
import androidx.work.Worker;
 | 
			
		||||
import androidx.work.WorkerParameters;
 | 
			
		||||
 | 
			
		||||
import com.grack.nanojson.JsonObject;
 | 
			
		||||
import com.grack.nanojson.JsonParser;
 | 
			
		||||
import com.grack.nanojson.JsonParserException;
 | 
			
		||||
 | 
			
		||||
import org.schabi.newpipe.extractor.downloader.Response;
 | 
			
		||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
 | 
			
		||||
import org.schabi.newpipe.util.ReleaseVersionUtil;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
 | 
			
		||||
public final class NewVersionWorker extends Worker {
 | 
			
		||||
 | 
			
		||||
    private static final boolean DEBUG = MainActivity.DEBUG;
 | 
			
		||||
    private static final String TAG = NewVersionWorker.class.getSimpleName();
 | 
			
		||||
    private static final String NEWPIPE_API_URL = "https://newpipe.net/api/data.json";
 | 
			
		||||
 | 
			
		||||
    public NewVersionWorker(@NonNull final Context context,
 | 
			
		||||
                            @NonNull final WorkerParameters workerParams) {
 | 
			
		||||
        super(context, workerParams);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to compare the current and latest available app version.
 | 
			
		||||
     * If a newer version is available, we show the update notification.
 | 
			
		||||
     *
 | 
			
		||||
     * @param versionName    Name of new version
 | 
			
		||||
     * @param apkLocationUrl Url with the new apk
 | 
			
		||||
     * @param versionCode    Code of new version
 | 
			
		||||
     */
 | 
			
		||||
    private static void compareAppVersionAndShowNotification(final String versionName,
 | 
			
		||||
                                                            final String apkLocationUrl,
 | 
			
		||||
                                                            final int versionCode) {
 | 
			
		||||
        if (BuildConfig.VERSION_CODE >= versionCode) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final App app = App.getApp();
 | 
			
		||||
        // A pending intent to open the apk location url in the browser.
 | 
			
		||||
        final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl));
 | 
			
		||||
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 | 
			
		||||
        final PendingIntent pendingIntent = PendingIntent.getActivity(app, 0, intent, 0);
 | 
			
		||||
 | 
			
		||||
        final String channelId = app.getString(R.string.app_update_notification_channel_id);
 | 
			
		||||
        final NotificationCompat.Builder notificationBuilder
 | 
			
		||||
                = new NotificationCompat.Builder(app, channelId)
 | 
			
		||||
                .setSmallIcon(R.drawable.ic_newpipe_update)
 | 
			
		||||
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
 | 
			
		||||
                .setContentIntent(pendingIntent)
 | 
			
		||||
                .setAutoCancel(true)
 | 
			
		||||
                .setContentTitle(app.getString(R.string.app_update_notification_content_title))
 | 
			
		||||
                .setContentText(app.getString(R.string.app_update_notification_content_text)
 | 
			
		||||
                        + " " + versionName);
 | 
			
		||||
 | 
			
		||||
        final NotificationManagerCompat notificationManager
 | 
			
		||||
                = NotificationManagerCompat.from(app);
 | 
			
		||||
        notificationManager.notify(2000, notificationBuilder.build());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkNewVersion() throws IOException, ReCaptchaException {
 | 
			
		||||
        final App app = App.getApp();
 | 
			
		||||
 | 
			
		||||
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);
 | 
			
		||||
 | 
			
		||||
        // Check if the current apk is a github one or not.
 | 
			
		||||
        if (!ReleaseVersionUtil.isReleaseApk()) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check if the last request has happened a certain time ago
 | 
			
		||||
        // to reduce the number of API requests.
 | 
			
		||||
        final long expiry = prefs.getLong(app.getString(R.string.update_expiry_key), 0);
 | 
			
		||||
        if (!ReleaseVersionUtil.isLastUpdateCheckExpired(expiry)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Make a network request to get latest NewPipe data.
 | 
			
		||||
        final Response response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL);
 | 
			
		||||
        handleResponse(response);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void handleResponse(@NonNull final Response response) {
 | 
			
		||||
        final App app = App.getApp();
 | 
			
		||||
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);
 | 
			
		||||
        try {
 | 
			
		||||
            // Store a timestamp which needs to be exceeded,
 | 
			
		||||
            // before a new request to the API is made.
 | 
			
		||||
            final long newExpiry = ReleaseVersionUtil
 | 
			
		||||
                    .coerceUpdateCheckExpiry(response.getHeader("expires"));
 | 
			
		||||
            prefs.edit()
 | 
			
		||||
                    .putLong(app.getString(R.string.update_expiry_key), newExpiry)
 | 
			
		||||
                    .apply();
 | 
			
		||||
        } catch (final Exception e) {
 | 
			
		||||
            if (DEBUG) {
 | 
			
		||||
                Log.w(TAG, "Could not extract and save new expiry date", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Parse the json from the response.
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
            final JsonObject githubStableObject = JsonParser.object()
 | 
			
		||||
                    .from(response.responseBody()).getObject("flavors")
 | 
			
		||||
                    .getObject("github").getObject("stable");
 | 
			
		||||
 | 
			
		||||
            final String versionName = githubStableObject.getString("version");
 | 
			
		||||
            final int versionCode = githubStableObject.getInt("version_code");
 | 
			
		||||
            final String apkLocationUrl = githubStableObject.getString("apk");
 | 
			
		||||
 | 
			
		||||
            compareAppVersionAndShowNotification(versionName,
 | 
			
		||||
                    apkLocationUrl, versionCode);
 | 
			
		||||
        } catch (final JsonParserException e) {
 | 
			
		||||
            // Most likely something is wrong in data received from NEWPIPE_API_URL.
 | 
			
		||||
            // Do not alarm user and fail silently.
 | 
			
		||||
            if (DEBUG) {
 | 
			
		||||
                Log.w(TAG, "Could not get NewPipe API: invalid json", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start a new worker which
 | 
			
		||||
     * checks if all conditions for performing a version check are met,
 | 
			
		||||
     * fetches the API endpoint {@link #NEWPIPE_API_URL} containing info
 | 
			
		||||
     * about the latest NewPipe version
 | 
			
		||||
     * and displays a notification about ana available update.
 | 
			
		||||
     * <br>
 | 
			
		||||
     * Following conditions need to be met, before data is request from the server:
 | 
			
		||||
     * <ul>
 | 
			
		||||
     * <li> The app is signed with the correct signing key (by TeamNewPipe / schabi).
 | 
			
		||||
     * If the signing key differs from the one used upstream, the update cannot be installed.</li>
 | 
			
		||||
     * <li>The user enabled searching for and notifying about updates in the settings.</li>
 | 
			
		||||
     * <li>The app did not recently check for updates.
 | 
			
		||||
     * We do not want to make unnecessary connections and DOS our servers.</li>
 | 
			
		||||
     * </ul>
 | 
			
		||||
     */
 | 
			
		||||
    public static void enqueueNewVersionCheckingWork(final Context context) {
 | 
			
		||||
        final WorkRequest workRequest =
 | 
			
		||||
                new OneTimeWorkRequest.Builder(NewVersionWorker.class).build();
 | 
			
		||||
        WorkManager.getInstance(context).enqueue(workRequest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @NonNull
 | 
			
		||||
    @Override
 | 
			
		||||
    public Result doWork() {
 | 
			
		||||
        try {
 | 
			
		||||
            checkNewVersion();
 | 
			
		||||
        } catch (final IOException e) {
 | 
			
		||||
            Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e);
 | 
			
		||||
            return Result.failure();
 | 
			
		||||
        } catch (final ReCaptchaException e) {
 | 
			
		||||
            Log.e(TAG, "ReCaptchaException should never happen here.", e);
 | 
			
		||||
            return Result.failure();
 | 
			
		||||
        }
 | 
			
		||||
        return Result.success();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										163
									
								
								app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,163 @@
 | 
			
		||||
package org.schabi.newpipe
 | 
			
		||||
 | 
			
		||||
import android.app.PendingIntent
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.util.Log
 | 
			
		||||
import androidx.core.app.NotificationCompat
 | 
			
		||||
import androidx.core.app.NotificationManagerCompat
 | 
			
		||||
import androidx.core.content.edit
 | 
			
		||||
import androidx.core.net.toUri
 | 
			
		||||
import androidx.preference.PreferenceManager
 | 
			
		||||
import androidx.work.OneTimeWorkRequest
 | 
			
		||||
import androidx.work.WorkManager
 | 
			
		||||
import androidx.work.WorkRequest
 | 
			
		||||
import androidx.work.Worker
 | 
			
		||||
import androidx.work.WorkerParameters
 | 
			
		||||
import com.grack.nanojson.JsonParser
 | 
			
		||||
import com.grack.nanojson.JsonParserException
 | 
			
		||||
import org.schabi.newpipe.extractor.downloader.Response
 | 
			
		||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
 | 
			
		||||
import org.schabi.newpipe.util.ReleaseVersionUtil.coerceUpdateCheckExpiry
 | 
			
		||||
import org.schabi.newpipe.util.ReleaseVersionUtil.isLastUpdateCheckExpired
 | 
			
		||||
import org.schabi.newpipe.util.ReleaseVersionUtil.isReleaseApk
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
 | 
			
		||||
class NewVersionWorker(
 | 
			
		||||
    context: Context,
 | 
			
		||||
    workerParams: WorkerParameters
 | 
			
		||||
) : Worker(context, workerParams) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Method to compare the current and latest available app version.
 | 
			
		||||
     * If a newer version is available, we show the update notification.
 | 
			
		||||
     *
 | 
			
		||||
     * @param versionName    Name of new version
 | 
			
		||||
     * @param apkLocationUrl Url with the new apk
 | 
			
		||||
     * @param versionCode    Code of new version
 | 
			
		||||
     */
 | 
			
		||||
    private fun compareAppVersionAndShowNotification(
 | 
			
		||||
        versionName: String,
 | 
			
		||||
        apkLocationUrl: String?,
 | 
			
		||||
        versionCode: Int
 | 
			
		||||
    ) {
 | 
			
		||||
        if (BuildConfig.VERSION_CODE >= versionCode) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
        val app = App.getApp()
 | 
			
		||||
 | 
			
		||||
        // A pending intent to open the apk location url in the browser.
 | 
			
		||||
        val intent = Intent(Intent.ACTION_VIEW, apkLocationUrl?.toUri())
 | 
			
		||||
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
 | 
			
		||||
        val pendingIntent = PendingIntent.getActivity(app, 0, intent, 0)
 | 
			
		||||
        val channelId = app.getString(R.string.app_update_notification_channel_id)
 | 
			
		||||
        val notificationBuilder = NotificationCompat.Builder(app, channelId)
 | 
			
		||||
            .setSmallIcon(R.drawable.ic_newpipe_update)
 | 
			
		||||
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
 | 
			
		||||
            .setContentIntent(pendingIntent)
 | 
			
		||||
            .setAutoCancel(true)
 | 
			
		||||
            .setContentTitle(app.getString(R.string.app_update_notification_content_title))
 | 
			
		||||
            .setContentText(
 | 
			
		||||
                app.getString(R.string.app_update_notification_content_text) +
 | 
			
		||||
                    " " + versionName
 | 
			
		||||
            )
 | 
			
		||||
        val notificationManager = NotificationManagerCompat.from(app)
 | 
			
		||||
        notificationManager.notify(2000, notificationBuilder.build())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Throws(IOException::class, ReCaptchaException::class)
 | 
			
		||||
    private fun checkNewVersion() {
 | 
			
		||||
        // Check if the current apk is a github one or not.
 | 
			
		||||
        if (!isReleaseApk()) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
 | 
			
		||||
        // Check if the last request has happened a certain time ago
 | 
			
		||||
        // to reduce the number of API requests.
 | 
			
		||||
        val expiry = prefs.getLong(applicationContext.getString(R.string.update_expiry_key), 0)
 | 
			
		||||
        if (!isLastUpdateCheckExpired(expiry)) {
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Make a network request to get latest NewPipe data.
 | 
			
		||||
        val response = DownloaderImpl.getInstance().get(NEWPIPE_API_URL)
 | 
			
		||||
        handleResponse(response)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun handleResponse(response: Response) {
 | 
			
		||||
        val prefs = PreferenceManager.getDefaultSharedPreferences(applicationContext)
 | 
			
		||||
        try {
 | 
			
		||||
            // Store a timestamp which needs to be exceeded,
 | 
			
		||||
            // before a new request to the API is made.
 | 
			
		||||
            val newExpiry = coerceUpdateCheckExpiry(response.getHeader("expires"))
 | 
			
		||||
            prefs.edit {
 | 
			
		||||
                putLong(applicationContext.getString(R.string.update_expiry_key), newExpiry)
 | 
			
		||||
            }
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            if (DEBUG) {
 | 
			
		||||
                Log.w(TAG, "Could not extract and save new expiry date", e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Parse the json from the response.
 | 
			
		||||
        try {
 | 
			
		||||
            val githubStableObject = JsonParser.`object`()
 | 
			
		||||
                .from(response.responseBody()).getObject("flavors")
 | 
			
		||||
                .getObject("github").getObject("stable")
 | 
			
		||||
 | 
			
		||||
            val versionName = githubStableObject.getString("version")
 | 
			
		||||
            val versionCode = githubStableObject.getInt("version_code")
 | 
			
		||||
            val apkLocationUrl = githubStableObject.getString("apk")
 | 
			
		||||
            compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode)
 | 
			
		||||
        } catch (e: JsonParserException) {
 | 
			
		||||
            // Most likely something is wrong in data received from NEWPIPE_API_URL.
 | 
			
		||||
            // Do not alarm user and fail silently.
 | 
			
		||||
            if (DEBUG) {
 | 
			
		||||
                Log.w(TAG, "Could not get NewPipe API: invalid json", e)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun doWork(): Result {
 | 
			
		||||
        try {
 | 
			
		||||
            checkNewVersion()
 | 
			
		||||
        } catch (e: IOException) {
 | 
			
		||||
            Log.w(TAG, "Could not fetch NewPipe API: probably network problem", e)
 | 
			
		||||
            return Result.failure()
 | 
			
		||||
        } catch (e: ReCaptchaException) {
 | 
			
		||||
            Log.e(TAG, "ReCaptchaException should never happen here.", e)
 | 
			
		||||
            return Result.failure()
 | 
			
		||||
        }
 | 
			
		||||
        return Result.success()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        private val DEBUG = MainActivity.DEBUG
 | 
			
		||||
        private val TAG = NewVersionWorker::class.java.simpleName
 | 
			
		||||
        private const val NEWPIPE_API_URL = "https://newpipe.net/api/data.json"
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Start a new worker which
 | 
			
		||||
         * checks if all conditions for performing a version check are met,
 | 
			
		||||
         * fetches the API endpoint [.NEWPIPE_API_URL] containing info
 | 
			
		||||
         * about the latest NewPipe version
 | 
			
		||||
         * and displays a notification about ana available update.
 | 
			
		||||
         * <br></br>
 | 
			
		||||
         * Following conditions need to be met, before data is request from the server:
 | 
			
		||||
         *
 | 
			
		||||
         *  *  The app is signed with the correct signing key (by TeamNewPipe / schabi).
 | 
			
		||||
         * If the signing key differs from the one used upstream, the update cannot be installed.
 | 
			
		||||
         *  * The user enabled searching for and notifying about updates in the settings.
 | 
			
		||||
         *  * The app did not recently check for updates.
 | 
			
		||||
         * We do not want to make unnecessary connections and DOS our servers.
 | 
			
		||||
         *
 | 
			
		||||
         */
 | 
			
		||||
        @JvmStatic
 | 
			
		||||
        fun enqueueNewVersionCheckingWork(context: Context) {
 | 
			
		||||
            val workRequest: WorkRequest =
 | 
			
		||||
                OneTimeWorkRequest.Builder(NewVersionWorker::class.java).build()
 | 
			
		||||
            WorkManager.getInstance(context).enqueue(workRequest)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -94,7 +94,6 @@ object ReleaseVersionUtil {
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JvmStatic
 | 
			
		||||
    fun isLastUpdateCheckExpired(expiry: Long): Boolean {
 | 
			
		||||
        return Instant.ofEpochSecond(expiry).isBefore(Instant.now())
 | 
			
		||||
    }
 | 
			
		||||
@@ -104,7 +103,6 @@ object ReleaseVersionUtil {
 | 
			
		||||
     *
 | 
			
		||||
     * @return Epoch second of expiry date time
 | 
			
		||||
     */
 | 
			
		||||
    @JvmStatic
 | 
			
		||||
    fun coerceUpdateCheckExpiry(expiryString: String?): Long {
 | 
			
		||||
        val now = ZonedDateTime.now()
 | 
			
		||||
        return expiryString?.let {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user