package shts.jp.android.nogifeed.receivers; import android.annotation.SuppressLint; import android.app.IntentService; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; import com.google.firebase.iid.FirebaseInstanceId; import java.util.concurrent.TimeUnit; import rx.Observable; import rx.Subscriber; import rx.functions.Func1; import shts.jp.android.nogifeed.api.NogiFeedApiClient; /** * FCMのトークンを登録するサービス */ public class TokenRegistrationService extends IntentService { private static final String TAG = TokenRegistrationService.class.getSimpleName(); public TokenRegistrationService() { super(TokenRegistrationService.class.getSimpleName()); } @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent: in"); final Context context = getApplicationContext(); createGetTokenObservable() .flatMap(new Func1<String, Observable<?>>() { @Override public Observable<?> call(final String regId) { // getToken()で取得した値が空の場合 if (TextUtils.isEmpty(regId)) { return null; } String oldRegId = Store.getRegId(context); // Idが更新された場合は既存のIDを上書き登録する if (!regId.equals(oldRegId)) { Store.setRegId(context, regId); return NogiFeedApiClient.registrationId(regId); } // 旧サーバーから新サーバーにトークンを送信する if (Store.isLegacy(context)) { Store.removeLegacy(context); return NogiFeedApiClient.registrationId(oldRegId); } return null; } }) .subscribe(new Subscriber<Object>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(Object o) { } }); Log.d(TAG, "onHandleIntent: out"); } /** * FCMのトークンを取得する * <p> * 初回起動時にnullの場合があるのでリトライする * * @return FCMのトークン */ private static Observable<String> createGetTokenObservable() { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { try { String regId = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "call: regId(" + regId + ")"); // null の場合があるのでリトライするためExceptionをなげる if (TextUtils.isEmpty(regId)) { throw new Throwable(); } subscriber.onNext(regId); subscriber.onCompleted(); } catch (Throwable throwable) { subscriber.onError(throwable); } } }).retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() { @Override public Observable<?> call(final Observable<? extends Throwable> observable) { return observable.flatMap(new Func1<Throwable, Observable<?>>() { @Override public Observable<?> call(Throwable throwable) { Log.d(TAG, "call: Retry get token"); // 3秒後にリトライする return Observable.timer(3, TimeUnit.SECONDS); } }); } }); } private static class Store { private static final String IS_LEGACY = "is_legacy"; private static final String REG_PREF = "reg_pref"; private static final String REG_ID = "reg_id"; private static SharedPreferences getPref(@NonNull Context context) { return context.getSharedPreferences(REG_PREF, Context.MODE_PRIVATE); } private static boolean isLegacy(@NonNull Context context) { return getPref(context).getBoolean(IS_LEGACY, true); } @SuppressLint("CommitPrefEdits") private static void removeLegacy(@NonNull Context context) { getPref(context).edit().putBoolean(IS_LEGACY, false).commit(); } @SuppressLint("CommitPrefEdits") private static void setRegId(@NonNull Context context, @NonNull String regId) { getPref(context).edit().putString(REG_ID, regId).commit(); } @Nullable private static String getRegId(@NonNull Context context) { return getPref(context).getString(REG_ID, null); } } }