Browse Source

wip account management - account list changes aren't propagated back to the drawer yet, preferences haven't been cleaned up yet

Andy Scherzinger 9 years ago
parent
commit
37da1a7920

+ 1 - 0
AndroidManifest.xml

@@ -71,6 +71,7 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity android:name=".ui.activity.ManageAccountsActivity" />
         <activity android:name=".ui.activity.UploadFilesActivity" />
         <activity android:name=".ui.activity.ReceiveExternalFilesActivity"
                   android:taskAffinity=""

BIN
res/drawable-hdpi/ic_key.png


BIN
res/drawable-mdpi/ic_key.png


BIN
res/drawable-xhdpi/ic_key.png


BIN
res/drawable-xxhdpi/ic_key.png


+ 68 - 0
res/layout/account_item.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  Copyright (C) 2016 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  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 <http://www.gnu.org/licenses/>.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="72dp"
+    android:orientation="horizontal"
+    android:weightSum="1">
+
+    <ImageView
+        android:id="@+id/user_icon"
+        android:layout_width="@dimen/file_icon_size"
+        android:layout_height="@dimen/file_icon_size"
+        android:layout_gravity="center_vertical"
+        android:layout_marginLeft="@dimen/standard_margin"
+        android:src="@drawable/ic_menu_archive"/>
+
+    <TextView
+        android:id="@+id/user_name"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layout_marginLeft="@dimen/standard_margin"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:paddingRight="@dimen/standard_padding"
+        android:text="@string/placeholder_filename"
+        android:textColor="@color/textColor"
+        android:textSize="@dimen/two_line_primary_text_size"/>
+
+    <ImageView
+        android:id="@+id/passwordButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:paddingLeft="@dimen/standard_half_padding"
+        android:paddingTop="@dimen/standard_padding"
+        android:paddingBottom="@dimen/standard_padding"
+        android:paddingRight="@dimen/standard_half_padding"
+        android:src="@drawable/ic_key"/>
+
+    <ImageView
+        android:id="@+id/removeButton"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:paddingLeft="@dimen/standard_half_padding"
+        android:paddingTop="@dimen/standard_padding"
+        android:paddingBottom="@dimen/standard_padding"
+        android:paddingRight="@dimen/standard_padding"
+        android:src="@drawable/ic_close"/>
+
+</LinearLayout>         

+ 37 - 0
res/layout/accounts_layout.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 
+  ownCloud Android client application
+
+  Copyright (C) 2016 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  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 <http://www.gnu.org/licenses/>.
+ -->
+<LinearLayout
+	android:id="@+id/upload_files_layout"
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="fill_parent"
+	android:layout_height="fill_parent"
+	android:orientation="vertical">
+
+	<include
+		layout="@layout/toolbar_standard"/>
+
+	<ListView
+		android:id="@+id/account_list"
+		android:layout_width="fill_parent"
+		android:layout_height="fill_parent"
+		android:divider="@color/list_divider_background"
+		android:dividerHeight="1dip">
+	</ListView>
+
+</LinearLayout>

+ 8 - 3
src/com/owncloud/android/ui/activity/DrawerActivity.java

@@ -188,7 +188,9 @@ public abstract class DrawerActivity extends ToolbarActivity {
                                         null, null);
                                 break;
                             case R.id.drawer_menu_account_manage:
-                                Toast.makeText(getApplicationContext(), "Not implemented yet", Toast.LENGTH_SHORT);
+                                Intent manageAccountsIntent = new Intent(getApplicationContext(),
+                                        ManageAccountsActivity.class);
+                                startActivity(manageAccountsIntent);
                                 break;
                             case Menu.NONE:
                                 // account clicked
