/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.thoughtcrime.securesms.jobs;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import org.thoughtcrime.securesms.gcm.FcmUtil;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.PlayServicesProblemActivity;
import network.loki.messenger.R;
import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
public class FcmRefreshJob extends BaseJob implements InjectableType {
public static final String KEY = "FcmRefreshJob";
private static final String TAG = FcmRefreshJob.class.getSimpleName();
@Inject SignalServiceAccountManager textSecureAccountManager;
public FcmRefreshJob() {
this(new Job.Parameters.Builder()
.setQueue("FcmRefreshJob")
.addConstraint(NetworkConstraint.KEY)
.setMaxAttempts(1)
.setLifespan(TimeUnit.MINUTES.toMillis(5))
.setMaxInstances(1)
.build());
}
private FcmRefreshJob(@NonNull Job.Parameters parameters) {
super(parameters);
}
@Override
public @NonNull Data serialize() {
return Data.EMPTY;
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
public void onRun() throws Exception {
if (TextSecurePreferences.isFcmDisabled(context)) return;
Log.i(TAG, "Reregistering FCM...");
int result = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
if (result != ConnectionResult.SUCCESS) {
notifyFcmFailure();
} else {
Optional token = FcmUtil.getToken();
if (token.isPresent()) {
String oldToken = TextSecurePreferences.getFcmToken(context);
if (!token.get().equals(oldToken)) {
int oldLength = oldToken != null ? oldToken.length() : -1;
Log.i(TAG, "Token changed. oldLength: " + oldLength + " newLength: " + token.get().length());
} else {
Log.i(TAG, "Token didn't change.");
}
textSecureAccountManager.setGcmId(token);
TextSecurePreferences.setFcmToken(context, token.get());
TextSecurePreferences.setFcmTokenLastSetTime(context, System.currentTimeMillis());
TextSecurePreferences.setWebsocketRegistered(context, true);
} else {
throw new RetryLaterException(new IOException("Failed to retrieve a token."));
}
}
}
@Override
public void onCanceled() {
Log.w(TAG, "GCM reregistration failed after retry attempt exhaustion!");
}
@Override
public boolean onShouldRetry(@NonNull Exception throwable) {
if (throwable instanceof NonSuccessfulResponseCodeException) return false;
return true;
}
private void notifyFcmFailure() {
Intent intent = new Intent(context, PlayServicesProblemActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1122, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NotificationChannels.FAILURES);
builder.setSmallIcon(R.drawable.ic_notification);
builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
R.drawable.ic_action_warning_red));
builder.setContentTitle(context.getString(R.string.GcmRefreshJob_Permanent_Signal_communication_failure));
builder.setContentText(context.getString(R.string.GcmRefreshJob_Signal_was_unable_to_register_with_Google_Play_Services));
builder.setTicker(context.getString(R.string.GcmRefreshJob_Permanent_Signal_communication_failure));
builder.setVibrate(new long[] {0, 1000});
builder.setContentIntent(pendingIntent);
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
.notify(12, builder.build());
}
public static final class Factory implements Job.Factory {
@Override
public @NonNull FcmRefreshJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new FcmRefreshJob(parameters);
}
}
}