Android: add LaunchActivity as splashscreen

At first launch, the app is displaying the smartListFragment with an
empty list even if there is no account

This commit fix this behaviour by adding a splashscreen that check
permissions and load accounts at start
This commit is compatible android and AndroidTV.

Change-Id: I917c59cb66e0c09c145ddcc85ca19374f1ef640a
diff --git a/ring-android/app/src/main/AndroidManifest.xml b/ring-android/app/src/main/AndroidManifest.xml
index f46b3c6..b57eab0 100644
--- a/ring-android/app/src/main/AndroidManifest.xml
+++ b/ring-android/app/src/main/AndroidManifest.xml
@@ -74,6 +74,20 @@
         android:label="@string/app_name"
         android:resizeableActivity="true"
         android:supportsRtl="true">
+
+        <activity
+            android:name=".launch.LaunchActivity"
+            android:configChanges="screenSize|screenLayout|smallestScreenSize"
+
+            android:screenOrientation="fullUser"
+            android:theme="@style/AppThemeBase">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
         <activity
             android:name=".client.HomeActivity"
             android:configChanges="screenSize|screenLayout|smallestScreenSize"
@@ -83,11 +97,6 @@
             android:theme="@style/AppThemeBase"
             android:windowSoftInputMode="adjustResize">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-            <intent-filter>
                 <action android:name="android.intent.action.DIAL" />
                 <action android:name="android.intent.action.VIEW" />
 
@@ -258,20 +267,23 @@
 
         <!-- AndroidTV section  -->
         <activity
-            android:name="cx.ring.tv.main.HomeActivity"
+            android:name=".tv.launch.TVLaunchActivity"
             android:banner="@drawable/banner"
             android:icon="@drawable/ic_launcher"
             android:label="@string/title_activity_sflphone_home"
             android:logo="@drawable/ic_launcher"
-            android:theme="@style/Theme.Leanback"
+            android:theme="@style/AppThemeBase"
             android:screenOrientation="landscape">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
             </intent-filter>
         </activity>
-
-
+        <activity
+            android:name=".tv.main.HomeActivity"
+            android:label="@string/title_activity_sflphone_home"
+            android:theme="@style/Theme.Leanback"
+            android:screenOrientation="landscape"/>
         <activity
             android:name=".tv.account.TVAccountWizard"
             android:configChanges="screenSize|screenLayout|smallestScreenSize"
diff --git a/ring-android/app/src/main/java/cx/ring/account/AccountWizard.java b/ring-android/app/src/main/java/cx/ring/account/AccountWizard.java
index b51aeeb..3e891d8 100644
--- a/ring-android/app/src/main/java/cx/ring/account/AccountWizard.java
+++ b/ring-android/app/src/main/java/cx/ring/account/AccountWizard.java
@@ -44,6 +44,7 @@
 import butterknife.ButterKnife;
 import cx.ring.R;
 import cx.ring.application.RingApplication;
+import cx.ring.client.HomeActivity;
 import cx.ring.fragments.AccountMigrationFragment;
 import cx.ring.fragments.SIPAccountCreationFragment;
 import cx.ring.model.AccountConfig;
@@ -281,6 +282,7 @@
                     if (fm.getBackStackEntryCount() >= 1) {
                         fm.popBackStack();
                     } else {
+                        startActivity(new Intent(AccountWizard.this, HomeActivity.class));
                         finish();
                     }
                 } else {
@@ -360,7 +362,7 @@
                         setResult(Activity.RESULT_OK, new Intent());
                         //unlock the screen orientation
                         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
-                        finish();
+                        presenter.successDialogClosed();
                     }
                 });
 
diff --git a/ring-android/app/src/main/java/cx/ring/account/RingAccountCreationFragment.java b/ring-android/app/src/main/java/cx/ring/account/RingAccountCreationFragment.java
index 6b2074c..549dbc9 100644
--- a/ring-android/app/src/main/java/cx/ring/account/RingAccountCreationFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/account/RingAccountCreationFragment.java
@@ -142,54 +142,95 @@
 
     @Override
     public void enableTextError() {
-        mUsernameTxtBox.setErrorEnabled(true);
-        mUsernameTxtBox.setError(getString(R.string.looking_for_username_availability));
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mUsernameTxtBox.setErrorEnabled(true);
+                mUsernameTxtBox.setError(getString(R.string.looking_for_username_availability));
+
+            }
+        });
     }
 
     @Override
     public void disableTextError() {
-        mUsernameTxtBox.setErrorEnabled(false);
-        mUsernameTxtBox.setError(null);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mUsernameTxtBox.setErrorEnabled(false);
+                mUsernameTxtBox.setError(null);
+            }
+        });
     }
 
     @Override
     public void showExistingNameError() {
-        mUsernameTxtBox.setErrorEnabled(true);
-        mUsernameTxtBox.setError(getString(R.string.username_already_taken));
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mUsernameTxtBox.setErrorEnabled(true);
+                mUsernameTxtBox.setError(getString(R.string.username_already_taken));
+            }
+        });
     }
 
     @Override
     public void showInvalidNameError() {
-        mUsernameTxtBox.setErrorEnabled(true);
-        mUsernameTxtBox.setError(getString(R.string.invalid_username));
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mUsernameTxtBox.setErrorEnabled(true);
+                mUsernameTxtBox.setError(getString(R.string.invalid_username));
+            }
+        });
     }
 
     @Override