@@ -269,8 +271,11 @@ public abstract class DrawerActivity extends ToolbarActivity {
         AccountManager am = (AccountManager) this.getSystemService(this.ACCOUNT_SERVICE);
 
         // populate UI
-        repopulateAccountList(am.getAccountsByType(MainApp.getAccountType()));
-        setUsernameInDrawer(AccountUtils.getCurrentOwnCloudAccount(this).name);
+        Account[] accounts = am.getAccountsByType(MainApp.getAccountType());
+        if(accounts.length > 0) {
+            repopulateAccountList(accounts);
+            setUsernameInDrawer(AccountUtils.getCurrentOwnCloudAccount(this).name);
+        }
     }
 
     /**

+ 269 - 0
src/com/owncloud/android/ui/activity/ManageAccountsActivity.java

@@ -0,0 +1,269 @@
+/**
+ * ownCloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2016 ownCloud Inc.
+ * <p/>
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ * <p/>
+ * 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.
+ * <p/>
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.activity;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.annotation.NonNull;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.authentication.AuthenticatorActivity;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.files.FileOperationsHelper;
+import com.owncloud.android.files.services.FileDownloader;
+import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.services.OperationsService;
+import com.owncloud.android.ui.adapter.AccountListAdapter;
+import com.owncloud.android.ui.adapter.AccountListItem;
+
+import java.util.ArrayList;
+
+/**
+ * Managing the accounts.
+ */
+public class ManageAccountsActivity extends ToolbarActivity
+        implements AccountListAdapter.AccountListAdapterListener, AccountManagerCallback<Boolean>, ComponentsGetter {
+    private static final String TAG = ManageAccountsActivity.class.getSimpleName();
+
+    private ListView mListView;
+    private final Handler mHandler = new Handler();
+    private String mAccountName;
+    private AccountListAdapter mAccountListAdapter;
+    protected FileUploader.FileUploaderBinder mUploaderBinder = null;
+    protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
+    private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.accounts_layout);
+
+        mListView = (ListView) findViewById(R.id.account_list);
+
+        setupToolbar();
+        updateActionBarTitleAndHomeButtonByString(getResources().getString(R.string.prefs_manage_accounts));
+
+        mAccountListAdapter = new AccountListAdapter(this, getAccountListItems());
+
+        mListView.setAdapter(mAccountListAdapter);
+
+        initializeComponentGetters();
+    }
+
+    /**
+     * Initialize ComponentsGetters.
+     */
+    private void initializeComponentGetters() {
+        mDownloadServiceConnection = newTransferenceServiceConnection();
+        if (mDownloadServiceConnection != null) {
+            bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection,
+                    Context.BIND_AUTO_CREATE);
+        }
+        mUploadServiceConnection = newTransferenceServiceConnection();
+        if (mUploadServiceConnection != null) {
+            bindService(new Intent(this, FileUploader.class), mUploadServiceConnection,
+                    Context.BIND_AUTO_CREATE);
+        }
+    }
+
+    /**
+     * creates the account list items list including the add-account action in case multiaccount_support is enabled.
+     *
+     * @return list of account list items
+     */
+    @NonNull
+    private ArrayList<AccountListItem> getAccountListItems() {
+        AccountManager am = (AccountManager) this.getSystemService(this.ACCOUNT_SERVICE);
+        Account[] accountList = am.getAccountsByType(MainApp.getAccountType());
+        ArrayList<AccountListItem> adapterAccountList = new ArrayList<AccountListItem>(accountList.length);
+        for (Account account : accountList) {
+            adapterAccountList.add(new AccountListItem(account));
+        }
+
+        // Add Create Account item at the end of account list if multi-account is enabled
+        if (getResources().getBoolean(R.bool.multiaccount_support)) {
+            adapterAccountList.add(new AccountListItem());
+        }
+
+        return adapterAccountList;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        boolean retval = true;
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                onBackPressed();
+                break;
+            default:
+                retval = super.onOptionsItemSelected(item);
+        }
+        return retval;
+    }
+
+    @Override
+    public void removeAccount(Account account) {
+        AccountManager am = (AccountManager) this.getSystemService(ACCOUNT_SERVICE);
+        mAccountName = account.name;
+        am.removeAccount(account, ManageAccountsActivity.this, mHandler);
+        Log_OC.d(TAG, "Remove an account " + account.name);
+    }
+
+    @Override
+    public void changePasswordOfAccount(Account account) {
+        Intent updateAccountCredentials = new Intent(ManageAccountsActivity.this, AuthenticatorActivity.class);
+        updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, account);
+        updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACTION,
+                AuthenticatorActivity.ACTION_UPDATE_TOKEN);
+        startActivity(updateAccountCredentials);
+    }
+
+    @Override
+    public void createAccount() {
+        // TODO Show create account screen if there isn't any account, probably via the drawer implementation
+        AccountManager am = AccountManager.get(getApplicationContext());
+        am.addAccount(MainApp.getAccountType(), null, null, null, ManageAccountsActivity.this, null, null);
+    }
+
+    @Override
+    public void run(AccountManagerFuture<Boolean> future) {
+        if (future.isDone()) {
+            // after remove account
+            Account account = new Account(mAccountName, MainApp.getAccountType());
+            if (!AccountUtils.exists(account, MainApp.getAppContext())) {
+                // Cancel transfers of the removed account
+                if (mUploaderBinder != null) {
+                    mUploaderBinder.cancel(account);
+                }
+                if (mDownloaderBinder != null) {
+                    mDownloaderBinder.cancel(account);
+                }
+            }
+
+            Account a = AccountUtils.getCurrentOwnCloudAccount(this);
+            String accountName = "";
+            if (a == null) {
+                Account[] accounts = AccountManager.get(this)
+                        .getAccountsByType(MainApp.getAccountType());
+                if (accounts.length != 0)
+                    accountName = accounts[0].name;
+                AccountUtils.setCurrentOwnCloudAccount(this, accountName);
+            }
+
+            mAccountListAdapter = new AccountListAdapter(this, getAccountListItems());
+            mAccountListAdapter.notifyDataSetChanged();
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mDownloadServiceConnection != null) {
+            unbindService(mDownloadServiceConnection);
+            mDownloadServiceConnection = null;
+        }
+        if (mUploadServiceConnection != null) {
+            unbindService(mUploadServiceConnection);
+            mUploadServiceConnection = null;
+        }
+
+        super.onDestroy();
+    }
+
+    // Methods for ComponentsGetter
+    @Override
+    public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() {
+        return mDownloaderBinder;
+    }
+
+    @Override
+    public FileUploader.FileUploaderBinder getFileUploaderBinder() {
+        return mUploaderBinder;
+    }
+
+    @Override
+    public OperationsService.OperationsServiceBinder getOperationsServiceBinder() {
+        return null;
+    }
+
+    @Override
+    public FileDataStorageManager getStorageManager() {
+        return null;
+    }
+
+    @Override
+    public FileOperationsHelper getFileOperationsHelper() {
+        return null;
+    }
+
+    protected ServiceConnection newTransferenceServiceConnection() {
+        return new ManageAccountsServiceConnection();
+    }
+
+    /**
+     * Defines callbacks for service binding, passed to bindService()
+     */
+    private class ManageAccountsServiceConnection implements ServiceConnection {
+
+        @Override
+        public void onServiceConnected(ComponentName component, IBinder service) {
+
+            if (component.equals(new ComponentName(ManageAccountsActivity.this, FileDownloader.class))) {
+                mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service;
+
+            } else if (component.equals(new ComponentName(ManageAccountsActivity.this, FileUploader.class))) {
+                Log_OC.d(TAG, "Upload service connected");
+                mUploaderBinder = (FileUploader.FileUploaderBinder) service;
+            } else {
+                return;
+            }
+
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName component) {
+            if (component.equals(new ComponentName(ManageAccountsActivity.this, FileDownloader.class))) {
+                Log_OC.d(TAG, "Download service suddenly disconnected");
+                mDownloaderBinder = null;
+            } else if (component.equals(new ComponentName(ManageAccountsActivity.this, FileUploader.class))) {
+                Log_OC.d(TAG, "Upload service suddenly disconnected");
+                mUploaderBinder = null;
+            }
+        }
+    }
+
+    ;
+}

