Skip to content

Commit

Permalink
Automatically check for new releases
Browse files Browse the repository at this point in the history
Closes #19
  • Loading branch information
valldrac committed Mar 7, 2021
1 parent 3373fca commit 702c913
Show file tree
Hide file tree
Showing 81 changed files with 255 additions and 169 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ android {
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"

buildConfigField "String", "CANONICAL_VERSION_NAME", "\"$canonicalVersionName\""
buildConfigField "boolean", "AUTOMATIC_UPDATES", "false"
buildConfigField "String", "NOPLAY_UPDATE_URL", "\"https://updates.signal.org/android\""
buildConfigField "String", "FDROID_UPDATE_URL", "\"https://molly.im/fdroid/repo\""
buildConfigField "String", "BACKUP_FILENAME", "\"" + appName.toLowerCase() + "\""

ndk {
Expand Down Expand Up @@ -269,6 +268,7 @@ android {
free {
dimension 'distribution'
versionNameSuffix '-FOSS'
buildConfigField "String", "FDROID_UPDATE_URL", "\"https://molly.im/fdroid/foss/repo\""
}

nonFree {
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
<!-- Set image as wallpaper -->
<uses-permission android:name="android.permission.SET_WALLPAPER"/>

<!-- For the APK auto-updater -->
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />

Expand Down Expand Up @@ -701,6 +705,18 @@
</intent-filter>
</receiver>

<receiver android:name=".service.UpdateApkRefreshListener">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

<receiver android:name=".service.UpdateApkReadyListener">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</receiver>

<receiver android:name=".notifications.LocaleChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ private void initializePeriodicTasks() {
RotateSenderCertificateListener.schedule(this);
MessageProcessReceiver.startOrUpdateAlarm(this);

if (BuildConfig.AUTOMATIC_UPDATES) {
if (TextSecurePreferences.isUpdateApkEnabled(this)) {
UpdateApkRefreshListener.schedule(this);
}
}
Expand Down
75 changes: 54 additions & 21 deletions app/src/main/java/org/thoughtcrime/securesms/jobs/UpdateApkJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.net.Network;
import org.thoughtcrime.securesms.service.UpdateApkReadyListener;
import org.thoughtcrime.securesms.util.FileUtils;
import org.thoughtcrime.securesms.util.Hex;
Expand All @@ -29,6 +30,8 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.Request;
Expand Down Expand Up @@ -64,26 +67,42 @@ private UpdateApkJob(@NonNull Job.Parameters parameters) {

@Override
public void onRun() throws IOException, PackageManager.NameNotFoundException {
if (!BuildConfig.AUTOMATIC_UPDATES) return;
if (!TextSecurePreferences.isUpdateApkEnabled(context)) {
return;
}

Log.i(TAG, "Checking for APK update...");

OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build();
OkHttpClient client = new OkHttpClient.Builder()
.socketFactory(Network.getSocketFactory())
.dns(Network.getDns())
.build();
Request request = new Request.Builder().url(String.format("%s/index-v1.json", BuildConfig.FDROID_UPDATE_URL)).build();

Response response = client.newCall(request).execute();

if (!response.isSuccessful()) {
throw new IOException("Bad response: " + response.message());
}

UpdateDescriptor updateDescriptor = JsonUtils.fromJson(response.body().string(), UpdateDescriptor.class);
RepoIndex repoIndex = JsonUtils.fromJson(response.body().string(), RepoIndex.class);
if (repoIndex.packages == null ||
repoIndex.packages.appReleases == null ||
repoIndex.packages.appReleases.isEmpty()) {
return;
}
Collections.sort(repoIndex.packages.appReleases);

UpdateDescriptor updateDescriptor = repoIndex.packages.appReleases.get(0);
byte[] digest = Hex.fromStringCondensed(updateDescriptor.getDigest());

Log.i(TAG, "Got descriptor: " + updateDescriptor);

if (updateDescriptor.getVersionCode() > getVersionCode()) {
DownloadStatus downloadStatus = getDownloadStatus(updateDescriptor.getUrl(), digest);
Uri uri = Uri.parse(BuildConfig.FDROID_UPDATE_URL).buildUpon()
.appendPath(updateDescriptor.getApkName())
.build();
DownloadStatus downloadStatus = getDownloadStatus(uri, digest);

Log.i(TAG, "Download status: " + downloadStatus.getStatus());

Expand All @@ -92,7 +111,7 @@ public void onRun() throws IOException, PackageManager.NameNotFoundException {
handleDownloadNotify(downloadStatus.getDownloadId());
} else if (downloadStatus.getStatus() == DownloadStatus.Status.MISSING) {
Log.i(TAG, "Download status missing, starting download...");
handleDownloadStart(updateDescriptor.getUrl(), updateDescriptor.getVersionName(), digest);
handleDownloadStart(uri, updateDescriptor.getVersionName(), digest);
}
}
}
Expand All @@ -114,7 +133,7 @@ private int getVersionCode() throws PackageManager.NameNotFoundException {
return packageInfo.versionCode;
}

private DownloadStatus getDownloadStatus(String uri, byte[] theirDigest) {
private DownloadStatus getDownloadStatus(Uri uri, byte[] theirDigest) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();

Expand All @@ -133,7 +152,7 @@ private DownloadStatus getDownloadStatus(String uri, byte[] theirDigest) {
long downloadId = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID));
byte[] digest = getDigestForDownloadId(downloadId);

if (jobRemoteUri != null && jobRemoteUri.equals(uri) && downloadId == pendingDownloadId) {
if (jobRemoteUri != null && jobRemoteUri.equals(uri.toString()) && downloadId == pendingDownloadId) {

if (jobStatus == DownloadManager.STATUS_SUCCESSFUL &&
digest != null && pendingDigest != null &&
Expand All @@ -153,17 +172,17 @@ private DownloadStatus getDownloadStatus(String uri, byte[] theirDigest) {
}
}

private void handleDownloadStart(String uri, String versionName, byte[] digest) {
private void handleDownloadStart(Uri uri, String versionName, byte[] digest) {
clearPreviousDownloads(context);

DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(uri));
DownloadManager.Request downloadRequest = new DownloadManager.Request(uri);

downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
downloadRequest.setTitle("Downloading Signal update");
downloadRequest.setDescription("Downloading Signal " + versionName);
downloadRequest.setTitle("Downloading Molly update");
downloadRequest.setDescription("Downloading Molly " + versionName);
downloadRequest.setVisibleInDownloadsUi(false);
downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk");
downloadRequest.setDestinationInExternalFilesDir(context, null, "molly-update.apk");
downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);

long downloadId = downloadManager.enqueue(downloadRequest);
Expand Down Expand Up @@ -215,27 +234,41 @@ private static void clearPreviousDownloads(@NonNull Context context) {
}

for (File file : directory.listFiles()) {
if (file.getName().startsWith("signal-update")) {
if (file.getName().startsWith("molly-update")) {
if (file.delete()) {
Log.d(TAG, "Deleted " + file.getName());
}
}
}
}

private static class UpdateDescriptor {
private static class RepoIndex {
@JsonProperty
PackageIndex packages;
}

private static class PackageIndex {
@JsonProperty(BuildConfig.APPLICATION_ID)
List<UpdateDescriptor> appReleases;
}

private static class UpdateDescriptor implements Comparable<UpdateDescriptor> {
@JsonProperty
private int versionCode;

@JsonProperty
private String versionName;

@JsonProperty
private String url;
private String apkName;

@JsonProperty
private String sha256sum;
private String hash;

@Override
public int compareTo(UpdateDescriptor o) {
return Integer.compare(o.versionCode, versionCode);
}

public int getVersionCode() {
return versionCode;
Expand All @@ -245,16 +278,16 @@ public String getVersionName() {
return versionName;
}

public String getUrl() {
return url;
public String getApkName() {
return apkName;
}

public @NonNull String toString() {
return "[" + versionCode + ", " + versionName + ", " + url + "]";
return "[" + versionCode + ", " + versionName + ", " + apkName + "]";
}

public String getDigest() {
return sha256sum;
return hash;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ private static void onCreate(@NonNull Context context, @NonNull NotificationMana

notificationManager.createNotificationChannels(Arrays.asList(messages, calls, failures, backups, lockedStatus, other, voiceNotes));

if (BuildConfig.AUTOMATIC_UPDATES) {
if (TextSecurePreferences.isUpdateApkEnabled(context)) {
NotificationChannel appUpdates = new NotificationChannel(APP_UPDATES, context.getString(R.string.NotificationChannel_app_updates), NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(appUpdates);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.ContactIdentityManager;
import org.thoughtcrime.securesms.delete.DeleteAccountFragment;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobs.UpdateApkJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
import org.thoughtcrime.securesms.registration.RegistrationNavigationActivity;
import org.thoughtcrime.securesms.service.UpdateApkRefreshListener;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
Expand Down Expand Up @@ -68,6 +72,7 @@ public void onCreate(Bundle paramBundle) {
submitDebugLog.setEnabled(TextSecurePreferences.isLogEnabled(getContext()));

findPreference(TextSecurePreferences.LOG_ENABLED).setOnPreferenceChangeListener(new EnableLogClickListener());
findPreference(TextSecurePreferences.UPDATE_APK_ENABLED).setOnPreferenceChangeListener(new ApkUpdateClickListener());

Preference pinSettings = this.findPreference(ADVANCED_PIN_PREF);
pinSettings.setOnPreferenceClickListener(preference -> {
Expand Down Expand Up @@ -295,4 +300,20 @@ public boolean onPreferenceChange(final Preference preference, Object newValue)
return true;
}
}

private static class ApkUpdateClickListener implements Preference.OnPreferenceChangeListener {
@Override
public boolean onPreferenceChange(final Preference preference, Object newValue) {
boolean enabled = (boolean) newValue;
((SwitchPreferenceCompat) preference).setChecked(enabled);

NotificationChannels.create(preference.getContext());
if (enabled) {
UpdateApkRefreshListener.schedule(preference.getContext());
ApplicationDependencies.getJobManager().add(new UpdateApkJob());
}

return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class UpdateApkRefreshListener extends PersistentAlarmManagerListener {

private static final String TAG = UpdateApkRefreshListener.class.getSimpleName();

private static final long INTERVAL = TimeUnit.HOURS.toMillis(6);
private static final long INTERVAL = TimeUnit.HOURS.toMillis(22);

@Override
protected long getNextScheduledExecutionTime(Context context) {
Expand All @@ -27,7 +27,7 @@ protected long getNextScheduledExecutionTime(Context context) {
protected long onAlarm(Context context, long scheduledTime) {
Log.i(TAG, "onAlarm...");

if (scheduledTime != 0 && BuildConfig.AUTOMATIC_UPDATES) {
if (scheduledTime != 0) {
Log.i(TAG, "Queueing APK update job...");
ApplicationDependencies.getJobManager().add(new UpdateApkJob());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class TextSecurePreferences {
private static final String PROMPTED_PUSH_REGISTRATION_PREF = "pref_prompted_push_registration";
private static final String PROMPTED_OPTIMIZE_DOZE_PREF = "pref_prompted_optimize_doze";
public static final String DIRECTORY_FRESH_TIME_PREF = "pref_directory_refresh_time";
public static final String UPDATE_APK_ENABLED = "pref_update_apk_enabled";
private static final String UPDATE_APK_REFRESH_TIME_PREF = "pref_update_apk_refresh_time";
private static final String UPDATE_APK_DOWNLOAD_ID = "pref_update_apk_download_id";
private static final String UPDATE_APK_DIGEST = "pref_update_apk_digest";
Expand Down Expand Up @@ -625,6 +626,14 @@ public static String getUpdateApkDigest(Context context) {
return getStringPreference(context, UPDATE_APK_DIGEST, null);
}

public static boolean isUpdateApkEnabled(@NonNull Context context) {
return getBooleanPreference(context, UPDATE_APK_ENABLED, false);
}

public static void setUpdateApkEnabled(@NonNull Context context, boolean value) {
setBooleanPreference(context, UPDATE_APK_ENABLED, value);
}

public static String getLocalNumber(Context context) {
return getStringPreference(context, LOCAL_NUMBER_PREF, null);
}
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1616,8 +1616,8 @@
<string name="ThreadRecord_video">فيديو</string>
<string name="ThreadRecord_chat_session_refreshed">تم إنعاش جلسة المحادثة</string>
<!--UpdateApkReadyListener-->
<string name="UpdateApkReadyListener_Signal_update">تحديث Signal</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">إصدار جديد لـ Signal متوفر، أنقر للتحديث</string>
<string name="UpdateApkReadyListener_Signal_update">تحديث Molly</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">إصدار جديد لـ Molly متوفر، أنقر للتحديث</string>
<!--UntrustedSendDialog-->
<string name="UntrustedSendDialog_send_message">هل تود إرسال الرسالة ؟</string>
<string name="UntrustedSendDialog_send">أرسل</string>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-az/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -622,8 +622,8 @@
<string name="ThreadRecord_you_marked_verified">Sən təsdiqlənmiş kimi işarələnmisən</string>
<string name="ThreadRecord_you_marked_unverified">Sən təsdiqlənməmiş kimi işarələnmisən.</string>
<!--UpdateApkReadyListener-->
<string name="UpdateApkReadyListener_Signal_update">Signal yenilənməsi</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Signal-ın yeni versiyası hazırdır, yeniləmək üçün kliklə</string>
<string name="UpdateApkReadyListener_Signal_update">Molly yenilənməsi</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Molly-ın yeni versiyası hazırdır, yeniləmək üçün kliklə</string>
<!--UnknownSenderView-->
<!-- Removed by excludeNonTranslatables <string name="UnknownSenderView_block_s">%səlaqəsini kilidləyirsən?</string> -->
<!-- Removed by excludeNonTranslatables <string name="UnknownSenderView_blocked_contacts_will_no_longer_be_able_to_send_you_messages_or_call_you"> Kilidlənmiş əlaqələr daha sənə mesaj göndərə və ya zəng edə bilməyəcək.</string> -->
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-bg/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1368,8 +1368,8 @@
<string name="ThreadRecord_video">Видео</string>
<string name="ThreadRecord_chat_session_refreshed">Чат сесията е презаредена.</string>
<!--UpdateApkReadyListener-->
<string name="UpdateApkReadyListener_Signal_update">Обновление на Signal</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Има нова версия на Signal, натиснете, за да обновите.</string>
<string name="UpdateApkReadyListener_Signal_update">Обновление на Molly</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Има нова версия на Molly, натиснете, за да обновите.</string>
<!--UntrustedSendDialog-->
<string name="UntrustedSendDialog_send_message">Изпращане на съобщение?</string>
<string name="UntrustedSendDialog_send">Изпращане</string>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-bn/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -999,8 +999,8 @@
<string name="ThreadRecord_file">ফাইল</string>
<string name="ThreadRecord_video">ভিডিও</string>
<!--UpdateApkReadyListener-->
<string name="UpdateApkReadyListener_Signal_update">Signal আপডেট</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Signal এর একটি নতুন ভার্সন পাওয়া যাচ্ছে, অাপডেট করতে ট্যাপ করুন</string>
<string name="UpdateApkReadyListener_Signal_update">Molly আপডেট</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Molly এর একটি নতুন ভার্সন পাওয়া যাচ্ছে, অাপডেট করতে ট্যাপ করুন</string>
<!--UnknownSenderView-->
<!-- Removed by excludeNonTranslatables <string name="UnknownSenderView_block_s">%s কে ব্লক করবেন?</string> -->
<!-- Removed by excludeNonTranslatables <string name="UnknownSenderView_blocked_contacts_will_no_longer_be_able_to_send_you_messages_or_call_you">ব্লক করা পরিচিতিসমূহ আপনাকে আর বার্তা প্রেরণ বা কল করতে সক্ষম হবে না।</string> -->
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-bs/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1436,8 +1436,8 @@
<string name="ThreadRecord_video">Video</string>
<string name="ThreadRecord_chat_session_refreshed">Konverzacija je osvježena</string>
<!--UpdateApkReadyListener-->
<string name="UpdateApkReadyListener_Signal_update">Nova verzija Signala</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Dostupna je nova verzija Signala, pritisnite da ažurirate</string>
<string name="UpdateApkReadyListener_Signal_update">Nova verzija Mollya</string>
<string name="UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update">Dostupna je nova verzija Mollya, pritisnite da ažurirate</string>
<!--UntrustedSendDialog-->
<string name="UntrustedSendDialog_send_message">Poslati poruku?</string>
<string name="UntrustedSendDialog_send">Šalji</string>
Expand Down
Loading

0 comments on commit 702c913

Please sign in to comment.