Add ktlint and run it in CI

Fixes formatting issues it found.

Also remove version variables from gradle scripts as they are not wanted by the project.
This commit is contained in:
Torsten Grote 2022-01-27 13:54:12 -03:00
parent 82b131ff71
commit decc2cc6e3
No known key found for this signature in database
GPG Key ID: 3E5F77D92CF891FF
38 changed files with 500 additions and 155 deletions

2
.editorconfig Normal file
View File

@ -0,0 +1,2 @@
[*.{kt, kts}]
max_line_length = 100

View File

@ -34,6 +34,7 @@ stages:
- app/build/reports - app/build/reports
- app/build/outputs/*ml - app/build/outputs/*ml
- app/build/outputs/apk - app/build/outputs/apk
- build/reports
expire_in: 1 week expire_in: 1 week
when: on_failure when: on_failure
after_script: after_script:
@ -49,10 +50,11 @@ test_lint_pmd_checkstyle:
- ./gradlew assemble - ./gradlew assemble
# always report on lint errors to the build log # always report on lint errors to the build log
- sed -i -e 's,textReport .*,textReport true,' app/build.gradle - sed -i -e 's,textReport .*,textReport true,' app/build.gradle
- ./gradlew testFullDebugUnitTest || set_error - ./gradlew testDebugUnitTest testFullDebugUnitTest || set_error
- ./gradlew lint || set_error - ./gradlew lint || set_error
- ./gradlew pmd || set_error - ./gradlew pmd || set_error
- ./gradlew checkstyle || set_error - ./gradlew checkstyle || set_error
- ./gradlew ktlintCheck || set_error
- ./tools/check-format-strings.py || set_error - ./tools/check-format-strings.py || set_error
- ./tools/check-fastlane-whitespace.py || set_error - ./tools/check-fastlane-whitespace.py || set_error
- ./tools/remove-unused-and-blank-translations.py || set_error - ./tools/remove-unused-and-blank-translations.py || set_error

View File

@ -177,8 +177,8 @@ dependencies {
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.1' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.1'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1'
implementation "com.github.bumptech.glide:glide:$glide_version" implementation "com.github.bumptech.glide:glide:4.12.0"
annotationProcessor "com.github.bumptech.glide:compiler:$glide_version" annotationProcessor "com.github.bumptech.glide:compiler:4.12.0"
implementation 'org.bouncycastle:bcprov-jdk15on:1.65' implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
fullImplementation 'org.bouncycastle:bcpkix-jdk15on:1.65' fullImplementation 'org.bouncycastle:bcpkix-jdk15on:1.65'

View File

@ -26,7 +26,7 @@ import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.data.Schema;
import org.fdroid.fdroid.nearby.peers.Peer; import org.fdroid.fdroid.nearby.peers.Peer;
import org.fdroid.download.Downloader; import org.fdroid.fdroid.net.DownloaderService;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
@ -392,9 +392,9 @@ public class SwapService extends Service {
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.onErrorComplete(e -> { .onErrorComplete(e -> {
Intent intent = new Intent(Downloader.ACTION_INTERRUPTED); Intent intent = new Intent(DownloaderService.ACTION_INTERRUPTED);
intent.setData(Uri.parse(repo.address)); intent.setData(Uri.parse(repo.address));
intent.putExtra(Downloader.EXTRA_ERROR_MESSAGE, e.getLocalizedMessage()); intent.putExtra(DownloaderService.EXTRA_ERROR_MESSAGE, e.getLocalizedMessage());
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent); LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
return true; return true;
}) })

View File

@ -153,15 +153,15 @@ public class SwapSuccessView extends SwapView implements LoaderManager.LoaderCal
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) { switch (intent.getAction()) {
case Downloader.ACTION_STARTED: case DownloaderService.ACTION_STARTED:
resetView(); resetView();
break; break;
case Downloader.ACTION_PROGRESS: case DownloaderService.ACTION_PROGRESS:
if (progressView.getVisibility() != View.VISIBLE) { if (progressView.getVisibility() != View.VISIBLE) {
showProgress(); showProgress();
} }
long read = intent.getLongExtra(Downloader.EXTRA_BYTES_READ, 0); long read = intent.getLongExtra(DownloaderService.EXTRA_BYTES_READ, 0);
long total = intent.getLongExtra(Downloader.EXTRA_TOTAL_BYTES, 0); long total = intent.getLongExtra(DownloaderService.EXTRA_TOTAL_BYTES, 0);
if (total > 0) { if (total > 0) {
progressView.setIndeterminate(false); progressView.setIndeterminate(false);
progressView.setMax(100); progressView.setMax(100);
@ -170,17 +170,17 @@ public class SwapSuccessView extends SwapView implements LoaderManager.LoaderCal
progressView.setIndeterminate(true); progressView.setIndeterminate(true);
} }
break; break;
case Downloader.ACTION_COMPLETE: case DownloaderService.ACTION_COMPLETE:
localBroadcastManager.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
resetView(); resetView();
statusInstalled.setText(R.string.installing); statusInstalled.setText(R.string.installing);
statusInstalled.setVisibility(View.VISIBLE); statusInstalled.setVisibility(View.VISIBLE);
btnInstall.setVisibility(View.GONE); btnInstall.setVisibility(View.GONE);
break; break;
case Downloader.ACTION_INTERRUPTED: case DownloaderService.ACTION_INTERRUPTED:
localBroadcastManager.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
if (intent.hasExtra(Downloader.EXTRA_ERROR_MESSAGE)) { if (intent.hasExtra(DownloaderService.EXTRA_ERROR_MESSAGE)) {
String msg = intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE) String msg = intent.getStringExtra(DownloaderService.EXTRA_ERROR_MESSAGE)
+ " " + intent.getDataString(); + " " + intent.getDataString();
Toast.makeText(context, R.string.download_error, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.download_error, Toast.LENGTH_SHORT).show();
Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); Toast.makeText(context, msg, Toast.LENGTH_LONG).show();

View File

@ -54,6 +54,7 @@ import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.nearby.peers.BluetoothPeer; import org.fdroid.fdroid.nearby.peers.BluetoothPeer;
import org.fdroid.fdroid.nearby.peers.Peer; import org.fdroid.fdroid.nearby.peers.Peer;
import org.fdroid.fdroid.net.BluetoothDownloader; import org.fdroid.fdroid.net.BluetoothDownloader;
import org.fdroid.fdroid.net.DownloaderService;
import org.fdroid.fdroid.qr.CameraCharacteristicsChecker; import org.fdroid.fdroid.qr.CameraCharacteristicsChecker;
import org.fdroid.fdroid.views.main.MainActivity; import org.fdroid.fdroid.views.main.MainActivity;
@ -273,7 +274,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
localBroadcastManager = LocalBroadcastManager.getInstance(this); localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(downloaderInterruptedReceiver, localBroadcastManager.registerReceiver(downloaderInterruptedReceiver,
new IntentFilter(Downloader.ACTION_INTERRUPTED)); new IntentFilter(DownloaderService.ACTION_INTERRUPTED));
wifiManager = ContextCompat.getSystemService(getApplicationContext(), WifiManager.class); wifiManager = ContextCompat.getSystemService(getApplicationContext(), WifiManager.class);
wifiApControl = WifiApControl.getInstance(this); wifiApControl = WifiApControl.getInstance(this);
@ -1505,7 +1506,7 @@ public class SwapWorkflowActivity extends AppCompatActivity {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
Repo repo = RepoProvider.Helper.findByUrl(context, intent.getData(), null); Repo repo = RepoProvider.Helper.findByUrl(context, intent.getData(), null);
if (repo != null && repo.isSwap) { if (repo != null && repo.isSwap) {
setUpConnectingProgressText(intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE)); setUpConnectingProgressText(intent.getStringExtra(DownloaderService.EXTRA_ERROR_MESSAGE));
} }
} }
}; };

View File

@ -10,13 +10,13 @@ import android.content.pm.PackageManager;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.Repo; import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.installer.ErrorDialogActivity; import org.fdroid.fdroid.installer.ErrorDialogActivity;
import org.fdroid.fdroid.installer.InstallManagerService; import org.fdroid.fdroid.installer.InstallManagerService;
import org.fdroid.fdroid.net.DownloaderService;
import org.fdroid.fdroid.views.AppDetailsActivity; import org.fdroid.fdroid.views.AppDetailsActivity;
import java.util.ArrayList; import java.util.ArrayList;
@ -292,7 +292,7 @@ public final class AppUpdateStatusManager {
private void notifyAdd(AppUpdateStatus entry) { private void notifyAdd(AppUpdateStatus entry) {
if (!isBatchUpdating) { if (!isBatchUpdating) {
Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_ADDED); Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_ADDED);
broadcastIntent.putExtra(Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy());
localBroadcastManager.sendBroadcast(broadcastIntent); localBroadcastManager.sendBroadcast(broadcastIntent);
} }
@ -301,7 +301,7 @@ public final class AppUpdateStatusManager {
private void notifyChange(AppUpdateStatus entry, boolean isStatusUpdate) { private void notifyChange(AppUpdateStatus entry, boolean isStatusUpdate) {
if (!isBatchUpdating) { if (!isBatchUpdating) {
Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_CHANGED); Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_CHANGED);
broadcastIntent.putExtra(Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy());
broadcastIntent.putExtra(EXTRA_IS_STATUS_UPDATE, isStatusUpdate); broadcastIntent.putExtra(EXTRA_IS_STATUS_UPDATE, isStatusUpdate);
localBroadcastManager.sendBroadcast(broadcastIntent); localBroadcastManager.sendBroadcast(broadcastIntent);
@ -311,7 +311,7 @@ public final class AppUpdateStatusManager {
private void notifyRemove(AppUpdateStatus entry) { private void notifyRemove(AppUpdateStatus entry) {
if (!isBatchUpdating) { if (!isBatchUpdating) {
Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_REMOVED); Intent broadcastIntent = new Intent(BROADCAST_APPSTATUS_REMOVED);
broadcastIntent.putExtra(Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); broadcastIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
broadcastIntent.putExtra(EXTRA_STATUS, entry.copy()); broadcastIntent.putExtra(EXTRA_STATUS, entry.copy());
localBroadcastManager.sendBroadcast(broadcastIntent); localBroadcastManager.sendBroadcast(broadcastIntent);
} }

View File

@ -4,7 +4,7 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.fdroid.download.Downloader; import org.fdroid.fdroid.net.DownloaderService;
/** /**
* For security purposes we need to ensure that all Intent objects we give to a PendingIntent are * For security purposes we need to ensure that all Intent objects we give to a PendingIntent are
@ -16,7 +16,7 @@ public class NotificationBroadcastReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context); AppUpdateStatusManager manager = AppUpdateStatusManager.getInstance(context);
String canonicalUrl = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); String canonicalUrl = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
switch (intent.getAction()) { switch (intent.getAction()) {
case NotificationHelper.BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED: case NotificationHelper.BROADCAST_NOTIFICATIONS_ALL_UPDATES_CLEARED:
manager.clearAllUpdates(); manager.clearAllUpdates();

View File

@ -30,8 +30,8 @@ import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition; import com.bumptech.glide.request.transition.Transition;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.net.DownloaderService;
import org.fdroid.fdroid.views.AppDetailsActivity; import org.fdroid.fdroid.views.AppDetailsActivity;
import org.fdroid.fdroid.views.main.MainActivity; import org.fdroid.fdroid.views.main.MainActivity;
@ -114,14 +114,14 @@ public class NotificationHelper {
case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED: case AppUpdateStatusManager.BROADCAST_APPSTATUS_ADDED:
updateStatusLists(); updateStatusLists();
createSummaryNotifications(); createSummaryNotifications();
url = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); url = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
entry = appUpdateStatusManager.get(url); entry = appUpdateStatusManager.get(url);
if (entry != null) { if (entry != null) {
createNotification(entry); createNotification(entry);
} }
break; break;
case AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED: case AppUpdateStatusManager.BROADCAST_APPSTATUS_CHANGED:
url = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); url = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
entry = appUpdateStatusManager.get(url); entry = appUpdateStatusManager.get(url);
updateStatusLists(); updateStatusLists();
if (entry != null) { if (entry != null) {
@ -132,7 +132,7 @@ public class NotificationHelper {
} }
break; break;
case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED: case AppUpdateStatusManager.BROADCAST_APPSTATUS_REMOVED:
url = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); url = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
notificationManager.cancel(url, NOTIFY_ID_INSTALLED); notificationManager.cancel(url, NOTIFY_ID_INSTALLED);
notificationManager.cancel(url, NOTIFY_ID_UPDATES); notificationManager.cancel(url, NOTIFY_ID_UPDATES);
updateStatusLists(); updateStatusLists();
@ -365,7 +365,7 @@ public class NotificationHelper {
} }
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED); Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_UPDATE_CLEARED);
intentDeleted.putExtra(Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); intentDeleted.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
intentDeleted.setClass(context, NotificationBroadcastReceiver.class); intentDeleted.setClass(context, NotificationBroadcastReceiver.class);
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setDeleteIntent(piDeleted); builder.setDeleteIntent(piDeleted);
@ -453,7 +453,7 @@ public class NotificationHelper {
} }
Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED); Intent intentDeleted = new Intent(BROADCAST_NOTIFICATIONS_INSTALLED_CLEARED);
intentDeleted.putExtra(Downloader.EXTRA_CANONICAL_URL, entry.getCanonicalUrl()); intentDeleted.putExtra(DownloaderService.EXTRA_CANONICAL_URL, entry.getCanonicalUrl());
intentDeleted.setClass(context, NotificationBroadcastReceiver.class); intentDeleted.setClass(context, NotificationBroadcastReceiver.class);
PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent piDeleted = PendingIntent.getBroadcast(context, 0, intentDeleted, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setDeleteIntent(piDeleted); builder.setDeleteIntent(piDeleted);

View File

@ -28,7 +28,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.io.filefilter.RegexFileFilter; import org.apache.commons.io.filefilter.RegexFileFilter;
import org.fdroid.download.DownloadRequest; import org.fdroid.download.DownloadRequest;
import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.Preferences;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;

View File

@ -25,8 +25,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.net.DownloaderService;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -50,7 +50,7 @@ public class DefaultInstaller extends Installer {
Intent installIntent = new Intent(context, DefaultInstallerActivity.class); Intent installIntent = new Intent(context, DefaultInstallerActivity.class);
installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE); installIntent.setAction(DefaultInstallerActivity.ACTION_INSTALL_PACKAGE);
installIntent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUri.toString()); installIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
installIntent.putExtra(Installer.EXTRA_APK, apk); installIntent.putExtra(Installer.EXTRA_APK, apk);
installIntent.setData(localApkUri); installIntent.setData(localApkUri);

View File

@ -30,9 +30,9 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.net.DownloaderService;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@ -69,7 +69,7 @@ public class DefaultInstallerActivity extends FragmentActivity {
installer = new DefaultInstaller(this, apk); installer = new DefaultInstaller(this, apk);
if (ACTION_INSTALL_PACKAGE.equals(action)) { if (ACTION_INSTALL_PACKAGE.equals(action)) {
Uri localApkUri = intent.getData(); Uri localApkUri = intent.getData();
canonicalUri = Uri.parse(intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
installPackage(localApkUri); installPackage(localApkUri);
} else if (ACTION_UNINSTALL_PACKAGE.equals(action)) { } else if (ACTION_UNINSTALL_PACKAGE.equals(action)) {
uninstallPackage(apk.packageName); uninstallPackage(apk.packageName);

View File

@ -24,8 +24,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.net.DownloaderService;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@ -54,7 +54,7 @@ public class FileInstaller extends Installer {
protected void installPackageInternal(Uri localApkUri, Uri canonicalUri) { protected void installPackageInternal(Uri localApkUri, Uri canonicalUri) {
Intent installIntent = new Intent(context, FileInstallerActivity.class); Intent installIntent = new Intent(context, FileInstallerActivity.class);
installIntent.setAction(FileInstallerActivity.ACTION_INSTALL_FILE); installIntent.setAction(FileInstallerActivity.ACTION_INSTALL_FILE);
installIntent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUri.toString()); installIntent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
installIntent.putExtra(Installer.EXTRA_APK, apk); installIntent.putExtra(Installer.EXTRA_APK, apk);
installIntent.setData(localApkUri); installIntent.setData(localApkUri);

View File

@ -10,11 +10,11 @@ import android.view.ContextThemeWrapper;
import android.widget.Toast; import android.widget.Toast;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
import org.fdroid.fdroid.R; import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.net.DownloaderService;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -59,7 +59,7 @@ public class FileInstallerActivity extends FragmentActivity {
apk = intent.getParcelableExtra(Installer.EXTRA_APK); apk = intent.getParcelableExtra(Installer.EXTRA_APK);
installer = new FileInstaller(this, apk); installer = new FileInstaller(this, apk);
if (ACTION_INSTALL_FILE.equals(action)) { if (ACTION_INSTALL_FILE.equals(action)) {
canonicalUri = Uri.parse(intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
if (hasStoragePermission()) { if (hasStoragePermission()) {
installPackage(localApkUri, canonicalUri, apk); installPackage(localApkUri, canonicalUri, apk);
} else { } else {

View File

@ -217,8 +217,8 @@ public class InstallManagerService extends Service {
DownloaderService.queue(this, apk.repoId, canonicalUrl); DownloaderService.queue(this, apk.repoId, canonicalUrl);
} else if (ApkCache.apkIsCached(apkFilePath, apk)) { } else if (ApkCache.apkIsCached(apkFilePath, apk)) {
Utils.debugLog(TAG, "skip download, we have it, straight to install " + canonicalUrl + " " + apkFilePath); Utils.debugLog(TAG, "skip download, we have it, straight to install " + canonicalUrl + " " + apkFilePath);
sendBroadcast(intent.getData(), Downloader.ACTION_STARTED, apkFilePath); sendBroadcast(intent.getData(), DownloaderService.ACTION_STARTED, apkFilePath);
sendBroadcast(intent.getData(), Downloader.ACTION_COMPLETE, apkFilePath); sendBroadcast(intent.getData(), DownloaderService.ACTION_COMPLETE, apkFilePath);
} else { } else {
Utils.debugLog(TAG, "delete and download again " + canonicalUrl + " " + apkFilePath); Utils.debugLog(TAG, "delete and download again " + canonicalUrl + " " + apkFilePath);
apkFilePath.delete(); apkFilePath.delete();
@ -231,7 +231,7 @@ public class InstallManagerService extends Service {
private void sendBroadcast(Uri uri, String action, File file) { private void sendBroadcast(Uri uri, String action, File file) {
Intent intent = new Intent(action); Intent intent = new Intent(action);
intent.setData(uri); intent.setData(uri);
intent.putExtra(Downloader.EXTRA_DOWNLOAD_PATH, file.getAbsolutePath()); intent.putExtra(DownloaderService.EXTRA_DOWNLOAD_PATH, file.getAbsolutePath());
localBroadcastManager.sendBroadcast(intent); localBroadcastManager.sendBroadcast(intent);
} }
@ -263,16 +263,16 @@ public class InstallManagerService extends Service {
return; return;
} }
String action = intent.getAction(); String action = intent.getAction();
if (Downloader.ACTION_STARTED.equals(action)) { if (DownloaderService.ACTION_STARTED.equals(action)) {
Utils.debugLog(TAG, action + " " + intent); Utils.debugLog(TAG, action + " " + intent);
} else if (Downloader.ACTION_PROGRESS.equals(action)) { } else if (DownloaderService.ACTION_PROGRESS.equals(action)) {
long bytesRead = intent.getLongExtra(Downloader.EXTRA_BYTES_READ, 0); long bytesRead = intent.getLongExtra(DownloaderService.EXTRA_BYTES_READ, 0);
long totalBytes = intent.getLongExtra(Downloader.EXTRA_TOTAL_BYTES, 0); long totalBytes = intent.getLongExtra(DownloaderService.EXTRA_TOTAL_BYTES, 0);
appUpdateStatusManager.updateApkProgress(canonicalUrl, totalBytes, bytesRead); appUpdateStatusManager.updateApkProgress(canonicalUrl, totalBytes, bytesRead);
} else if (Downloader.ACTION_COMPLETE.equals(action)) { } else if (DownloaderService.ACTION_COMPLETE.equals(action)) {
localBroadcastManager.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
File localFile = new File(intent.getStringExtra(Downloader.EXTRA_DOWNLOAD_PATH)); File localFile = new File(intent.getStringExtra(DownloaderService.EXTRA_DOWNLOAD_PATH));
Uri localApkUri = Uri.fromFile(localFile); Uri localApkUri = Uri.fromFile(localFile);
Utils.debugLog(TAG, "OBB download completed " + intent.getDataString() Utils.debugLog(TAG, "OBB download completed " + intent.getDataString()
+ " to " + localApkUri); + " to " + localApkUri);
@ -298,9 +298,9 @@ public class InstallManagerService extends Service {
} finally { } finally {
FileUtils.deleteQuietly(localFile); FileUtils.deleteQuietly(localFile);
} }
} else if (Downloader.ACTION_INTERRUPTED.equals(action)) { } else if (DownloaderService.ACTION_INTERRUPTED.equals(action)) {
localBroadcastManager.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
} else if (Downloader.ACTION_CONNECTION_FAILED.equals(action)) { } else if (DownloaderService.ACTION_CONNECTION_FAILED.equals(action)) {
localBroadcastManager.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
} else { } else {
throw new RuntimeException("intent action not handled!"); throw new RuntimeException("intent action not handled!");
@ -329,7 +329,7 @@ public class InstallManagerService extends Service {
String canonicalUrl = intent.getDataString(); String canonicalUrl = intent.getDataString();
switch (intent.getAction()) { switch (intent.getAction()) {
case Downloader.ACTION_STARTED: case DownloaderService.ACTION_STARTED:
// App should currently be in the "PendingDownload" state, so this changes it to "Downloading". // App should currently be in the "PendingDownload" state, so this changes it to "Downloading".
Intent intentObject = new Intent(context, InstallManagerService.class); Intent intentObject = new Intent(context, InstallManagerService.class);
intentObject.setAction(ACTION_CANCEL); intentObject.setAction(ACTION_CANCEL);
@ -338,17 +338,17 @@ public class InstallManagerService extends Service {
appUpdateStatusManager.updateApk(canonicalUrl, appUpdateStatusManager.updateApk(canonicalUrl,
AppUpdateStatusManager.Status.Downloading, action); AppUpdateStatusManager.Status.Downloading, action);
break; break;
case Downloader.ACTION_PROGRESS: case DownloaderService.ACTION_PROGRESS:
long bytesRead = intent.getLongExtra(Downloader.EXTRA_BYTES_READ, 0); long bytesRead = intent.getLongExtra(DownloaderService.EXTRA_BYTES_READ, 0);
long totalBytes = intent.getLongExtra(Downloader.EXTRA_TOTAL_BYTES, 0); long totalBytes = intent.getLongExtra(DownloaderService.EXTRA_TOTAL_BYTES, 0);
appUpdateStatusManager.updateApkProgress(canonicalUrl, totalBytes, bytesRead); appUpdateStatusManager.updateApkProgress(canonicalUrl, totalBytes, bytesRead);
break; break;
case Downloader.ACTION_COMPLETE: case DownloaderService.ACTION_COMPLETE:
File localFile = new File(intent.getStringExtra(Downloader.EXTRA_DOWNLOAD_PATH)); File localFile = new File(intent.getStringExtra(DownloaderService.EXTRA_DOWNLOAD_PATH));
Uri localApkUri = Uri.fromFile(localFile); Uri localApkUri = Uri.fromFile(localFile);
Utils.debugLog(TAG, "download completed of " Utils.debugLog(TAG, "download completed of "
+ intent.getStringExtra(Downloader.EXTRA_MIRROR_URL) + " to " + localApkUri); + intent.getStringExtra(DownloaderService.EXTRA_MIRROR_URL) + " to " + localApkUri);
appUpdateStatusManager.updateApk(canonicalUrl, appUpdateStatusManager.updateApk(canonicalUrl,
AppUpdateStatusManager.Status.ReadyToInstall, null); AppUpdateStatusManager.Status.ReadyToInstall, null);
@ -360,10 +360,10 @@ public class InstallManagerService extends Service {
InstallerService.install(context, localApkUri, canonicalUri, apk); InstallerService.install(context, localApkUri, canonicalUri, apk);
} }
break; break;
case Downloader.ACTION_INTERRUPTED: case DownloaderService.ACTION_INTERRUPTED:
case Downloader.ACTION_CONNECTION_FAILED: case DownloaderService.ACTION_CONNECTION_FAILED:
appUpdateStatusManager.setDownloadError(canonicalUrl, appUpdateStatusManager.setDownloadError(canonicalUrl,
intent.getStringExtra(Downloader.EXTRA_ERROR_MESSAGE)); intent.getStringExtra(DownloaderService.EXTRA_ERROR_MESSAGE));
localBroadcastManager.unregisterReceiver(this); localBroadcastManager.unregisterReceiver(this);
break; break;
default: default:

View File

@ -27,10 +27,10 @@ import android.os.Build;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter; import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.Utils; import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.net.DownloaderService;
import org.fdroid.fdroid.views.AppDetailsActivity; import org.fdroid.fdroid.views.AppDetailsActivity;
import java.io.File; import java.io.File;
@ -77,7 +77,7 @@ public class InstallerService extends JobIntentService {
if (ACTION_INSTALL.equals(intent.getAction())) { if (ACTION_INSTALL.equals(intent.getAction())) {
Uri uri = intent.getData(); Uri uri = intent.getData();
Uri canonicalUri = Uri.parse(intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); Uri canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
installer.installPackage(uri, canonicalUri); installer.installPackage(uri, canonicalUri);
} else if (ACTION_UNINSTALL.equals(intent.getAction())) { } else if (ACTION_UNINSTALL.equals(intent.getAction())) {
installer.uninstallPackage(); installer.uninstallPackage();
@ -127,7 +127,7 @@ public class InstallerService extends JobIntentService {
Intent intent = new Intent(context, InstallerService.class); Intent intent = new Intent(context, InstallerService.class);
intent.setAction(ACTION_INSTALL); intent.setAction(ACTION_INSTALL);
intent.setData(localApkUri); intent.setData(localApkUri);
intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUri.toString()); intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
intent.putExtra(Installer.EXTRA_APK, apk); intent.putExtra(Installer.EXTRA_APK, apk);
enqueueWork(context, intent); enqueueWork(context, intent);
} }

View File

@ -12,8 +12,8 @@ import android.util.Log;
import android.webkit.MimeTypeMap; import android.webkit.MimeTypeMap;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.net.DownloaderService;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -41,7 +41,7 @@ public class ObfInstallerService extends IntentService {
public static void install(Context context, Uri canonicalUri, Apk apk, File path) { public static void install(Context context, Uri canonicalUri, Apk apk, File path) {
Intent intent = new Intent(context, ObfInstallerService.class); Intent intent = new Intent(context, ObfInstallerService.class);
intent.setAction(ACTION_INSTALL_OBF); intent.setAction(ACTION_INSTALL_OBF);
intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUri.toString()); intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUri.toString());
intent.putExtra(Installer.EXTRA_APK, apk); intent.putExtra(Installer.EXTRA_APK, apk);
intent.putExtra(EXTRA_OBF_PATH, path.getAbsolutePath()); intent.putExtra(EXTRA_OBF_PATH, path.getAbsolutePath());
context.startService(intent); context.startService(intent);
@ -53,7 +53,7 @@ public class ObfInstallerService extends IntentService {
Log.e(TAG, "received invalid intent: " + intent); Log.e(TAG, "received invalid intent: " + intent);
return; return;
} }
Uri canonicalUri = Uri.parse(intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); Uri canonicalUri = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
final Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK); final Apk apk = intent.getParcelableExtra(Installer.EXTRA_APK);
final String path = intent.getStringExtra(EXTRA_OBF_PATH); final String path = intent.getStringExtra(EXTRA_OBF_PATH);
final String extension = MimeTypeMap.getFileExtensionFromUrl(path); final String extension = MimeTypeMap.getFileExtensionFromUrl(path);

View File

@ -99,6 +99,29 @@ public class DownloaderService extends Service {
private static final String ACTION_QUEUE = "org.fdroid.fdroid.net.DownloaderService.action.QUEUE"; private static final String ACTION_QUEUE = "org.fdroid.fdroid.net.DownloaderService.action.QUEUE";
private static final String ACTION_CANCEL = "org.fdroid.fdroid.net.DownloaderService.action.CANCEL"; private static final String ACTION_CANCEL = "org.fdroid.fdroid.net.DownloaderService.action.CANCEL";
public static final String ACTION_STARTED = "org.fdroid.fdroid.net.Downloader.action.STARTED";
public static final String ACTION_PROGRESS = "org.fdroid.fdroid.net.Downloader.action.PROGRESS";
public static final String ACTION_INTERRUPTED = "org.fdroid.fdroid.net.Downloader.action.INTERRUPTED";
public static final String ACTION_CONNECTION_FAILED = "org.fdroid.fdroid.net.Downloader.action.CONNECTION_FAILED";
public static final String ACTION_COMPLETE = "org.fdroid.fdroid.net.Downloader.action.COMPLETE";
public static final String EXTRA_DOWNLOAD_PATH = "org.fdroid.fdroid.net.Downloader.extra.DOWNLOAD_PATH";
public static final String EXTRA_BYTES_READ = "org.fdroid.fdroid.net.Downloader.extra.BYTES_READ";
public static final String EXTRA_TOTAL_BYTES = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES";
public static final String EXTRA_ERROR_MESSAGE = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MESSAGE";
public static final String EXTRA_REPO_ID = "org.fdroid.fdroid.net.Downloader.extra.REPO_ID";
public static final String EXTRA_MIRROR_URL = "org.fdroid.fdroid.net.Downloader.extra.MIRROR_URL";
/**
* Unique ID used to represent this specific package's install process,
* including {@link android.app.Notification}s, also known as {@code canonicalUrl}.
* Careful about types, this should always be a {@link String}, so it can
* be handled on the receiving side by {@link android.content.Intent#getStringArrayExtra(String)}.
*
* @see org.fdroid.fdroid.installer.InstallManagerService
* @see android.content.Intent#EXTRA_ORIGINATING_URI
*/
public static final String EXTRA_CANONICAL_URL = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL";
private volatile Looper serviceLooper; private volatile Looper serviceLooper;
private static volatile ServiceHandler serviceHandler; private static volatile ServiceHandler serviceHandler;
private static volatile Downloader downloader; private static volatile Downloader downloader;
@ -149,7 +172,7 @@ public class DownloaderService extends Service {
Utils.debugLog(TAG, "Received Intent with no URI: " + intent); Utils.debugLog(TAG, "Received Intent with no URI: " + intent);
return START_NOT_STICKY; return START_NOT_STICKY;
} }
String canonicalUrl = intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL); String canonicalUrl = intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL);
if (canonicalUrl == null) { if (canonicalUrl == null) {
Utils.debugLog(TAG, "Received Intent with no EXTRA_CANONICAL_URL: " + intent); Utils.debugLog(TAG, "Received Intent with no EXTRA_CANONICAL_URL: " + intent);
return START_NOT_STICKY; return START_NOT_STICKY;
@ -218,10 +241,10 @@ public class DownloaderService extends Service {
*/ */
private void handleIntent(Intent intent) { private void handleIntent(Intent intent) {
final Uri uri = intent.getData(); final Uri uri = intent.getData();
final long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); final long repoId = intent.getLongExtra(DownloaderService.EXTRA_REPO_ID, 0);
final Uri canonicalUrl = Uri.parse(intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); final Uri canonicalUrl = Uri.parse(intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrl); final SanitizedFile localFile = ApkCache.getApkDownloadPath(this, canonicalUrl);
sendBroadcast(uri, Downloader.ACTION_STARTED, localFile, repoId, canonicalUrl); sendBroadcast(uri, DownloaderService.ACTION_STARTED, localFile, repoId, canonicalUrl);
try { try {
activeCanonicalUrl = canonicalUrl.toString(); activeCanonicalUrl = canonicalUrl.toString();
@ -230,26 +253,26 @@ public class DownloaderService extends Service {
downloader.setListener(new ProgressListener() { downloader.setListener(new ProgressListener() {
@Override @Override
public void onProgress(long bytesRead, long totalBytes) { public void onProgress(long bytesRead, long totalBytes) {
Intent intent = new Intent(Downloader.ACTION_PROGRESS); Intent intent = new Intent(DownloaderService.ACTION_PROGRESS);
intent.setData(canonicalUrl); intent.setData(canonicalUrl);
intent.putExtra(Downloader.EXTRA_BYTES_READ, bytesRead); intent.putExtra(DownloaderService.EXTRA_BYTES_READ, bytesRead);
intent.putExtra(Downloader.EXTRA_TOTAL_BYTES, totalBytes); intent.putExtra(DownloaderService.EXTRA_TOTAL_BYTES, totalBytes);
localBroadcastManager.sendBroadcast(intent); localBroadcastManager.sendBroadcast(intent);
} }
}); });
downloader.download(); downloader.download();
sendBroadcast(uri, Downloader.ACTION_COMPLETE, localFile, repoId, canonicalUrl); sendBroadcast(uri, DownloaderService.ACTION_COMPLETE, localFile, repoId, canonicalUrl);
} catch (InterruptedException e) { } catch (InterruptedException e) {
sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, repoId, canonicalUrl); sendBroadcast(uri, DownloaderService.ACTION_INTERRUPTED, localFile, repoId, canonicalUrl);
} catch (ConnectException | HttpRetryException | NoRouteToHostException | SocketTimeoutException } catch (ConnectException | HttpRetryException | NoRouteToHostException | SocketTimeoutException
| SSLHandshakeException | SSLKeyException | SSLPeerUnverifiedException | SSLProtocolException | SSLHandshakeException | SSLKeyException | SSLPeerUnverifiedException | SSLProtocolException
| ProtocolException | UnknownHostException e) { | ProtocolException | UnknownHostException e) {
// if the above list of exceptions changes, also change it in IndexV1Updater.update() // if the above list of exceptions changes, also change it in IndexV1Updater.update()
Log.e(TAG, "CONNECTION_FAILED: " + e.getLocalizedMessage()); Log.e(TAG, "CONNECTION_FAILED: " + e.getLocalizedMessage());
sendBroadcast(uri, Downloader.ACTION_CONNECTION_FAILED, localFile, repoId, canonicalUrl); sendBroadcast(uri, DownloaderService.ACTION_CONNECTION_FAILED, localFile, repoId, canonicalUrl);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, localFile, sendBroadcast(uri, DownloaderService.ACTION_INTERRUPTED, localFile,
e.getLocalizedMessage(), repoId, canonicalUrl); e.getLocalizedMessage(), repoId, canonicalUrl);
} finally { } finally {
if (downloader != null) { if (downloader != null) {
@ -261,7 +284,7 @@ public class DownloaderService extends Service {
} }
private void sendCancelledBroadcast(Uri uri, String canonicalUrl) { private void sendCancelledBroadcast(Uri uri, String canonicalUrl) {
sendBroadcast(uri, Downloader.ACTION_INTERRUPTED, null, 0, Uri.parse(canonicalUrl)); sendBroadcast(uri, DownloaderService.ACTION_INTERRUPTED, null, 0, Uri.parse(canonicalUrl));
} }
private void sendBroadcast(Uri uri, String action, File file, long repoId, Uri canonicalUrl) { private void sendBroadcast(Uri uri, String action, File file, long repoId, Uri canonicalUrl) {
@ -275,13 +298,13 @@ public class DownloaderService extends Service {
intent.setData(canonicalUrl); intent.setData(canonicalUrl);
} }
if (file != null) { if (file != null) {
intent.putExtra(Downloader.EXTRA_DOWNLOAD_PATH, file.getAbsolutePath()); intent.putExtra(DownloaderService.EXTRA_DOWNLOAD_PATH, file.getAbsolutePath());
} }
if (!TextUtils.isEmpty(errorMessage)) { if (!TextUtils.isEmpty(errorMessage)) {
intent.putExtra(Downloader.EXTRA_ERROR_MESSAGE, errorMessage); intent.putExtra(DownloaderService.EXTRA_ERROR_MESSAGE, errorMessage);
} }
intent.putExtra(Downloader.EXTRA_REPO_ID, repoId); intent.putExtra(DownloaderService.EXTRA_REPO_ID, repoId);
intent.putExtra(Downloader.EXTRA_MIRROR_URL, uri.toString()); intent.putExtra(DownloaderService.EXTRA_MIRROR_URL, uri.toString());
localBroadcastManager.sendBroadcast(intent); localBroadcastManager.sendBroadcast(intent);
} }
@ -303,8 +326,8 @@ public class DownloaderService extends Service {
Intent intent = new Intent(context, DownloaderService.class); Intent intent = new Intent(context, DownloaderService.class);
intent.setAction(ACTION_QUEUE); intent.setAction(ACTION_QUEUE);
intent.setData(Uri.parse(canonicalUrl)); intent.setData(Uri.parse(canonicalUrl));
intent.putExtra(Downloader.EXTRA_REPO_ID, repoId); intent.putExtra(DownloaderService.EXTRA_REPO_ID, repoId);
intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUrl); intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUrl);
context.startService(intent); context.startService(intent);
} }
@ -325,7 +348,7 @@ public class DownloaderService extends Service {
Intent intent = new Intent(context, DownloaderService.class); Intent intent = new Intent(context, DownloaderService.class);
intent.setAction(ACTION_CANCEL); intent.setAction(ACTION_CANCEL);
intent.setData(Uri.parse(canonicalUrl)); intent.setData(Uri.parse(canonicalUrl));
intent.putExtra(Downloader.EXTRA_CANONICAL_URL, canonicalUrl); intent.putExtra(DownloaderService.EXTRA_CANONICAL_URL, canonicalUrl);
context.startService(intent); context.startService(intent);
} }
@ -359,11 +382,11 @@ public class DownloaderService extends Service {
public static IntentFilter getIntentFilter(String canonicalUrl) { public static IntentFilter getIntentFilter(String canonicalUrl) {
Uri uri = Uri.parse(canonicalUrl); Uri uri = Uri.parse(canonicalUrl);
IntentFilter intentFilter = new IntentFilter(); IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Downloader.ACTION_STARTED); intentFilter.addAction(DownloaderService.ACTION_STARTED);
intentFilter.addAction(Downloader.ACTION_PROGRESS); intentFilter.addAction(DownloaderService.ACTION_PROGRESS);
intentFilter.addAction(Downloader.ACTION_COMPLETE); intentFilter.addAction(DownloaderService.ACTION_COMPLETE);
intentFilter.addAction(Downloader.ACTION_INTERRUPTED); intentFilter.addAction(DownloaderService.ACTION_INTERRUPTED);
intentFilter.addAction(Downloader.ACTION_CONNECTION_FAILED); intentFilter.addAction(DownloaderService.ACTION_CONNECTION_FAILED);
intentFilter.addDataScheme(uri.getScheme()); intentFilter.addDataScheme(uri.getScheme());
intentFilter.addDataAuthority(uri.getHost(), String.valueOf(uri.getPort())); intentFilter.addDataAuthority(uri.getHost(), String.valueOf(uri.getPort()));
intentFilter.addDataPath(uri.getPath(), PatternMatcher.PATTERN_LITERAL); intentFilter.addDataPath(uri.getPath(), PatternMatcher.PATTERN_LITERAL);

View File

@ -45,7 +45,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.badge.BadgeDrawable; import com.google.android.material.badge.BadgeDrawable;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
import org.fdroid.download.Downloader;
import org.fdroid.fdroid.AppUpdateStatusManager; import org.fdroid.fdroid.AppUpdateStatusManager;
import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus; import org.fdroid.fdroid.AppUpdateStatusManager.AppUpdateStatus;
import org.fdroid.fdroid.FDroidApp; import org.fdroid.fdroid.FDroidApp;
@ -60,6 +59,7 @@ import org.fdroid.fdroid.nearby.SwapService;
import org.fdroid.fdroid.nearby.SwapWorkflowActivity; import org.fdroid.fdroid.nearby.SwapWorkflowActivity;
import org.fdroid.fdroid.nearby.TreeUriScannerIntentService; import org.fdroid.fdroid.nearby.TreeUriScannerIntentService;
import org.fdroid.fdroid.nearby.WifiStateChangeService; import org.fdroid.fdroid.nearby.WifiStateChangeService;
import org.fdroid.fdroid.net.DownloaderService;
import org.fdroid.fdroid.views.AppDetailsActivity; import org.fdroid.fdroid.views.AppDetailsActivity;
import org.fdroid.fdroid.views.ManageReposActivity; import org.fdroid.fdroid.views.ManageReposActivity;
import org.fdroid.fdroid.views.apps.AppListActivity; import org.fdroid.fdroid.views.apps.AppListActivity;
@ -431,7 +431,7 @@ public class MainActivity extends AppCompatActivity {
// Check if we have moved into the ReadyToInstall or Installed state. // Check if we have moved into the ReadyToInstall or Installed state.
AppUpdateStatus status = manager.get( AppUpdateStatus status = manager.get(
intent.getStringExtra(Downloader.EXTRA_CANONICAL_URL)); intent.getStringExtra(DownloaderService.EXTRA_CANONICAL_URL));
boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false); boolean isStatusChange = intent.getBooleanExtra(AppUpdateStatusManager.EXTRA_IS_STATUS_UPDATE, false);
if (isStatusChange if (isStatusChange
&& status != null && status != null

View File

@ -1,15 +1,11 @@
buildscript { buildscript {
ext {
kotlin_version = "1.6.10"
glide_version = "4.12.0"
}
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'https://maven.google.com/' } maven { url 'https://maven.google.com/' }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.android.tools.build:gradle:3.6.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
} }
} }
allprojects { allprojects {

View File

@ -1,6 +1,7 @@
plugins { plugins {
id 'org.jetbrains.kotlin.multiplatform' id 'org.jetbrains.kotlin.multiplatform'
id 'com.android.library' id 'com.android.library'
id "org.jlleitschuh.gradle.ktlint" version "10.1.0"
} }
group = 'org.fdroid' group = 'org.fdroid'
@ -28,8 +29,7 @@ kotlin {
all { all {
languageSettings { languageSettings {
optIn('kotlin.RequiresOptIn') optIn('kotlin.RequiresOptIn')
explicitApi() explicitApi('strict')
explicitApi = 'strict'
} }
} }
commonMain { commonMain {
@ -58,10 +58,10 @@ kotlin {
androidMain { androidMain {
dependencies { dependencies {
implementation "io.ktor:ktor-client-okhttp:$ktor_version" implementation "io.ktor:ktor-client-okhttp:$ktor_version"
implementation("com.github.bumptech.glide:glide:$glide_version") { implementation("com.github.bumptech.glide:glide:4.12.0") {
transitive = false // we don't need all that it pulls in, just the basics transitive = false // we don't need all that it pulls in, just the basics
} }
implementation "com.github.bumptech.glide:annotations:$glide_version" implementation "com.github.bumptech.glide:annotations:4.12.0"
implementation 'ch.qos.logback:logback-classic:1.2.5' implementation 'ch.qos.logback:logback-classic:1.2.5'
} }
} }
@ -96,3 +96,5 @@ android {
disable "InvalidPackage" // FIXME remove when Ktor 2.0 has been released disable "InvalidPackage" // FIXME remove when Ktor 2.0 has been released
} }
} }
apply from: "${rootProject.rootDir}/gradle/ktlint.gradle"

View File

@ -15,29 +15,6 @@ public abstract class Downloader constructor(
public companion object { public companion object {
private val log = KotlinLogging.logger {} private val log = KotlinLogging.logger {}
public const val ACTION_STARTED: String = "org.fdroid.fdroid.net.Downloader.action.STARTED"
public const val ACTION_PROGRESS: String = "org.fdroid.fdroid.net.Downloader.action.PROGRESS"
public const val ACTION_INTERRUPTED: String = "org.fdroid.fdroid.net.Downloader.action.INTERRUPTED"
public const val ACTION_CONNECTION_FAILED: String =
"org.fdroid.fdroid.net.Downloader.action.CONNECTION_FAILED"
public const val ACTION_COMPLETE: String = "org.fdroid.fdroid.net.Downloader.action.COMPLETE"
public const val EXTRA_DOWNLOAD_PATH: String = "org.fdroid.fdroid.net.Downloader.extra.DOWNLOAD_PATH"
public const val EXTRA_BYTES_READ: String = "org.fdroid.fdroid.net.Downloader.extra.BYTES_READ"
public const val EXTRA_TOTAL_BYTES: String = "org.fdroid.fdroid.net.Downloader.extra.TOTAL_BYTES"
public const val EXTRA_ERROR_MESSAGE: String = "org.fdroid.fdroid.net.Downloader.extra.ERROR_MESSAGE"
public const val EXTRA_REPO_ID: String = "org.fdroid.fdroid.net.Downloader.extra.REPO_ID"
public const val EXTRA_MIRROR_URL: String = "org.fdroid.fdroid.net.Downloader.extra.MIRROR_URL"
/**
* Unique ID used to represent this specific package's install process,
* including [android.app.Notification]s, also known as `canonicalUrl`.
* Careful about types, this should always be a [String], so it can
* be handled on the receiving side by [android.content.Intent.getStringArrayExtra].
*
* @see android.content.Intent.EXTRA_ORIGINATING_URI
*/
public const val EXTRA_CANONICAL_URL: String = "org.fdroid.fdroid.net.Downloader.extra.CANONICAL_URL"
} }
/** /**

View File

@ -140,10 +140,12 @@ public class HttpDownloader constructor(
var resumable = false var resumable = false
val fileLength = outputFile.length() val fileLength = outputFile.length()
if (fileLength > fileSize) { if (fileLength > fileSize) {
if (!outputFile.delete()) log.warn { "Warning: " + outputFile.absolutePath + " not deleted" } if (!outputFile.delete()) log.warn {
"Warning: " + outputFile.absolutePath + " not deleted"
}
} else if (fileLength == fileSize && outputFile.isFile) { } else if (fileLength == fileSize && outputFile.isFile) {
log.debug { "Already have outputFile, not download. ${outputFile.absolutePath}" } log.debug { "Already have outputFile, not download. ${outputFile.absolutePath}" }
return // already have it! return // already have it!
} else if (fileLength > 0) { } else if (fileLength > 0) {
resumable = true resumable = true
} }
@ -153,7 +155,9 @@ public class HttpDownloader constructor(
downloadFromBytesReceiver(resumable) downloadFromBytesReceiver(resumable)
} catch (e: NoResumeException) { } catch (e: NoResumeException) {
require(resumable) { "Got $e even though download was not resumable" } require(resumable) { "Got $e even though download was not resumable" }
if (!outputFile.delete()) log.warn { "Warning: " + outputFile.absolutePath + " not deleted" } if (!outputFile.delete()) log.warn {
"Warning: " + outputFile.absolutePath + " not deleted"
}
downloadFromBytesReceiver(false) downloadFromBytesReceiver(false)
} }
} }

View File

@ -30,7 +30,9 @@ public class DownloadRequestLoader(
public class Factory( public class Factory(
private val httpManager: HttpManager, private val httpManager: HttpManager,
) : ModelLoaderFactory<DownloadRequest, InputStream> { ) : ModelLoaderFactory<DownloadRequest, InputStream> {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<DownloadRequest, InputStream> { override fun build(
multiFactory: MultiModelLoaderFactory,
): ModelLoader<DownloadRequest, InputStream> {
return DownloadRequestLoader(httpManager) return DownloadRequestLoader(httpManager)
} }

View File

@ -25,7 +25,8 @@ internal class HttpFetcher(
@Deprecated("Use DownloadRequests with other constructor instead") @Deprecated("Use DownloadRequests with other constructor instead")
constructor( constructor(
httpManager: HttpManager, httpManager: HttpManager,
glideUrl: GlideUrl, proxy: ProxyConfig?, glideUrl: GlideUrl,
proxy: ProxyConfig?,
) : this(httpManager, getDownloadRequest(glideUrl, proxy)) ) : this(httpManager, getDownloadRequest(glideUrl, proxy))
companion object { companion object {

View File

@ -25,7 +25,12 @@ public class HttpGlideUrlLoader(
return true return true
} }
override fun buildLoadData(glideUrl: GlideUrl, width: Int, height: Int, options: Options): LoadData<InputStream> { override fun buildLoadData(
glideUrl: GlideUrl,
width: Int,
height: Int,
options: Options,
): LoadData<InputStream> {
log.warn { "Not using mirrors when loading $glideUrl" } log.warn { "Not using mirrors when loading $glideUrl" }
return LoadData(glideUrl, HttpFetcher(httpManager, glideUrl, proxyGetter())) return LoadData(glideUrl, HttpFetcher(httpManager, glideUrl, proxyGetter()))
} }
@ -34,7 +39,9 @@ public class HttpGlideUrlLoader(
private val httpManager: HttpManager, private val httpManager: HttpManager,
private val proxyGetter: () -> ProxyConfig?, private val proxyGetter: () -> ProxyConfig?,
) : ModelLoaderFactory<GlideUrl, InputStream> { ) : ModelLoaderFactory<GlideUrl, InputStream> {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader<GlideUrl, InputStream> { override fun build(
multiFactory: MultiModelLoaderFactory,
): ModelLoader<GlideUrl, InputStream> {
return HttpGlideUrlLoader(httpManager, proxyGetter) return HttpGlideUrlLoader(httpManager, proxyGetter)
} }

View File

@ -159,7 +159,8 @@ class HttpDownloaderTest {
val file = folder.newFile() val file = folder.newFile()
val httpManager = HttpManager(userAgent, null) val httpManager = HttpManager(userAgent, null)
val torHost = "http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion" // tor-project.org // tor-project.org
val torHost = "http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"
val proxy = ProxyBuilder.socks("localhost", TOR_SOCKS_PORT) val proxy = ProxyBuilder.socks("localhost", TOR_SOCKS_PORT)
val downloadRequest = DownloadRequest("index.html", listOf(Mirror(torHost)), proxy) val downloadRequest = DownloadRequest("index.html", listOf(Mirror(torHost)), proxy)
val httpDownloader = HttpDownloader(httpManager, downloadRequest, file) val httpDownloader = HttpDownloader(httpManager, downloadRequest, file)

View File

@ -157,7 +157,7 @@ public open class HttpManager @JvmOverloads constructor(
// increase connect timeout if using Tor mirror // increase connect timeout if using Tor mirror
if (mirror.isOnion()) timeout { connectTimeoutMillis = 20_000 } if (mirror.isOnion()) timeout { connectTimeoutMillis = 20_000 }
// add range header if set // add range header if set
if (skipFirstBytes != null) header(Range, "bytes=${skipFirstBytes}-") if (skipFirstBytes != null) header(Range, "bytes=$skipFirstBytes-")
} }
} }
} }
@ -178,7 +178,10 @@ public open class HttpManager @JvmOverloads constructor(
* Thus, this is intentionally visible internally only. * Thus, this is intentionally visible internally only.
* Does not use [getChannel] so, it gets the [NoResumeException] as in the public API. * Does not use [getChannel] so, it gets the [NoResumeException] as in the public API.
*/ */
internal suspend fun getBytes(request: DownloadRequest, skipFirstBytes: Long? = null): ByteArray { internal suspend fun getBytes(
request: DownloadRequest,
skipFirstBytes: Long? = null,
): ByteArray {
val channel = ByteChannel() val channel = ByteChannel()
get(request, skipFirstBytes) { bytes -> get(request, skipFirstBytes) { bytes ->
channel.writeFully(bytes) channel.writeFully(bytes)
@ -198,7 +201,9 @@ public open class HttpManager @JvmOverloads constructor(
private fun resetProxyIfNeeded(proxyConfig: ProxyConfig?, mirror: Mirror? = null) { private fun resetProxyIfNeeded(proxyConfig: ProxyConfig?, mirror: Mirror? = null) {
// force no-proxy when trying to hit a local mirror // force no-proxy when trying to hit a local mirror
val newProxy = if (mirror.isLocal() && proxyConfig != null) { val newProxy = if (mirror.isLocal() && proxyConfig != null) {
if (currentProxy != null) log.info { "Forcing mirror to null, because mirror is local: $mirror" } if (currentProxy != null) log.info {
"Forcing mirror to null, because mirror is local: $mirror"
}
null null
} else proxyConfig } else proxyConfig
if (currentProxy != newProxy) { if (currentProxy != newProxy) {

View File

@ -58,7 +58,7 @@ internal fun Url.isLocal(): Boolean {
return num in 16..31 return num in 16..31
} }
return host.startsWith("169.254.") || return host.startsWith("169.254.") ||
host.startsWith("10.") || host.startsWith("10.") ||
host.startsWith("192.168.") || host.startsWith("192.168.") ||
host == "127.0.0.1" host == "127.0.0.1"
} }

View File

@ -27,9 +27,10 @@ internal abstract class MirrorChooserImpl : MirrorChooser {
): T { ): T {
val mirrors = if (downloadRequest.proxy == null) { val mirrors = if (downloadRequest.proxy == null) {
// if we don't use a proxy, filter out onion mirrors (won't work without Orbot) // if we don't use a proxy, filter out onion mirrors (won't work without Orbot)
val orderedMirrors = orderMirrors(downloadRequest).filter { mirror -> !mirror.isOnion() } val orderedMirrors =
orderMirrors(downloadRequest).filter { mirror -> !mirror.isOnion() }
// if we only have onion mirrors, take what we have and expect errors // if we only have onion mirrors, take what we have and expect errors
if (orderedMirrors.isEmpty()) downloadRequest.mirrors else orderedMirrors orderedMirrors.ifEmpty { downloadRequest.mirrors }
} else { } else {
orderMirrors(downloadRequest) orderMirrors(downloadRequest)
} }
@ -39,7 +40,10 @@ internal abstract class MirrorChooserImpl : MirrorChooser {
return request(mirror, url) return request(mirror, url)
} catch (e: ResponseException) { } catch (e: ResponseException) {
val wasLastMirror = index == downloadRequest.mirrors.size - 1 val wasLastMirror = index == downloadRequest.mirrors.size - 1
log.warn(e) { if (wasLastMirror) "Last mirror, rethrowing..." else "Trying other mirror now..." } log.warn(e) {
if (wasLastMirror) "Last mirror, rethrowing..."
else "Trying other mirror now..."
}
if (wasLastMirror) throw e if (wasLastMirror) throw e
} }
} }

View File

@ -16,5 +16,5 @@ internal fun ProxyConfig?.isTor(): Boolean {
if (this == null || !hostIsIp(DEFAULT_PROXY_HOST)) return false if (this == null || !hostIsIp(DEFAULT_PROXY_HOST)) return false
val address = resolveAddress() val address = resolveAddress()
return (type == HTTP && address.port == DEFAULT_PROXY_HTTP_PORT) || return (type == HTTP && address.port == DEFAULT_PROXY_HTTP_PORT) ||
(type == SOCKS && address.port == DEFAULT_PROXY_SOCKS_PORT) (type == SOCKS && address.port == DEFAULT_PROXY_SOCKS_PORT)
} }

View File

@ -2,9 +2,9 @@ package org.fdroid.download
import io.ktor.client.engine.ProxyBuilder import io.ktor.client.engine.ProxyBuilder
import io.ktor.http.Url import io.ktor.http.Url
import io.ktor.utils.io.errors.IOException
import org.fdroid.getRandomString import org.fdroid.getRandomString
import org.fdroid.runSuspend import org.fdroid.runSuspend
import java.net.ConnectException
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
@ -28,7 +28,7 @@ class HttpManagerIntegrationTest {
val proxyRequest = downloadRequest.copy(proxy = ProxyBuilder.http(Url("http://127.0.0.1"))) val proxyRequest = downloadRequest.copy(proxy = ProxyBuilder.http(Url("http://127.0.0.1")))
val httpManager = HttpManager(userAgent, null) val httpManager = HttpManager(userAgent, null)
val e = assertFailsWith<ConnectException> { val e = assertFailsWith<IOException> {
httpManager.getBytes(proxyRequest) httpManager.getBytes(proxyRequest)
} }
assertEquals("Failed to connect to /127.0.0.1:80", e.message) assertEquals("Failed to connect to /127.0.0.1:80", e.message)

View File

@ -60,7 +60,8 @@ class HttpManagerTest {
val version = getRandomString() val version = getRandomString()
val queryString = "id=$id&client_version=$version" val queryString = "id=$id&client_version=$version"
val mockEngine = MockEngine { respondOk() } val mockEngine = MockEngine { respondOk() }
val httpManager = HttpManager(userAgent, queryString, httpClientEngineFactory = get(mockEngine)) val httpManager =
HttpManager(userAgent, queryString, httpClientEngineFactory = get(mockEngine))
httpManager.head(downloadRequest) httpManager.head(downloadRequest)
httpManager.getBytes(downloadRequest) httpManager.getBytes(downloadRequest)
@ -119,8 +120,11 @@ class HttpManagerTest {
var requestNum = 1 var requestNum = 1
val mockEngine = MockEngine { request -> val mockEngine = MockEngine { request ->
assertNotNull(request.headers[Range]) assertNotNull(request.headers[Range])
val (fromStr, endStr) = request.headers[Range]!!.replace("bytes=", "").split('-') val (fromStr, endStr) = request.headers[Range]!!
val from = fromStr.toIntOrNull() ?: fail("No valid content range ${request.headers[Range]}") .replace("bytes=", "")
.split('-')
val from =
fromStr.toIntOrNull() ?: fail("No valid content range ${request.headers[Range]}")
assertEquals("", endStr) assertEquals("", endStr)
assertEquals(skipBytes, from) assertEquals(skipBytes, from)
if (requestNum++ == 1) respond(content.copyOfRange(from, content.size), PartialContent) if (requestNum++ == 1) respond(content.copyOfRange(from, content.size), PartialContent)
@ -129,8 +133,10 @@ class HttpManagerTest {
val httpManager = HttpManager(userAgent, null, httpClientEngineFactory = get(mockEngine)) val httpManager = HttpManager(userAgent, null, httpClientEngineFactory = get(mockEngine))
// first request gets only the skipped bytes // first request gets only the skipped bytes
assertContentEquals(content.copyOfRange(skipBytes, content.size), assertContentEquals(
httpManager.getBytes(downloadRequest, skipBytes.toLong())) content.copyOfRange(skipBytes, content.size),
httpManager.getBytes(downloadRequest, skipBytes.toLong())
)
// second request fails, because it responds with OK and full content // second request fails, because it responds with OK and full content
assertFailsWith<NoResumeException> { assertFailsWith<NoResumeException> {
httpManager.getBytes(downloadRequest, skipBytes.toLong()) httpManager.getBytes(downloadRequest, skipBytes.toLong())
@ -238,7 +244,8 @@ class HttpManagerTest {
} }
} }
} }
val httpManager = HttpManager(userAgent, null, proxyConfig, httpClientEngineFactory = factory) val httpManager =
HttpManager(userAgent, null, proxyConfig, httpClientEngineFactory = factory)
assertEquals(proxyConfig, httpManager.currentProxy) assertEquals(proxyConfig, httpManager.currentProxy)
// does not need a new engine, because also does use a proxy (1) // does not need a new engine, because also does use a proxy (1)

View File

@ -22,7 +22,11 @@ class MirrorTest {
@Test @Test
fun testIsOnion() { fun testIsOnion() {
assertTrue(Mirror("http://ftpfaudev4triw2vxiwzf4334e3mynz7osqgtozhbc77fixncqzbyoyd.onion/fdroid/repo").isOnion()) assertTrue(
Mirror(
"http://ftpfaudev4triw2vxiwzf4334e3mynz7osqgtozhbc77fixncqzbyoyd.onion/fdroid/repo"
).isOnion()
)
assertFalse(Mirror("https://www.f-droid.org/fdroid/repo").isOnion()) assertFalse(Mirror("https://www.f-droid.org/fdroid/repo").isOnion())
assertFalse(Mirror("http://192.168.0.1/fdroid/repo").isOnion()) assertFalse(Mirror("http://192.168.0.1/fdroid/repo").isOnion())
} }

10
gradle/ktlint.gradle Normal file
View File

@ -0,0 +1,10 @@
ktlint {
version = "0.43.2"
android = true
enableExperimentalRules = false
verbose = true
disabledRules = [
"import-ordering",
"no-blank-line-before-rbrace",
]
}

Binary file not shown.

View File

@ -7,6 +7,10 @@
<trust file=".*-javadoc[.]jar" regex="true"/> <trust file=".*-javadoc[.]jar" regex="true"/>
<trust file=".*-sources[.]jar" regex="true"/> <trust file=".*-sources[.]jar" regex="true"/>
</trusted-artifacts> </trusted-artifacts>
<ignored-keys>
<ignored-key id="3967d4eda591b991" reason="Key couldn't be downloaded from any key server"/>
<ignored-key id="02216ed811210daa" reason="Key couldn't be downloaded from any key server"/>
</ignored-keys>
<trusted-keys> <trusted-keys>
<trusted-key id="0394681addddb4f6388a64d295123567c1886c47" group="ch.acra" name="acra" version="4.9.1"/> <trusted-key id="0394681addddb4f6388a64d295123567c1886c47" group="ch.acra" name="acra" version="4.9.1"/>
<trusted-key id="042b29e928995b9db963c636c7ca19b7b620d787" group="org.apache.maven" name="maven-ant-tasks" version="2.1.3"/> <trusted-key id="042b29e928995b9db963c636c7ca19b7b620d787" group="org.apache.maven" name="maven-ant-tasks" version="2.1.3"/>
@ -99,11 +103,16 @@
<trusted-key id="984460dfd8f76a226f7dede2e483332711b8c7d6" group="com.ashokvarma.android" name="bottom-navigation-bar" version="2.0.5"/> <trusted-key id="984460dfd8f76a226f7dede2e483332711b8c7d6" group="com.ashokvarma.android" name="bottom-navigation-bar" version="2.0.5"/>
<trusted-key id="998af0e2b935996f5cebd56b9b1fda9f3c062231" group="^org[.]apache($|([.].*))" regex="true"/> <trusted-key id="998af0e2b935996f5cebd56b9b1fda9f3c062231" group="^org[.]apache($|([.].*))" regex="true"/>
<trusted-key id="9ffed7a118d45a44e4a1e47130e6f80434a72a7f" group="^org[.]apache[.]maven($|([.].*))" regex="true"/> <trusted-key id="9ffed7a118d45a44e4a1e47130e6f80434a72a7f" group="^org[.]apache[.]maven($|([.].*))" regex="true"/>
<trusted-key id="a2570288e10932263e8326cbaa49c633b4734832">
<trusting group="com.pinterest"/>
<trusting group="com.pinterest.ktlint"/>
</trusted-key>
<trusted-key id="a6d6c97108b8585f91b158748671a8df71296252"> <trusted-key id="a6d6c97108b8585f91b158748671a8df71296252">
<trusting group="com.squareup" name="javapoet" version="1.10.0"/> <trusting group="com.squareup" name="javapoet" version="1.10.0"/>
<trusting group="^com[.]squareup($|([.].*))" regex="true"/> <trusting group="^com[.]squareup($|([.].*))" regex="true"/>
</trusted-key> </trusted-key>
<trusted-key id="a7892505cf1a58076453e52d7999befba1039e8b" group="net.bytebuddy"/> <trusted-key id="a7892505cf1a58076453e52d7999befba1039e8b" group="net.bytebuddy"/>
<trusted-key id="adbc987d1a7b91db6b0aaa81995efbf4a3d20beb" group="^com[.]pinterest($|([.].*))" regex="true"/>
<trusted-key id="ae2b18e836c5f30687f37efdcc6346f2ce3872d9" group="com.google.protobuf" name="protobuf-java" version="2.6.1"/> <trusted-key id="ae2b18e836c5f30687f37efdcc6346f2ce3872d9" group="com.google.protobuf" name="protobuf-java" version="2.6.1"/>
<trusted-key id="afcc4c7594d09e2182c60e0f7a01b0f236e5430f"> <trusted-key id="afcc4c7594d09e2182c60e0f7a01b0f236e5430f">
<trusting group="com.google.code.gson"/> <trusting group="com.google.code.gson"/>
@ -861,6 +870,16 @@
<sha256 value="68b010ca532615ccfe212310e38cfd32f6ef93804d5a389be797dd67bef8afa4" origin="Generated by Gradle"/> <sha256 value="68b010ca532615ccfe212310e38cfd32f6ef93804d5a389be797dd67bef8afa4" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="ch.qos.logback" name="logback-classic" version="1.2.5">
<artifact name="logback-classic-1.2.5.jar">
<sha256 value="056b300701b7cb53e22315b29103d1cd6e7346b04b47655448675c1fa71916a5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="ch.qos.logback" name="logback-core" version="1.2.5">
<artifact name="logback-core-1.2.5.jar">
<sha256 value="fc98d2d927bd2991d5f45d0ccd9039a08d162c6d0611e2f71172deae9dbe122c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="classworlds" name="classworlds" version="1.1-alpha-2"> <component group="classworlds" name="classworlds" version="1.1-alpha-2">
<artifact name="classworlds-1.1-alpha-2.jar"> <artifact name="classworlds-1.1-alpha-2.jar">
<sha256 value="2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3" origin="Generated by Gradle because artifact wasn't signed"/>
@ -1477,6 +1496,12 @@
<sha256 value="ed971f009354e68c09414c964fbe1a2c85c2c8bbd460122b7497a7b8c5d4f388" origin="Generated by Gradle"/> <sha256 value="ed971f009354e68c09414c964fbe1a2c85c2c8bbd460122b7497a7b8c5d4f388" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.github.shyiko.klob" name="klob" version="0.2.1">
<artifact name="klob-0.2.1.jar">
<pgp value="160a7a9cf46221a56b06ad64461a804f2609fd89"/>
<sha256 value="2f6174e3049008f263fd832813390df645ac5c7cfa79f170ace58690810476f2" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.github.stephenc.jcip" name="jcip-annotations" version="1.0-1"> <component group="com.github.stephenc.jcip" name="jcip-annotations" version="1.0-1">
<artifact name="jcip-annotations-1.0-1.jar"> <artifact name="jcip-annotations-1.0-1.jar">
<sha256 value="4fccff8382aafc589962c4edb262f6aa595e34f1e11e61057d1c6a96e8fc7323" origin="Generated by Gradle"/> <sha256 value="4fccff8382aafc589962c4edb262f6aa595e34f1e11e61057d1c6a96e8fc7323" origin="Generated by Gradle"/>
@ -1671,14 +1696,10 @@
<pgp value="5ce325996a35213326ae2c68912d2c0eccda55c0"/> <pgp value="5ce325996a35213326ae2c68912d2c0eccda55c0"/>
</artifact> </artifact>
</component> </component>
<component group="com.google.errorprone" name="error_prone_annotations" version="2.3.2">
<artifact name="error_prone_annotations-2.3.2.jar">
<pgp value="5ce325996a35213326ae2c68912d2c0eccda55c0"/>
</artifact>
</component>
<component group="com.google.errorprone" name="error_prone_annotations" version="2.3.4"> <component group="com.google.errorprone" name="error_prone_annotations" version="2.3.4">
<artifact name="error_prone_annotations-2.3.4.jar"> <artifact name="error_prone_annotations-2.3.4.jar">
<pgp value="7615ad56144df2376f49d98b1669c4bb543e0445"/> <pgp value="7615ad56144df2376f49d98b1669c4bb543e0445"/>
<sha256 value="baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.google.errorprone" name="error_prone_check_api" version="2.2.0"> <component group="com.google.errorprone" name="error_prone_check_api" version="2.2.0">
@ -1942,6 +1963,61 @@
<sha256 value="b6a88ca9583f1d8c3cf69bc704db7d173ce3e964aaaaa3b05b1f7091631ade5c" origin="Generated by Gradle"/> <sha256 value="b6a88ca9583f1d8c3cf69bc704db7d173ce3e964aaaaa3b05b1f7091631ade5c" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.pinterest" name="ktlint" version="0.43.2">
<artifact name="ktlint-0.43.2.jar">
<sha256 value="99ec69ef0628695c24dbbc2cc4b8d7c61a754697d624f5233fc65f43faf2d235" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-core" version="0.43.2">
<artifact name="ktlint-core-0.43.2.jar">
<sha256 value="401515a76b780a32ef9dfeaf69f77316934c4bb90f339488638311789eca7a1a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-baseline" version="0.43.2">
<artifact name="ktlint-reporter-baseline-0.43.2.jar">
<sha256 value="733ee7e2cadb321d6597b3501c70c7da73117adaa0c6bc084dfc16c455d68806" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-checkstyle" version="0.43.2">
<artifact name="ktlint-reporter-checkstyle-0.43.2.jar">
<sha256 value="becafb4006b9f2e82c99749864a1a8de340ee84ac7271631a68981a44f51e808" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-html" version="0.43.2">
<artifact name="ktlint-reporter-html-0.43.2.jar">
<sha256 value="800392e150d3266e72ca53c6ccca3136d4e26445dd9216c6ac6cfc1ba3afafe5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-json" version="0.43.2">
<artifact name="ktlint-reporter-json-0.43.2.jar">
<sha256 value="9d4a94190d96d671000a06a50c9d1ce111d0dcf629bef8b4f0221a9e3f3699a0" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-plain" version="0.43.2">
<artifact name="ktlint-reporter-plain-0.43.2.jar">
<sha256 value="1cab63f431ec4e9463df7a767f131ccfa8d76259c01fecc63a4c000063e8ee43" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-reporter-sarif" version="0.43.2">
<artifact name="ktlint-reporter-sarif-0.43.2.jar">
<sha256 value="ed0046aaa4a2e4544197bfdccf88d472ef413a55ad05b6dc8aae41338e9d3748" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-experimental" version="0.43.2">
<artifact name="ktlint-ruleset-experimental-0.43.2.jar">
<sha256 value="d89e0edcdca0ae375c090565e323520ab5d424d82fd6ac6290ea986d360f0b11" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-standard" version="0.43.2">
<artifact name="ktlint-ruleset-standard-0.43.2.jar">
<sha256 value="6774dc9d42aa7c7fdd4a7f3732b56fdab99ba78ce0c4eb5159036525657d0014" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.pinterest.ktlint" name="ktlint-ruleset-test" version="0.43.2">
<artifact name="ktlint-ruleset-test-0.43.2.jar">
<sha256 value="7270c4d98b2cda268c25397a02b7dea0ab8cb923958cb3853121e0d9366ce797" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.puppycrawl.tools" name="checkstyle" version="7.2"> <component group="com.puppycrawl.tools" name="checkstyle" version="7.2">
<artifact name="checkstyle-7.2.jar"> <artifact name="checkstyle-7.2.jar">
<pgp value="06d34ed6ff73de368a772a781063fe98bcecb758"/> <pgp value="06d34ed6ff73de368a772a781063fe98bcecb758"/>
@ -1978,6 +2054,11 @@
<sha256 value="e1abd7f1116cf5e0c59947693e2189208ec94296b2a3394c959e3511d399a7b0" origin="Generated by Gradle"/> <sha256 value="e1abd7f1116cf5e0c59947693e2189208ec94296b2a3394c959e3511d399a7b0" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="com.squareup.okhttp3" name="okhttp" version="4.9.2">
<artifact name="okhttp-4.9.2.jar">
<sha256 value="3b2ee1b768c1df28c30d2fe6b38dda4d2c519210e30ca3d27950618c563c92de" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.squareup.okio" name="okio" version="2.6.0"> <component group="com.squareup.okio" name="okio" version="2.6.0">
<artifact name="okio-jvm-2.6.0.jar"> <artifact name="okio-jvm-2.6.0.jar">
<sha256 value="4d84ef686277b58eb05691ac19cd3befa3429a27274982ee65ea0f07044bcc00" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="4d84ef686277b58eb05691ac19cd3befa3429a27274982ee65ea0f07044bcc00" origin="Generated by Gradle because artifact wasn't signed"/>
@ -1988,6 +2069,11 @@
<sha256 value="4496b06e73982fcdd8a5393f46e5df2ce2fa4465df5895454cac68a32f09bbc8" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="4496b06e73982fcdd8a5393f46e5df2ce2fa4465df5895454cac68a32f09bbc8" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
</component> </component>
<component group="com.squareup.okio" name="okio-metadata" version="2.8.0">
<artifact name="okio-metadata-2.8.0.jar">
<sha256 value="f7dc3883ceae2e1fe3425e1b54c5df28b8857c5fd00381b521fda60790f2952c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="com.sun.activation" name="all" version="1.2.0"> <component group="com.sun.activation" name="all" version="1.2.0">
<artifact name="all-1.2.0.pom"> <artifact name="all-1.2.0.pom">
<pgp value="4f7e32d440ef90a83011a8fc6425559c47cc79c4"/> <pgp value="4f7e32d440ef90a83011a8fc6425559c47cc79c4"/>
@ -2148,11 +2234,30 @@
<sha256 value="e2b8153dd1bd760c1a8521cd500205dbf36b6fe89526a190e1ced65193cd51d3" origin="Generated by Gradle"/> <sha256 value="e2b8153dd1bd760c1a8521cd500205dbf36b6fe89526a190e1ced65193cd51d3" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="info.picocli" name="picocli" version="3.9.6">
<artifact name="picocli-3.9.6.jar">
<pgp value="8756c4f765c9ac3cb6b85d62379ce192d401ab61"/>
<sha256 value="9442a6a18d869354a0d922ba37b40032aa1b0a172f414a7a644de39d1972f1f4" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.github.detekt.sarif4k" name="sarif4k" version="0.0.1">
<artifact name="sarif4k-0.0.1.jar">
<sha256 value="41ec72cf2521783224581c76aaa7e97d4a50f396a66d642500ff4777b395a376" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.github.microutils" name="kotlin-logging" version="2.1.21"> <component group="io.github.microutils" name="kotlin-logging" version="2.1.21">
<artifact name="kotlin-logging-2.1.21.jar">
<sha256 value="a64e348bcb6a729ab0215b8bb2af48919832a061b2696a582c73f97414c1132a" origin="Generated by Gradle"/>
</artifact>
<artifact name="kotlin-logging-metadata-2.1.21-all.jar"> <artifact name="kotlin-logging-metadata-2.1.21-all.jar">
<sha256 value="03815406ca6f4cf7ca49432a353a0072ddd616b68c39afddb1239bac1877e315" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="03815406ca6f4cf7ca49432a353a0072ddd616b68c39afddb1239bac1877e315" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
</component> </component>
<component group="io.github.microutils" name="kotlin-logging-jvm" version="2.1.21">
<artifact name="kotlin-logging-jvm-2.1.21.jar">
<sha256 value="7b15ccb488261de2a77004f13b2d4a00c92d1bbbb2ad79efb9b6c2e56c5a7ae6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="io.github.microutils" name="kotlin-logging-linuxx64" version="2.1.21"> <component group="io.github.microutils" name="kotlin-logging-linuxx64" version="2.1.21">
<artifact name="kotlin-logging.klib"> <artifact name="kotlin-logging.klib">
<sha256 value="308b7c34dbfef24f39f3aff02540a407edfd59d9bae14d1e3a0de76438142788" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="308b7c34dbfef24f39f3aff02540a407edfd59d9bae14d1e3a0de76438142788" origin="Generated by Gradle because artifact wasn't signed"/>
@ -2199,6 +2304,9 @@
</artifact> </artifact>
</component> </component>
<component group="io.ktor" name="ktor-client-core" version="1.6.7"> <component group="io.ktor" name="ktor-client-core" version="1.6.7">
<artifact name="ktor-client-core-1.6.7.jar">
<sha256 value="45ba8bf544930877caff06433b6b14c8047111320ae1aa32cb5446d93019c0ce" origin="Generated by Gradle"/>
</artifact>
<artifact name="ktor-client-core-metadata-1.6.7-all.jar"> <artifact name="ktor-client-core-metadata-1.6.7-all.jar">
<sha256 value="06116f26a94ab0d97c0e4c031aa3d5e3fbd584c242c674d784d4c68bcf1aa844" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="06116f26a94ab0d97c0e4c031aa3d5e3fbd584c242c674d784d4c68bcf1aa844" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
@ -2307,6 +2415,9 @@
</artifact> </artifact>
</component> </component>
<component group="io.ktor" name="ktor-http" version="1.6.7"> <component group="io.ktor" name="ktor-http" version="1.6.7">
<artifact name="ktor-http-1.6.7.jar">
<sha256 value="01419c93d54f411411ea310806dbeb797a928dfe0562a50ad56a83d03d969047" origin="Generated by Gradle"/>
</artifact>
<artifact name="ktor-http-metadata-1.6.7-all.jar"> <artifact name="ktor-http-metadata-1.6.7-all.jar">
<sha256 value="e59f1461a59fd344cb54622104b9ce375ba367bef869b59a7e891cffe6f238a7" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="e59f1461a59fd344cb54622104b9ce375ba367bef869b59a7e891cffe6f238a7" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
@ -2320,6 +2431,9 @@
</artifact> </artifact>
</component> </component>
<component group="io.ktor" name="ktor-http-cio" version="1.6.7"> <component group="io.ktor" name="ktor-http-cio" version="1.6.7">
<artifact name="ktor-http-cio-1.6.7.jar">
<sha256 value="27729d01a5a51c925ea804dff908152796d704041d5be3b245bd538c0ce8f701" origin="Generated by Gradle"/>
</artifact>
<artifact name="ktor-http-cio-metadata-1.6.7-all.jar"> <artifact name="ktor-http-cio-metadata-1.6.7-all.jar">
<sha256 value="794417960660de176f8f3e4a98a16ad6b901b82c9af0f450000a80e26707723f" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="794417960660de176f8f3e4a98a16ad6b901b82c9af0f450000a80e26707723f" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
@ -2370,6 +2484,9 @@
</artifact> </artifact>
</component> </component>
<component group="io.ktor" name="ktor-io" version="1.6.7"> <component group="io.ktor" name="ktor-io" version="1.6.7">
<artifact name="ktor-io-1.6.7.jar">
<sha256 value="4e149892c99cfbffe9a027b4f7172b1375897df27f670bdf4e6a398937eaccb3" origin="Generated by Gradle"/>
</artifact>
<artifact name="ktor-io-metadata-1.6.7-all.jar"> <artifact name="ktor-io-metadata-1.6.7-all.jar">
<sha256 value="53f5419c84eec51a19f28e269b65ac440eb9e9abbb7fc914a62b7d50ab257263" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="53f5419c84eec51a19f28e269b65ac440eb9e9abbb7fc914a62b7d50ab257263" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
@ -2467,6 +2584,9 @@
</artifact> </artifact>
</component> </component>
<component group="io.ktor" name="ktor-utils" version="1.6.7"> <component group="io.ktor" name="ktor-utils" version="1.6.7">
<artifact name="ktor-utils-1.6.7.jar">
<sha256 value="a60fbe69b9300bc511642b184d6d798b48fc0d00759d8014a9e3b83fd2402b9a" origin="Generated by Gradle"/>
</artifact>
<artifact name="ktor-utils-metadata-1.6.7-all.jar"> <artifact name="ktor-utils-metadata-1.6.7-all.jar">
<sha256 value="7e401d9327a631e0d85dfdc1a123d57a26998bfb8aa1fe132b53ba0211518b6c" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="7e401d9327a631e0d85dfdc1a123d57a26998bfb8aa1fe132b53ba0211518b6c" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
@ -2648,6 +2768,7 @@
<component group="junit" name="junit" version="4.13.2"> <component group="junit" name="junit" version="4.13.2">
<artifact name="junit-4.13.2.jar"> <artifact name="junit-4.13.2.jar">
<pgp value="ff6e2c001948c5f2f38b0cc385911f425ec61b51"/> <pgp value="ff6e2c001948c5f2f38b0cc385911f425ec61b51"/>
<sha256 value="8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="nekohtml" name="nekohtml" version="1.9.6.2"> <component group="nekohtml" name="nekohtml" version="1.9.6.2">
@ -3300,6 +3421,12 @@
<sha256 value="12a3c9a32b82fdc95223cab1f9d344e14ef3e396da14c4d0013451646f3280e7" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="12a3c9a32b82fdc95223cab1f9d344e14ef3e396da14c4d0013451646f3280e7" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
</component> </component>
<component group="org.ec4j.core" name="ec4j-core" version="0.3.0">
<artifact name="ec4j-core-0.3.0.jar">
<pgp value="2e92113263fc31c74ccbaab20e91c2de43b72bb1"/>
<sha256 value="cadef0207077074b11a12be442f89ab6cf93fbc2f848702d9371a9611414d558" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.glassfish.jaxb" name="jaxb-bom" version="2.3.1"> <component group="org.glassfish.jaxb" name="jaxb-bom" version="2.3.1">
<artifact name="jaxb-bom-2.3.1.pom"> <artifact name="jaxb-bom-2.3.1.pom">
<sha256 value="6cc1266cf306557b4f2d09cbd8cd6e75b5ef0c5773ca4ef763d4f730df947b64" origin="Generated by Gradle"/> <sha256 value="6cc1266cf306557b4f2d09cbd8cd6e75b5ef0c5773ca4ef763d4f730df947b64" origin="Generated by Gradle"/>
@ -3399,6 +3526,11 @@
<sha256 value="6c93db1a10263fe1001d15ec17608707c37a73d6a9b4076219a9eae382dfeca2" origin="Generated by Gradle"/> <sha256 value="6c93db1a10263fe1001d15ec17608707c37a73d6a9b4076219a9eae382dfeca2" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-compiler-embeddable" version="1.5.31">
<artifact name="kotlin-compiler-embeddable-1.5.31.jar">
<sha256 value="e39811a9e4c102e779c659eefe90b041c66ce87578c1bfdac07cf504d1551745" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-compiler-embeddable" version="1.6.10"> <component group="org.jetbrains.kotlin" name="kotlin-compiler-embeddable" version="1.6.10">
<artifact name="kotlin-compiler-embeddable-1.6.10.jar"> <artifact name="kotlin-compiler-embeddable-1.6.10.jar">
<sha256 value="a4a3096b6159659245be113960a6883863c43f3a53926f38c16b8c5c5993b49d" origin="Generated by Gradle"/> <sha256 value="a4a3096b6159659245be113960a6883863c43f3a53926f38c16b8c5c5993b49d" origin="Generated by Gradle"/>
@ -3414,6 +3546,11 @@
<sha256 value="fd5700dc2f987783e1eff4d14fe2084af9712e7259dd777349dc4e72472dd214" origin="Generated by Gradle"/> <sha256 value="fd5700dc2f987783e1eff4d14fe2084af9712e7259dd777349dc4e72472dd214" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-daemon-embeddable" version="1.5.31">
<artifact name="kotlin-daemon-embeddable-1.5.31.jar">
<sha256 value="f61eaf89e5e3848631650b25cdfb66fe8cae0281a054d9d986716000a15ba8d6" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-daemon-embeddable" version="1.6.10"> <component group="org.jetbrains.kotlin" name="kotlin-daemon-embeddable" version="1.6.10">
<artifact name="kotlin-daemon-embeddable-1.6.10.jar"> <artifact name="kotlin-daemon-embeddable-1.6.10.jar">
<sha256 value="d727708eefddfde89b1a4f7416eaf65287d123cfee6b6ed37ec8526cc6f3b548" origin="Generated by Gradle"/> <sha256 value="d727708eefddfde89b1a4f7416eaf65287d123cfee6b6ed37ec8526cc6f3b548" origin="Generated by Gradle"/>
@ -3439,6 +3576,11 @@
<sha256 value="db14015976f9d4f3579935d1639ec857b48322c2d3b4144f513e508ad7f69f7e" origin="Generated by Gradle"/> <sha256 value="db14015976f9d4f3579935d1639ec857b48322c2d3b4144f513e508ad7f69f7e" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-klib-commonizer-embeddable" version="1.6.10">
<artifact name="kotlin-klib-commonizer-embeddable-1.6.10.jar">
<sha256 value="96cd91eb44fc090ee9cd5bc39d680259089e2783ed2e004c6c7556bed59c8477" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-native-prebuilt-linux-x86_64" version="1.6.10"> <component group="org.jetbrains.kotlin" name="kotlin-native-prebuilt-linux-x86_64" version="1.6.10">
<artifact name="kotlin-kotlin-native-prebuilt-linux-x86_64-1.6.10.jar"> <artifact name="kotlin-kotlin-native-prebuilt-linux-x86_64-1.6.10.jar">
<sha256 value="a0b6d712414de6e1213727c145d35fa7ea5a554f2e3df18ebd8690f9df9019a0" origin="Generated by Gradle"/> <sha256 value="a0b6d712414de6e1213727c145d35fa7ea5a554f2e3df18ebd8690f9df9019a0" origin="Generated by Gradle"/>
@ -3462,6 +3604,26 @@
<sha256 value="4df94aaeee8d900be431386e31ef44e82a66e57c3ae30866aec2875aff01fe70" origin="Generated by Gradle"/> <sha256 value="4df94aaeee8d900be431386e31ef44e82a66e57c3ae30866aec2875aff01fe70" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.5.31">
<artifact name="kotlin-reflect-1.5.31.jar">
<sha256 value="6e0f5490e6b9649ddd2670534e4d3a03bd283c3358b8eef5d1304fd5f8a5a4fb" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-reflect" version="1.6.10">
<artifact name="kotlin-reflect-1.6.10.jar">
<sha256 value="3277ac102ae17aad10a55abec75ff5696c8d109790396434b496e75087854203" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-script-runtime" version="1.5.31">
<artifact name="kotlin-script-runtime-1.5.31.jar">
<sha256 value="24e450fee7645ed3590981dddccf397c0d9ebb725815c94c4f555cc3db2f9f96" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-script-runtime" version="1.6.10">
<artifact name="kotlin-script-runtime-1.6.10.jar">
<sha256 value="c123e7bc733e4a08b772704690540c9fd28aed8d85a446477f25c57d4be2a25b" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-scripting-common" version="1.6.10"> <component group="org.jetbrains.kotlin" name="kotlin-scripting-common" version="1.6.10">
<artifact name="kotlin-scripting-common-1.6.10.jar"> <artifact name="kotlin-scripting-common-1.6.10.jar">
<sha256 value="f00943ce5008713f24828eac6e5eff73239f17a5912df32f76864f2e7c48c217" origin="Generated by Gradle"/> <sha256 value="f00943ce5008713f24828eac6e5eff73239f17a5912df32f76864f2e7c48c217" origin="Generated by Gradle"/>
@ -3490,6 +3652,26 @@
<sha256 value="ff03e9989faa2d40fa4a9098aaad71e247f27ea4d24b0754da642eb0924bd8c5" origin="Generated by Gradle"/> <sha256 value="ff03e9989faa2d40fa4a9098aaad71e247f27ea4d24b0754da642eb0924bd8c5" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.4.30">
<artifact name="kotlin-stdlib-1.4.30.jar">
<sha256 value="a7810cf68dd2c8fa79e61a463478880d1df8a5ab9597d151595a9c743b48b90f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.5.31">
<artifact name="kotlin-stdlib-1.5.31.jar">
<sha256 value="4800ceacb2ec0bb9959a087154b8e35318ead1ea4eba32d4bb1b9734222a7e68" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.6.0">
<artifact name="kotlin-stdlib-1.6.0.jar">
<sha256 value="115daea30b0d484afcf2360237b9d9537f48a4a2f03f3cc2a16577dfc6e90342" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib" version="1.6.10">
<artifact name="kotlin-stdlib-1.6.10.jar">
<sha256 value="5305f7a4dee7a6cb79a29c258aca93de47b49588a6dfc6da01bd8772589ea66c" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.3.71"> <component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.3.71">
<artifact name="kotlin-stdlib-common-1.3.71.jar"> <artifact name="kotlin-stdlib-common-1.3.71.jar">
<sha256 value="974f8a9b7bfce3d730a86efe0eab219a72621e8530f91e30c89f400ba98092ec" origin="Generated by Gradle"/> <sha256 value="974f8a9b7bfce3d730a86efe0eab219a72621e8530f91e30c89f400ba98092ec" origin="Generated by Gradle"/>
@ -3498,6 +3680,21 @@
<sha256 value="93f5cb50148dee7da746ed487e6278ee8d94da9a99b670f9f5248456c2f66341" origin="Generated by Gradle"/> <sha256 value="93f5cb50148dee7da746ed487e6278ee8d94da9a99b670f9f5248456c2f66341" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.4.30">
<artifact name="kotlin-stdlib-common-1.4.30.jar">
<sha256 value="32010683330a6f31b8d309f10433acaa109b61f2df3d252dae7dade9730074c2" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.5.31">
<artifact name="kotlin-stdlib-common-1.5.31.jar">
<sha256 value="dfa2a18e26b028388ee1968d199bf6f166f737ab7049c25a5e2da614404e22ad" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-common" version="1.6.10">
<artifact name="kotlin-stdlib-common-1.6.10.jar">
<sha256 value="280ddd0994e4560c9a49ee81c1b047ddc2b8f2176159475066025b474b37effd" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.3.71"> <component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.3.71">
<artifact name="kotlin-stdlib-jdk7-1.3.71.jar"> <artifact name="kotlin-stdlib-jdk7-1.3.71.jar">
<sha256 value="b046a5ef54c7006db852e48e547aaff525a9e7a0a5909ffe5fe2c966c1a3a72e" origin="Generated by Gradle"/> <sha256 value="b046a5ef54c7006db852e48e547aaff525a9e7a0a5909ffe5fe2c966c1a3a72e" origin="Generated by Gradle"/>
@ -3506,6 +3703,26 @@
<sha256 value="7163f88887d050f76f86ad2304f84a9d79c39a96178bf02e4524bdeacc5bb149" origin="Generated by Gradle"/> <sha256 value="7163f88887d050f76f86ad2304f84a9d79c39a96178bf02e4524bdeacc5bb149" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.4.30">
<artifact name="kotlin-stdlib-jdk7-1.4.30.jar">
<sha256 value="751cf4a51089dc4c60caec5f30125983cd1d3998a4138ae8e66db0d496f73646" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.5.31">
<artifact name="kotlin-stdlib-jdk7-1.5.31.jar">
<sha256 value="a25bf47353ce899d843cbddee516d621a73473e7fba97f8d0301e7b4aed7c15f" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.6.0">
<artifact name="kotlin-stdlib-jdk7-1.6.0.jar">
<sha256 value="870d35fd266b2daf64c1080fe51824d3c368f7995384a8d7c5fc2fdc40eb7b3a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk7" version="1.6.10">
<artifact name="kotlin-stdlib-jdk7-1.6.10.jar">
<sha256 value="2aedcdc6b69b33bdf5cc235bcea88e7cf6601146bb6bcdffdb312bbacd7be261" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.3.71"> <component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.3.71">
<artifact name="kotlin-stdlib-jdk8-1.3.71.jar"> <artifact name="kotlin-stdlib-jdk8-1.3.71.jar">
<sha256 value="a22192ac779ba8eff09d07084ae503e8be9e7c8ca1cb2b511ff8af4c68d83d66" origin="Generated by Gradle"/> <sha256 value="a22192ac779ba8eff09d07084ae503e8be9e7c8ca1cb2b511ff8af4c68d83d66" origin="Generated by Gradle"/>
@ -3514,6 +3731,51 @@
<sha256 value="daa4f98393b7196473ac7b347618a244d3c7eaa3554b5f86f9cddcce6a4cded6" origin="Generated by Gradle"/> <sha256 value="daa4f98393b7196473ac7b347618a244d3c7eaa3554b5f86f9cddcce6a4cded6" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.4.30">
<artifact name="kotlin-stdlib-jdk8-1.4.30.jar">
<sha256 value="c1ca432b7b4e0533deef6fe372387464f47f49260f706728854a508e413b4e66" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.5.30">
<artifact name="kotlin-stdlib-jdk8-1.5.30.jar">
<sha256 value="b3aca0539c58326223b07dc7c0ac79b5a875ba80cb91ee1609ec89bb37b8990e" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.5.31">
<artifact name="kotlin-stdlib-jdk8-1.5.31.jar">
<sha256 value="b548f7767aacf029d2417e47440742bd6d3ebede19b60386e23554ce5c4c5fdc" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.6.0">
<artifact name="kotlin-stdlib-jdk8-1.6.0.jar">
<sha256 value="ab0547c495953214a5f2b28150014f4e02133678d52b77d76375ea235e443dbd" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-stdlib-jdk8" version="1.6.10">
<artifact name="kotlin-stdlib-jdk8-1.6.10.jar">
<sha256 value="1456d82d039ea30d8485b032901f52bbf07e7cdbe8bb1f8708ad32a8574c41ce" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-test" version="1.6.10">
<artifact name="kotlin-test-1.6.10.jar">
<sha256 value="b891453cafbf961532d2ba0fb8969e40b0f7c168c9a2fc6a8cdf7c1b0577a36a" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-test-annotations-common" version="1.6.10">
<artifact name="kotlin-test-annotations-common-1.6.10.jar">
<sha256 value="4091ce07e91e8d96e9186cf3093431e4305800405a0f03aecfc10678b8bec4d4" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-test-common" version="1.6.10">
<artifact name="kotlin-test-common-1.6.10.jar">
<sha256 value="40a6199a1a3fe2c5153e9e4844c63f01947e0195aa1f15ced6e8caafa5f50596" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-test-junit" version="1.6.10">
<artifact name="kotlin-test-junit-1.6.10.jar">
<sha256 value="43327c79c6e88a4c404adeec08b57b7d5dae417eb3b0bd9b709e67f614b86b90" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlin" name="kotlin-tooling-metadata" version="1.6.10"> <component group="org.jetbrains.kotlin" name="kotlin-tooling-metadata" version="1.6.10">
<artifact name="kotlin-tooling-metadata-1.6.10.jar"> <artifact name="kotlin-tooling-metadata-1.6.10.jar">
<sha256 value="5f79b547f80ceba482d6f71844b23445e109f685eb74481044678cd75c28ad77" origin="Generated by Gradle"/> <sha256 value="5f79b547f80ceba482d6f71844b23445e109f685eb74481044678cd75c28ad77" origin="Generated by Gradle"/>
@ -3566,16 +3828,29 @@
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core" version="1.5.2-native-mt"> <component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core" version="1.5.2-native-mt">
<artifact name="kotlinx-coroutines-core-1.5.2-native-mt.jar">
<sha256 value="78492527a0d09e0c53c81aacc2e073a83ee0fc3105e701496819ec67c98df16f" origin="Generated by Gradle"/>
</artifact>
<artifact name="kotlinx-coroutines-core-metadata-1.5.2-native-mt-all.jar"> <artifact name="kotlinx-coroutines-core-metadata-1.5.2-native-mt-all.jar">
<sha256 value="540250c45b0c88bcd139d537924bfba138f50932503a3aa333e81a9c07a2527b" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="540250c45b0c88bcd139d537924bfba138f50932503a3aa333e81a9c07a2527b" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core" version="1.6.0">
<artifact name="kotlinx-coroutines-core-metadata-1.6.0-all.jar">
<sha256 value="2185ed84d158e4c1881d9465a11a13721a289987a1da8d37df6825254ea95ecf" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-jvm" version="1.5.0"> <component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-jvm" version="1.5.0">
<artifact name="kotlinx-coroutines-core-jvm-1.5.0.jar"> <artifact name="kotlinx-coroutines-core-jvm-1.5.0.jar">
<pgp value="e7dc75fc24fb3c8dfe8086ad3d5839a2262cbbfb"/> <pgp value="e7dc75fc24fb3c8dfe8086ad3d5839a2262cbbfb"/>
<sha256 value="78d6cc7135f84d692ff3752fcfd1fa1bbe0940d7df70652e4f1eaeec0c78afbb" origin="Generated by Gradle"/> <sha256 value="78d6cc7135f84d692ff3752fcfd1fa1bbe0940d7df70652e4f1eaeec0c78afbb" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-jvm" version="1.5.2-native-mt">
<artifact name="kotlinx-coroutines-core-jvm-1.5.2-native-mt.jar">
<sha256 value="db754be65cd22e18c8861a141cc35cedc3b659292eacb7f9d2c78a5386795dec" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-linuxx64" version="1.5.2-native-mt"> <component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-core-linuxx64" version="1.5.2-native-mt">
<artifact name="kotlinx-coroutines-core.klib"> <artifact name="kotlinx-coroutines-core.klib">
<sha256 value="bd5e3639e853cc1e8dca4db696ab29f95924453da93db96e20f30979e9463ef2" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="bd5e3639e853cc1e8dca4db696ab29f95924453da93db96e20f30979e9463ef2" origin="Generated by Gradle because artifact wasn't signed"/>
@ -3589,11 +3864,21 @@
<sha256 value="aedb7bc0b0669b51fb20c6f0ca2f6a7b3e7b76ebf46f64a5b2a842eaaa386913" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="aedb7bc0b0669b51fb20c6f0ca2f6a7b3e7b76ebf46f64a5b2a842eaaa386913" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-jvm" version="1.1.0">
<artifact name="kotlinx-serialization-core-jvm-1.1.0.jar">
<sha256 value="69d18c700cfdf207b3e9bf6f5d58e7de08482d9e34d7c2a0adcb1db8082df943" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-linuxx64" version="1.3.0"> <component group="org.jetbrains.kotlinx" name="kotlinx-serialization-core-linuxx64" version="1.3.0">
<artifact name="kotlinx-serialization-core.klib"> <artifact name="kotlinx-serialization-core.klib">
<sha256 value="ad49d11305253b69fdfab52bb88b2181701916871442081010c82950650021ad" origin="Generated by Gradle because artifact wasn't signed"/> <sha256 value="ad49d11305253b69fdfab52bb88b2181701916871442081010c82950650021ad" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact> </artifact>
</component> </component>
<component group="org.jetbrains.kotlinx" name="kotlinx-serialization-json-jvm" version="1.1.0">
<artifact name="kotlinx-serialization-json-jvm-1.1.0.jar">
<sha256 value="cea6836d3a3990b7ac59f61a9534a0bf1c8d3932bd206080a3a13622ec7587d1" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jetbrains.trove4j" name="trove4j" version="20160824"> <component group="org.jetbrains.trove4j" name="trove4j" version="20160824">
<artifact name="trove4j-20160824.jar"> <artifact name="trove4j-20160824.jar">
<pgp value="33fd4bfd33554634053d73c0c2148900bcd3c2af"/> <pgp value="33fd4bfd33554634053d73c0c2148900bcd3c2af"/>
@ -3607,6 +3892,11 @@
</sha256> </sha256>
</artifact> </artifact>
</component> </component>
<component group="org.jlleitschuh.gradle" name="ktlint-gradle" version="10.1.0">
<artifact name="ktlint-gradle-10.1.0.jar">
<sha256 value="485a286f85e555792d6a560b0d2de2b1854d61fd1b0c76b6b95018bffcc63ea6" origin="Generated by Gradle because artifact wasn't signed"/>
</artifact>
</component>
<component group="org.jmdns" name="jmdns" version="3.5.5"> <component group="org.jmdns" name="jmdns" version="3.5.5">
<artifact name="jmdns-3.5.5.jar"> <artifact name="jmdns-3.5.5.jar">
<pgp value="5f7903f86c625ed6efa07ab85110767b6248d3c0"/> <pgp value="5f7903f86c625ed6efa07ab85110767b6248d3c0"/>
@ -3849,6 +4139,7 @@
<component group="org.slf4j" name="slf4j-api" version="1.7.32"> <component group="org.slf4j" name="slf4j-api" version="1.7.32">
<artifact name="slf4j-api-1.7.32.jar"> <artifact name="slf4j-api-1.7.32.jar">
<pgp value="475f3b8e59e6e63aa78067482c7b12f2a511e325"/> <pgp value="475f3b8e59e6e63aa78067482c7b12f2a511e325"/>
<sha256 value="3624f8474c1af46d75f98bc097d7864a323c81b3808aa43689a6e1c601c027be" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.slf4j" name="slf4j-parent" version="1.7.25"> <component group="org.slf4j" name="slf4j-parent" version="1.7.25">

View File

@ -3,8 +3,15 @@
TOOLS_DIR=$(cd "$(dirname "$0")"; pwd) TOOLS_DIR=$(cd "$(dirname "$0")"; pwd)
cd "$TOOLS_DIR"/.. cd "$TOOLS_DIR"/..
./gradlew --write-verification-metadata pgp,sha256 build connectedCheck assembleFullDebug ./gradlew --write-verification-metadata pgp,sha256 \
build \
assembleFullDebug \
loadKtlintReporters \
-x :app:test \
-x :app:lint \
-x :download:nativeTest
printf "\nIf you changed dependencies related to tests, also add 'test' or 'connectedCheck'.\n\n"
printf "\nPlease review the following diff:\n\n" printf "\nPlease review the following diff:\n\n"
git diff gradle/verification-metadata.xml git diff gradle/verification-metadata.xml