+ 42 - 24
src/com/owncloud/android/ui/activity/Preferences.java

@@ -4,7 +4,7 @@
  *   @author Bartek Przybylski
  *   @author David A. Velasco
  *   Copyright (C) 2011  Bartek Przybylski
- *   Copyright (C) 2016 ownCloud Inc.
+ *   Copyright (C) 2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -71,6 +71,7 @@ import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.files.FileOperationsHelper;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
@@ -86,24 +87,25 @@ import com.owncloud.android.utils.DisplayUtils;
  * It proxies the necessary calls via {@link android.support.v7.app.AppCompatDelegate} to be used
  * with AppCompat.
  */
-public class Preferences extends PreferenceActivity
-        implements AccountManagerCallback<Boolean>, ComponentsGetter {
+// TODO possible remove AccountManagerCallback and ComponentsGetter
+public class Preferences extends PreferenceActivity {
+        //implements AccountManagerCallback<Boolean>, ComponentsGetter {
     
     private static final String TAG = Preferences.class.getSimpleName();
 
-
     private static final int ACTION_SELECT_UPLOAD_PATH = 1;
     private static final int ACTION_SELECT_UPLOAD_VIDEO_PATH = 2;
     private static final int ACTION_REQUEST_PASSCODE = 5;
     private static final int ACTION_CONFIRM_PASSCODE = 6;
 
+    private DbHandler mDbHandler;
     private CheckBoxPreference pCode;
     private Preference pAboutApp;
     private AppCompatDelegate mDelegate;
 
     private PreferenceCategory mAccountsPrefCategory = null;
-    private final Handler mHandler = new Handler();
-    private String mAccountName;
+    //private final Handler mHandler = new Handler();
+    //private String mAccountName;
     private boolean mShowContextMenu = false;
     private String mUploadPath;
     private PreferenceCategory mPrefInstantUploadCategory;
@@ -116,9 +118,9 @@ public class Preferences extends PreferenceActivity
     private Preference mPrefInstantVideoUploadPathWiFi;
     private String mUploadVideoPath;
 
-    protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
-    protected FileUploader.FileUploaderBinder mUploaderBinder = null;
-    private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
+    //protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
+    //protected FileUploader.FileUploaderBinder mUploaderBinder = null;
+    //private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
 
 
     @SuppressWarnings("deprecation")
@@ -127,6 +129,7 @@ public class Preferences extends PreferenceActivity
         getDelegate().installViewFactory();
         getDelegate().onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
+        mDbHandler = new DbHandler(getBaseContext());
         addPreferencesFromResource(R.xml.preferences);
 
         ActionBar actionBar = getSupportActionBar();
@@ -141,6 +144,7 @@ public class Preferences extends PreferenceActivity
                     setContentDescription(getString(R.string.actionbar_settings));
         }
 
+        // TODO remove accounts code - DONE
         // Load the accounts category for adding the list of accounts
         mAccountsPrefCategory = (PreferenceCategory) findPreference("accounts_category");
 
@@ -154,7 +158,7 @@ public class Preferences extends PreferenceActivity
 
                 if (obj != null && obj instanceof RadioButtonPreference) {
                     mShowContextMenu = true;
-                    mAccountName = ((RadioButtonPreference) obj).getKey();
+                    //mAccountName = ((RadioButtonPreference) obj).getKey();
 
                     String[] items = {
                             getResources().getString(R.string.change_password),
@@ -176,7 +180,8 @@ public class Preferences extends PreferenceActivity
                             AccountManager am = (AccountManager) getSystemService(ACCOUNT_SERVICE);
                             Account accounts[] = am.getAccountsByType(MainApp.getAccountType());
                             for (Account a : accounts) {
-                                if (a.name.equals(mAccountName)) {
+                                //if (a.name.equals(mAccountName)) {
+                                if (a.name.equals("")) {
                                     if (position==0) {
 
                                         // Change account password
@@ -190,7 +195,8 @@ public class Preferences extends PreferenceActivity
                                     } else if (position==1) {
 
                                         // Remove account
-                                        am.removeAccount(a, Preferences.this, mHandler);
+                                        //am.removeAccount(a, Preferences.this, mHandler);
+                                        am.removeAccount(a, null, new Handler());
                                         Log_OC.d(TAG, "Remove an account " + a.name);
                                         alertDialog.cancel();
                                     }
@@ -286,8 +292,7 @@ public class Preferences extends PreferenceActivity
                         String appName = getString(R.string.app_name);
                         String downloadUrl = getString(R.string.url_app_download);
 
-                        String recommendSubject =
-                                String.format(getString(R.string.recommend_subject),
+                        String recommendSubject = String.format(getString(R.string.recommend_subject),
                                 appName);
                         String recommendText = String.format(getString(R.string.recommend_text),
                                 appName, downloadUrl);
@@ -314,8 +319,7 @@ public class Preferences extends PreferenceActivity
                     @Override
                     public boolean onPreferenceClick(Preference preference) {
                         String feedbackMail   =(String) getText(R.string.mail_feedback);
-                        String feedback   =(String) getText(R.string.prefs_feedback) +
-                                " - android v" + appVersion;
+                        String feedback   =(String) getText(R.string.prefs_feedback) + " - android v" + appVersion;
                         Intent intent = new Intent(Intent.ACTION_SENDTO); 
                         intent.setType("text/plain");
                         intent.putExtra(Intent.EXTRA_SUBJECT, feedback);
@@ -451,15 +455,15 @@ public class Preferences extends PreferenceActivity
         /* About App */
        pAboutApp = (Preference) findPreference("about_app");
        if (pAboutApp != null) { 
-               pAboutApp.setTitle(String.format(getString(R.string.about_android),
-                       getString(R.string.app_name)));
+               pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name)));
                pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion));
        }
 
        loadInstantUploadPath();
        loadInstantUploadVideoPath();
 
-        /* ComponentsGetter */
+        // TODO remove after test - DONE
+        /* ComponentsGetter
         mDownloadServiceConnection = newTransferenceServiceConnection();
         if (mDownloadServiceConnection != null) {
             bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection,
@@ -470,7 +474,7 @@ public class Preferences extends PreferenceActivity
             bindService(new Intent(this, FileUploader.class), mUploadServiceConnection,
                     Context.BIND_AUTO_CREATE);
         }
-
+*/
     }
     
     private void toggleInstantPictureOptions(Boolean value){
@@ -513,6 +517,8 @@ public class Preferences extends PreferenceActivity
         super.onCreateContextMenu(menu, v, menuInfo);
     }
 
+    // TODO remove, moved to account manager - DONE
+    /*
     @Override
     public void run(AccountManagerFuture<Boolean> future) {
         if (future.isDone()) {
@@ -540,6 +546,7 @@ public class Preferences extends PreferenceActivity
             addAccountsCheckboxPreferences();
         }
     }
+    */
 
     @Override
     protected void onResume() {
@@ -691,6 +698,10 @@ public class Preferences extends PreferenceActivity
 
     @Override
     protected void onDestroy() {
+        mDbHandler.close();
+
+        // TODO remove after test - DONE
+        /*
         if (mDownloadServiceConnection != null) {
             unbindService(mDownloadServiceConnection);
             mDownloadServiceConnection = null;
@@ -699,6 +710,7 @@ public class Preferences extends PreferenceActivity
             unbindService(mUploadServiceConnection);
             mUploadServiceConnection = null;
         }
+        */
 
         super.onDestroy();
         getDelegate().onDestroy();
@@ -721,6 +733,7 @@ public class Preferences extends PreferenceActivity
         return mDelegate;
     }
 
+    // TODO remove/move after test
     /**
      * Create the list of accounts that has been added into the app
      */
@@ -806,6 +819,7 @@ public class Preferences extends PreferenceActivity
         }
     }
 
+    // TODO remove after finished -DONE
     /**
      * Create the preference for allow adding new accounts
      */
@@ -869,7 +883,9 @@ public class Preferences extends PreferenceActivity
         editor.commit();
     }
 
