diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bc47fd647..46a679c06 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,11 +14,17 @@
+
+
diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
index e398145e0..454630b00 100644
--- a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
+++ b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java
@@ -20,6 +20,8 @@
package com.nextcloud.talk.adapters.items;
+import android.accounts.Account;
+import android.support.annotation.Nullable;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
@@ -52,10 +54,12 @@ public class AdvancedUserItem extends AbstractFlexibleItem checkServerAndProceed());
- if (TextUtils.isEmpty(getResources().getString(R.string.nc_providers_url))) {
+ if (TextUtils.isEmpty(getResources().getString(R.string.nc_providers_url)) && (TextUtils.isEmpty(getResources
+ ().getString(R.string.nc_import_account_type)))) {
providersTextView.setVisibility(View.GONE);
} else {
- providersTextView.setOnClickListener(view12 -> {
- Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources()
- .getString(R.string.nc_providers_url)));
- startActivity(browserIntent);
- });
+ if ((TextUtils.isEmpty(getResources
+ ().getString(R.string.nc_import_account_type)) || AccountUtils.findAccounts().size() == 0) &&
+ userUtils.getUsers().size() == 0) {
+
+ providersTextView.setText(R.string.nc_get_from_provider);
+ providersTextView.setOnClickListener(view12 -> {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getResources()
+ .getString(R.string.nc_providers_url)));
+ startActivity(browserIntent);
+ });
+ } else if (AccountUtils.findAccounts().size() > 0) {
+ if (!TextUtils.isEmpty(AccountUtils.getAppNameBasedOnPackage(getResources()
+ .getString(R.string.nc_import_accounts_from)))) {
+ providersTextView.setText(String.format(getResources().getString(R.string
+ .nc_server_import_accounts), AccountUtils.getAppNameBasedOnPackage(getResources()
+ .getString(R.string.nc_import_accounts_from))));
+ } else {
+ providersTextView.setText(getResources().getString(R.string.nc_server_import_accounts_plain_plural));
+ }
+
+ providersTextView.setOnClickListener(view13 -> {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean("isAccountImport", true);
+ getRouter().pushController(RouterTransaction.with(
+ new SwitchAccountController(bundle))
+ .pushChangeHandler(new HorizontalChangeHandler())
+ .popChangeHandler(new HorizontalChangeHandler()));
+ });
+ } else {
+ providersTextView.setVisibility(View.GONE);
+ }
}
serverEntry.requestFocus();
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
index 7bd417e73..6fa1d0fce 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
+++ b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
@@ -16,15 +16,27 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
+ *
+ * Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
+ * https://github.com/nextcloud/ownCloud-Account-Importer
*/
package com.nextcloud.talk.controllers;
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.OperationCanceledException;
+import android.os.Bundle;
+import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.app.AlertDialog;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -34,7 +46,9 @@ import com.nextcloud.talk.adapters.items.AdvancedUserItem;
import com.nextcloud.talk.api.models.json.participants.Participant;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.controllers.base.BaseController;
+import com.nextcloud.talk.models.ImportAccount;
import com.nextcloud.talk.persistence.entities.UserEntity;
+import com.nextcloud.talk.utils.AccountUtils;
import com.nextcloud.talk.utils.database.user.UserUtils;
import java.net.CookieManager;
@@ -54,6 +68,7 @@ import io.reactivex.disposables.Disposable;
@AutoInjector(NextcloudTalkApplication.class)
public class SwitchAccountController extends BaseController {
+ private static final String TAG = "SwitchAccountController";
@Inject
UserUtils userUtils;
@@ -68,7 +83,21 @@ public class SwitchAccountController extends BaseController {
private FlexibleAdapter adapter;
private List userItems = new ArrayList<>();
- private FlexibleAdapter.OnItemClickListener onItemClickListener =
+ private boolean isAccountImport = false;
+
+ private FlexibleAdapter.OnItemClickListener onImportItemClickListener = new FlexibleAdapter.OnItemClickListener() {
+ @Override
+ public boolean onItemClick(int position) {
+ if (userItems.size() > position) {
+ Account account = ((AdvancedUserItem) userItems.get(position)).getAccount();
+ getAuthTokenForAccount(account);
+ }
+
+ return true;
+ }
+ };
+
+ private FlexibleAdapter.OnItemClickListener onSwitchItemClickListener =
new FlexibleAdapter.OnItemClickListener() {
@Override
public boolean onItemClick(int position) {
@@ -106,6 +135,17 @@ public class SwitchAccountController extends BaseController {
}
};
+ public SwitchAccountController() {
+ }
+
+ public SwitchAccountController(Bundle args) {
+ super(args);
+
+ if (args.containsKey("isAccountImport")) {
+ isAccountImport = true;
+ }
+ }
+
@Override
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
return inflater.inflate(R.layout.controller_generic_rv, container, false);
@@ -123,19 +163,39 @@ public class SwitchAccountController extends BaseController {
UserEntity userEntity;
Participant participant;
- for (Object userEntityObject : userUtils.getUsers()) {
- userEntity = (UserEntity) userEntityObject;
- if (!userEntity.getCurrent()) {
- participant = new Participant();
- participant.setName(userEntity.getDisplayName());
- participant.setUserId(userEntity.getUsername());
- userItems.add(new AdvancedUserItem(participant, userEntity));
+ if (!isAccountImport) {
+ for (Object userEntityObject : userUtils.getUsers()) {
+ userEntity = (UserEntity) userEntityObject;
+ if (!userEntity.getCurrent()) {
+ participant = new Participant();
+ participant.setName(userEntity.getDisplayName());
+ participant.setUserId(userEntity.getUsername());
+ userItems.add(new AdvancedUserItem(participant, userEntity, null));
+ }
}
- }
- adapter.addListener(onItemClickListener);
- adapter.updateDataSet(userItems, false);
- }
+ adapter.addListener(onSwitchItemClickListener);
+ adapter.updateDataSet(userItems, false);
+ } else {
+ getActionBar().show();
+ Account account;
+ ImportAccount importAccount;
+ for (Object accountObject : AccountUtils.findAccounts(userUtils.getUsers())) {
+ account = (Account) accountObject;
+ importAccount = AccountUtils.getInformationFromAccount(account, null);
+
+ participant = new Participant();
+ participant.setName(importAccount.getUsername());
+ participant.setUserId(importAccount.getUsername());
+ userEntity = new UserEntity();
+ userEntity.setBaseUrl(importAccount.getServerUrl());
+ userItems.add(new AdvancedUserItem(participant, userEntity, account));
+ }
+ }
+
+ adapter.addListener(onSwitchItemClickListener);
+ adapter.updateDataSet(userItems, false);
+ }
prepareViews();
}
@@ -154,10 +214,46 @@ public class SwitchAccountController extends BaseController {
swipeRefreshLayout.setEnabled(false);
}
+ private void getAuthTokenForAccount(Account account) {
+ final AccountManager accMgr = AccountManager.get(getActivity());
+
+ final AlertDialog alertDialog = new AlertDialog.Builder(getActivity())
+ .setTitle(getResources().getString(R.string.nc_server_import_accounts_plain_singular))
+ .setMessage(getResources().getString(R.string.nc_server_import_account_notification))
+ .create();
+
+ alertDialog.show();
+
+ String authTokenType = getResources().getString(R.string.nc_import_account_type) + ".password";
+
+ final Handler handler = new Handler();
+ accMgr.getAuthToken(account, authTokenType, true,
+ new AccountManagerCallback() {
+
+ @Override
+ public void run(AccountManagerFuture future) {
+
+ try {
+ ImportAccount importAccount = AccountUtils.getInformationFromAccount(account, future
+ .getResult());
+ } catch (OperationCanceledException e) {
+ Log.e(TAG, "Access was denied");
+ // TODO: The user has denied you access to the API, handle this later on
+ } catch (Exception e) {
+ Log.e(TAG, "Something went wrong while accessing token");
+ }
+
+ alertDialog.dismiss();
+
+ }
+ }, handler
+
+ );
+
+ }
+
@Override
protected String getTitle() {
return getResources().getString(R.string.nc_select_an_account);
}
-
-
}
diff --git a/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java b/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java
new file mode 100644
index 000000000..d25baae83
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/models/ImportAccount.java
@@ -0,0 +1,38 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.nextcloud.talk.models;
+
+import android.support.annotation.Nullable;
+
+import lombok.Data;
+
+@Data
+public class ImportAccount {
+ public String username;
+ @Nullable public String token;
+ public String serverUrl;
+
+ public ImportAccount(String username, @Nullable String token, String serverUrl) {
+ this.username = username;
+ this.token = token;
+ this.serverUrl = serverUrl;
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.java b/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.java
new file mode 100644
index 000000000..3f4f8e383
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/utils/AccountUtils.java
@@ -0,0 +1,122 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
+ * https://github.com/nextcloud/ownCloud-Account-Importer
+ */
+
+package com.nextcloud.talk.utils;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import com.nextcloud.talk.R;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
+import com.nextcloud.talk.models.ImportAccount;
+import com.nextcloud.talk.persistence.entities.UserEntity;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public class AccountUtils {
+
+ private static final String TAG = "AccountUtils";
+
+ public static List findAccounts(List userEntitiesList) {
+ Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
+ final AccountManager accMgr = AccountManager.get(context);
+ final Account[] accounts = accMgr.getAccounts();
+
+ List accountsAvailable = new ArrayList<>();
+ ImportAccount importAccount;
+ UserEntity internalUserEntity;
+ boolean accountFound;
+ for (Account account : accounts) {
+ accountFound = false;
+ String accountType = account.type.intern();
+
+ if (context.getResources().getString(R.string.nc_import_account_type).equals(accountType)) {
+ for (int i = 0; i < userEntitiesList.size(); i++) {
+ internalUserEntity = userEntitiesList.get(i);
+ importAccount = getInformationFromAccount(account, null);
+ if (internalUserEntity.getUsername().equals(importAccount.getUsername()) &&
+ internalUserEntity.getBaseUrl().equals(importAccount.getServerUrl())) {
+ accountFound = true;
+ break;
+ }
+ }
+
+ if (!accountFound) {
+ accountsAvailable.add(account);
+ }
+ }
+ }
+
+ return accountsAvailable;
+ }
+
+ public static String getAppNameBasedOnPackage(String packageName) {
+ Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
+ PackageManager packageManager = context.getPackageManager();
+ String appName = "";
+ try {
+ appName = (String) packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Failed to get app name based on package");
+ }
+
+ return appName;
+ }
+
+ public static ImportAccount getInformationFromAccount(Account account, @Nullable Bundle data) {
+ int lastAtPos = account.name.lastIndexOf("@");
+ String urlString = account.name.substring(lastAtPos + 1);
+ String username = account.name.substring(0, lastAtPos);
+
+ if (!urlString.startsWith("http"))
+ urlString = "https://" + urlString;
+
+ String password = null;
+ if (data != null) {
+ password = data.getString(AccountManager.KEY_AUTHTOKEN);
+ }
+
+ try {
+ final String urlStringOrig = urlString;
+ URL url = new URL(urlStringOrig);
+ urlString = url.getProtocol() + "://" + url.getHost();
+ if (url.getPath().contains("/owncloud")) {
+ urlString += url.getPath().substring(0, url.getPath().indexOf("/owncloud") + 9);
+ } else if (url.getPath().contains("/")) {
+ urlString += url.getPath().substring(0, url.getPath().indexOf("/"));
+ }
+ } catch (Exception ex) {
+ Log.e(TAG, "Something went wrong while trying to create url string");
+ }
+
+ return new ImportAccount(username, password, urlString);
+ }
+}
+
diff --git a/app/src/main/res/layout/controller_server_selection.xml b/app/src/main/res/layout/controller_server_selection.xml
index ddad2be0d..1b9a70e86 100644
--- a/app/src/main/res/layout/controller_server_selection.xml
+++ b/app/src/main/res/layout/controller_server_selection.xml
@@ -80,7 +80,7 @@
android:visibility="invisible"/>
https://www.gnu.org/licenses/gpl-3.0.en.html
https://github.com/nextcloud/talk-android
https://nextcloud.com/providers
+
+
+ com.nextcloud.client
+ nextcloud
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 147f8d454..8d773534d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -11,6 +11,10 @@
Please upgrade your %1$s database
Please bring your %1$s out of maintenance
%1$s only works with %2$s 13 and up
+ Import account
+ Import accounts
+ Import accounts from the %1$s app
+ Please grant access to the selected account in the notification bar!"
Do you not have a server yet?\nClick here to get one from a provider