2
\$\begingroup\$

In the SplashActivity of my Android Application, the following sequence of events occur:

  1. Check if Google Play Services is installed
  2. If Google Play Services are available, start the InstanceIDListener service
  3. Check if app needs to be updated
  4. Load country info using network IP

Previously, I'd implemented this logic using listeners but I decided to switch to RxJava/RxAndroid so that the sequence of events could be implemented more cleanly.

I'm very new to the whole Reactive Programming thing so I'd appreciate it if someone would go through my implementation below and tell me how I can improve it.

SplashActivity.java

public class SplashActivity extends BaseActivity {

    private Subscription mSubscription;

    @
    Override
    protected boolean showToolbar() {
        return false;
    }

    @
    Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        mSubscription = Observable.just(GooglePlayServicesInstallation.verify(this, 100))
            .flatMap(new Func1 < GooglePlayServicesInstallation, Observable < Void >> () {@
                Override
                public Observable < Void > call(GooglePlayServicesInstallation installation) {
                    return handleInstallationStatus(installation);
                }
            }).flatMap(new Func1 < Object, Observable < Void >> () {@
                Override
                public Observable < Void > call(Object o) {
                    startGCMTokenService();
                    return Observable.just(null);
                }
            }).flatMap(new Func1 < Object, Observable < AppStatus >> () {@
                Override
                public Observable < AppStatus > call(Object o) {
                    return AppStatusAssistant.checkAppVersion(SplashActivity.this);
                }
            }).flatMap(new Func1 < AppStatus, Observable < Void >> () {@
                Override
                public Observable < Void > call(AppStatus appStatus) {
                    return handleAppStatus(appStatus);
                }
            }).flatMap(new Func1 < Void, Observable < Void >> () {@
                Override
                public Observable < Void > call(Void aVoid) {
                    return getApp().loadCountryInfo();
                }
            }).flatMap(new Func1 < Void, Observable < Void >> () {@
                Override
                public Observable < Void > call(Void aVoid) {
                    onInitializationComplete();
                    return Observable.just(null);
                }
            }).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe();
    }

    @
    Override
    protected void onStop() {
        super.onStop();
        if (mSubscription != null && !mSubscription.isUnsubscribed()) {
            mSubscription.unsubscribe();
        }
    }

    private Observable < Void > handleInstallationStatus(GooglePlayServicesInstallation googlePlayServices) {
        if (googlePlayServices.isInstalled()) {
            return Observable.just(null);
        }

        if (googlePlayServices.isNotInstalledRecoverable()) {
            googlePlayServices.getDialog().show();
        } else if (googlePlayServices.isNotInstalledIrrecoverable()) {
            showMessageDialog("app can not run on this device because it does not support Google Play Services");
        }
        return Observable.empty();
    }

    private void startGCMTokenService() {
        Intent intent = new Intent(SplashActivity.this, MyInstanceIDListenerService.class);
        SplashActivity.this.startService(intent);
    }

    private Observable < Void > handleAppStatus(AppStatus status) {
        if (status == null) {
            return Observable.just(null);
        }
        mAppUpdateRequired = status.isEnforced() || status.isRecommended();
        return mAppUpdateRequired ? showUpdateAppDialog(status.isEnforced()) : Observable. < Void > just(null);
    }

    private Observable < Void > showUpdateAppDialog(final boolean enforced) {
        return Observable.create(new Observable.OnSubscribe < Void > () {@
            Override
            public void call(final Subscriber < ? super Void > subscriber) {
                runOnUiThread(new Runnable() {@
                    Override
                    public void run() {
                        AlertDialog.Builder builder = new AlertDialog.Builder(SplashActivity.this);
                        builder.setCancelable(false)
                            .setTitle(R.string.update_available)
                            .setMessage(R.string.update_available_message)
                            .setPositiveButton(R.string.update_now, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {
                                    subscriber.onCompleted();
                                    openAppInGooglePlay();
                                    finish();
                                }
                            })
                            .setNegativeButton(R.string.later, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {

                                    if (enforced) {
                                        subscriber.onCompleted();
                                        finish();
                                    } else {
                                        mAppUpdateRequired = false;
                                        subscriber.onNext(null);
                                    }
                                }
                            });

                        AlertDialog alertDialog = builder.create();
                        try {
                            alertDialog.show();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }

    private void openAppInGooglePlay() {
        Uri uri = Uri.parse("market://details?id=" + getPackageName());
        Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
        try {
            startActivity(goToMarket);
        } catch (ActivityNotFoundException e) {
            startActivity(new Intent(
                Intent.ACTION_VIEW,
                Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName())
            ));
        }
    }

    private void onInitializationComplete() {

        if (getApp().isUserSignedIn()) {
            IntentUtils.startActivity(this, HomeActivity.class);
        } else {
            IntentUtils.startActivity(this, HomeRegisterActivity.class);
        }
        finish();

    }

    @
    Override
    protected void onNewIntent(Intent intent) {
        this.setIntent(intent);
    }


    @
    Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 100) {
            IntentUtils.restartApp(this);
        }
    }
}

AppStatusAssistant.java

public class AppStatusAssistant {

    public static Observable < AppStatus > checkAppVersion(@NonNull final BaseActivity activity) {

        return activity.getWebApi().getAppStatus("android", getAppVersionCode(activity))
            .flatMap(new Func1 < Response, Observable < AppStatus >> () {@
                Override
                public Observable < AppStatus > call(Response response) {
                    String responseString = APIUtils.responseToString(response);
                    if (TextUtils.isEmpty(responseString)) {
                        return Observable.just(null);
                    }

                    Gson gson = GsonUtils.getGson();
                    try {
                        JSONArray array = new JSONArray(responseString);
                        if (array.length() > 0) {
                            List < AppStatus > appStatuses = gson.fromJson(responseString, new TypeToken < List < AppStatus >> () {}.getType());
                            return Observable.just(appStatuses.get(0));
                        } else {
                            return Observable.just(null);
                        }
                    } catch (Exception ex) {
                        return Observable.just(null);
                    }
                }
            }).onErrorResumeNext(new Func1 < Throwable, Observable <? extends AppStatus >> () {@
                Override
                public Observable <? extends AppStatus > call(Throwable throwable) {
                    return Observable.just(null);
                }
            });

    }
}

Note: I'm aware I should use Dagger to inject the API. That's another refactoring thing I'm working on.

\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.