+    //TODO remove this implementation
     // Methods for ComponetsGetter
+    /*
     @Override
     public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() {
         return mDownloaderBinder;
@@ -896,11 +912,14 @@ public class Preferences extends PreferenceActivity
         return null;
     }
 
+
     protected ServiceConnection newTransferenceServiceConnection() {
         return new PreferencesServiceConnection();
     }
+    */
 
     /** Defines callbacks for service binding, passed to bindService() */
+    /*
     private class PreferencesServiceConnection implements ServiceConnection {
 
         @Override
@@ -909,8 +928,7 @@ public class Preferences extends PreferenceActivity
             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
                 mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service;
 
-            } else if (component.equals(new ComponentName(Preferences.this,
-                    FileUploader.class))) {
+            } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
                 Log_OC.d(TAG, "Upload service connected");
                 mUploaderBinder = (FileUploader.FileUploaderBinder) service;
             } else {
@@ -924,11 +942,11 @@ public class Preferences extends PreferenceActivity
             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
                 Log_OC.d(TAG, "Download service suddenly disconnected");
                 mDownloaderBinder = null;
-            } else if (component.equals(new ComponentName(Preferences.this,
-                    FileUploader.class))) {
+            } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
                 Log_OC.d(TAG, "Upload service suddenly disconnected");
                 mUploaderBinder = null;
             }
         }
     };
+    */
 }

