package com.openfarmanager.android.core.network; import android.app.Activity; import android.app.Dialog; import android.content.Intent; import android.net.Uri; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.Pair; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.openfarmanager.android.App; import com.openfarmanager.android.R; import com.openfarmanager.android.adapters.NetworkAccountChooserAdapter; import com.openfarmanager.android.adapters.NetworkChooserAdapter; import com.openfarmanager.android.controllers.FileSystemController; import com.openfarmanager.android.core.dbadapters.NetworkAccountDbAdapter; import com.openfarmanager.android.core.network.dropbox.DropboxAPI; import com.openfarmanager.android.core.network.ftp.FtpAPI; import com.openfarmanager.android.core.network.ftp.SftpAPI; import com.openfarmanager.android.core.network.googledrive.GoogleDriveApi; import com.openfarmanager.android.core.network.mediafire.MediaFireApi; import com.openfarmanager.android.core.network.skydrive.SkyDriveAPI; import com.openfarmanager.android.core.network.smb.SmbAPI; import com.openfarmanager.android.core.network.webdav.WebDavApi; import com.openfarmanager.android.core.network.yandexdisk.YandexDiskApi; import com.openfarmanager.android.dialogs.FtpAuthDialog; import com.openfarmanager.android.dialogs.MediaFireAuthDialog; import com.openfarmanager.android.dialogs.NetworkScanDialog; import com.openfarmanager.android.dialogs.SftpAuthDialog; import com.openfarmanager.android.dialogs.SmbAuthDialog; import com.openfarmanager.android.dialogs.WebDavAuthDialog; import com.openfarmanager.android.dialogs.YandexDiskAuthDialog; import com.openfarmanager.android.fragments.ErrorDialog; import com.openfarmanager.android.fragments.MainPanel; import com.openfarmanager.android.googledrive.GoogleDriveAuthWindow; import com.openfarmanager.android.googledrive.model.About; import com.openfarmanager.android.googledrive.model.Token; import com.openfarmanager.android.model.Bookmark; import com.openfarmanager.android.model.NetworkAccount; import com.openfarmanager.android.model.NetworkEnum; import com.openfarmanager.android.model.exeptions.InAppAuthException; import com.openfarmanager.android.model.exeptions.InitYandexDiskException; import com.openfarmanager.android.utils.NetworkUtil; import com.openfarmanager.android.utils.SystemUtils; import com.openfarmanager.android.view.ToastNotification; import com.yandex.disk.client.Credentials; import rx.Observable; import rx.Observer; import rx.Subscriber; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; import rx.subscriptions.CompositeSubscription; import static com.openfarmanager.android.utils.Extensions.runAsync; import static com.openfarmanager.android.controllers.FileSystemController.*; /** * @author Vlad Namashko */ public class NetworkConnectionManager { private Dialog mProgressDialog; private FileSystemController mFileSystemController; protected boolean mNetworkAuthRequested; protected CompositeSubscription mSubscription; public void setRxSubscription(CompositeSubscription subscription) { mSubscription = subscription; } public void setFileSystemController(FileSystemController fileSystemController) { mFileSystemController = fileSystemController; } public boolean isNetworkAuthRequested() { return mNetworkAuthRequested; } public void resetNetworkAuth() { mNetworkAuthRequested = false; } public void openAvailableCloudsList() { MainPanel panel = mFileSystemController.getActivePanel(); if (NetworkUtil.isNetworkAvailable()) { showNetworksDialog(); } else { if (panel != null && panel.getActivity() != null) { ToastNotification.makeText(panel.getActivity(), App.sInstance.getString(R.string.error_no_network), Toast.LENGTH_LONG).show(); } } } public void openNetworkBookmark(Bookmark bookmark) { openNetworkAccount(bookmark); } /** * Show dialog with available networks (clouds). */ private void showNetworksDialog() { final MainPanel panel = mFileSystemController.getActivePanel(); if (panel == null || panel.getActivity() == null) { // very weired situation; try to avoid crash. return; } final Dialog dialog = new Dialog(panel.getActivity(), R.style.Action_Dialog); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); View dialogView = View.inflate(App.sInstance.getApplicationContext(), R.layout.network_type_chooser, null); final ListView networks = (ListView) dialogView.findViewById(R.id.network_types); final NetworkChooserAdapter adapter = new NetworkChooserAdapter(); networks.setAdapter(adapter); dialogView.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dialog.dismiss(); } }); networks.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { NetworkEnum network = (NetworkEnum) view.getTag(); switch (network) { case FTP: openFTP(panel); break; case SFTP: openSFTP(panel); break; case SMB: openSmb(panel); break; case Dropbox: openDropbox(panel); break; case SkyDrive: openSkyDrive(panel); break; case YandexDisk: openYandexDisk(panel); break; case GoogleDrive: openGoogleDrive(panel); break; case MediaFire: openMediaFire(panel); break; case WebDav: openWebDav(panel); break; } if (dialog.isShowing()) { dialog.dismiss(); } } }); dialog.setContentView(dialogView); dialog.show(); adjustDialogSize(dialog, panel); } public void openSmb(MainPanel panel) { SmbAPI api = App.sInstance.getSmbAPI(); if (api.getAuthorizedAccountsCount() == 0) { startSmbAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.SMB, panel); } } public void openMediaFire(MainPanel panel) { MediaFireApi api = App.sInstance.getMediaFireApi(); if (api.getAuthorizedAccountsCount() == 0) { startMediaFireAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.MediaFire, panel); } } public void openFTP(MainPanel panel) { FtpAPI api = App.sInstance.getFtpApi(); if (api.getAuthorizedAccountsCount() == 0) { startFtpAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.FTP, panel); } } public void openSFTP(MainPanel panel) { SftpAPI api = App.sInstance.getSftpApi(); if (api.getAuthorizedAccountsCount() == 0) { startSftpAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.SFTP, panel); } } public void openDropbox(MainPanel panel) { DropboxAPI api = App.sInstance.getDropboxApi(); if (api.getAuthorizedAccountsCount() == 0) { startDropboxAuthentication(panel); } else { resetNetworkAuth(); showSelectAccountDialog(NetworkEnum.Dropbox, panel); } } public void openSkyDrive(MainPanel panel) { SkyDriveAPI api = App.sInstance.getSkyDriveApi(); if (api.getAuthorizedAccountsCount() == 0) { // no authorized accounts startSkyDriveAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.SkyDrive, panel); } } public void openYandexDisk(MainPanel panel) { YandexDiskApi api = App.sInstance.getYandexDiskApi(); if (api.getAuthorizedAccountsCount() == 0) { // no authorized accounts startYandexDiskAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.YandexDisk, panel); } } public void openGoogleDrive(MainPanel panel) { GoogleDriveApi api = App.sInstance.getGoogleDriveApi(); if (api.getAuthorizedAccountsCount() == 0) { startGoogleDriveAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.GoogleDrive, panel); } } private void openWebDav(MainPanel panel) { WebDavApi api = App.sInstance.getWebDavApi(); if (api.getAuthorizedAccountsCount() == 0) { startWebDavAuthentication(panel); } else { showSelectAccountDialog(NetworkEnum.WebDav, panel); } } private void startFtpAuthentication(MainPanel panel) { final Dialog dialog = new FtpAuthDialog(panel.getActivity(), mInAppAuthHandler); dialog.show(); adjustDialogSize(dialog, panel); } private void startSftpAuthentication(MainPanel panel) { final Dialog dialog = new SftpAuthDialog(panel.getActivity(), mInAppAuthHandler); dialog.show(); adjustDialogSize(dialog, panel); } private void startSmbAuthentication(MainPanel panel) { startSmbAuthentication(null, panel); } private void startSmbAuthentication(String selectedIp, MainPanel panel) { final Dialog dialog = new SmbAuthDialog(panel.getActivity(), mInAppAuthHandler, selectedIp); dialog.show(); adjustDialogSize(dialog, panel); } private void startMediaFireAuthentication(MainPanel panel) { final Dialog dialog = new MediaFireAuthDialog(panel.getActivity(), mInAppAuthHandler); dialog.show(); adjustDialogSize(dialog, panel); } private void startDropboxAuthentication(MainPanel panel) { App.sInstance.getDropboxApi().getSession().startAuthentication(panel.getActivity()); mNetworkAuthRequested = true; } private void startGoogleDriveAuthentication(MainPanel panel) { GoogleDriveAuthWindow popupWindow = new GoogleDriveAuthWindow(panel.getActivity(), mInAppAuthHandler); popupWindow.show(); } private void startWebDavAuthentication(MainPanel panel) { final Dialog dialog = new WebDavAuthDialog(panel.getActivity(), mInAppAuthHandler); dialog.show(); adjustDialogSize(dialog, panel); } private void startSkyDriveAuthentication(MainPanel panel) { App.sInstance.getSkyDriveApi().startAuthentication(panel.getActivity(), mOnSkyDriveLoginListener); } private void startYandexDiskAuthentication(MainPanel panel) { final Dialog dialog = new YandexDiskAuthDialog(panel.getActivity(), mInAppAuthHandler); dialog.show(); adjustDialogSize(dialog, panel); } /** * Show dialog with available (authenticated) network (cloud) accounts for certain cloud type. * * @param networkType selected cloud type */ private void showSelectAccountDialog(final NetworkEnum networkType, final MainPanel panel) { if (panel == null || panel.getActivity() == null) { // very weired situation; try to avoid crash. return; } final Dialog dialog = new Dialog(panel.getActivity(), R.style.Action_Dialog); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); View dialogView = View.inflate(App.sInstance.getApplicationContext(), R.layout.network_type_chooser, null); ((TextView) dialogView.findViewById(R.id.network_dialog_title)).setText(App.sInstance.getString(R.string.action_select_account)); final ListView networks = (ListView) dialogView.findViewById(R.id.network_types); NetworkApi api = App.sInstance.getNetworkApi(networkType); final BaseAdapter adapter = new NetworkAccountChooserAdapter(api, new NetworkAccountChooserAdapter.OnDeleteItemListener() { @Override public void onAccountDelete(NetworkAccount account) { NetworkAccountDbAdapter.delete(account.getId()); ((NetworkAccountChooserAdapter) networks.getAdapter()).dataSetChanged(); } }); networks.setAdapter(adapter); dialogView.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dialog.dismiss(); } }); networks.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { openNetworkAccount((NetworkAccount) view.getTag(), null, panel); if (dialog.isShowing()) { dialog.dismiss(); } } }); dialog.setContentView(dialogView); dialog.show(); adjustDialogSize(dialog, panel); } private void openNetworkAccount(Bookmark bookmark) { openNetworkAccount(bookmark.getNetworkAccount(), bookmark.getBookmarkPath(), mFileSystemController.getActivePanel()); } private void openNetworkAccount(NetworkAccount networkAccount, final String path, MainPanel panel) { if (networkAccount == null) { return; } switch (networkAccount.getNetworkType()) { case FTP: final FtpAPI.FtpAccount ftpAccount = (FtpAPI.FtpAccount) networkAccount; if (ftpAccount.getServer() == null) { // new startFtpAuthentication(panel); } else { showProgressDialog(R.string.connecting_to_ftp); runAsync(new Runnable() { @Override public void run() { try { App.sInstance.getFtpApi().connect(ftpAccount); dismissProgressDialog(); openNetworkPanel(NetworkEnum.FTP, path); } catch (final InAppAuthException e) { handleInAppAuthError(e); } catch (final Exception e) { handleNetworkAuthError(e); } } }); } break; case SFTP: final SftpAPI.SftpAccount sftpAccount = (SftpAPI.SftpAccount) networkAccount; if (sftpAccount.getServer() == null) { // new startSftpAuthentication(panel); } else { showProgressDialog(R.string.connecting_to_sftp); runAsync(new Runnable() { @Override public void run() { try { App.sInstance.getSftpApi().connect(sftpAccount); dismissProgressDialog(); openNetworkPanel(NetworkEnum.SFTP, path); } catch (final InAppAuthException e) { handleInAppAuthError(e); } catch (final Exception e) { handleNetworkAuthError(e); } } }); } break; case SMB: final SmbAPI.SmbAccount smbAccount = (SmbAPI.SmbAccount) networkAccount; if (smbAccount.getDomain() == null) { // new startSmbAuthentication(panel); } else { showProgressDialog(R.string.connecting_to_smb); runAsync(new Runnable() { @Override public void run() { try { App.sInstance.getSmbAPI().connect(smbAccount); dismissProgressDialog(); openNetworkPanel(NetworkEnum.SMB, path); } catch (final InAppAuthException e) { handleInAppAuthError(e); } catch (final Exception e) { handleNetworkAuthError(e); } } }); } break; case Dropbox: DropboxAPI.DropboxAccount dropboxAccount = (DropboxAPI.DropboxAccount) networkAccount; if (dropboxAccount.getKey() == null && dropboxAccount.getSecret() == null) { // new startDropboxAuthentication(panel); } else { App.sInstance.getDropboxApi().setAuthTokensToSession(dropboxAccount); openNetworkPanel(NetworkEnum.Dropbox, path); } break; case SkyDrive: SkyDriveAPI.SkyDriveAccount skyDriveAccount = (SkyDriveAPI.SkyDriveAccount) networkAccount; if (skyDriveAccount.getToken() == null) { // new startSkyDriveAuthentication(panel); } else { showProgressDialog(R.string.restoring_skydrive_session); App.sInstance.getSkyDriveApi().setAuthTokensToSession(skyDriveAccount, mOnSkyDriveLoginListener, path); } break; case YandexDisk: YandexDiskApi.YandexDiskAccount yandexDiskAccount = (YandexDiskApi.YandexDiskAccount) networkAccount; if (yandexDiskAccount.getToken() == null && yandexDiskAccount.getUser() == null) { // new startYandexDiskAuthentication(panel); } else { try { App.sInstance.getYandexDiskApi().setupToken(yandexDiskAccount); } catch (InitYandexDiskException e) { e.printStackTrace(); showErrorDialog(App.sInstance.getResources().getString(R.string.error_init_yandex_sdk)); return; } openNetworkPanel(NetworkEnum.YandexDisk, path); } break; case GoogleDrive: final GoogleDriveApi.GoogleDriveAccount driveAccount = (GoogleDriveApi.GoogleDriveAccount) networkAccount; if (driveAccount.getToken() == null) { // new startGoogleDriveAuthentication(panel); } else { App.sInstance.getGoogleDriveApi().setup(driveAccount); openNetworkPanel(NetworkEnum.GoogleDrive, path); } break; case MediaFire: final MediaFireApi.MediaFireAccount account = (MediaFireApi.MediaFireAccount) networkAccount; if (account.getPassword() == null) { // new startMediaFireAuthentication(panel); } else { showProgressDialog(R.string.loading); Subscription subscription = Observable.create(new Observable.OnSubscribe<Void>() { @Override public void call(Subscriber<? super Void> subscriber) { try { App.sInstance.getMediaFireApi().startSession(account); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Void>() { @Override public void onCompleted() { dismissProgressDialog(); openNetworkPanel(NetworkEnum.MediaFire, path); } @Override public void onError(Throwable e) { dismissProgressDialog(); ToastNotification.makeText(App.sInstance.getApplicationContext(), App.sInstance.getString(R.string.mediafire_connection_error), Toast.LENGTH_LONG).show(); } @Override public void onNext(Void aVoid) { } }); mSubscription.add(subscription); } break; case WebDav: final WebDavApi.WebDavAccount webDavAccount = (WebDavApi.WebDavAccount) networkAccount; if (webDavAccount.getServer() == null) { // new startWebDavAuthentication(panel); } else { showProgressDialog(R.string.connecting_to_webdav); runAsync(new Runnable() { @Override public void run() { try { App.sInstance.getWebDavApi().connect(webDavAccount); dismissProgressDialog(); openNetworkPanel(NetworkEnum.WebDav, path); } catch (final InAppAuthException e) { handleInAppAuthError(e); } catch (final Exception e) { handleNetworkAuthError(e); } } }); } break; } } private void openNetworkPanel(NetworkEnum type, String path) { mFileSystemController.openNetworkPanel(type, path); } private void showErrorDialog(String message) { try { ErrorDialog.newInstance(message).show(mFileSystemController.getActivePanel().getActivity().getSupportFragmentManager(), "errorDialog"); } catch (Exception ex) { ex.printStackTrace(); } } public void showProgressDialog(final int messageId) { try { final MainPanel panel = mFileSystemController.getActivePanel(); panel.getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (mProgressDialog != null && mProgressDialog.isShowing()) { dismissProgressDialog(); } mProgressDialog = new Dialog(panel.getActivity(), android.R.style.Theme_Translucent); mProgressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); mProgressDialog.setCancelable(false); mProgressDialog.setContentView(R.layout.dialog_progress); mProgressDialog.show(); } }); ((TextView) mProgressDialog.findViewById(R.id.progress_bar_text)).setText(messageId); } catch (Exception e) { e.printStackTrace(); } } public void dismissProgressDialog() { mFileSystemController.getActivePanel().getActivity().runOnUiThread(new Runnable() { @Override public void run() { if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); mProgressDialog = null; } } }); } private void adjustDialogSize(Dialog dialog, MainPanel panel) { adjustDialogSize(dialog, panel, 0.8f); } /** * Adjust dialog size. Actuall for old android version only (due to absence of Holo themes). * * @param dialog dialog whose size should be adjusted. * @param panel active panel * @param scaleFactor relative size scale factor (between 0 and 1) */ private void adjustDialogSize(Dialog dialog, MainPanel panel, float scaleFactor) { if (!SystemUtils.isHoneycombOrNever()) { DisplayMetrics metrics = new DisplayMetrics(); panel.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics); WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.copyFrom(dialog.getWindow().getAttributes()); params.width = (int) (metrics.widthPixels * scaleFactor); params.height = (int) (metrics.heightPixels * scaleFactor); dialog.getWindow().setAttributes(params); } } private Handler mInAppAuthHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); MainPanel panel = mFileSystemController.getActivePanel(); if (msg.what == FTP_CONNECTED) { mFileSystemController.openNetworkPanel(NetworkEnum.FTP); } else if (msg.what == SFTP_CONNECTED) { mFileSystemController.openNetworkPanel(NetworkEnum.SFTP); } else if (msg.what == SMB_CONNECTED) { mFileSystemController.openNetworkPanel(NetworkEnum.SMB); } else if (msg.what == YANDEX_DISK_CONNECTED) { mFileSystemController.openNetworkPanel(NetworkEnum.YandexDisk); } else if (msg.what == SMB_SCAN_NETWORK_REQUESTED) { final Dialog dialog = new NetworkScanDialog(panel.getActivity(), mInAppAuthHandler); dialog.show(); adjustDialogSize(dialog, panel); } else if (msg.what == SMB_SCAN_CANCELED) { startSmbAuthentication(panel); } else if (msg.what == SMB_IP_SELECTED) { startSmbAuthentication((String) msg.obj, panel); } else if (msg.what == GoogleDriveAuthWindow.MSG_HIDE_LOADING_DIALOG) { GoogleDriveApi.GoogleDriveAccount account = null; if (msg.arg1 == GoogleDriveAuthWindow.MSG_ARG_SUCCESS) { GoogleDriveApi api = App.sInstance.getGoogleDriveApi(); Pair<About, Token> data = (Pair<About, Token>) msg.obj; account = (GoogleDriveApi.GoogleDriveAccount) api.saveAccount(data.first, data.second); } else { ToastNotification.makeText(App.sInstance.getApplicationContext(), App.sInstance.getString(R.string.google_drive_get_token_error), Toast.LENGTH_LONG).show(); } dismissProgressDialog(); if (account != null) { App.sInstance.getGoogleDriveApi().setup(account); mFileSystemController.openNetworkPanel(NetworkEnum.GoogleDrive); } } else if (msg.what == GoogleDriveAuthWindow.MSG_SHOW_LOADING_DIALOG) { showProgressDialog(R.string.loading); } else if (msg.what == MEDIA_FIRE_CONNECTED) { mFileSystemController.openNetworkPanel(NetworkEnum.MediaFire); } else if (msg.what == WEBDAV_CONNECTED) { mFileSystemController.openNetworkPanel(NetworkEnum.WebDav); } } }; private void handleNetworkAuthError(Exception e) { mFileSystemController.getActivePanel().getActivity().runOnUiThread(new Runnable() { @Override public void run() { ToastNotification.makeText(App.sInstance.getApplicationContext(), App.sInstance.getString(R.string.error_unknown_unexpected_error), Toast.LENGTH_LONG).show(); } }); dismissProgressDialog(); e.printStackTrace(); } private void handleInAppAuthError(final InAppAuthException e) { mFileSystemController.getActivePanel().getActivity().runOnUiThread(new Runnable() { @Override public void run() { ToastNotification.makeText(App.sInstance.getApplicationContext(), e.getErrorMessage(), Toast.LENGTH_LONG).show(); } }); dismissProgressDialog(); } private SkyDriveAPI.OnLoginListener mOnSkyDriveLoginListener = new SkyDriveAPI.OnLoginListener() { @Override public void onGetUserInfo() { showProgressDialog(R.string.loading); } @Override public void onComplete(String driveDefaultPath) { dismissProgressDialog(); openNetworkPanel(NetworkEnum.SkyDrive, driveDefaultPath); } @Override public void onError(int errorCode) { dismissProgressDialog(); ToastNotification.makeText(App.sInstance.getApplicationContext(), App.sInstance.getString(errorCode), Toast.LENGTH_LONG).show(); } }; }