-    public void showInvalidPasswordError(boolean display) {
-        if (display) {
-            mPasswordTxtBox.setError(getString(R.string.error_password_char_count));
-        } else {
-            mPasswordTxtBox.setError(null);
-        }
+    public void showInvalidPasswordError(final boolean display) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (display) {
+                    mPasswordTxtBox.setError(getString(R.string.error_password_char_count));
+                } else {
+                    mPasswordTxtBox.setError(null);
+                }
+            }
+        });
     }
 
     @Override
-    public void showNonMatchingPasswordError(boolean display) {
-        if (display) {
-            mPasswordRepeatTxtBox.setError(getString(R.string.error_passwords_not_equals));
-        } else {
-            mPasswordRepeatTxtBox.setError(null);
-        }
+    public void showNonMatchingPasswordError(final boolean display) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if (display) {
+                    mPasswordRepeatTxtBox.setError(getString(R.string.error_passwords_not_equals));
+                } else {
+                    mPasswordRepeatTxtBox.setError(null);
+                }
+            }
+        });
     }
 
     @Override
-    public void displayUsernameBox(boolean display) {
-        mUsernameBox.setVisibility(display ? View.VISIBLE : View.GONE);
+    public void displayUsernameBox(final boolean display) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mUsernameBox.setVisibility(display ? View.VISIBLE : View.GONE);
+            }
+        });
     }
 
     @Override
-    public void enableNextButton(boolean enabled) {
-        mCreateAccountButton.setEnabled(enabled);
+    public void enableNextButton(final boolean enabled) {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mCreateAccountButton.setEnabled(enabled);
+            }
+        });
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
index 4647630..59b8d98 100644
--- a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
@@ -110,9 +110,7 @@
     private static final String NAVIGATION_TAG = "Navigation";
     static public final String ACTION_PRESENT_TRUST_REQUEST_FRAGMENT = BuildConfig.APPLICATION_ID + "presentTrustRequestFragment";
 
-    private boolean mNoAccountOpened = false;
     private boolean mIsMigrationDialogAlreadyShowed;
-    private boolean mIsAskingForPermissions = false;
 
     private ActionBarDrawerToggle mDrawerToggle;
     private Boolean isDrawerLocked = false;
@@ -168,28 +166,17 @@
 
         switch (event.getEventType()) {
             case ACCOUNTS_CHANGED:
-                loadAccounts();
+                for (Account account : mAccountService.getAccounts()) {
+                    if (account.needsMigration()) {
+                        showMigrationDialog();
+                    }
+                }
                 break;
             default:
-                Log.d(TAG, "Event " + event.getEventType() + " is not handled here");
                 break;
         }
 
     }
-
-    private void loadAccounts() {
-        for (Account account : mAccountService.getAccounts()) {
-            if (account.needsMigration()) {
-                showMigrationDialog();
-            }
-        }
-
-        if (!mNoAccountOpened && mAccountService.getAccounts().isEmpty() && !mIsAskingForPermissions) {
-            mNoAccountOpened = true;
-            startActivityForResult(new Intent(HomeActivity.this, AccountWizard.class), AccountsManagementFragment.ACCOUNT_CREATE_REQUEST);
-        }
-    }
-
     public interface Refreshable {
         void refresh();
     }
@@ -257,20 +244,6 @@
                     .commit();
         }
 
-        String[] toRequest = buildPermissionsToAsk();
-        ArrayList<String> permissionsWeCanAsk = new ArrayList<>();
-
-        for (String permission : toRequest) {
-            if (((RingApplication) getApplication()).canAskForPermission(permission)) {
-                permissionsWeCanAsk.add(permission);
-            }
-        }
-
-        if (!permissionsWeCanAsk.isEmpty()) {
-            mIsAskingForPermissions = true;
-            ActivityCompat.requestPermissions(this, permissionsWeCanAsk.toArray(new String[permissionsWeCanAsk.size()]), RingApplication.PERMISSIONS_REQUEST);
-        }
-
         // if app opened from notification display trust request fragment when mService will connected
         Intent intent = getIntent();
         Bundle extra = intent.getExtras();
@@ -330,30 +303,6 @@
         }
     }
 
