Use semi-type-safe Pref

This commit is contained in:
bemusementpark 2024-07-10 20:18:11 +09:30
parent f23a0fb5d8
commit 182d3f6973
19 changed files with 249 additions and 1184 deletions

View File

@ -27,6 +27,7 @@ import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.prefs
import org.session.libsignal.utilities.KeyHelper
import org.session.libsignal.utilities.hexEncodedPublicKey
import org.thoughtcrime.securesms.ApplicationContext
@ -82,18 +83,14 @@ class LibSessionTests {
@Before
fun setupUser() {
PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext.applicationContext).edit {
putBoolean(TextSecurePreferences.HAS_FORCED_NEW_CONFIG, true).apply()
}
val newBytes = randomSeedBytes().toByteArray()
val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
val kp = KeyPairUtilities.generate(newBytes)
KeyPairUtilities.store(context, kp.seed, kp.ed25519KeyPair, kp.x25519KeyPair)
val registrationID = KeyHelper.generateRegistrationId(false)
context.prefs.setLocalRegistrationId(context, registrationID)
context.prefs.setLocalNumber(context, kp.x25519KeyPair.hexEncodedPublicKey)
context.prefs.setRestorationTime(context, 0)
context.prefs.setHasViewedSeed(context, false)
context.prefs.setLocalRegistrationId(registrationID)
context.prefs.setLocalNumber(kp.x25519KeyPair.hexEncodedPublicKey)
context.prefs.setHasViewedSeed(false)
}
@Test

View File

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms;
import static android.os.Build.VERSION.SDK_INT;
import static org.session.libsession.utilities.TextSecurePreferences.SELECTED_ACCENT_COLOR;
import android.app.ActivityManager;
import android.content.Context;
@ -62,7 +61,7 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
@StyleRes @Nullable
private Integer getAccentTheme() {
if (!getPreferences().hasPreference(SELECTED_ACCENT_COLOR)) return null;
if (!getPreferences().hasSelectedAccentColor()) return null;
ThemeState themeState = ActivityUtilitiesKt.themeState(getPreferences());
return themeState.getAccentStyle();
}

View File

