mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 22:43:38 +00:00
Support for using Signal without Play Services
This is now possible with beta calling, so non-GCM users are a part of beta calling by default. // FREEBIE
This commit is contained in:
parent
4112f23f33
commit
1669731329
@ -84,6 +84,7 @@
|
|||||||
<uses-permission android:name="android.permission.READ_CALL_STATE"/>
|
<uses-permission android:name="android.permission.READ_CALL_STATE"/>
|
||||||
<uses-permission android:name="android.permission.READ_LOGS"/>
|
<uses-permission android:name="android.permission.READ_LOGS"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
|
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||||
|
|
||||||
<permission android:name="org.thoughtcrime.securesms.permission.C2D_MESSAGE"
|
<permission android:name="org.thoughtcrime.securesms.permission.C2D_MESSAGE"
|
||||||
android:protectionLevel="signature" />
|
android:protectionLevel="signature" />
|
||||||
@ -533,6 +534,12 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name=".service.PersistentConnectionBootListener">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".notifications.MessageNotifier$ReminderReceiver">
|
<receiver android:name=".notifications.MessageNotifier$ReminderReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION"/>
|
<action android:name="org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION"/>
|
||||||
|
16
build.gradle
16
build.gradle
@ -57,7 +57,7 @@ dependencies {
|
|||||||
|
|
||||||
compile 'org.whispersystems:jobmanager:1.0.2'
|
compile 'org.whispersystems:jobmanager:1.0.2'
|
||||||
compile 'org.whispersystems:libpastelog:1.0.7'
|
compile 'org.whispersystems:libpastelog:1.0.7'
|
||||||
compile 'org.whispersystems:signal-service-android:2.5.0'
|
compile 'org.whispersystems:signal-service-android:2.5.1'
|
||||||
compile 'org.whispersystems:webrtc-android:M56-S1'
|
compile 'org.whispersystems:webrtc-android:M56-S1'
|
||||||
|
|
||||||
compile "me.leolin:ShortcutBadger:1.10-WS1"
|
compile "me.leolin:ShortcutBadger:1.10-WS1"
|
||||||
@ -127,7 +127,7 @@ dependencyVerification {
|
|||||||
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
|
'com.google.android.gms:play-services-places:abf3a4a3b146ec7e6e753be62775e512868cf37d6f88ffe2d81167b33b57132b',
|
||||||
'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181',
|
'org.whispersystems:jobmanager:506f679fc2fcf7bb6d10f00f41d6f6ea0abf75c70dc95b913398661ad538a181',
|
||||||
'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88',
|
'org.whispersystems:libpastelog:bb331d9a98240fc139101128ba836c1edec3c40e000597cdbb29ebf4cbf34d88',
|
||||||
'org.whispersystems:signal-service-android:f207fcf8f17b5a1f04053151cad518f9520f8fbfb2e5563a19828f6b2c2b7b6d',
|
'org.whispersystems:signal-service-android:b0329b155cc9ad5e7fc08e4660538df1827c6d9485b05cab41946f36ad7ee0ab',
|
||||||
'org.whispersystems:webrtc-android:776a2769348f62aec28b9be6e97dcfea9c07b472ddbe24ac1ca1c46567cf8a8e',
|
'org.whispersystems:webrtc-android:776a2769348f62aec28b9be6e97dcfea9c07b472ddbe24ac1ca1c46567cf8a8e',
|
||||||
'me.leolin:ShortcutBadger:e8e39df8a59d8211a30f40b1eeab21b3fa57b3f3e0f03abb995f82d66588778c',
|
'me.leolin:ShortcutBadger:e8e39df8a59d8211a30f40b1eeab21b3fa57b3f3e0f03abb995f82d66588778c',
|
||||||
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
'se.emilsjolander:stickylistheaders:a08ca948aa6b220f09d82f16bbbac395f6b78897e9eeac6a9f0b0ba755928eeb',
|
||||||
@ -162,22 +162,22 @@ dependencyVerification {
|
|||||||
'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49',
|
'com.google.android.gms:play-services-base:0ca636a8fc9a5af45e607cdcd61783bf5d561cbbb0f862021ce69606eee5ad49',
|
||||||
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
|
'com.google.android.gms:play-services-basement:95dd882c5ffba15b9a99de3fefb05d3a01946623af67454ca00055d222f85a8d',
|
||||||
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
|
'com.google.android.gms:play-services-iid:54e919f9957b8b7820da7ee9b83471d00d0cac1cf08ddea8b5b41aea80bb1a70',
|
||||||
|
'org.whispersystems:signal-service-java:e0b9c41fcf614d58a71afcbb290d1864275b65364ca8fafeb5fbcbdc2d59a57a',
|
||||||
'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19',
|
'org.whispersystems:signal-protocol-android:1b4b9d557c8eaf861797ff683990d482d4aa8e9f23d9b17ff0cc67a02f38cb19',
|
||||||
'org.whispersystems:signal-service-java:910ed96e928355d118454e1dff6c11b9f95daa801f3b4022e5c8999bff47a888',
|
|
||||||
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
'com.nineoldandroids:library:68025a14e3e7673d6ad2f95e4b46d78d7d068343aa99256b686fe59de1b3163a',
|
||||||
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
|
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
|
||||||
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
|
'com.google.android.gms:play-services-tasks:69ec265168e601d0203d04cd42e34bb019b2f029aa1e16fabd38a5153eea2086',
|
||||||
|
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
|
||||||
|
'com.googlecode.libphonenumber:libphonenumber:141ebcafba7070a13d879c44e7648ddbe10beab665cb64d7b0c1bea93afb8dc2',
|
||||||
|
'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d',
|
||||||
|
'com.squareup.okhttp3:okhttp:a992938d7203ca557cd7a116f002e8c427ec9cdae7ea852441abb8aec891f948',
|
||||||
'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0',
|
'org.whispersystems:curve25519-android:bf6c34223d45d2f2813a8efcab9923caf99115115c760c9acea680bcb42d23c0',
|
||||||
'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c',
|
'org.whispersystems:signal-protocol-java:a835cd0609cf116a74651bd0aa748db9392bba48c2d2af787757b8a1b50d131c',
|
||||||
'com.googlecode.libphonenumber:libphonenumber:7214dc6dfc6243e34fb1a3e02ad15331bfff6ab902d679e3ba337695265c21ca',
|
|
||||||
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
|
|
||||||
'com.fasterxml.jackson.core:jackson-databind:835097bcdd11f5bc8a08378c70d4c8054dfa4b911691cc2752063c75534d198d',
|
|
||||||
'com.squareup.okhttp3:okhttp:eecd834b09d12c3cd568b811522b97012619f7f00378c3c719a1957fac6458ef',
|
|
||||||
'org.whispersystems:curve25519-java:00f1d4919f759055f41f7853a3d475dc7c8decf0dbf045ae93414f8f23b066cc',
|
|
||||||
'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94',
|
'com.fasterxml.jackson.core:jackson-annotations:0ca408c24202a7626ec8b861e99d85eca5e38b73311dd6dd12e3e9deecc3fe94',
|
||||||
'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0',
|
'com.fasterxml.jackson.core:jackson-core:cbf4604784b4de226262845447a1ad3bb38a6728cebe86562e2c5afada8be2c0',
|
||||||
'com.squareup.okio:okio:8c5436cadfab36bbd97db5f5c43b7bfdb5bf2f5f894ec8709b1929f14bdd010c',
|
'com.squareup.okio:okio:8c5436cadfab36bbd97db5f5c43b7bfdb5bf2f5f894ec8709b1929f14bdd010c',
|
||||||
|
'org.whispersystems:curve25519-java:00f1d4919f759055f41f7853a3d475dc7c8decf0dbf045ae93414f8f23b066cc',
|
||||||
'com.android.support:support-media-compat:8d6a1a5ba3d9eb1a25cb8f21bb312ac6280202e3d2900cb0b447d065d0d8a125',
|
'com.android.support:support-media-compat:8d6a1a5ba3d9eb1a25cb8f21bb312ac6280202e3d2900cb0b447d065d0d8a125',
|
||||||
'com.android.support:support-core-utils:a7649e18c04143dde40c218c5ce9a030e7ae674089cd7b18c6cf8ed2a22cf01a',
|
'com.android.support:support-core-utils:a7649e18c04143dde40c218c5ce9a030e7ae674089cd7b18c6cf8ed2a22cf01a',
|
||||||
'com.android.support:support-fragment:1294500b357f52cf3779e2521c79f54ae7844f3b9a5f6727495dbbda7f231377',
|
'com.android.support:support-fragment:1294500b357f52cf3779e2521c79f54ae7844f3b9a5f6727495dbbda7f231377',
|
||||||
|
@ -370,6 +370,10 @@
|
|||||||
<string name="MessageDetailsRecipient_failed_to_send">Failed to send</string>
|
<string name="MessageDetailsRecipient_failed_to_send">Failed to send</string>
|
||||||
<string name="MessageDetailsRecipient_new_safety_number">New safety number</string>
|
<string name="MessageDetailsRecipient_new_safety_number">New safety number</string>
|
||||||
|
|
||||||
|
<!-- MessageRetrievalService -->
|
||||||
|
<string name="MessageRetrievalService_signal">Signal</string>
|
||||||
|
<string name="MessageRetrievalService_background_connection_enabled">Background connection enabled</string>
|
||||||
|
|
||||||
<!-- MmsDownloader -->
|
<!-- MmsDownloader -->
|
||||||
<string name="MmsDownloader_error_storing_mms">Error storing MMS!</string>
|
<string name="MmsDownloader_error_storing_mms">Error storing MMS!</string>
|
||||||
<string name="MmsDownloader_error_connecting_to_mms_provider">Error connecting to MMS provider</string>
|
<string name="MmsDownloader_error_connecting_to_mms_provider">Error connecting to MMS provider</string>
|
||||||
@ -501,17 +505,16 @@
|
|||||||
<string name="RegistrationActivity_the_number_you_specified_s_is_invalid">The number you
|
<string name="RegistrationActivity_the_number_you_specified_s_is_invalid">The number you
|
||||||
specified (%s) is invalid.
|
specified (%s) is invalid.
|
||||||
</string>
|
</string>
|
||||||
<string name="RegistrationActivity_unsupported">Unsupported</string>
|
|
||||||
<string name="RegistrationActivity_sorry_this_device_is_not_supported_for_data_messaging">Sorry,
|
|
||||||
this device is not supported for data messaging. Devices running versions of Android older
|
|
||||||
than 4.0 must have a registered Google Account. Devices running Android 4.0 or newer do not
|
|
||||||
require a Google account, but must have the Play Store app installed.
|
|
||||||
</string>
|
|
||||||
<string name="RegistrationActivity_we_will_now_verify_that_the_following_number_is_associated_with_your_device_s">
|
<string name="RegistrationActivity_we_will_now_verify_that_the_following_number_is_associated_with_your_device_s">
|
||||||
Double-check that this is your number! We\'re about to verify it with an SMS.
|
Double-check that this is your number! We\'re about to verify it with an SMS.
|
||||||
</string>
|
</string>
|
||||||
<string name="RegistrationActivity_continue">Continue</string>
|
<string name="RegistrationActivity_continue">Continue</string>
|
||||||
<string name="RegistrationActivity_edit">Edit</string>
|
<string name="RegistrationActivity_edit">Edit</string>
|
||||||
|
<string name="RegistrationActivity_missing_google_play_services">Missing Google Play Services</string>
|
||||||
|
<string name="RegistrationActivity_this_device_is_missing_google_play_services">This device is missing Google Play Services. You can still use Signal, but this configuration may result in reduced reliability or performance.\n\nIf you are not an advanced user, are not running an aftermarket Android ROM, or believe that you are seeing this in error, please contact support@whispersystems.org for help trouble shooting.</string>
|
||||||
|
<string name="RegistrationActivity_i_understand">I understand</string>
|
||||||
|
<string name="RegistrationActivity_play_services_error">Play Services Error</string>
|
||||||
|
<string name="RegistrationActivity_google_play_services_is_updating_or_unavailable">Google Play Services is updating or temporarily unavailable. Please try again.</string>
|
||||||
|
|
||||||
<!-- RegistrationProblemsActivity -->
|
<!-- RegistrationProblemsActivity -->
|
||||||
<string name="RegistrationProblemsActivity_possible_problems">Possible problems</string>
|
<string name="RegistrationProblemsActivity_possible_problems">Possible problems</string>
|
||||||
|
@ -54,6 +54,7 @@ import android.view.ViewGroup;
|
|||||||
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
|
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
|
||||||
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
||||||
import org.thoughtcrime.securesms.components.reminder.DefaultSmsReminder;
|
import org.thoughtcrime.securesms.components.reminder.DefaultSmsReminder;
|
||||||
|
import org.thoughtcrime.securesms.components.reminder.DozeReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
|
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.OutdatedBuildReminder;
|
import org.thoughtcrime.securesms.components.reminder.OutdatedBuildReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.PushRegistrationReminder;
|
import org.thoughtcrime.securesms.components.reminder.PushRegistrationReminder;
|
||||||
@ -184,6 +185,8 @@ public class ConversationListFragment extends Fragment
|
|||||||
return Optional.of((new PushRegistrationReminder(context, masterSecret)));
|
return Optional.of((new PushRegistrationReminder(context, masterSecret)));
|
||||||
} else if (ShareReminder.isEligible(context)) {
|
} else if (ShareReminder.isEligible(context)) {
|
||||||
return Optional.of(new ShareReminder(context));
|
return Optional.of(new ShareReminder(context));
|
||||||
|
} else if (DozeReminder.isEligible(context)) {
|
||||||
|
return Optional.of(new DozeReminder(context));
|
||||||
} else {
|
} else {
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -20,6 +21,7 @@ import android.widget.TextView;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.android.gms.common.ConnectionResult;
|
import com.google.android.gms.common.ConnectionResult;
|
||||||
|
import com.google.android.gms.common.GoogleApiAvailability;
|
||||||
import com.google.android.gms.common.GooglePlayServicesUtil;
|
import com.google.android.gms.common.GooglePlayServicesUtil;
|
||||||
import com.google.i18n.phonenumbers.AsYouTypeFormatter;
|
import com.google.i18n.phonenumbers.AsYouTypeFormatter;
|
||||||
import com.google.i18n.phonenumbers.NumberParseException;
|
import com.google.i18n.phonenumbers.NumberParseException;
|
||||||
@ -44,6 +46,13 @@ public class RegistrationActivity extends BaseActionBarActivity {
|
|||||||
private static final int PICK_COUNTRY = 1;
|
private static final int PICK_COUNTRY = 1;
|
||||||
private static final String TAG = RegistrationActivity.class.getSimpleName();
|
private static final String TAG = RegistrationActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
private enum PlayServicesStatus {
|
||||||
|
SUCCESS,
|
||||||
|
MISSING,
|
||||||
|
NEEDS_UPDATE,
|
||||||
|
TRANSIENT_ERROR
|
||||||
|
}
|
||||||
|
|
||||||
private AsYouTypeFormatter countryFormatter;
|
private AsYouTypeFormatter countryFormatter;
|
||||||
private ArrayAdapter<String> countrySpinnerAdapter;
|
private ArrayAdapter<String> countrySpinnerAdapter;
|
||||||
private Spinner countrySpinner;
|
private Spinner countrySpinner;
|
||||||
@ -211,28 +220,32 @@ public class RegistrationActivity extends BaseActionBarActivity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gcmStatus = GooglePlayServicesUtil.isGooglePlayServicesAvailable(self);
|
PlayServicesStatus gcmStatus = checkPlayServices(self);
|
||||||
|
|
||||||
if (gcmStatus != ConnectionResult.SUCCESS) {
|
if (gcmStatus == PlayServicesStatus.SUCCESS) {
|
||||||
if (GooglePlayServicesUtil.isUserRecoverableError(gcmStatus)) {
|
promptForRegistrationStart(self, e164number, true);
|
||||||
GooglePlayServicesUtil.getErrorDialog(gcmStatus, self, 9000).show();
|
} else if (gcmStatus == PlayServicesStatus.MISSING) {
|
||||||
|
promptForNoPlayServices(self, e164number);
|
||||||
|
} else if (gcmStatus == PlayServicesStatus.NEEDS_UPDATE) {
|
||||||
|
GoogleApiAvailability.getInstance().getErrorDialog(self, ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED, 0);
|
||||||
} else {
|
} else {
|
||||||
Dialogs.showAlertDialog(self, getString(R.string.RegistrationActivity_unsupported),
|
Dialogs.showAlertDialog(self, getString(R.string.RegistrationActivity_play_services_error),
|
||||||
getString(R.string.RegistrationActivity_sorry_this_device_is_not_supported_for_data_messaging));
|
getString(R.string.RegistrationActivity_google_play_services_is_updating_or_unavailable));
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog.Builder dialog = new AlertDialog.Builder(self);
|
private void promptForRegistrationStart(final Context context, final String e164number, final boolean gcmSupported) {
|
||||||
|
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||||
dialog.setTitle(PhoneNumberFormatter.getInternationalFormatFromE164(e164number));
|
dialog.setTitle(PhoneNumberFormatter.getInternationalFormatFromE164(e164number));
|
||||||
dialog.setMessage(R.string.RegistrationActivity_we_will_now_verify_that_the_following_number_is_associated_with_your_device_s);
|
dialog.setMessage(R.string.RegistrationActivity_we_will_now_verify_that_the_following_number_is_associated_with_your_device_s);
|
||||||
dialog.setPositiveButton(getString(R.string.RegistrationActivity_continue),
|
dialog.setPositiveButton(getString(R.string.RegistrationActivity_continue),
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Intent intent = new Intent(self, RegistrationProgressActivity.class);
|
Intent intent = new Intent(context, RegistrationProgressActivity.class);
|
||||||
intent.putExtra("e164number", e164number);
|
intent.putExtra(RegistrationProgressActivity.NUMBER_EXTRA, e164number);
|
||||||
intent.putExtra("master_secret", masterSecret);
|
intent.putExtra(RegistrationProgressActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
|
intent.putExtra(RegistrationProgressActivity.GCM_SUPPORTED_EXTRA, gcmSupported);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@ -240,6 +253,48 @@ public class RegistrationActivity extends BaseActionBarActivity {
|
|||||||
dialog.setNegativeButton(getString(R.string.RegistrationActivity_edit), null);
|
dialog.setNegativeButton(getString(R.string.RegistrationActivity_edit), null);
|
||||||
dialog.show();
|
dialog.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void promptForNoPlayServices(final Context context, final String e164number) {
|
||||||
|
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||||
|
dialog.setTitle(R.string.RegistrationActivity_missing_google_play_services);
|
||||||
|
dialog.setMessage(R.string.RegistrationActivity_this_device_is_missing_google_play_services);
|
||||||
|
dialog.setPositiveButton(R.string.RegistrationActivity_i_understand, new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
promptForRegistrationStart(context, e164number, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.setNegativeButton(android.R.string.cancel, null);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayServicesStatus checkPlayServices(Context context) {
|
||||||
|
int gcmStatus = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
gcmStatus = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.w(TAG, t);
|
||||||
|
return PlayServicesStatus.MISSING;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.w(TAG, "Play Services: " + gcmStatus);
|
||||||
|
|
||||||
|
switch (gcmStatus) {
|
||||||
|
case ConnectionResult.SUCCESS:
|
||||||
|
return PlayServicesStatus.SUCCESS;
|
||||||
|
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
|
||||||
|
return PlayServicesStatus.NEEDS_UPDATE;
|
||||||
|
case ConnectionResult.SERVICE_DISABLED:
|
||||||
|
case ConnectionResult.SERVICE_MISSING:
|
||||||
|
case ConnectionResult.SERVICE_INVALID:
|
||||||
|
case ConnectionResult.API_UNAVAILABLE:
|
||||||
|
case ConnectionResult.SERVICE_MISSING_PERMISSION:
|
||||||
|
return PlayServicesStatus.MISSING;
|
||||||
|
default:
|
||||||
|
return PlayServicesStatus.TRANSIENT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CountryCodeChangedListener implements TextWatcher {
|
private class CountryCodeChangedListener implements TextWatcher {
|
||||||
|
@ -49,6 +49,10 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
|
|
||||||
private static final String TAG = RegistrationProgressActivity.class.getSimpleName();
|
private static final String TAG = RegistrationProgressActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final String NUMBER_EXTRA = "e164number";
|
||||||
|
public static final String MASTER_SECRET_EXTRA = "master_secret";
|
||||||
|
public static final String GCM_SUPPORTED_EXTRA = "gcm_supported";
|
||||||
|
|
||||||
private static final int FOCUSED_COLOR = Color.parseColor("#ff333333");
|
private static final int FOCUSED_COLOR = Color.parseColor("#ff333333");
|
||||||
private static final int UNFOCUSED_COLOR = Color.parseColor("#ff808080");
|
private static final int UNFOCUSED_COLOR = Color.parseColor("#ff808080");
|
||||||
|
|
||||||
@ -89,6 +93,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
private EditText codeEditText;
|
private EditText codeEditText;
|
||||||
|
|
||||||
private MasterSecret masterSecret;
|
private MasterSecret masterSecret;
|
||||||
|
private boolean gcmSupported;
|
||||||
private volatile boolean visible;
|
private volatile boolean visible;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -131,7 +136,8 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
this.masterSecret = getIntent().getParcelableExtra("master_secret");
|
this.masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
|
||||||
|
this.gcmSupported = getIntent().getBooleanExtra(GCM_SUPPORTED_EXTRA, true);
|
||||||
this.registrationLayout = (LinearLayout)findViewById(R.id.registering_layout);
|
this.registrationLayout = (LinearLayout)findViewById(R.id.registering_layout);
|
||||||
this.verificationFailureLayout = (LinearLayout)findViewById(R.id.verification_failure_layout);
|
this.verificationFailureLayout = (LinearLayout)findViewById(R.id.verification_failure_layout);
|
||||||
this.connectivityFailureLayout = (LinearLayout)findViewById(R.id.connectivity_failure_layout);
|
this.connectivityFailureLayout = (LinearLayout)findViewById(R.id.connectivity_failure_layout);
|
||||||
@ -199,8 +205,9 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
if (hasNumberDirective()) {
|
if (hasNumberDirective()) {
|
||||||
Intent intent = new Intent(this, RegistrationService.class);
|
Intent intent = new Intent(this, RegistrationService.class);
|
||||||
intent.setAction(RegistrationService.REGISTER_NUMBER_ACTION);
|
intent.setAction(RegistrationService.REGISTER_NUMBER_ACTION);
|
||||||
intent.putExtra("e164number", getNumberDirective());
|
intent.putExtra(RegistrationService.NUMBER_EXTRA, getNumberDirective());
|
||||||
intent.putExtra("master_secret", masterSecret);
|
intent.putExtra(RegistrationService.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
|
intent.putExtra(RegistrationService.GCM_SUPPORTED_EXTRA, gcmSupported);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
} else {
|
} else {
|
||||||
Intent intent = new Intent(this, RegistrationActivity.class);
|
Intent intent = new Intent(this, RegistrationActivity.class);
|
||||||
@ -295,7 +302,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
|
|
||||||
private void handleVerificationRequestedVoice(RegistrationState state) {
|
private void handleVerificationRequestedVoice(RegistrationState state) {
|
||||||
handleVerificationTimeout(state);
|
handleVerificationTimeout(state);
|
||||||
verifyButton.setOnClickListener(new VerifyClickListener(state.number, state.password));
|
verifyButton.setOnClickListener(new VerifyClickListener(state.number, state.password, gcmSupported));
|
||||||
verifyButton.setEnabled(true);
|
verifyButton.setEnabled(true);
|
||||||
codeEditText.setEnabled(true);
|
codeEditText.setEnabled(true);
|
||||||
}
|
}
|
||||||
@ -354,11 +361,11 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasNumberDirective() {
|
private boolean hasNumberDirective() {
|
||||||
return getIntent().getStringExtra("e164number") != null;
|
return getIntent().getStringExtra(NUMBER_EXTRA) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getNumberDirective() {
|
private String getNumberDirective() {
|
||||||
return getIntent().getStringExtra("e164number");
|
return getIntent().getStringExtra(NUMBER_EXTRA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shutdownServiceBinding() {
|
private void shutdownServiceBinding() {
|
||||||
@ -426,7 +433,8 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
shutdownService();
|
shutdownService();
|
||||||
|
|
||||||
Intent activityIntent = new Intent(RegistrationProgressActivity.this, RegistrationActivity.class);
|
Intent activityIntent = new Intent(RegistrationProgressActivity.this, RegistrationActivity.class);
|
||||||
activityIntent.putExtra("master_secret", masterSecret);
|
activityIntent.putExtra(RegistrationProgressActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
|
activityIntent.putExtra(RegistrationProgressActivity.GCM_SUPPORTED_EXTRA, gcmSupported);
|
||||||
startActivity(activityIntent);
|
startActivity(activityIntent);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
@ -450,14 +458,16 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
private final String e164number;
|
private final String e164number;
|
||||||
private final String password;
|
private final String password;
|
||||||
private final String signalingKey;
|
private final String signalingKey;
|
||||||
|
private final boolean gcmSupported;
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
|
|
||||||
public VerifyClickListener(String e164number, String password) {
|
public VerifyClickListener(String e164number, String password, boolean gcmSupported) {
|
||||||
this.e164number = e164number;
|
this.e164number = e164number;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.signalingKey = Util.getSecret(52);
|
this.signalingKey = Util.getSecret(52);
|
||||||
|
this.gcmSupported = gcmSupported;
|
||||||
this.context = RegistrationProgressActivity.this;
|
this.context = RegistrationProgressActivity.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,10 +500,11 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
Intent intent = new Intent(context, RegistrationService.class);
|
Intent intent = new Intent(context, RegistrationService.class);
|
||||||
intent.setAction(RegistrationService.VOICE_REGISTER_ACTION);
|
intent.setAction(RegistrationService.VOICE_REGISTER_ACTION);
|
||||||
intent.putExtra("e164number", e164number);
|
intent.putExtra(RegistrationService.NUMBER_EXTRA, e164number);
|
||||||
intent.putExtra("password", password);
|
intent.putExtra(RegistrationService.PASSWORD_EXTRA, password);
|
||||||
intent.putExtra("signaling_key", signalingKey);
|
intent.putExtra(RegistrationService.SIGNALING_KEY_EXTRA, signalingKey);
|
||||||
intent.putExtra("master_secret", masterSecret);
|
intent.putExtra(RegistrationService.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
|
intent.putExtra(RegistrationService.GCM_SUPPORTED_EXTRA, gcmSupported);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
break;
|
break;
|
||||||
case NETWORK_ERROR:
|
case NETWORK_ERROR:
|
||||||
@ -522,7 +533,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
|
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
|
||||||
boolean video = TextSecurePreferences.isWebrtcCallingEnabled(context);
|
boolean video = TextSecurePreferences.isWebrtcCallingEnabled(context);
|
||||||
|
|
||||||
accountManager.verifyAccountWithCode(code, signalingKey, registrationId, true, video);
|
accountManager.verifyAccountWithCode(code, signalingKey, registrationId, true, video, !gcmSupported);
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
} catch (ExpectationFailedException e) {
|
} catch (ExpectationFailedException e) {
|
||||||
@ -578,9 +589,10 @@ public class RegistrationProgressActivity extends BaseActionBarActivity {
|
|||||||
case SUCCESS:
|
case SUCCESS:
|
||||||
Intent intent = new Intent(context, RegistrationService.class);
|
Intent intent = new Intent(context, RegistrationService.class);
|
||||||
intent.setAction(RegistrationService.VOICE_REQUESTED_ACTION);
|
intent.setAction(RegistrationService.VOICE_REQUESTED_ACTION);
|
||||||
intent.putExtra("e164number", e164number);
|
intent.putExtra(RegistrationService.NUMBER_EXTRA, e164number);
|
||||||
intent.putExtra("password", password);
|
intent.putExtra(RegistrationService.PASSWORD_EXTRA, password);
|
||||||
intent.putExtra("master_secret", masterSecret);
|
intent.putExtra(RegistrationService.MASTER_SECRET_EXTRA, masterSecret);
|
||||||
|
intent.putExtra(RegistrationService.GCM_SUPPORTED_EXTRA, gcmSupported);
|
||||||
startService(intent);
|
startService(intent);
|
||||||
|
|
||||||
callButton.setEnabled(false);
|
callButton.setEnabled(false);
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
package org.thoughtcrime.securesms.components.reminder;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.RequiresApi;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
|
public class DozeReminder extends Reminder {
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
|
public DozeReminder(@NonNull final Context context) {
|
||||||
|
super("Optimize for missing Play Services",
|
||||||
|
"This device does not support Play Services. Tap to disable system battery optimizations that prevent Signal from retrieving messages while inactive.");
|
||||||
|
|
||||||
|
setOkListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
TextSecurePreferences.setPromptedOptimizeDoze(context, true);
|
||||||
|
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
||||||
|
Uri.parse("package:" + context.getPackageName()));
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setDismissListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
TextSecurePreferences.setPromptedOptimizeDoze(context, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEligible(Context context) {
|
||||||
|
return TextSecurePreferences.isGcmDisabled(context) &&
|
||||||
|
!TextSecurePreferences.hasPromptedOptimizeDoze(context) &&
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||||
|
!((PowerManager)context.getSystemService(Context.POWER_SERVICE)).isIgnoringBatteryOptimizations(context.getPackageName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -60,6 +60,8 @@ public class GcmRefreshJob extends ContextJob implements InjectableType {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRun() throws Exception {
|
public void onRun() throws Exception {
|
||||||
|
if (TextSecurePreferences.isGcmDisabled(context)) return;
|
||||||
|
|
||||||
String registrationId = TextSecurePreferences.getGcmRegistrationId(context);
|
String registrationId = TextSecurePreferences.getGcmRegistrationId(context);
|
||||||
|
|
||||||
if (registrationId == null) {
|
if (registrationId == null) {
|
||||||
|
@ -43,11 +43,12 @@ public class RefreshAttributesJob extends ContextJob implements InjectableType {
|
|||||||
String gcmRegistrationId = TextSecurePreferences.getGcmRegistrationId(context);
|
String gcmRegistrationId = TextSecurePreferences.getGcmRegistrationId(context);
|
||||||
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
|
int registrationId = TextSecurePreferences.getLocalRegistrationId(context);
|
||||||
boolean video = TextSecurePreferences.isWebrtcCallingEnabled(context);
|
boolean video = TextSecurePreferences.isWebrtcCallingEnabled(context);
|
||||||
|
boolean fetchesMessages = TextSecurePreferences.isGcmDisabled(context);
|
||||||
|
|
||||||
String token = signalAccountManager.getAccountVerificationToken();
|
String token = signalAccountManager.getAccountVerificationToken();
|
||||||
|
|
||||||
redPhoneAccountManager.createAccount(token, new RedPhoneAccountAttributes(signalingKey, gcmRegistrationId));
|
redPhoneAccountManager.createAccount(token, new RedPhoneAccountAttributes(signalingKey, gcmRegistrationId));
|
||||||
signalAccountManager.setAccountAttributes(signalingKey, registrationId, true, video);
|
signalAccountManager.setAccountAttributes(signalingKey, registrationId, true, video || fetchesMessages, fetchesMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,9 +58,11 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
|||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
|
import org.thoughtcrime.securesms.service.MessageRetrievalService;
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
import org.thoughtcrime.securesms.webrtc.CallNotificationManager;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -155,7 +157,12 @@ public class MessageNotifier {
|
|||||||
for (StatusBarNotification notification : activeNotifications) {
|
for (StatusBarNotification notification : activeNotifications) {
|
||||||
boolean validNotification = false;
|
boolean validNotification = false;
|
||||||
|
|
||||||
if (notification.getId() != SUMMARY_NOTIFICATION_ID && notification.getId() != NotificationBarManager.RED_PHONE_NOTIFICATION) {
|
if (notification.getId() != SUMMARY_NOTIFICATION_ID &&
|
||||||
|
notification.getId() != NotificationBarManager.RED_PHONE_NOTIFICATION &&
|
||||||
|
notification.getId() != CallNotificationManager.WEBRTC_NOTIFICATION &&
|
||||||
|
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
|
||||||
|
notification.getId() != MessageRetrievalService.FOREGROUND_ID)
|
||||||
|
{
|
||||||
for (NotificationItem item : notificationState.getNotifications()) {
|
for (NotificationItem item : notificationState.getNotifications()) {
|
||||||
if (notification.getId() == (SUMMARY_NOTIFICATION_ID + item.getThreadId())) {
|
if (notification.getId() == (SUMMARY_NOTIFICATION_ID + item.getThreadId())) {
|
||||||
validNotification = true;
|
validNotification = true;
|
||||||
|
@ -99,7 +99,9 @@ public class AdvancedPreferenceFragment extends PreferenceFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeWebrtcCallingToggle() {
|
private void initializeWebrtcCallingToggle() {
|
||||||
if (Build.VERSION.SDK_INT >= 11) {
|
if (TextSecurePreferences.isGcmDisabled(getContext())) {
|
||||||
|
getPreferenceScreen().removePreference(findPreference(TextSecurePreferences.WEBRTC_CALLING_PREF));
|
||||||
|
} else if (Build.VERSION.SDK_INT >= 11) {
|
||||||
this.findPreference(TextSecurePreferences.WEBRTC_CALLING_PREF)
|
this.findPreference(TextSecurePreferences.WEBRTC_CALLING_PREF)
|
||||||
.setOnPreferenceChangeListener(new WebRtcClickListener());
|
.setOnPreferenceChangeListener(new WebRtcClickListener());
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,9 +5,11 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||||
import org.thoughtcrime.securesms.gcm.GcmBroadcastReceiver;
|
import org.thoughtcrime.securesms.gcm.GcmBroadcastReceiver;
|
||||||
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob;
|
import org.thoughtcrime.securesms.jobs.PushContentReceiveJob;
|
||||||
@ -24,16 +26,20 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
public class MessageRetrievalService extends Service implements Runnable, InjectableType, RequirementListener {
|
public class MessageRetrievalService extends Service implements InjectableType, RequirementListener {
|
||||||
|
|
||||||
private static final String TAG = MessageRetrievalService.class.getSimpleName();
|
private static final String TAG = MessageRetrievalService.class.getSimpleName();
|
||||||
|
|
||||||
public static final String ACTION_ACTIVITY_STARTED = "ACTIVITY_STARTED";
|
public static final String ACTION_ACTIVITY_STARTED = "ACTIVITY_STARTED";
|
||||||
public static final String ACTION_ACTIVITY_FINISHED = "ACTIVITY_FINISHED";
|
public static final String ACTION_ACTIVITY_FINISHED = "ACTIVITY_FINISHED";
|
||||||
public static final String ACTION_PUSH_RECEIVED = "PUSH_RECEIVED";
|
public static final String ACTION_PUSH_RECEIVED = "PUSH_RECEIVED";
|
||||||
|
public static final String ACTION_INITIALIZE = "INITIALIZE";
|
||||||
|
public static final int FOREGROUND_ID = 313399;
|
||||||
|
|
||||||
private static final long REQUEST_TIMEOUT_MINUTES = 1;
|
private static final long REQUEST_TIMEOUT_MINUTES = 1;
|
||||||
|
|
||||||
private NetworkRequirement networkRequirement;
|
private NetworkRequirement networkRequirement;
|
||||||
@ -44,6 +50,7 @@ public class MessageRetrievalService extends Service implements Runnable, Inject
|
|||||||
|
|
||||||
private int activeActivities = 0;
|
private int activeActivities = 0;
|
||||||
private List<Intent> pushPending = new LinkedList<>();
|
private List<Intent> pushPending = new LinkedList<>();
|
||||||
|
private MessageRetrievalThread retrievalThread = null;
|
||||||
|
|
||||||
public static SignalServiceMessagePipe pipe = null;
|
public static SignalServiceMessagePipe pipe = null;
|
||||||
|
|
||||||
@ -56,7 +63,11 @@ public class MessageRetrievalService extends Service implements Runnable, Inject
|
|||||||
networkRequirementProvider = new NetworkRequirementProvider(this);
|
networkRequirementProvider = new NetworkRequirementProvider(this);
|
||||||
|
|
||||||
networkRequirementProvider.setListener(this);
|
networkRequirementProvider.setListener(this);
|
||||||
new Thread(this, "MessageRetrievalService").start();
|
|
||||||
|
retrievalThread = new MessageRetrievalThread();
|
||||||
|
retrievalThread.start();
|
||||||
|
|
||||||
|
setForegroundIfNecessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
@ -70,44 +81,11 @@ public class MessageRetrievalService extends Service implements Runnable, Inject
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void onDestroy() {
|
||||||
while (true) {
|
super.onDestroy();
|
||||||
Log.w(TAG, "Waiting for websocket state change....");
|
|
||||||
waitForConnectionNecessary();
|
|
||||||
|
|
||||||
Log.w(TAG, "Making websocket connection....");
|
if (retrievalThread != null) {
|
||||||
pipe = receiver.createMessagePipe();
|
retrievalThread.stopThread();
|
||||||
|
|
||||||
try {
|
|
||||||
while (isConnectionNecessary()) {
|
|
||||||
try {
|
|
||||||
Log.w(TAG, "Reading message...");
|
|
||||||
pipe.read(REQUEST_TIMEOUT_MINUTES, TimeUnit.MINUTES,
|
|
||||||
new SignalServiceMessagePipe.MessagePipeCallback() {
|
|
||||||
@Override
|
|
||||||
public void onMessage(SignalServiceEnvelope envelope) {
|
|
||||||
Log.w(TAG, "Retrieved envelope! " + envelope.getSource());
|
|
||||||
|
|
||||||
PushContentReceiveJob receiveJob = new PushContentReceiveJob(MessageRetrievalService.this);
|
|
||||||
receiveJob.handle(envelope, false);
|
|
||||||
|
|
||||||
decrementPushReceived();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (TimeoutException e) {
|
|
||||||
Log.w(TAG, "Application level read timeout...");
|
|
||||||
} catch (InvalidVersionException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
} finally {
|
|
||||||
Log.w(TAG, "Shutting down pipe...");
|
|
||||||
shutdown(pipe);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.w(TAG, "Looping...");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +101,18 @@ public class MessageRetrievalService extends Service implements Runnable, Inject
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setForegroundIfNecessary() {
|
||||||
|
if (TextSecurePreferences.isGcmDisabled(this)) {
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||||
|
builder.setContentTitle(getString(R.string.MessageRetrievalService_signal));
|
||||||
|
builder.setContentText(getString(R.string.MessageRetrievalService_background_connection_enabled));
|
||||||
|
builder.setPriority(NotificationCompat.PRIORITY_MIN);
|
||||||
|
builder.setWhen(0);
|
||||||
|
builder.setSmallIcon(R.drawable.ic_signal_grey_24dp);
|
||||||
|
startForeground(FOREGROUND_ID, builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void incrementActive() {
|
private synchronized void incrementActive() {
|
||||||
activeActivities++;
|
activeActivities++;
|
||||||
Log.w(TAG, "Active Count: " + activeActivities);
|
Log.w(TAG, "Active Count: " + activeActivities);
|
||||||
@ -149,11 +139,13 @@ public class MessageRetrievalService extends Service implements Runnable, Inject
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized boolean isConnectionNecessary() {
|
private synchronized boolean isConnectionNecessary() {
|
||||||
Log.w(TAG, String.format("Network requirement: %s, active activities: %s, push pending: %s",
|
boolean isGcmDisabled = TextSecurePreferences.isGcmDisabled(this);
|
||||||
networkRequirement.isPresent(), activeActivities, pushPending.size()));
|
|
||||||
|
Log.w(TAG, String.format("Network requirement: %s, active activities: %s, push pending: %s, gcm disabled: %b",
|
||||||
|
networkRequirement.isPresent(), activeActivities, pushPending.size(), isGcmDisabled));
|
||||||
|
|
||||||
return TextSecurePreferences.isWebsocketRegistered(this) &&
|
return TextSecurePreferences.isWebsocketRegistered(this) &&
|
||||||
(activeActivities > 0 || !pushPending.isEmpty()) &&
|
(activeActivities > 0 || !pushPending.isEmpty() || isGcmDisabled) &&
|
||||||
networkRequirement.isPresent();
|
networkRequirement.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,4 +180,59 @@ public class MessageRetrievalService extends Service implements Runnable, Inject
|
|||||||
public static @Nullable SignalServiceMessagePipe getPipe() {
|
public static @Nullable SignalServiceMessagePipe getPipe() {
|
||||||
return pipe;
|
return pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MessageRetrievalThread extends Thread {
|
||||||
|
|
||||||
|
private AtomicBoolean stopThread = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!stopThread.get()) {
|
||||||
|
Log.w(TAG, "Waiting for websocket state change....");
|
||||||
|
waitForConnectionNecessary();
|
||||||
|
|
||||||
|
Log.w(TAG, "Making websocket connection....");
|
||||||
|
pipe = receiver.createMessagePipe();
|
||||||
|
|
||||||
|
SignalServiceMessagePipe localPipe = pipe;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (isConnectionNecessary() && !stopThread.get()) {
|
||||||
|
try {
|
||||||
|
Log.w(TAG, "Reading message...");
|
||||||
|
localPipe.read(REQUEST_TIMEOUT_MINUTES, TimeUnit.MINUTES,
|
||||||
|
new SignalServiceMessagePipe.MessagePipeCallback() {
|
||||||
|
@Override
|
||||||
|
public void onMessage(SignalServiceEnvelope envelope) {
|
||||||
|
Log.w(TAG, "Retrieved envelope! " + envelope.getSource());
|
||||||
|
|
||||||
|
PushContentReceiveJob receiveJob = new PushContentReceiveJob(MessageRetrievalService.this);
|
||||||
|
receiveJob.handle(envelope, false);
|
||||||
|
|
||||||
|
decrementPushReceived();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
Log.w(TAG, "Application level read timeout...");
|
||||||
|
} catch (InvalidVersionException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
} finally {
|
||||||
|
Log.w(TAG, "Shutting down pipe...");
|
||||||
|
shutdown(localPipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.w(TAG, "Looping...");
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.w(TAG, "Exiting...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopThread() {
|
||||||
|
stopThread.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.thoughtcrime.securesms.service;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
|
|
||||||
|
public class PersistentConnectionBootListener extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (TextSecurePreferences.isGcmDisabled(context)) {
|
||||||
|
Intent serviceIntent = new Intent(context, MessageRetrievalService.class);
|
||||||
|
serviceIntent.setAction(MessageRetrievalService.ACTION_INITIALIZE);
|
||||||
|
context.startService(serviceIntent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -71,6 +71,11 @@ public class RegistrationService extends Service {
|
|||||||
public static final String CHALLENGE_EVENT = "org.thoughtcrime.securesms.CHALLENGE_EVENT";
|
public static final String CHALLENGE_EVENT = "org.thoughtcrime.securesms.CHALLENGE_EVENT";
|
||||||
public static final String REGISTRATION_EVENT = "org.thoughtcrime.securesms.REGISTRATION_EVENT";
|
public static final String REGISTRATION_EVENT = "org.thoughtcrime.securesms.REGISTRATION_EVENT";
|
||||||
|
|
||||||
|
public static final String NUMBER_EXTRA = "e164number";
|
||||||
|
public static final String MASTER_SECRET_EXTRA = "master_secret";
|
||||||
|
public static final String GCM_SUPPORTED_EXTRA = "gcm_supported";
|
||||||
|
public static final String PASSWORD_EXTRA = "password";
|
||||||
|
public static final String SIGNALING_KEY_EXTRA = "signaling_key";
|
||||||
public static final String CHALLENGE_EXTRA = "CAAChallenge";
|
public static final String CHALLENGE_EXTRA = "CAAChallenge";
|
||||||
|
|
||||||
private static final long REGISTRATION_TIMEOUT_MILLIS = 120000;
|
private static final long REGISTRATION_TIMEOUT_MILLIS = 120000;
|
||||||
@ -149,21 +154,22 @@ public class RegistrationService extends Service {
|
|||||||
|
|
||||||
private void handleVoiceRequestedIntent(Intent intent) {
|
private void handleVoiceRequestedIntent(Intent intent) {
|
||||||
setState(new RegistrationState(RegistrationState.STATE_VOICE_REQUESTED,
|
setState(new RegistrationState(RegistrationState.STATE_VOICE_REQUESTED,
|
||||||
intent.getStringExtra("e164number"),
|
intent.getStringExtra(NUMBER_EXTRA),
|
||||||
intent.getStringExtra("password")));
|
intent.getStringExtra(PASSWORD_EXTRA)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleVoiceRegistrationIntent(Intent intent) {
|
private void handleVoiceRegistrationIntent(Intent intent) {
|
||||||
markAsVerifying(true);
|
markAsVerifying(true);
|
||||||
|
|
||||||
String number = intent.getStringExtra("e164number");
|
String number = intent.getStringExtra(NUMBER_EXTRA);
|
||||||
String password = intent.getStringExtra("password");
|
String password = intent.getStringExtra(PASSWORD_EXTRA);
|
||||||
String signalingKey = intent.getStringExtra("signaling_key");
|
String signalingKey = intent.getStringExtra(SIGNALING_KEY_EXTRA);
|
||||||
|
boolean supportsGcm = intent.getBooleanExtra(GCM_SUPPORTED_EXTRA, true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(this, number, password);
|
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(this, number, password);
|
||||||
|
|
||||||
handleCommonRegistration(accountManager, number, password, signalingKey);
|
handleCommonRegistration(accountManager, number, password, signalingKey, supportsGcm);
|
||||||
|
|
||||||
markAsVerified(number, password, signalingKey);
|
markAsVerified(number, password, signalingKey);
|
||||||
|
|
||||||
@ -183,8 +189,10 @@ public class RegistrationService extends Service {
|
|||||||
private void handleSmsRegistrationIntent(Intent intent) {
|
private void handleSmsRegistrationIntent(Intent intent) {
|
||||||
markAsVerifying(true);
|
markAsVerifying(true);
|
||||||
|
|
||||||
String number = intent.getStringExtra("e164number");
|
String number = intent.getStringExtra(NUMBER_EXTRA);
|
||||||
|
boolean supportsGcm = intent.getBooleanExtra(GCM_SUPPORTED_EXTRA, true);
|
||||||
int registrationId = TextSecurePreferences.getLocalRegistrationId(this);
|
int registrationId = TextSecurePreferences.getLocalRegistrationId(this);
|
||||||
|
boolean supportsVideo = TextSecurePreferences.isWebrtcCallingEnabled(this) || !supportsGcm;
|
||||||
|
|
||||||
if (registrationId == 0) {
|
if (registrationId == 0) {
|
||||||
registrationId = KeyHelper.generateRegistrationId(false);
|
registrationId = KeyHelper.generateRegistrationId(false);
|
||||||
@ -203,9 +211,9 @@ public class RegistrationService extends Service {
|
|||||||
|
|
||||||
setState(new RegistrationState(RegistrationState.STATE_VERIFYING, number));
|
setState(new RegistrationState(RegistrationState.STATE_VERIFYING, number));
|
||||||
String challenge = waitForChallenge();
|
String challenge = waitForChallenge();
|
||||||
accountManager.verifyAccountWithCode(challenge, signalingKey, registrationId, true, TextSecurePreferences.isWebrtcCallingEnabled(this));
|
accountManager.verifyAccountWithCode(challenge, signalingKey, registrationId, true, supportsVideo, !supportsGcm);
|
||||||
|
|
||||||
handleCommonRegistration(accountManager, number, password, signalingKey);
|
handleCommonRegistration(accountManager, number, password, signalingKey, supportsGcm);
|
||||||
markAsVerified(number, password, signalingKey);
|
markAsVerified(number, password, signalingKey);
|
||||||
|
|
||||||
setState(new RegistrationState(RegistrationState.STATE_COMPLETE, number));
|
setState(new RegistrationState(RegistrationState.STATE_COMPLETE, number));
|
||||||
@ -231,7 +239,7 @@ public class RegistrationService extends Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleCommonRegistration(SignalServiceAccountManager accountManager, String number, String password, String signalingKey)
|
private void handleCommonRegistration(SignalServiceAccountManager accountManager, String number, String password, String signalingKey, boolean supportsGcm)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
setState(new RegistrationState(RegistrationState.STATE_GENERATING_KEYS, number));
|
setState(new RegistrationState(RegistrationState.STATE_GENERATING_KEYS, number));
|
||||||
@ -244,21 +252,29 @@ public class RegistrationService extends Service {
|
|||||||
|
|
||||||
setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number));
|
setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number));
|
||||||
|
|
||||||
|
if (supportsGcm) {
|
||||||
String gcmRegistrationId = GoogleCloudMessaging.getInstance(this).register(GcmRefreshJob.REGISTRATION_ID);
|
String gcmRegistrationId = GoogleCloudMessaging.getInstance(this).register(GcmRefreshJob.REGISTRATION_ID);
|
||||||
accountManager.setGcmId(Optional.of(gcmRegistrationId));
|
accountManager.setGcmId(Optional.of(gcmRegistrationId));
|
||||||
|
|
||||||
TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId);
|
TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId);
|
||||||
|
TextSecurePreferences.setGcmDisabled(this, false);
|
||||||
|
} else {
|
||||||
|
TextSecurePreferences.setGcmDisabled(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
TextSecurePreferences.setWebsocketRegistered(this, true);
|
TextSecurePreferences.setWebsocketRegistered(this, true);
|
||||||
|
|
||||||
DatabaseFactory.getIdentityDatabase(this).saveIdentity(self.getRecipientId(), identityKey.getPublicKey());
|
DatabaseFactory.getIdentityDatabase(this).saveIdentity(self.getRecipientId(), identityKey.getPublicKey());
|
||||||
DirectoryHelper.refreshDirectory(this, accountManager, number);
|
DirectoryHelper.refreshDirectory(this, accountManager, number);
|
||||||
|
|
||||||
|
if (supportsGcm) {
|
||||||
RedPhoneAccountManager redPhoneAccountManager = new RedPhoneAccountManager(BuildConfig.REDPHONE_MASTER_URL,
|
RedPhoneAccountManager redPhoneAccountManager = new RedPhoneAccountManager(BuildConfig.REDPHONE_MASTER_URL,
|
||||||
new RedPhoneTrustStore(this),
|
new RedPhoneTrustStore(this),
|
||||||
number, password);
|
number, password);
|
||||||
|
|
||||||
String verificationToken = accountManager.getAccountVerificationToken();
|
String verificationToken = accountManager.getAccountVerificationToken();
|
||||||
redPhoneAccountManager.createAccount(verificationToken, new RedPhoneAccountAttributes(signalingKey, gcmRegistrationId));
|
redPhoneAccountManager.createAccount(verificationToken, new RedPhoneAccountAttributes(signalingKey, TextSecurePreferences.getGcmRegistrationId(this)));
|
||||||
|
}
|
||||||
|
|
||||||
DirectoryRefreshListener.schedule(this);
|
DirectoryRefreshListener.schedule(this);
|
||||||
RotateSignedPreKeyListener.schedule(this);
|
RotateSignedPreKeyListener.schedule(this);
|
||||||
|
@ -69,6 +69,7 @@ public class TextSecurePreferences {
|
|||||||
private static final String GCM_PASSWORD_PREF = "pref_gcm_password";
|
private static final String GCM_PASSWORD_PREF = "pref_gcm_password";
|
||||||
private static final String PROMPTED_PUSH_REGISTRATION_PREF = "pref_prompted_push_registration";
|
private static final String PROMPTED_PUSH_REGISTRATION_PREF = "pref_prompted_push_registration";
|
||||||
private static final String PROMPTED_DEFAULT_SMS_PREF = "pref_prompted_default_sms";
|
private static final String PROMPTED_DEFAULT_SMS_PREF = "pref_prompted_default_sms";
|
||||||
|
private static final String PROMPTED_OPTIMIZE_DOZE_PREF = "pref_prompted_optimize_doze";
|
||||||
private static final String PROMPTED_SHARE_PREF = "pref_prompted_share";
|
private static final String PROMPTED_SHARE_PREF = "pref_prompted_share";
|
||||||
private static final String SIGNALING_KEY_PREF = "pref_signaling_key";
|
private static final String SIGNALING_KEY_PREF = "pref_signaling_key";
|
||||||
private static final String DIRECTORY_FRESH_TIME_PREF = "pref_directory_refresh_time";
|
private static final String DIRECTORY_FRESH_TIME_PREF = "pref_directory_refresh_time";
|
||||||
@ -80,6 +81,7 @@ public class TextSecurePreferences {
|
|||||||
private static final String SIGNED_PREKEY_REGISTERED_PREF = "pref_signed_prekey_registered";
|
private static final String SIGNED_PREKEY_REGISTERED_PREF = "pref_signed_prekey_registered";
|
||||||
private static final String WIFI_SMS_PREF = "pref_wifi_sms";
|
private static final String WIFI_SMS_PREF = "pref_wifi_sms";
|
||||||
|
|
||||||
|
private static final String GCM_DISABLED_PREF = "pref_gcm_disabled";
|
||||||
private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
|
private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
|
||||||
private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
|
private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
|
||||||
private static final String WEBSOCKET_REGISTERED_PREF = "pref_websocket_registered";
|
private static final String WEBSOCKET_REGISTERED_PREF = "pref_websocket_registered";
|
||||||
@ -105,6 +107,14 @@ public class TextSecurePreferences {
|
|||||||
return getBooleanPreference(context, ALWAYS_RELAY_CALLS_PREF, false);
|
return getBooleanPreference(context, ALWAYS_RELAY_CALLS_PREF, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isGcmDisabled(Context context) {
|
||||||
|
return getBooleanPreference(context, GCM_DISABLED_PREF, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setGcmDisabled(Context context, boolean disabled) {
|
||||||
|
setBooleanPreference(context, GCM_DISABLED_PREF, disabled);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isWebrtcCallingEnabled(Context context) {
|
public static boolean isWebrtcCallingEnabled(Context context) {
|
||||||
return getBooleanPreference(context, WEBRTC_CALLING_PREF, false);
|
return getBooleanPreference(context, WEBRTC_CALLING_PREF, false);
|
||||||
}
|
}
|
||||||
@ -481,6 +491,14 @@ public class TextSecurePreferences {
|
|||||||
setBooleanPreference(context, PROMPTED_DEFAULT_SMS_PREF, value);
|
setBooleanPreference(context, PROMPTED_DEFAULT_SMS_PREF, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setPromptedOptimizeDoze(Context context, boolean value) {
|
||||||
|
setBooleanPreference(context, PROMPTED_OPTIMIZE_DOZE_PREF, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasPromptedOptimizeDoze(Context context) {
|
||||||
|
return getBooleanPreference(context, PROMPTED_OPTIMIZE_DOZE_PREF, false);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean hasPromptedShare(Context context) {
|
public static boolean hasPromptedShare(Context context) {
|
||||||
return getBooleanPreference(context, PROMPTED_SHARE_PREF, false);
|
return getBooleanPreference(context, PROMPTED_SHARE_PREF, false);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user