-    private String[] buildPermissionsToAsk() {
-        ArrayList<String> perms = new ArrayList<>();
-
-        if (!mDeviceRuntimeService.hasAudioPermission()) {
-            perms.add(Manifest.permission.RECORD_AUDIO);
-        }
-
-        Settings settings = mPreferencesService.loadSettings();
-
-        if (settings.isAllowSystemContacts() && !mDeviceRuntimeService.hasContactPermission()) {
-            perms.add(Manifest.permission.READ_CONTACTS);
-        }
-
-        if (!mDeviceRuntimeService.hasVideoPermission()) {
-            perms.add(Manifest.permission.CAMERA);
-        }
-
-        if (settings.isAllowPlaceSystemCalls() && !mDeviceRuntimeService.hasCallLogPermission()) {
-            perms.add(Manifest.permission.WRITE_CALL_LOG);
-        }
-
-        return perms.toArray(new String[perms.size()]);
-    }
-
     private void showMigrationDialog() {
 
         if (mIsMigrationDialogAlreadyShowed) {
@@ -427,61 +376,6 @@
         Log.d(TAG, "onRequestPermissionsResult");
 
         switch (requestCode) {
-            case RingApplication.PERMISSIONS_REQUEST: {
-                if (grantResults.length == 0) {
-                    return;
-                }
-                SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
-                for (int i = 0, n = permissions.length; i < n; i++) {
-                    String permission = permissions[i];
-                    ((RingApplication) getApplication()).permissionHasBeenAsked(permission);
-                    switch (permission) {
-                        case Manifest.permission.RECORD_AUDIO:
-                            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
-                                Log.e(TAG, "Missing required permission RECORD_AUDIO");
-                                AlertDialog.Builder builder = new AlertDialog.Builder(this)
-                                        .setTitle(R.string.start_error_title)
-                                        .setMessage(R.string.start_error_mic_required)
-                                        .setIcon(R.drawable.ic_mic_black)
-                                        .setCancelable(false)
-                                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-                                            @Override
-                                            public void onClick(DialogInterface dialog, int which) {
-                                                finish();
-                                            }
-                                        }).setOnCancelListener(new DialogInterface.OnCancelListener() {
-                                            @Override
-                                            public void onCancel(DialogInterface dialog) {
-                                                finish();
-                                            }
-                                        });
-                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                                    builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                                        @Override
-                                        public void onDismiss(DialogInterface dialog) {
-                                            finish();
-                                        }
-                                    });
-                                }
-                                builder.show();
-                                return;
-                            }
-                            break;
-                        case Manifest.permission.READ_CONTACTS:
-                            sharedPref.edit().putBoolean(getString(R.string.pref_systemContacts_key), grantResults[i] == PackageManager.PERMISSION_GRANTED).apply();
-                            break;
-                        case Manifest.permission.CAMERA:
-                            sharedPref.edit().putBoolean(getString(R.string.pref_systemCamera_key), grantResults[i] == PackageManager.PERMISSION_GRANTED).apply();
-                            // permissions have changed, video params should be reset
-                            final boolean isVideoAllowed = mDeviceRuntimeService.hasVideoPermission();
-                            if (isVideoAllowed) {
-                                mHardwareService.initVideo();
-                            }
-                    }
-                }
-
-                break;
-            }
             case REQUEST_PERMISSION_READ_STORAGE:
                 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                     Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
@@ -499,9 +393,6 @@
                 }
                 break;
         }