@ -1,261 +0,0 @@
package org.thoughtcrime.securesms.components;
import android.app.Dialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.DialogPreference;
import androidx.preference.PreferenceDialogFragmentCompat;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.AttributeSet;
import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsignal.utilities.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.components.CustomDefaultPreference.CustomDefaultPreferenceDialogFragmentCompat.CustomPreferenceValidator;
import org.session.libsession.utilities.TextSecurePreferences;
import java.net.URI;
import java.net.URISyntaxException;
public class CustomDefaultPreference extends DialogPreference {
private static final String TAG = CustomDefaultPreference.class.getSimpleName();
private final int inputType;
private final String customPreference;
private final String customToggle;
private CustomPreferenceValidator validator;
private String defaultValue;
public CustomDefaultPreference(Context context, AttributeSet attrs) {
super(context, attrs);
int[] attributeNames = new int[]{android.R.attr.inputType, R.attr.custom_pref_toggle};
TypedArray attributes = context.obtainStyledAttributes(attrs, attributeNames);
this.inputType = attributes.getInt(0, 0);
this.customPreference = getKey();
this.customToggle = attributes.getString(1);
this.validator = new CustomDefaultPreferenceDialogFragmentCompat.NullValidator();
attributes.recycle();
setPersistent(false);
setDialogLayoutResource(R.layout.custom_default_preference_dialog);
}
public CustomDefaultPreference setValidator(CustomPreferenceValidator validator) {
this.validator = validator;
return this;
}
public CustomDefaultPreference setDefaultValue(String defaultValue) {
this.defaultValue = defaultValue;
this.setSummary(getSummary());
return this;
}
@Override
public String getSummary() {
if (isCustom()) {
return getContext().getString(R.string.CustomDefaultPreference_using_custom,
getPrettyPrintValue(getCustomValue()));
} else {
return getContext().getString(R.string.CustomDefaultPreference_using_default,
getPrettyPrintValue(getDefaultValue()));
}
}
private String getPrettyPrintValue(String value) {
if (TextUtils.isEmpty(value)) return getContext().getString(R.string.CustomDefaultPreference_none);
else return value;
}
private boolean isCustom() {
return MessagingModuleConfiguration.getShared().getPrefs().getBooleanPreference(customToggle, false);
}
private void setCustom(boolean custom) {
MessagingModuleConfiguration.getShared().getPrefs().setBooleanPreference(customToggle, custom);
}
private String getCustomValue() {
return MessagingModuleConfiguration.getShared().getPrefs().getStringPreference(customPreference, "");
}
private void setCustomValue(String value) {
MessagingModuleConfiguration.getShared().getPrefs().setStringPreference(customPreference, value);
}
private String getDefaultValue() {
return defaultValue;
}
public static class CustomDefaultPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat {
private static final String INPUT_TYPE = "input_type";
private Spinner spinner;
private EditText customText;
private TextView defaultLabel;
public static CustomDefaultPreferenceDialogFragmentCompat newInstance(String key) {
CustomDefaultPreferenceDialogFragmentCompat fragment = new CustomDefaultPreferenceDialogFragmentCompat();
Bundle b = new Bundle(1);
b.putString(PreferenceDialogFragmentCompat.ARG_KEY, key);
fragment.setArguments(b);
return fragment;
}
@Override
protected void onBindDialogView(@NonNull View view) {
Log.i(TAG, "onBindDialogView");
super.onBindDialogView(view);
CustomDefaultPreference preference = (CustomDefaultPreference)getPreference();
this.spinner = (Spinner) view.findViewById(R.id.default_or_custom);
this.defaultLabel = (TextView) view.findViewById(R.id.default_label);
this.customText = (EditText) view.findViewById(R.id.custom_edit);
this.customText.setInputType(preference.inputType);
this.customText.addTextChangedListener(new TextValidator());
this.customText.setText(preference.getCustomValue());
this.spinner.setOnItemSelectedListener(new SelectionLister());
this.defaultLabel.setText(preference.getPrettyPrintValue(preference.defaultValue));
}
@Override
public @NonNull Dialog onCreateDialog(Bundle instanceState) {
Dialog dialog = super.onCreateDialog(instanceState);
CustomDefaultPreference preference = (CustomDefaultPreference)getPreference();
if (preference.isCustom()) spinner.setSelection(1, true);
else spinner.setSelection(0, true);
return dialog;
}
@Override
public void onDialogClosed(boolean positiveResult) {
CustomDefaultPreference preference = (CustomDefaultPreference)getPreference();
if (positiveResult) {
if (spinner != null) preference.setCustom(spinner.getSelectedItemPosition() == 1);
if (customText != null) preference.setCustomValue(customText.getText().toString());
preference.setSummary(preference.getSummary());
}
}
interface CustomPreferenceValidator {
public boolean isValid(String value);
}
private static class NullValidator implements CustomPreferenceValidator {
@Override
public boolean isValid(String value) {
return true;
}
}
private class TextValidator implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
@Override
public void afterTextChanged(Editable s) {
CustomDefaultPreference preference = (CustomDefaultPreference)getPreference();
if (spinner.getSelectedItemPosition() == 1) {
Button positiveButton = ((AlertDialog)getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setEnabled(preference.validator.isValid(s.toString()));
}
}
}
public static class UriValidator implements CustomPreferenceValidator {
@Override
public boolean isValid(String value) {
if (TextUtils.isEmpty(value)) return true;
try {
new URI(value);
return true;
} catch (URISyntaxException mue) {
return false;
}
}
}
public static class HostnameValidator implements CustomPreferenceValidator {
@Override
public boolean isValid(String value) {
if (TextUtils.isEmpty(value)) return true;
try {
URI uri = new URI(null, value, null, null);
return true;
} catch (URISyntaxException mue) {
return false;
}
}
}
public static class PortValidator implements CustomPreferenceValidator {
@Override
public boolean isValid(String value) {
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}
private class SelectionLister implements AdapterView.OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
CustomDefaultPreference preference = (CustomDefaultPreference)getPreference();
Button positiveButton = ((AlertDialog)getDialog()).getButton(AlertDialog.BUTTON_POSITIVE);
defaultLabel.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
customText.setVisibility(position == 0 ? View.GONE : View.VISIBLE);
positiveButton.setEnabled(position == 0 || preference.validator.isValid(customText.getText().toString()));
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
defaultLabel.setVisibility(View.VISIBLE);
customText.setVisibility(View.GONE);
}
}
}
}