+ 161 - 0
src/com/owncloud/android/ui/adapter/AccountListAdapter.java

@@ -0,0 +1,161 @@
+/**
+ * ownCloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2016 ownCloud Inc.
+ * <p/>
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ * <p/>
+ * 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.
+ * <p/>
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.ui.adapter;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.ui.TextDrawable;
+import com.owncloud.android.ui.activity.ManageAccountsActivity;
+import com.owncloud.android.utils.BitmapUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+/**
+ * This Adapter populates a ListView with all accounts within the app.
+ */
+public class AccountListAdapter extends ArrayAdapter<AccountListItem> {
+    private static final String TAG = AccountListAdapter.class.getSimpleName();
+
+    private final Context mContext;
+    private final List<AccountListItem> mValues;
+    private AccountListAdapterListener mListener;
+
+    public AccountListAdapter(Context context, List<AccountListItem> values) {
+        super(context, -1, values);
+        this.mContext = context;
+        this.mValues = values;
+        this.mListener = (AccountListAdapterListener) context;
+    }
+
+    @Override
+    public View getView(final int position, View convertView, ViewGroup parent) {
+        AccountViewHolderItem viewHolder;
+
+        if (convertView == null) {
+            LayoutInflater inflater = ((ManageAccountsActivity) mContext).getLayoutInflater();
+            convertView = inflater.inflate(R.layout.account_item, parent, false);
+
+            viewHolder = new AccountViewHolderItem();
+            viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.user_name);
+            viewHolder.imageViewItem = (ImageView) convertView.findViewById(R.id.user_icon);
+            viewHolder.passwordButtonItem = (ImageView) convertView.findViewById(R.id.passwordButton);
+            viewHolder.removeButtonItem = (ImageView) convertView.findViewById(R.id.removeButton);
+
+            convertView.setTag(viewHolder);
+        } else {
+            viewHolder = (AccountViewHolderItem) convertView.getTag();
+        }
+
+        AccountListItem accountListItem = mValues.get(position);
+
+
+        if (accountListItem != null) {
+            // create account item
+            if (AccountListItem.TYPE_ACCOUNT == accountListItem.getType()) {
+                Account account = accountListItem.getAccount();
+                viewHolder.textViewItem.setText(account.name);
+                viewHolder.textViewItem.setTag(account.name);
+
+                try {
+                    int[] rgb = BitmapUtils.calculateRGB(account.name);
+                    TextDrawable icon = new TextDrawable(account.name.substring(0, 1).toUpperCase()
+                            , rgb[0], rgb[1], rgb[2]);
+                    viewHolder.imageViewItem.setImageDrawable(icon);
+                } catch (Exception e) {
+                    Log_OC.e(TAG, "Error calculating RGB value for account list item.", e);
+                    // use user icon as a fallback
+                    viewHolder.imageViewItem.setImageResource(R.drawable.ic_user);
+                }
+
+                /// bind listener to change password
+                viewHolder.passwordButtonItem.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mListener.changePasswordOfAccount(mValues.get(position).getAccount());
+                    }
+                });
+
+                /// bind listener to remove account
+                viewHolder.removeButtonItem.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mListener.removeAccount(mValues.get(position).getAccount());
+                        mValues.remove(position);
+                        AccountListAdapter.this.notifyDataSetChanged();
+                    }
+                });
+            } // create add account action item
+            else if (AccountListItem.TYPE_ACTION_ADD == accountListItem.getType()) {
+                LayoutInflater inflater = ((ManageAccountsActivity) mContext).getLayoutInflater();
+                View actionView = inflater.inflate(R.layout.account_item, parent, false);
+                ((TextView) actionView.findViewById(R.id.user_name)).setText(R.string.prefs_add_account);
+                ((ImageView) actionView.findViewById(R.id.user_icon)).setImageResource(R.drawable.ic_account_plus);
+                actionView.findViewById(R.id.passwordButton).setVisibility(View.GONE);
+                actionView.findViewById(R.id.removeButton).setVisibility(View.GONE);
+
+                // bind action listener
+                actionView.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        mListener.createAccount();
+                    }
+                });
+
+                return actionView;
+            }
+        }
+
+        return convertView;
+    }
+
+    /**
+     * Listener interface for Activities using the {@link AccountListAdapter}
+     */
+    public interface AccountListAdapterListener {
+        void removeAccount(Account account);
+
+        void changePasswordOfAccount(Account account);
+
+        void createAccount();
+    }
+
+    /**
+     * Account ViewHolderItem to get smooth scrolling.
+     */
+    static class AccountViewHolderItem {
+        TextView textViewItem;
+        ImageView imageViewItem;
+
+        ImageView passwordButtonItem;
+        ImageView removeButtonItem;
+    }
+}

+ 39 - 0
src/com/owncloud/android/ui/adapter/AccountListItem.java

@@ -0,0 +1,39 @@
+package com.owncloud.android.ui.adapter;
+
+import android.accounts.Account;
+
+/**
+ * Container implementation to add {@link Account}s and the add action to the list.
+ */
+public class AccountListItem {
+    public static final int TYPE_ACCOUNT = 0;
+    public static final int TYPE_ACTION_ADD = 1;
+
+    private Account mAccount;
+    private int mType;
+
+    /**
+     * creates an account list item containing an {@link Account}.
+     *
+     * @param account the account
+     */
+    public AccountListItem(Account account) {
+        mAccount = account;
+        mType = TYPE_ACCOUNT;
+    }
+
+    /**
+     * creates an account list item flagged as add-action.
+     */
+    public AccountListItem() {
+        mType = TYPE_ACTION_ADD;
+    }
+
+    public Account getAccount() {
+        return mAccount;
+    }
+
+    public int getType() {
+        return mType;
+    }
+}