-
-        mIsAskingForPermissions = false;
-        loadAccounts();
     }
 
     public void setToolbarState(boolean doubleHeight, int titleRes) {
@@ -623,9 +514,6 @@
         super.onActivityResult(requestCode, resultCode, data);
 
         switch (requestCode) {
-            case REQUEST_CODE_CREATE_ACCOUNT:
-                mNoAccountOpened = false;
-                break;
             case REQUEST_CODE_CALL:
                 if (resultCode == CallActivity.RESULT_FAILURE) {
                     Log.w(TAG, "Call Failed");
diff --git a/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java b/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
index f1a0d90..80d5a4b 100755
--- a/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
+++ b/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
@@ -24,13 +24,15 @@
 import cx.ring.about.AboutFragment;
 import cx.ring.about.AboutPresenter;
 import cx.ring.account.AccountEditionActivity;
+import cx.ring.account.AccountWizard;
 import cx.ring.account.HomeAccountCreationFragment;
+import cx.ring.account.ProfileCreationFragment;
 import cx.ring.account.RegisterNameDialog;
+import cx.ring.account.RingAccountCreationFragment;
 import cx.ring.account.RingAccountSummaryFragment;
 import cx.ring.account.RingAccountSummaryPresenter;
 import cx.ring.account.RingLinkAccountFragment;
 import cx.ring.application.RingApplication;
-import cx.ring.account.AccountWizard;
 import cx.ring.client.HomeActivity;
 import cx.ring.contactrequests.BlackListFragment;
 import cx.ring.contactrequests.ContactRequestsFragment;
@@ -42,11 +44,10 @@
 import cx.ring.fragments.ConversationFragment;
 import cx.ring.fragments.GeneralAccountFragment;
 import cx.ring.fragments.MediaPreferenceFragment;
-import cx.ring.account.ProfileCreationFragment;
-import cx.ring.account.RingAccountCreationFragment;
 import cx.ring.fragments.SIPAccountCreationFragment;
 import cx.ring.fragments.SecurityAccountFragment;
 import cx.ring.fragments.SmartListFragment;
+import cx.ring.launch.LaunchActivity;
 import cx.ring.navigation.RingNavigationFragment;
 import cx.ring.navigation.RingNavigationPresenter;
 import cx.ring.service.BootReceiver;
@@ -74,6 +75,7 @@
 import cx.ring.tv.call.TVCallActivity;
 import cx.ring.tv.call.TVCallFragment;
 import cx.ring.tv.main.MainFragment;
+import cx.ring.tv.launch.TVLaunchActivity;
 import cx.ring.tv.search.RingSearchFragment;
 import dagger.Component;
 
@@ -170,6 +172,9 @@
 
     void inject(RingLinkAccountFragment fragment);
 
+    void inject(LaunchActivity activity);
+
+
 //    AndroidTV section
 
     void inject(TVCallFragment fragment);
@@ -191,4 +196,7 @@
     void inject(TVRingAccountCreationFragment fragment);
 
     void inject(TVRingLinkAccountFragment fragment);
+
+    void inject(TVLaunchActivity activity);
+
 }
diff --git a/ring-android/app/src/main/java/cx/ring/launch/LaunchActivity.java b/ring-android/app/src/main/java/cx/ring/launch/LaunchActivity.java
new file mode 100644
index 0000000..aed35e4
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/launch/LaunchActivity.java
@@ -0,0 +1,135 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package cx.ring.launch;
+
+import android.Manifest;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+import cx.ring.R;
+import cx.ring.account.AccountWizard;
+import cx.ring.application.RingApplication;
+import cx.ring.client.HomeActivity;
+import cx.ring.mvp.BaseActivity;
+
+public class LaunchActivity extends BaseActivity<LaunchPresenter> implements LaunchView {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        // dependency injection
+        ((RingApplication) getApplication()).getRingInjectionComponent().inject(this);
+        super.onCreate(savedInstanceState);
+        Log.d(TAG, "onCreate");
+
+        setContentView(R.layout.activity_launch);
+
+        presenter.init();
+    }
+
+    @Override
+    public void askPermissions(ArrayList<String> permissionsWeCanAsk) {
+        ActivityCompat.requestPermissions(this, permissionsWeCanAsk.toArray(new String[permissionsWeCanAsk.size()]), RingApplication.PERMISSIONS_REQUEST);
+    }
+
+    @Override
+    public void goToHome() {
+        startActivity(new Intent(LaunchActivity.this, HomeActivity.class));
+        finish();
+    }
+
+    @Override
+    public void goToAccountCreation() {
+        startActivity(new Intent(LaunchActivity.this, AccountWizard.class));
+        finish();
+    }
+
+    @Override
+    public void displayAudioPermissionDialog() {
+        Log.e(TAG, "Missing required permission RECORD_AUDIO");
+        AlertDialog.Builder builder = new AlertDialog.Builder(this)
+                .setTitle(R.string.start_error_title)
+                .setMessage(R.string.start_error_mic_required)
+                .setIcon(R.drawable.ic_mic_black)
+                .setCancelable(false)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        finish();
+                    }
+                }).setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        finish();
+                    }
+                });
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                @Override
+                public void onDismiss(DialogInterface dialog) {
+                    finish();
+                }
+            });
+        }
+        builder.show();
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
+        Log.d(TAG, "onRequestPermissionsResult");
+
+        switch (requestCode) {
+            case RingApplication.PERMISSIONS_REQUEST: {
+                if (grantResults.length == 0) {
+                    return;
+                }
+                boolean isAudioGranted = false;
+                for (int i = 0, n = permissions.length; i < n; i++) {
+                    String permission = permissions[i];
+                    ((RingApplication) getApplication()).permissionHasBeenAsked(permission);
+                    switch (permission) {
+                        case Manifest.permission.RECORD_AUDIO:
+                            isAudioGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
+                            presenter.audioPermissionChanged(isAudioGranted);
+                            break;
+                        case Manifest.permission.READ_CONTACTS:
+                            presenter.contactPermissionChanged(grantResults[i] == PackageManager.PERMISSION_GRANTED);
+                            break;
+                        case Manifest.permission.CAMERA:
+                            presenter.cameraPermissionChanged(grantResults[i] == PackageManager.PERMISSION_GRANTED);
+                    }
+                }
+                if (isAudioGranted) {
+                    presenter.checkAccounts();
+                }
+                break;
+            }
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/launch/LaunchPresenter.java b/ring-android/app/src/main/java/cx/ring/launch/LaunchPresenter.java
new file mode 100644
index 0000000..b50f258
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/launch/LaunchPresenter.java
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package cx.ring.launch;
+
+import android.Manifest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import cx.ring.model.Account;
+import cx.ring.model.ServiceEvent;
+import cx.ring.model.Settings;
+import cx.ring.mvp.RootPresenter;
+import cx.ring.services.AccountService;
+import cx.ring.services.DeviceRuntimeService;
+import cx.ring.services.HardwareService;
+import cx.ring.services.PreferencesService;
+import cx.ring.utils.Observable;
+import cx.ring.utils.Observer;
+
+public class LaunchPresenter extends RootPresenter<LaunchView> implements Observer<ServiceEvent> {
+
+    protected AccountService mAccountService;
+    protected DeviceRuntimeService mDeviceRuntimeService;
+    protected PreferencesService mPreferencesService;
+    protected HardwareService mHardwareService;
+
+    @Inject
+    public LaunchPresenter(AccountService accountService, DeviceRuntimeService deviceRuntimeService,
+                           PreferencesService preferencesService, HardwareService hardwareService) {
+        this.mAccountService = accountService;
+        this.mDeviceRuntimeService = deviceRuntimeService;
+        this.mPreferencesService = preferencesService;
+        this.mHardwareService = hardwareService;
+    }
+
+    @Override
+    public void afterInjection() {
+
+    }
+
+    @Override
+    public void unbindView() {
+        super.unbindView();
+        mAccountService.removeObserver(this);
+    }
+
+    public void init() {
+        String[] toRequest = buildPermissionsToAsk();
+        ArrayList<String> permissionsWeCanAsk = new ArrayList<>();
+
+        for (String permission : toRequest) {
+            permissionsWeCanAsk.add(permission);
+        }
+
+        if (!permissionsWeCanAsk.isEmpty()) {
+            getView().askPermissions(permissionsWeCanAsk);
+        } else {
+            checkAccounts();
+        }
+    }
+
+    public void audioPermissionChanged(boolean isGranted) {
+        if (!isGranted) {
+            getView().displayAudioPermissionDialog();
+        }
+    }
+
+    public void contactPermissionChanged(boolean isGranted) {
+
+    }
+
+    public void cameraPermissionChanged(boolean isGranted) {
+        if (isGranted) {
+            mHardwareService.initVideo();
+        }
+    }
+
+    public void checkAccounts() {
+        List<Account> accounts = mAccountService.getAccounts();
+
+        if (accounts == null) {
+            mAccountService.addObserver(this);
+            mAccountService.loadAccountsFromDaemon(mPreferencesService.hasNetworkConnected());
+        } else if (accounts.isEmpty()) {
+            getView().goToAccountCreation();
+        } else {
+            getView().goToHome();
+        }
+    }
+
+    private String[] buildPermissionsToAsk() {
+        ArrayList<String> perms = new ArrayList<>();
+
+        if (!mDeviceRuntimeService.hasAudioPermission()) {
+            perms.add(Manifest.permission.RECORD_AUDIO);
+        }
+
+        Settings settings = mPreferencesService.loadSettings();
+
+        if (settings.isAllowSystemContacts() && !mDeviceRuntimeService.hasContactPermission()) {
+            perms.add(Manifest.permission.READ_CONTACTS);
+        }
+
+        if (!mDeviceRuntimeService.hasVideoPermission()) {
+            perms.add(Manifest.permission.CAMERA);
+        }
+
+        if (settings.isAllowPlaceSystemCalls() && !mDeviceRuntimeService.hasCallLogPermission()) {
+            perms.add(Manifest.permission.WRITE_CALL_LOG);
+        }
+
+        return perms.toArray(new String[perms.size()]);
+    }
+
+    @Override
+    public void update(Observable observable, ServiceEvent event) {
+        if (event == null) {
+            return;
+        }
+
+        switch (event.getEventType()) {
+            case ACCOUNTS_CHANGED:
+                checkAccounts();
+                break;
+            default:
+                break;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/launch/LaunchView.java b/ring-android/app/src/main/java/cx/ring/launch/LaunchView.java
new file mode 100644
index 0000000..217e2b4
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/launch/LaunchView.java
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package cx.ring.launch;
+
+import java.util.ArrayList;
+
+public interface LaunchView {
+
+    void askPermissions(ArrayList<String> permissionsWeCanAsk);
+
+    void goToHome();
+
+    void goToAccountCreation();
+
+    void displayAudioPermissionDialog();
+
+}
diff --git a/ring-android/app/src/main/java/cx/ring/tv/account/TVAccountWizard.java b/ring-android/app/src/main/java/cx/ring/tv/account/TVAccountWizard.java
index 576696c..92893c6 100644
--- a/ring-android/app/src/main/java/cx/ring/tv/account/TVAccountWizard.java
+++ b/ring-android/app/src/main/java/cx/ring/tv/account/TVAccountWizard.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
-import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.support.v17.leanback.app.GuidedStepFragment;
 import android.support.v7.app.AlertDialog;
@@ -39,6 +38,7 @@
 import cx.ring.application.RingApplication;
 import cx.ring.model.AccountConfig;
 import cx.ring.mvp.BaseActivity;
+import cx.ring.tv.main.HomeActivity;
 import cx.ring.utils.Log;
 import cx.ring.utils.VCardUtils;
 import ezvcard.VCard;
@@ -70,7 +70,6 @@
         // dependency injection
         ((RingApplication) getApplication()).getRingInjectionComponent().inject(this);
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_wizard);
         ButterKnife.bind(this);
 
 
@@ -83,7 +82,7 @@
         }
 
         if (savedInstanceState == null) {
-            GuidedStepFragment.add(getFragmentManager(), mHomeFragment);
+            GuidedStepFragment.addAsRoot(this, mHomeFragment, android.R.id.content);
         } else {
             mProfileFragment = (TVProfileCreationFragment) getFragmentManager().getFragment(savedInstanceState, PROFILE_TAG);
             mFullname = savedInstanceState.getString("mFullname");
@@ -119,16 +118,6 @@
     }
 
     @Override
-    public void onBackPressed() {
-        FragmentManager fm = getFragmentManager();
-        if (fm.getBackStackEntryCount() > 0) {
-            fm.popBackStack();
-            return;
-        }
-        presenter.backPressed();
-    }
-
-    @Override
     public void saveProfile(String accountID, String username) {
         VCard vcard = new VCard();
         vcard.setFormattedName(new FormattedName(mFullname));
@@ -303,6 +292,7 @@
                         setResult(Activity.RESULT_OK, new Intent());
                         //unlock the screen orientation
                         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
+                        startActivity(new Intent(TVAccountWizard.this,HomeActivity.class));
                         finish();
                     }
                 });