View File

@ -480,11 +480,7 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
database.insertOrUpdate(openGroupPublicKeyTable, row, "${LokiAPIDatabase.server} = ?", wrap(server))
}
override fun getLastSnodePoolRefreshDate(): Date? {
val time = context.prefs.getLastSnodePoolRefreshDate()
if (time <= 0) { return null }
return Date(time)
}
override fun getLastSnodePoolRefreshDate(): Date? = context.prefs.getLastSnodePoolRefreshDate().takeIf { it > 0 }?.let(::Date)
override fun setLastSnodePoolRefreshDate(date: Date) {
context.prefs.setLastSnodePoolRefreshDate(date)

View File

@ -51,8 +51,6 @@ class ConfigFactory(
private val userGroupsLock = Object()
private var _userGroups: UserGroupsConfig? = null
private val isConfigForcedOn by lazy { context.prefs.hasForcedNewConfig() }
private val listeners: MutableList<ConfigFactoryUpdateListener> = mutableListOf()
fun registerListener(listener: ConfigFactoryUpdateListener) {
listeners += listener

View File

@ -156,7 +156,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
// Set up seed reminder view
lifecycleScope.launchWhenStarted {
binding.seedReminderView.setThemedContent {
if (!textSecurePreferences.getHasViewedSeed()) SeedReminder { start<RecoveryPasswordActivity>() }
if (!textSecurePreferences.hasViewedSeed()) SeedReminder { start<RecoveryPasswordActivity>() }
}
}
// Set up recycler view
@ -185,7 +185,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
// subscribe to outdated config updates, this should be removed after long enough time for device migration
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
TextSecurePreferences.events.filter { it == TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG }.collect {
TextSecurePreferences.events.filter { it == TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG.name }.collect {
updateLegacyConfigView()
}
}
@ -225,7 +225,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
withContext(Dispatchers.Main) {
updateProfileButton()
TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect {
TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF.name }.collect {
updateProfileButton()
}
}
@ -325,7 +325,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
binding.sessionToolbar.isVisible = !isShown
binding.recyclerView.isVisible = !isShown
binding.emptyStateContainer.isVisible = (binding.recyclerView.adapter as HomeAdapter).itemCount == 0 && binding.recyclerView.isVisible
binding.seedReminderView.isVisible = !prefs.getHasViewedSeed() && !isShown
binding.seedReminderView.isVisible = !prefs.hasViewedSeed() && !isShown
binding.globalSearchRecycler.isInvisible = !isShown
binding.newConversationButton.isVisible = !isShown
}
@ -341,7 +341,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
IdentityKeyUtil.checkUpdate(this)
binding.profileButton.recycle() // clear cached image before update tje profilePictureView
binding.profileButton.update()
if (textSecurePreferences.getHasViewedSeed()) {
if (textSecurePreferences.hasViewedSeed()) {
binding.seedReminderView.isVisible = false
}

View File

@ -61,7 +61,7 @@ class HomeViewModel @Inject constructor(
).stateIn(viewModelScope, SharingStarted.Eagerly, null)
private fun hasHiddenMessageRequests() = TextSecurePreferences.events
.filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS }
.filter { it == TextSecurePreferences.HAS_HIDDEN_MESSAGE_REQUESTS.name }
.map { prefs.hasHiddenMessageRequests() }
.onStart { emit(prefs.hasHiddenMessageRequests()) }

View File

@ -51,7 +51,7 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
}
public void setAlarms(@Nullable Uri ringtone, VibrateState vibrate) {
Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtone();
Uri defaultRingtone = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtoneUri();
boolean defaultVibrate = NotificationChannels.supported() ? NotificationChannels.getMessageVibrate(context) : MessagingModuleConfiguration.getShared().getPrefs().isNotificationVibrateEnabled();
if (ringtone == null && !TextUtils.isEmpty(defaultRingtone.toString())) setSound(defaultRingtone);

View File

@ -436,7 +436,7 @@ public class NotificationChannels {
messages.setGroup(CATEGORY_MESSAGES);
messages.enableVibration(MessagingModuleConfiguration.getShared().getPrefs().isNotificationVibrateEnabled());
messages.setSound(MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtone(), getRingtoneAudioAttributes());
messages.setSound(MessagingModuleConfiguration.getShared().getPrefs().getNotificationRingtoneUri(), getRingtoneAudioAttributes());
setLedPreference(messages, MessagingModuleConfiguration.getShared().getPrefs().getNotificationLedColor());
calls.setShowBadge(false);

View File

@ -30,7 +30,6 @@ class LoadAccountActivity : BaseActionBarActivity() {
super.onCreate(savedInstanceState)
supportActionBar?.setTitle(R.string.activity_link_load_account)
prefs.setConfigurationMessageSynced(false)
prefs.setRestorationTime(System.currentTimeMillis())
prefs.setLastProfileUpdateTime(0)
lifecycleScope.launch {

View File

@ -29,8 +29,6 @@ class LoadingActivity: BaseActionBarActivity() {
private val viewModel: LoadingViewModel by viewModels()
private fun register(loadFailed: Boolean) {
prefs.setLastConfigurationSyncTime(System.currentTimeMillis())
when {
loadFailed -> startPickDisplayNameActivity(loadFailed = true)
else -> startHomeActivity()

View File

@ -45,8 +45,8 @@ internal class LoadingViewModel @Inject constructor(
viewModelScope.launch(Dispatchers.IO) {
try {
TextSecurePreferences.events
.filter { it == TextSecurePreferences.CONFIGURATION_SYNCED }
.onStart { emit(TextSecurePreferences.CONFIGURATION_SYNCED) }
.filter { it == TextSecurePreferences.CONFIGURATION_SYNCED.name }
.onStart { emit(TextSecurePreferences.CONFIGURATION_SYNCED.name) }
.filter { prefs.getConfigurationMessageSynced() }
.timeout(TIMEOUT_TIME)
.collectLatest { onSuccess() }

View File

@ -40,6 +40,5 @@ class CreateAccountManager @Inject constructor(
val registrationID = KeyHelper.generateRegistrationId(false)
prefs.setLocalRegistrationId(registrationID)
prefs.setLocalNumber(userHexEncodedPublicKey)
prefs.setRestorationTime(0)
}
}

View File

@ -48,7 +48,6 @@ class LoadAccountManager @Inject constructor(
prefs.apply {
setLocalRegistrationId(registrationID)
setLocalNumber(userHexEncodedPublicKey)
setRestorationTime(System.currentTimeMillis())
setHasViewedSeed(true)
}

View File

@ -13,7 +13,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.DialogFragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
@ -22,7 +21,6 @@ import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.components.CustomDefaultPreference;
import org.thoughtcrime.securesms.conversation.v2.ViewUtil;
import network.loki.messenger.R;
@ -54,22 +52,6 @@ public abstract class CorrectedPreferenceFragment extends PreferenceFragmentComp
setDivider(null);
}
@Override
public void onDisplayPreferenceDialog(Preference preference) {
DialogFragment dialogFragment = null;
if (preference instanceof CustomDefaultPreference) {
dialogFragment = CustomDefaultPreference.CustomDefaultPreferenceDialogFragmentCompat.newInstance(preference.getKey());
}
if (dialogFragment != null) {
dialogFragment.setTargetFragment(this, 0);
dialogFragment.show(getFragmentManager(), "android.support.v7.preference.PreferenceFragment.DIALOG");
} else {
super.onDisplayPreferenceDialog(preference);
}
}
@Override
@SuppressLint("RestrictedApi")
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {

View File

@ -18,9 +18,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import network.loki.messenger.R
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.prefs
import org.session.libsession.utilities.findPreference
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat
import org.thoughtcrime.securesms.notifications.NotificationChannels
@ -74,7 +73,7 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
}
findPreference<Preference>(TextSecurePreferences.RINGTONE_PREF)!!.onPreferenceClickListener =
Preference.OnPreferenceClickListener {
val current = prefs.getNotificationRingtone()
val current = prefs.getNotificationRingtoneUri()
val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true)
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true)
@ -152,7 +151,7 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
private fun initializeRingtoneSummary(pref: Preference?) {
val listener = pref!!.onPreferenceChangeListener as RingtoneSummaryListener?
val uri = prefs.getNotificationRingtone()
val uri = prefs.getNotificationRingtoneUri()
listener!!.onPreferenceChange(pref, uri)
}
@ -172,13 +171,4 @@ class NotificationsPreferenceFragment : ListSummaryPreferenceFragment() {
return super.onPreferenceChange(preference, value)
}
}
companion object {
@Suppress("unused")
private val TAG = NotificationsPreferenceFragment::class.java.simpleName
fun getSummary(context: Context): CharSequence = when (context.prefs.isNotificationsEnabled()) {
true -> R.string.ApplicationPreferencesActivity_On
false -> R.string.ApplicationPreferencesActivity_Off
}.let(context::getString)
}
}

View File

@ -15,6 +15,7 @@ import network.loki.messenger.BuildConfig
import network.loki.messenger.R
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.findPreference
import org.session.libsession.utilities.prefs
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat

View File

@ -1,122 +0,0 @@
package org.thoughtcrime.securesms.service;
import android.app.DownloadManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsession.utilities.FileUtils;
import org.session.libsession.utilities.ServiceUtil;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsignal.utilities.Hex;
import org.session.libsignal.utilities.Log;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.util.FileProviderUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import network.loki.messenger.R;
public class UpdateApkReadyListener extends BroadcastReceiver {
private static final String TAG = UpdateApkReadyListener.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive()");
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -2);
if (downloadId == MessagingModuleConfiguration.getShared().getPrefs().getUpdateApkDownloadId()) {
Uri uri = getLocalUriForDownloadId(context, downloadId);
String encodedDigest = MessagingModuleConfiguration.getShared().getPrefs().getUpdateApkDigest();
if (uri == null) {
Log.w(TAG, "Downloaded local URI is null?");
return;
}
if (isMatchingDigest(context, downloadId, encodedDigest)) {
displayInstallNotification(context, uri);
} else {
Log.w(TAG, "Downloaded APK doesn't match digest...");
}
}
}
}
private void displayInstallNotification(Context context, Uri uri) {
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setData(uri);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
Notification notification = new NotificationCompat.Builder(context, NotificationChannels.APP_UPDATES)
.setOngoing(true)
.setContentTitle(context.getString(R.string.UpdateApkReadyListener_Signal_update))
.setContentText(context.getString(R.string.UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update))
.setSmallIcon(R.drawable.ic_notification)
.setColor(context.getResources().getColor(R.color.textsecure_primary))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_REMINDER)
.setContentIntent(pendingIntent)
.build();
ServiceUtil.getNotificationManager(context).notify(666, notification);
}
private @Nullable Uri getLocalUriForDownloadId(Context context, long downloadId) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
try {
if (cursor != null && cursor.moveToFirst()) {
String localUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI));
if (localUri != null) {
File localFile = new File(Uri.parse(localUri).getPath());
return FileProviderUtil.getUriFor(context, localFile);
}
}
} finally {
if (cursor != null) cursor.close();
}
return null;
}
private boolean isMatchingDigest(Context context, long downloadId, String theirEncodedDigest) {
try {
if (theirEncodedDigest == null) return false;
byte[] theirDigest = Hex.fromStringCondensed(theirEncodedDigest);
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor());
byte[] ourDigest = FileUtils.getFileDigest(fin);
fin.close();
return MessageDigest.isEqual(ourDigest, theirDigest);
} catch (IOException e) {
Log.w(TAG, e);
return false;
}
}
}