diff --git a/ring-android/app/src/main/java/cx/ring/tv/launch/TVLaunchActivity.java b/ring-android/app/src/main/java/cx/ring/tv/launch/TVLaunchActivity.java
new file mode 100644
index 0000000..4bfa332
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/tv/launch/TVLaunchActivity.java
@@ -0,0 +1,142 @@
+package cx.ring.tv.launch;/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import android.Manifest;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.util.Log;
+
+
+import java.util.ArrayList;
+
+import cx.ring.R;
+import cx.ring.launch.LaunchPresenter;
+import cx.ring.launch.LaunchView;
+import cx.ring.mvp.BaseActivity;
+import cx.ring.tv.account.TVAccountWizard;
+import cx.ring.application.RingApplication;
+import cx.ring.tv.main.HomeActivity;
+
+public class TVLaunchActivity  extends BaseActivity<LaunchPresenter> implements LaunchView {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        // dependency injection
+        ((RingApplication) getApplication()).getRingInjectionComponent().inject(this);
+        super.onCreate(savedInstanceState);
+        Log.d(TAG, "onCreate");
+
+        setContentView(R.layout.activity_launch);
+
+        presenter.init();
+    }
+
+
+    @Override
+    public void goToHome() {
+        startActivity(new Intent(TVLaunchActivity.this, HomeActivity.class));
+        finish();
+    }
+
+    @Override
+    public void goToAccountCreation() {
+        startActivity(new Intent(TVLaunchActivity.this, TVAccountWizard.class));
+        finish();
+    }
+
+  
+
+    @Override
+    public void askPermissions(ArrayList<String> permissionsWeCanAsk) {
+        ActivityCompat.requestPermissions(this, permissionsWeCanAsk.toArray(new String[permissionsWeCanAsk.size()]), RingApplication.PERMISSIONS_REQUEST);
+    }
+
+
+    @Override
+    public void displayAudioPermissionDialog() {
+        Log.e(TAG, "Missing required permission RECORD_AUDIO");
+        AlertDialog.Builder builder = new AlertDialog.Builder(this)
+                .setTitle(R.string.start_error_title)
+                .setMessage(R.string.start_error_mic_required)
+                .setIcon(R.drawable.ic_mic_black)
+                .setCancelable(false)
+                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        finish();
+                    }
+                }).setOnCancelListener(new DialogInterface.OnCancelListener() {
+                    @Override
+                    public void onCancel(DialogInterface dialog) {
+                        finish();
+                    }
+                });
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+            builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                @Override
+                public void onDismiss(DialogInterface dialog) {
+                    finish();
+                }
+            });
+        }
+        builder.show();
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
+        Log.d(TAG, "onRequestPermissionsResult");
+
+        switch (requestCode) {
+            case RingApplication.PERMISSIONS_REQUEST: {
+                if (grantResults.length == 0) {
+                    return;
+                }
+                boolean isAudioGranted = false;
+                for (int i = 0, n = permissions.length; i < n; i++) {
+                    String permission = permissions[i];
+                    ((RingApplication) getApplication()).permissionHasBeenAsked(permission);
+                    switch (permission) {
+                        case Manifest.permission.RECORD_AUDIO:
+                            isAudioGranted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
+                            presenter.audioPermissionChanged(isAudioGranted);
+                            break;
+                        case Manifest.permission.READ_CONTACTS:
+                            presenter.contactPermissionChanged(grantResults[i] == PackageManager.PERMISSION_GRANTED);
+                            break;
+                        case Manifest.permission.CAMERA:
+                            presenter.cameraPermissionChanged(grantResults[i] == PackageManager.PERMISSION_GRANTED);
+                    }
+                }
+                if (isAudioGranted) {
+                    presenter.checkAccounts();
+                }
+                break;
+            }
+
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/tv/main/HomeActivity.java b/ring-android/app/src/main/java/cx/ring/tv/main/HomeActivity.java
index d95477a..be59d2e 100644
--- a/ring-android/app/src/main/java/cx/ring/tv/main/HomeActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/tv/main/HomeActivity.java
@@ -31,6 +31,7 @@
 import android.provider.MediaStore;
 import android.support.annotation.NonNull;
 import android.support.v4.app.ActivityCompat;
+import android.support.v4.view.GravityCompat;
 
 import java.util.ArrayList;
 
@@ -42,6 +43,7 @@
 import cx.ring.model.Account;
 import cx.ring.model.ServiceEvent;
 import cx.ring.model.Settings;
+import cx.ring.navigation.RingNavigationFragment;
 import cx.ring.services.AccountService;
 import cx.ring.services.DeviceRuntimeService;
 import cx.ring.services.HardwareService;
@@ -51,18 +53,14 @@
 import cx.ring.utils.Observable;
 import cx.ring.utils.Observer;
 
-public class HomeActivity extends Activity implements Observer<ServiceEvent> {
+public class HomeActivity extends Activity  {
     private static final String TAG = HomeActivity.class.getName();
 
-    private boolean mNoAccountOpened = false;
-
     public static final int REQUEST_CODE_PHOTO = 5;
     public static final int REQUEST_CODE_GALLERY = 6;
     public static final int REQUEST_PERMISSION_CAMERA = 113;
     public static final int REQUEST_PERMISSION_READ_STORAGE = 114;
 
-    private boolean mIsAskingForPermissions = false;
-
     @Inject
     AccountService mAccountService;
 
@@ -84,44 +82,6 @@
 
         // dependency injection
         ((RingApplication) getApplication()).getRingInjectionComponent().inject(this);
-
-        String[] toRequest = buildPermissionsToAsk();
-        ArrayList<String> permissionsWeCanAsk = new ArrayList<>();
-
-        for (String permission : toRequest) {
-            if (((RingApplication) getApplication()).canAskForPermission(permission)) {
-                permissionsWeCanAsk.add(permission);
-            }
-        }
-
-        if (!permissionsWeCanAsk.isEmpty()) {
-            mIsAskingForPermissions = true;
-            ActivityCompat.requestPermissions(this, permissionsWeCanAsk.toArray(new String[permissionsWeCanAsk.size()]), RingApplication.PERMISSIONS_REQUEST);
-        }
-    }
-
-    private String[] buildPermissionsToAsk() {
-        ArrayList<String> perms = new ArrayList<>();
-
-        if (!mDeviceRuntimeService.hasAudioPermission()) {
-            perms.add(Manifest.permission.RECORD_AUDIO);
-        }
-
-        Settings settings = mPreferencesService.loadSettings();
-
-        if (settings.isAllowSystemContacts() && !mDeviceRuntimeService.hasContactPermission()) {
-            perms.add(Manifest.permission.READ_CONTACTS);
-        }
-
-        if (!mDeviceRuntimeService.hasVideoPermission()) {
-            perms.add(Manifest.permission.CAMERA);
-        }
-
-        if (settings.isAllowPlaceSystemCalls() && !mDeviceRuntimeService.hasCallLogPermission()) {
-            perms.add(Manifest.permission.WRITE_CALL_LOG);
-        }
-
-        return perms.toArray(new String[perms.size()]);
     }
 
     @Override
@@ -129,59 +89,6 @@
         Log.d(TAG, "onRequestPermissionsResult");
 
         switch (requestCode) {
-            case RingApplication.PERMISSIONS_REQUEST: {
-                if (grantResults.length == 0) {
-                    return;
-                }
-                SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
-                for (int i = 0, n = permissions.length; i < n; i++) {
-                    String permission = permissions[i];
-                    ((RingApplication) getApplication()).permissionHasBeenAsked(permission);
-                    switch (permission) {
-                        case Manifest.permission.RECORD_AUDIO:
-                            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
-                                Log.e(TAG, "Missing required permission RECORD_AUDIO");
-                                AlertDialog.Builder builder = new AlertDialog.Builder(this)
-                                        .setTitle(R.string.start_error_title)
-                                        .setMessage(R.string.start_error_mic_required)
-                                        .setIcon(R.drawable.ic_mic_black)
-                                        .setCancelable(false)
-                                        .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-                                            @Override
-                                            public void onClick(DialogInterface dialog, int which) {
-                                                finish();
-                                            }
-                                        }).setOnCancelListener(new DialogInterface.OnCancelListener() {
-                                            @Override
-                                            public void onCancel(DialogInterface dialog) {
-                                                finish();
-                                            }
-                                        });
-                                builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
-                                    @Override
-                                    public void onDismiss(DialogInterface dialog) {
-                                        finish();
-                                    }
-                                });
-                                builder.show();
-                                return;
-                            }
-                            break;
-                        case Manifest.permission.READ_CONTACTS:
-                            sharedPref.edit().putBoolean(getString(R.string.pref_systemContacts_key), grantResults[i] == PackageManager.PERMISSION_GRANTED).apply();
-                            break;
-                        case Manifest.permission.CAMERA:
-                            sharedPref.edit().putBoolean(getString(R.string.pref_systemCamera_key), grantResults[i] == PackageManager.PERMISSION_GRANTED).apply();
-                            // permissions have changed, video params should be reset
-                            final boolean isVideoAllowed = mDeviceRuntimeService.hasVideoPermission();
-                            if (isVideoAllowed) {
-                                mHardwareService.initVideo();
-                            }
-                    }
-                }
-
-                break;
-            }
             case REQUEST_PERMISSION_READ_STORAGE:
                 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                     Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
@@ -199,47 +106,9 @@
                 }
                 break;
         }
-        mIsAskingForPermissions = false;
-        loadAccounts();
     }
-
     @Override
-    protected void onResume() {
-        super.onResume();
-        mAccountService.addObserver(this);
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mAccountService.removeObserver(this);
-    }
-
-    @Override
-    public void update(Observable observable, ServiceEvent event) {
-        if (event == null) {
-            return;
-        }
-
-        switch (event.getEventType()) {
-            case ACCOUNTS_CHANGED:
-                loadAccounts();
-                break;
-            default:
-                break;
-        }
-    }
-
-    private void loadAccounts() {
-        for (Account account : mAccountService.getAccounts()) {
-            if (account.needsMigration()) {
-                //TODO: handle migration process
-            }
-        }
-
-        if (!mNoAccountOpened && mAccountService.getAccounts().isEmpty() && !mIsAskingForPermissions) {
-            mNoAccountOpened = true;
-            startActivityForResult(new Intent(HomeActivity.this, TVAccountWizard.class), TVAccountWizard.ACCOUNT_CREATE_REQUEST);
-        }
+    public void onBackPressed() {
+        finish();
     }
 }
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/activity_launch.xml b/ring-android/app/src/main/res/layout/activity_launch.xml
new file mode 100644
index 0000000..c948474
--- /dev/null
+++ b/ring-android/app/src/main/res/layout/activity_launch.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/color_primary_light"
+    android:orientation="vertical"
+    android:padding="88dp">
+
+    <ImageView
+        android:id="@+id/logo_ring"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true"
+        android:contentDescription="@string/app_name"
+        android:src="@drawable/ic_logo_ring_white" />
+
+    <ProgressBar
+        android:id="@+id/loading_indicator"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@+id/logo_ring"
+        android:layout_centerInParent="true" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/activity_wizard.xml b/ring-android/app/src/main/res/layout/activity_wizard.xml
index d82b543..21f93c2 100644
--- a/ring-android/app/src/main/res/layout/activity_wizard.xml
+++ b/ring-android/app/src/main/res/layout/activity_wizard.xml
@@ -1,8 +1,8 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:background="@color/color_primary_dark">
+    android:background="@color/color_primary_dark"
+    android:orientation="vertical">
 
     <cx.ring.views.WizardViewPager
         android:id="@+id/pager"
diff --git a/ring-android/libringclient/src/main/java/cx/ring/account/AccountWizardPresenter.java b/ring-android/libringclient/src/main/java/cx/ring/account/AccountWizardPresenter.java
index ad0bf94..ba774ff 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/account/AccountWizardPresenter.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/account/AccountWizardPresenter.java
@@ -118,6 +118,10 @@
         }
     }
 
+    public void successDialogClosed() {
+        getView().finish(true);
+    }
+
     private HashMap<String, String> initRingAccountDetails(String defaultAccountName) {
         HashMap<String, String> accountDetails = initAccountDetails();
         if (accountDetails != null) {
diff --git a/ring-android/app/src/main/java/cx/ring/account/RingAccountCreationPresenter.java b/ring-android/libringclient/src/main/java/cx/ring/account/RingAccountCreationPresenter.java
similarity index 89%
rename from ring-android/app/src/main/java/cx/ring/account/RingAccountCreationPresenter.java
rename to ring-android/libringclient/src/main/java/cx/ring/account/RingAccountCreationPresenter.java
index f9d70d8..fba4767 100644
--- a/ring-android/app/src/main/java/cx/ring/account/RingAccountCreationPresenter.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/account/RingAccountCreationPresenter.java
@@ -19,13 +19,8 @@
  */
 package cx.ring.account;
 
-import android.support.annotation.NonNull;
-
-import java.lang.ref.WeakReference;
-
 import javax.inject.Inject;
 
-import cx.ring.application.RingApplication;
 import cx.ring.model.ServiceEvent;
 import cx.ring.mvp.RingAccountViewModel;
 import cx.ring.mvp.RootPresenter;
@@ -68,7 +63,7 @@
         mAccountService.addObserver(this);
     }
 
-    public void userNameChanged(@NonNull String userName) {
+    public void userNameChanged(String userName) {
         if (!userName.isEmpty()) {
             if (mNameLookupInputHandler == null) {
                 mNameLookupInputHandler = new NameLookupInputHandler(mAccountService, "");
@@ -186,20 +181,15 @@
             return;
         }
 
-        RingApplication.uiHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                switch (event.getEventType()) {
-                    case REGISTERED_NAME_FOUND:
-                        int state = event.getEventInput(ServiceEvent.EventInput.STATE, Integer.class);
-                        String name = event.getEventInput(ServiceEvent.EventInput.NAME, String.class);
-                        handleBlockchainResult(state, name);
-                        break;
-                    default:
-                        break;
-                }
-            }
-        });
+        switch (event.getEventType()) {
+            case REGISTERED_NAME_FOUND:
+                int state = event.getEventInput(ServiceEvent.EventInput.STATE, Integer.class);
+                String name = event.getEventInput(ServiceEvent.EventInput.NAME, String.class);
+                handleBlockchainResult(state, name);
+                break;
+            default:
+                break;
+        }
     }
 
     @Override
diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java
index c0aa9f8..5dc91cb 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/services/AccountService.java
@@ -96,14 +96,13 @@
     DeviceRuntimeService mDeviceRuntimeService;
 
     private Account mCurrentAccount;
-    private List<Account> mAccountList;
+    private List<Account> mAccountList = null;
     private ConfigurationCallbackHandler mCallbackHandler;
     private boolean mHasSipAccount;
     private boolean mHasRingAccount;
 
     public AccountService() {
         mCallbackHandler = new ConfigurationCallbackHandler();
-        mAccountList = new ArrayList<>();
     }
 
     public ConfigurationCallbackHandler getCallbackHandler() {
@@ -134,6 +133,7 @@
         mApplicationExecutor.submit(new Runnable() {
             @Override
             public void run() {
+                mAccountList = new ArrayList<>();
                 refreshAccountsCacheFromDaemon();
 
                 if (!mAccountList.isEmpty()) {