/* * Copyright (C) Winson Chiu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cw.kop.autobackground.sources; import android.accounts.AccountManager; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.preference.Preference; import android.preference.PreferenceFragment; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; import android.view.animation.Transformation; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.Switch; import android.widget.TextView; import android.widget.TimePicker; import android.widget.Toast; import com.dropbox.client2.DropboxAPI; import com.dropbox.client2.DropboxAPI.Entry; import com.dropbox.client2.android.AndroidAuthSession; import com.dropbox.client2.exception.DropboxException; import com.dropbox.client2.session.AppKeyPair; import com.google.android.gms.auth.GoogleAuthException; import com.google.android.gms.auth.GoogleAuthUtil; import com.google.android.gms.auth.UserRecoverableAuthException; import com.google.api.client.extensions.android.http.AndroidHttp; import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential; import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException; import com.google.api.client.json.gson.GsonFactory; import com.google.api.services.drive.Drive; import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.model.FileList; import com.google.api.services.drive.model.ParentReference; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import java.io.BufferedReader; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import cw.kop.autobackground.BuildConfig; import cw.kop.autobackground.CustomSwitchPreference; import cw.kop.autobackground.DialogFactory; import cw.kop.autobackground.R; import cw.kop.autobackground.accounts.GoogleAccount; import cw.kop.autobackground.files.FileHandler; import cw.kop.autobackground.images.AdapterAlbum; import cw.kop.autobackground.images.AdapterDrive; import cw.kop.autobackground.images.AdapterDropbox; import cw.kop.autobackground.images.AdapterImages; import cw.kop.autobackground.images.FolderFragment; import cw.kop.autobackground.settings.ApiKeys; import cw.kop.autobackground.settings.AppSettings; /** * Created by TheKeeperOfPie on 11/5/2014. */ public class SourceInfoFragment extends PreferenceFragment { private static final String TAG = SourceInfoFragment.class.getCanonicalName(); private static final int FADE_IN_TIME = 350; private static final int SLIDE_EXIT_TIME = 350; private static final int DRIVE_RESOLVE_REQUEST_CODE = 9005; private static final int REQUEST_DRIVE_ACCOUNT = 9005; private static final int REQUEST_DRIVE_AUTH = 9006; public static final String LAYOUT_LANDSCAPE = "layoutLandscape"; private Activity appContext; private Drawable imageDrawable; private RelativeLayout settingsContainer; private LinearLayout sortContainer; private RelativeLayout numContainer; private TextView sourceSpinnerText; private Spinner sourceSpinner; private ImageView sourceImage; private EditText sourceTitle; private EditText sourcePrefix; private EditText sourceData; private EditText sourceSuffix; private EditText sourceNumPrefix; private EditText sourceNum; private TextView sourceSortText; private Spinner sourceSortSpinner; private Switch sourceUse; private Button cancelButton; private Button saveButton; private int sourcePosition; private String oldTitle; private String type; private String hint; private String prefix; private String suffix; private int startHour; private int startMinute; private int endHour; private int endMinute; private CustomSwitchPreference timePref; private Handler handler; private View headerView; private String folderData; private DropboxAPI<AndroidAuthSession> dropboxAPI; private SourceSortSpinnerAdapter sortAdapter; private Listener listener; private Drive drive; private GoogleAccountCredential driveCredential; private boolean needsRecycle; private boolean resumed; public SourceInfoFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences_source); handler = new Handler(); AppKeyPair appKeys = new AppKeyPair(ApiKeys.DROPBOX_KEY, ApiKeys.DROPBOX_SECRET); AndroidAuthSession session = new AndroidAuthSession(appKeys); dropboxAPI = new DropboxAPI<>(session); if (AppSettings.useDropboxAccount() && !TextUtils.isEmpty(AppSettings.getDropboxAccountToken())) { dropboxAPI.getSession().setOAuth2AccessToken(AppSettings.getDropboxAccountToken()); } } @Override public void onAttach(Activity activity) { super.onAttach(activity); appContext = activity; listener = (Listener) activity; } @Override public void onDetach() { appContext = null; listener = null; super.onDetach(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { int screenHeight = container.getHeight(); int screenWidth = container.getWidth(); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); if (screenWidth < 1 || screenHeight < 1) { screenWidth = displayMetrics.widthPixels; screenHeight = displayMetrics.heightPixels; } Bundle arguments = getArguments(); sourcePosition = (Integer) arguments.get(Source.POSITION); int colorFilterInt = AppSettings.getColorFilterInt(appContext); int layout; if (screenHeight > screenWidth) { layout = R.layout.fragment_source_info_portrait; } else { layout = arguments.getInt(LAYOUT_LANDSCAPE, R.layout.fragment_source_info_portrait); } View view = inflater.inflate(layout, container, false); ListView listView = (ListView) view.findViewById(android.R.id.list); if (layout == R.layout.fragment_source_info_portrait) { headerView = inflater.inflate(R.layout.source_info_header, null, false); listView.addHeaderView(headerView); } else { headerView = view.findViewById(R.id.source_info_header); screenWidth /= 2; } sortContainer = (LinearLayout) headerView.findViewById(R.id.source_sort_container); numContainer = (RelativeLayout) headerView.findViewById(R.id.source_num_container); settingsContainer = (RelativeLayout) headerView.findViewById(R.id.source_settings_container); sourceImage = (ImageView) headerView.findViewById(R.id.source_image); sourceTitle = (EditText) headerView.findViewById(R.id.source_title); sourcePrefix = (EditText) headerView.findViewById(R.id.source_data_prefix); sourceData = (EditText) headerView.findViewById(R.id.source_data); sourceSuffix = (EditText) headerView.findViewById(R.id.source_data_suffix); sourceNumPrefix = (EditText) headerView.findViewById(R.id.source_num_prefix); sourceNum = (EditText) headerView.findViewById(R.id.source_num); sourceSortText = (TextView) headerView.findViewById(R.id.source_data_sort_text); sourceSortSpinner = (Spinner) headerView.findViewById(R.id.source_data_sort_spinner); sortAdapter = new SourceSortSpinnerAdapter(appContext, new ArrayList<SortData>()); sourceSortSpinner.setAdapter(sortAdapter); ViewGroup.LayoutParams params = sourceImage.getLayoutParams(); params.height = (int) ((headerView.getWidth() - 2f * getResources().getDimensionPixelSize(R.dimen.side_margin)) / 16f * 9); sourceImage.setLayoutParams(params); cancelButton = (Button) view.findViewById(R.id.cancel_button); saveButton = (Button) view.findViewById(R.id.save_button); sourcePrefix.setTextColor(colorFilterInt); sourceSuffix.setTextColor(colorFilterInt); cancelButton.setTextColor(colorFilterInt); saveButton.setTextColor(colorFilterInt); // Adjust alpha to get faded hint color from regular text color int hintColor = Color.argb(0x88, Color.red(colorFilterInt), Color.green(colorFilterInt), Color.blue(colorFilterInt)); sourceTitle.setHintTextColor(hintColor); sourceData.setHintTextColor(hintColor); sourceNum.setHintTextColor(hintColor); sourceData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { switch (type) { case AppSettings.FOLDER: case AppSettings.GOOGLE_PLUS_ALBUM: case AppSettings.GOOGLE_DRIVE_ALBUM: case AppSettings.DROPBOX_FOLDER: selectSource(type); break; } Log.i(TAG, "Data launched folder fragment"); } }); cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); saveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { saveSource(); } }); sourceSpinnerText = (TextView) headerView.findViewById(R.id.source_spinner_text); sourceSpinner = (Spinner) headerView.findViewById(R.id.source_spinner); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { sourceSpinner.setPopupBackgroundResource(AppSettings.getDialogColorResource()); } timePref = (CustomSwitchPreference) findPreference("source_time"); timePref.setChecked(arguments.getBoolean(Source.USE_TIME)); timePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (!(Boolean) newValue) { return true; } DialogFactory.TimeDialogListener startTimeListener = new DialogFactory.TimeDialogListener() { @Override public void onTimeSet(TimePicker view, int hour, int minute) { startHour = hour; startMinute = minute; DialogFactory.TimeDialogListener endTimeListener = new DialogFactory.TimeDialogListener() { @Override public void onTimeSet(TimePicker view, int hour, int minute) { endHour = hour; endMinute = minute; timePref.setSummary(String.format( "Time active: %02d:%02d - %02d:%02d", startHour, startMinute, endHour, endMinute)); } }; DialogFactory.showTimeDialog(appContext, "End time?", endTimeListener, startHour, startMinute); } }; DialogFactory.showTimeDialog(appContext, "Start time?", startTimeListener, startHour, startMinute); return true; } }); if (sourcePosition == -1) { sourceImage.setVisibility(View.GONE); sourceSpinnerText.setVisibility(View.VISIBLE); sourceSpinner.setVisibility(View.VISIBLE); sourceNumPrefix.setVisibility(View.GONE); type = AppSettings.WEBSITE; SourceSpinnerAdapter adapter = new SourceSpinnerAdapter(appContext, R.layout.spinner_row, Arrays.asList(getResources().getStringArray(R.array.source_menu))); sourceSpinner.setAdapter(adapter); } else { sourceImage.setVisibility(View.VISIBLE); sourceSpinnerText.setVisibility(View.GONE); sourceSpinner.setVisibility(View.GONE); sourceSortText.setVisibility(View.VISIBLE); sourceSortSpinner.setVisibility(View.VISIBLE); sourceNumPrefix.setVisibility(View.VISIBLE); type = arguments.getString(Source.TYPE); setFocusBlocks(); List<SortData> sortDataList = AppSettings.getSourceSortList(type); sortAdapter.setSortData(sortDataList); if (!sortDataList.isEmpty()) { int index = sortDataList.indexOf(new SortData(arguments.getString(Source.SORT, ""), "", "")); if (index >= 0) { sourceSortSpinner.setSelection(index); } } folderData = arguments.getString(Source.DATA); String data = folderData; if (type.equals(AppSettings.FOLDER)) { data = Arrays.toString(folderData.split(AppSettings.DATA_SPLITTER)); } sourceTitle.setText(arguments.getString(Source.TITLE)); sourceData.setText(data); sourceNum.setText(getArguments().getInt(Source.NUM, -1) >= 0 ? "" + arguments.getInt(Source.NUM) : ""); if (imageDrawable != null) { sourceImage.setImageDrawable(imageDrawable); } else if (arguments.containsKey(Source.IMAGE_FILE)) { needsRecycle = true; sourceImage.setImageBitmap(ThumbnailUtils.extractThumbnail( BitmapFactory.decodeFile(arguments.getString(Source.IMAGE_FILE)), screenWidth, (int) (screenWidth / 16f * 9f), ThumbnailUtils.OPTIONS_RECYCLE_INPUT)); } boolean showPreview = arguments.getBoolean(Source.PREVIEW); if (showPreview) { sourceImage.setVisibility(View.VISIBLE); } ((CustomSwitchPreference) findPreference("source_show_preview")).setChecked(showPreview); String[] timeArray = arguments.getString(Source.TIME).split(":|[ -]+"); try { startHour = Integer.parseInt(timeArray[0]); startMinute = Integer.parseInt(timeArray[1]); endHour = Integer.parseInt(timeArray[2]); endMinute = Integer.parseInt(timeArray[3]); timePref.setSummary(String.format("Time active: %02d:%02d - %02d:%02d", startHour, startMinute, endHour, endMinute)); } catch (NumberFormatException e) { e.printStackTrace(); startHour = 0; startMinute = 0; endHour = 0; endMinute = 0; } } sourceImage.getLayoutParams().height = (int) (screenWidth / 16 * 9); sourceImage.requestLayout(); setDataWrappers(); sourceUse = (Switch) headerView.findViewById(R.id.source_use_switch); sourceUse.setChecked(arguments.getBoolean(Source.USE)); if (AppSettings.getTheme().equals(AppSettings.APP_LIGHT_THEME)) { view.setBackgroundColor(getResources().getColor(R.color.LIGHT_THEME_BACKGROUND)); } else { view.setBackgroundColor(getResources().getColor(R.color.DARK_THEME_BACKGROUND)); } if (savedInstanceState != null) { if (arguments.getString(Source.TYPE, "").length() > 0) { sourceSpinner.setSelection(getPositionOfType(savedInstanceState.getString(Source.TYPE, AppSettings.WEBSITE))); } sourceTitle.setText(savedInstanceState.getString(Source.TITLE, "")); sourceData.setText(savedInstanceState.getString(Source.DATA, "")); sourceNum.setText(savedInstanceState.getString(Source.NUM, "")); } sourceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Log.d(TAG, "onItemSelected: " + position); if (resumed) { selectSource(getTypeFromPosition(position)); } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); return view; } private int getPositionOfType(String type) { return Arrays.asList(getResources().getStringArray(R.array.source_menu)).indexOf(type); } @Override public void onSaveInstanceState(Bundle outState) { outState.putString(Source.TYPE, type); outState.putString(Source.TITLE, String.valueOf(sourceTitle.getText())); outState.putString(Source.DATA, String.valueOf(sourceData.getText())); outState.putString(Source.NUM, String.valueOf(sourceNum.getText())); outState.putString(Source.SORT, sortAdapter.getCount() > 0 ? ((SortData) sortAdapter.getItem( sourceSortSpinner.getSelectedItemPosition())).getTitle() : ""); super.onSaveInstanceState(outState); } @Override public void onResume() { super.onResume(); resumed = true; if (dropboxAPI.getSession().authenticationSuccessful()) { try { dropboxAPI.getSession().finishAuthentication(); if (!AppSettings.useDropboxAccount()) { AppSettings.setUseDropboxAccount(true); AppSettings.setDropboxAccountToken(dropboxAPI.getSession().getOAuth2AccessToken()); showDropboxFragment(); } } catch (IllegalStateException e) { Log.i("DbAuthLog", "Error authenticating", e); } } } @Override public void onPause() { super.onPause(); } @Override public void onStart() { super.onStart(); Animation animation; if (sourcePosition == -1) { animation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { sourceSpinnerText.setAlpha(interpolatedTime); sourceSpinner.setAlpha(interpolatedTime); sourceTitle.setAlpha(interpolatedTime); settingsContainer.setAlpha(interpolatedTime); sortContainer.setAlpha(interpolatedTime); numContainer.setAlpha(interpolatedTime); sourceUse.setAlpha(interpolatedTime); } }; } else { animation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { settingsContainer.setAlpha(interpolatedTime); sortContainer.setAlpha(interpolatedTime); numContainer.setAlpha(interpolatedTime); sourceUse.setAlpha(interpolatedTime); } }; } animation.setDuration(FADE_IN_TIME); animation.setInterpolator(new DecelerateInterpolator(3.0f)); settingsContainer.startAnimation(animation); } @Override public void onStop() { if (needsRecycle && sourceImage.getDrawable() instanceof BitmapDrawable) { ((BitmapDrawable) sourceImage.getDrawable()).getBitmap().recycle(); } super.onStop(); } private void saveSource() { if (FileHandler.isDownloading()) { Toast.makeText(appContext, "Cannot add/edit source while downloading", Toast.LENGTH_SHORT).show(); return; } String title = sourceTitle.getText().toString(); String data = sourceData.getText().toString(); if (type.equals(AppSettings.FOLDER)) { data = folderData; } if (TextUtils.isEmpty(title)) { Toast.makeText(appContext, "Title cannot be empty", Toast.LENGTH_SHORT).show(); return; } if (TextUtils.isEmpty(data)) { Toast.makeText(appContext, "Data cannot be empty", Toast.LENGTH_SHORT).show(); return; } if (TextUtils.isEmpty(sourceNum.getText().toString())) { Toast.makeText(appContext, "# of images cannot be empty", Toast.LENGTH_SHORT).show(); return; } int num; try { num = Integer.parseInt(sourceNum.getText().toString()); } catch (NumberFormatException e) { num = 1; } switch (type) { case AppSettings.WEBSITE: if (!data.contains("http")) { data = "http://" + data; } break; } Source source = new Source(); source.setType(type); source.setTitle(sourceTitle.getText() .toString()); source.setData(data); source.setNum(num); source.setUse(sourceUse.isChecked()); source.setPreview( ((CustomSwitchPreference) findPreference("source_show_preview")).isChecked()); source.setUseTime(timePref.isChecked()); source.setTime(String.format("%02d:%02d - %02d:%02d", startHour, startMinute, endHour, endMinute)); source.setSort(sourceSortSpinner.getCount() > 0 ? ((SortData) sourceSortSpinner.getSelectedItem()).getTitle() : ""); Log.d(TAG, "Sort set to " + source.getSort()); if (sourcePosition == -1) { if (!listener.addSource(source)) { listener.sendToast("Error: Title in use.\nPlease use a different title."); return; } } else { if (listener.saveSource(source, sourcePosition)) { if (!getArguments().getString(Source.TITLE).equals(title)) { FileHandler.renameFolder(getArguments().getString(Source.TITLE), title); } } else { listener.sendToast("Error: Title in use.\nPlease use a different title."); return; } } try { InputMethodManager im = (InputMethodManager) appContext.getSystemService(Context.INPUT_METHOD_SERVICE); im.hideSoftInputFromWindow(getView().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } catch (Exception e) { e.printStackTrace(); } final int screenHeight = getResources().getDisplayMetrics().heightPixels; final View fragmentView = getView(); if (fragmentView != null) { final float viewStartY = getView().getY(); Animation animation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { fragmentView.setY((screenHeight - viewStartY) * interpolatedTime + viewStartY); } @Override public boolean willChangeBounds() { return true; } }; animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { getFragmentManager().popBackStack(); } @Override public void onAnimationRepeat(Animation animation) { } }); animation.setDuration(SLIDE_EXIT_TIME); getView().startAnimation(animation); } } public void setImageDrawable(Drawable drawable) { imageDrawable = drawable; if (sourceImage != null) { sourceImage.setImageDrawable(imageDrawable); } } public void setData(String type, final String title, final String data, final int num) { this.type = type; this.folderData = data; handler.post(new Runnable() { @Override public void run() { sourceTitle.setText(title); sourceData.setText(SourceInfoFragment.this.type.equals(AppSettings.FOLDER) ? Arrays.toString(folderData.split(AppSettings.DATA_SPLITTER)) : data); sourceNum.setText(num >= 0 ? "" + num : ""); setDataWrappers(); } }); } private void setDataWrappers() { prefix = AppSettings.getSourceDataPrefix(type); hint = AppSettings.getSourceDataHint(type); suffix = AppSettings.getSourceDataSuffix(type); List<SortData> sortDataList = AppSettings.getSourceSortList(type); sortAdapter.setSortData(sortDataList); if (sortDataList.isEmpty()) { sourceSortText.setVisibility(View.GONE); sourceSortSpinner.setVisibility(View.GONE); } else { sourceSortText.setVisibility(View.VISIBLE); sourceSortSpinner.setVisibility(View.VISIBLE); } sourcePrefix.setText(prefix); sourceSuffix.setText(suffix); if (prefix.length() > 0) { sourcePrefix.setVisibility(View.VISIBLE); } else { sourcePrefix.setVisibility(View.GONE); } if (suffix.length() > 0) { sourceSuffix.setVisibility(View.VISIBLE); } else { sourceSuffix.setVisibility(View.GONE); } sourceData.setHint(hint); } private String getTypeFromPosition(int position) { return getResources().getStringArray(R.array.source_menu)[position]; } private void selectSource(String newType) { if (!type.equals(newType) && (type.equals(AppSettings.FOLDER) || type.equals(AppSettings.GOOGLE_PLUS_ALBUM) || type.equals(AppSettings.GOOGLE_DRIVE_ALBUM) || type.equals(AppSettings.DROPBOX_FOLDER))) { sourceTitle.setText(""); sourceData.setText(""); sourceNum.setText(""); } type = newType; switch (type) { case AppSettings.WEBSITE: break; case AppSettings.FOLDER: File externalStorageDirectory = Environment.getExternalStorageDirectory(); if (getFragmentManager().findFragmentByTag("folder_fragment") == null) { if (externalStorageDirectory.exists() && externalStorageDirectory.canRead()) { showImageFragment(new File(File.separator), externalStorageDirectory); } else { showImageFragment(new File(File.separator), new File(File.separator)); } } break; case AppSettings.IMGUR_SUBREDDIT: break; case AppSettings.IMGUR_ALBUM: break; case AppSettings.GOOGLE_PLUS_ALBUM: if (TextUtils.isEmpty(AppSettings.getGoogleAccountName())) { startActivityForResult(GoogleAccount.getPickerIntent(), GoogleAccount.GOOGLE_ACCOUNT_SIGN_IN); } else if (getFragmentManager().findFragmentByTag("folder_fragment") == null) { new PicasaAlbumTask().execute(); } break; case AppSettings.GOOGLE_DRIVE_ALBUM: if (drive == null) { driveCredential = GoogleAccountCredential.usingOAuth2( appContext, Collections.singleton(DriveScopes.DRIVE)); drive = new Drive.Builder(AndroidHttp.newCompatibleTransport(), GsonFactory.getDefaultInstance(), driveCredential) .setApplicationName(appContext.getResources() .getString(R.string.app_name) + "/" + BuildConfig.VERSION_NAME) .build(); } if (TextUtils.isEmpty(AppSettings.getDriveAccountName())) { startActivityForResult(driveCredential.newChooseAccountIntent(), REQUEST_DRIVE_ACCOUNT); } else { driveCredential.setSelectedAccountName(AppSettings.getDriveAccountName()); new Thread(new Runnable() { @Override public void run() { try { drive.about() .get() .execute(); handler.post(new Runnable() { @Override public void run() { showDriveFragment(); } }); } catch (UserRecoverableAuthIOException e) { startActivityForResult(e.getIntent(), REQUEST_DRIVE_AUTH); } catch (IOException e) { e.printStackTrace(); } } }).start(); } break; case AppSettings.TUMBLR_BLOG: break; case AppSettings.TUMBLR_TAG: break; case AppSettings.REDDIT_SUBREDDIT: break; case AppSettings.DROPBOX_FOLDER: if (!AppSettings.useDropboxAccount() || TextUtils.isEmpty(AppSettings.getDropboxAccountToken()) || !dropboxAPI.getSession().isLinked()) { AppSettings.setUseDropboxAccount(false); AppSettings.setDropboxAccountToken(""); dropboxAPI.getSession().startOAuth2Authentication(appContext); } else if (getFragmentManager().findFragmentByTag("folder_fragment") == null) { showDropboxFragment(); } break; default: } setFocusBlocks(); setDataWrappers(); } private void setFocusBlocks() { boolean focusData = true; boolean focusNum = true; switch (type) { case AppSettings.FOLDER: focusNum = false; case AppSettings.GOOGLE_DRIVE_ALBUM: case AppSettings.DROPBOX_FOLDER: focusData = false; break; } sourceData.setFocusableInTouchMode(focusData); sourceNum.setFocusableInTouchMode(focusNum); } @Override public void onActivityResult(int requestCode, int responseCode, Intent intent) { if (requestCode == REQUEST_DRIVE_AUTH && responseCode == Activity.RESULT_OK) { String accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME); if (!TextUtils.isEmpty(accountName)) { AppSettings.setDriveAccountName(accountName); AppSettings.setUseGoogleDriveAccount(true); driveCredential.setSelectedAccountName(accountName); new Thread(new Runnable() { @Override public void run() { try { // Send an about request to check if app is authenticated drive.about().get().execute(); handler.post(new Runnable() { @Override public void run() { showDriveFragment(); } }); } catch (UserRecoverableAuthIOException e) { startActivityForResult(e.getIntent(), REQUEST_DRIVE_AUTH); } catch (IOException e) { e.printStackTrace(); } } }).start(); } } else if (requestCode == REQUEST_DRIVE_ACCOUNT && responseCode == Activity.RESULT_OK) { String accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME); if (!TextUtils.isEmpty(accountName)) { AppSettings.setDriveAccountName(accountName); AppSettings.setUseGoogleDriveAccount(true); driveCredential.setSelectedAccountName(accountName); new Thread(new Runnable() { @Override public void run() { try { // Send an about request to check if app is authenticated drive.about().get().execute(); handler.post(new Runnable() { @Override public void run() { showDriveFragment(); } }); } catch (UserRecoverableAuthIOException e) { startActivityForResult(e.getIntent(), REQUEST_DRIVE_AUTH); } catch (IOException e) { e.printStackTrace(); } } }).start(); } } if (requestCode == GoogleAccount.GOOGLE_ACCOUNT_SIGN_IN) { if (intent != null && responseCode == Activity.RESULT_OK) { final String accountName = intent.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); AppSettings.setGoogleAccountName(accountName); new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { String authToken = GoogleAuthUtil.getToken(appContext, accountName, "oauth2:https://picasaweb.google.com/data/"); AppSettings.setGoogleAccountToken(authToken); AppSettings.setUseGoogleAccount(true); new PicasaAlbumTask().execute(); } catch (IOException transientEx) { return null; } catch (UserRecoverableAuthException e) { e.printStackTrace(); if (isAdded()) { startActivityForResult(e.getIntent(), GoogleAccount.GOOGLE_AUTH_CODE); } return null; } catch (GoogleAuthException authEx) { return null; } catch (Exception e) { throw new RuntimeException(e); } return null; } }.execute(); } } if (requestCode == GoogleAccount.GOOGLE_AUTH_CODE) { if (responseCode == Activity.RESULT_OK) { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { String authToken = GoogleAuthUtil.getToken(appContext, AppSettings.getGoogleAccountName(), "oauth2:https://picasaweb.google.com/data/"); AppSettings.setGoogleAccountToken(authToken); AppSettings.setUseGoogleAccount(true); new PicasaAlbumTask().execute(); } catch (IOException transientEx) { return null; } catch (UserRecoverableAuthException e) { return null; } catch (GoogleAuthException authEx) { return null; } catch (Exception e) { throw new RuntimeException(e); } return null; } }.execute(); } } } private void showImageFragment(File topDir, File startDir) { final FolderFragment folderFragment = new FolderFragment(); Bundle arguments = new Bundle(); arguments.putBoolean(FolderFragment.SHOW_DIRECTORY_TEXT, true); arguments.putBoolean(FolderFragment.USE_DIRECTORY, true); final AdapterImages adapter = new AdapterImages(appContext, topDir, startDir, folderFragment); folderFragment.setArguments(arguments); folderFragment.setAdapter(adapter); folderFragment.setStartingDirectoryText(startDir.getAbsolutePath()); folderFragment.setListener(new FolderFragment.FolderEventListener() { private Activity dialogActivity; @Override public void onUseDirectoryClick() { DialogFactory.ActionDialogListener listener = new DialogFactory.ActionDialogListener() { @Override public void onClickMiddle(View v) { setAppDirectory(false); this.dismissDialog(); } @Override public void onClickRight(View v) { setAppDirectory(true); this.dismissDialog(); } }; DialogFactory.showActionDialog(dialogActivity, "", "Include subdirectories?", listener, R.string.cancel_button, R.string.no_button, R.string.yes_button); } @Override public void onItemClick(int positionInList) { File selectedFile = adapter.getItem(positionInList); if (selectedFile.exists() && selectedFile.isDirectory()) { adapter.setDirectory(selectedFile); folderFragment.setDirectoryText(adapter.getDirectory() .getAbsolutePath()); } } private void setAppDirectory(boolean useSubdirectories) { final File dir = adapter.getDirectory(); final FilenameFilter filenameFilter = FileHandler.getImageFileNameFilter(); final StringBuilder stringBuilder = new StringBuilder(); if (useSubdirectories) { Toast.makeText(dialogActivity, "Loading subdirectories...", Toast.LENGTH_SHORT) .show(); new Thread(new Runnable() { @Override public void run() { int numImages = 0; ArrayList<File> folderNames = getAllDirectories(dir); for (File folderName : folderNames) { stringBuilder.append(folderName.getAbsolutePath()); stringBuilder.append(AppSettings.DATA_SPLITTER); numImages += folderName.list(filenameFilter).length; } if (isAdded()) { SourceInfoFragment sourceInfoFragment = (SourceInfoFragment) dialogActivity.getFragmentManager().findFragmentByTag("sourceInfoFragment"); if (sourceInfoFragment != null) { sourceInfoFragment.setData(AppSettings.FOLDER, dir.getName(), stringBuilder.toString(), numImages); } dialogActivity = null; } } }).start(); adapter.setFinished(); dialogActivity.onBackPressed(); } else { SourceInfoFragment sourceInfoFragment = (SourceInfoFragment) dialogActivity.getFragmentManager().findFragmentByTag("sourceInfoFragment"); if (sourceInfoFragment != null) { sourceInfoFragment.setData(AppSettings.FOLDER, dir.getName(), dir.getAbsolutePath(), dir.listFiles(filenameFilter) != null ? dir.listFiles(filenameFilter).length : 0); } adapter.setFinished(); dialogActivity.onBackPressed(); dialogActivity = null; } } private ArrayList<File> getAllDirectories(File dir) { ArrayList<File> directoryList = new ArrayList<>(); File[] fileList = dir.listFiles(); if (fileList != null) { directoryList.add(dir); for (File folder : fileList) { if (folder.isDirectory()) { directoryList.addAll(getAllDirectories(folder)); } } } return directoryList; } @Override public boolean onBackPressed() { boolean endDirectory = adapter.backDirectory(); folderFragment.setDirectoryText(adapter.getDirectory() .getAbsolutePath()); return endDirectory; } @Override public void setActivity(Activity activity) { this.dialogActivity = activity; } }); getFragmentManager().beginTransaction() .setCustomAnimations(R.animator.none, R.animator.slide_to_bottom, R.animator.none, R.animator.slide_to_bottom) .add(R.id.content_frame, folderFragment, "folder_fragment") .addToBackStack(null) .commit(); } private void showAlbumFragment(final String type, final ArrayList<String> names, ArrayList<String> images, final ArrayList<String> links, final ArrayList<String> nums) { FolderFragment folderFragment = new FolderFragment(); Bundle arguments = new Bundle(); arguments.putBoolean(FolderFragment.USE_DIRECTORY, false); arguments.putBoolean(FolderFragment.SHOW_DIRECTORY_TEXT, false); final AdapterAlbum adapter = new AdapterAlbum(appContext, names, images, links, folderFragment); folderFragment.setArguments(arguments); folderFragment.setAdapter(adapter); folderFragment.setListener(new FolderFragment.FolderEventListener() { public Activity dialogActivity; @Override public void onUseDirectoryClick() { // Not implemented } @Override public void onItemClick(int positionInList) { SourceInfoFragment sourceInfoFragment = (SourceInfoFragment) dialogActivity.getFragmentManager().findFragmentByTag("sourceInfoFragment"); if (sourceInfoFragment != null) { sourceInfoFragment.setData(type, names.get(positionInList), links.get(positionInList), Integer.parseInt(nums.get(positionInList))); } dialogActivity.onBackPressed(); dialogActivity = null; } @Override public boolean onBackPressed() { return true; } @Override public void setActivity(Activity activity) { this.dialogActivity = activity; } }); getFragmentManager().beginTransaction() .setCustomAnimations(R.animator.none, R.animator.slide_to_bottom, R.animator.none, R.animator.slide_to_bottom) .add(R.id.content_frame, folderFragment, "folder_fragment") .addToBackStack(null) .commit(); } private void showDriveFragment() { if (!type.equals(AppSettings.GOOGLE_DRIVE_ALBUM)) { return; } final FolderFragment folderFragment = new FolderFragment(); Bundle arguments = new Bundle(); arguments.putBoolean(FolderFragment.SHOW_DIRECTORY_TEXT, true); arguments.putBoolean(FolderFragment.USE_DIRECTORY, true); final AdapterDrive adapter = new AdapterDrive(appContext, folderFragment); folderFragment.setArguments(arguments); folderFragment.setListener(new FolderFragment.FolderEventListener() { public Activity dialogActivity; @Override public void onUseDirectoryClick() { com.google.api.services.drive.model.File file = adapter.getMainDir(); SourceInfoFragment sourceInfoFragment = (SourceInfoFragment) dialogActivity.getFragmentManager().findFragmentByTag("sourceInfoFragment"); if (sourceInfoFragment != null) { sourceInfoFragment.setData(AppSettings.GOOGLE_DRIVE_ALBUM, file.getTitle(), file.getId(), -1); } adapter.setFinished(true); dialogActivity.onBackPressed(); dialogActivity = null; } @Override public void onItemClick(int positionInList) { final com.google.api.services.drive.model.File file = adapter.getItem(positionInList); if (!file.getMimeType().equals("application/vnd.google-apps.folder")) { return; } new Thread(new Runnable() { @Override public void run() { try { Drive.Files.List request = drive.files().list(); final FileList files = request.setQ( "'" + file.getId() + "' in parents and trashed=false").execute(); final List<com.google.api.services.drive.model.File> fileList = files.getItems(); handler.post(new Runnable() { @Override public void run() { adapter.setDir(file, fileList); } }); } catch (IOException e) { e.printStackTrace(); } } }).start(); } @Override public boolean onBackPressed() { if (adapter.backDirectory()) { return true; } new Thread(new Runnable() { @Override public void run() { com.google.api.services.drive.model.File file = adapter.getMainDir(); try { ParentReference parentReference = drive.parents().list(file.getId()).execute().getItems().get(0); final com.google.api.services.drive.model.File parentFile = drive.files() .get(parentReference.getId()) .execute(); Drive.Files.List request = drive.files().list(); FileList files = request.setQ( "'" + parentReference.getId() + "' in parents and trashed=false").execute(); final List<com.google.api.services.drive.model.File> fileList = files.getItems(); handler.post(new Runnable() { @Override public void run() { adapter.setDir(parentFile, fileList); } }); } catch (IOException e) { e.printStackTrace(); } } }).start(); return false; } @Override public void setActivity(Activity activity) { this.dialogActivity = activity; } }); Toast.makeText(appContext, "Loading Google Drive", Toast.LENGTH_SHORT).show(); new Thread(new Runnable() { @Override public void run() { try { com.google.api.services.drive.model.File file = drive.files().get("root").execute(); Drive.Files.List request = drive.files().list(); FileList files = request.setQ("'root' in parents and trashed=false").execute(); adapter.setDirs(file, file, files.getItems()); folderFragment.setAdapter(adapter); folderFragment.setStartingDirectoryText(file.getTitle()); getFragmentManager().beginTransaction() .setCustomAnimations(R.animator.none, R.animator.slide_to_bottom, R.animator.none, R.animator.slide_to_bottom) .add(R.id.content_frame, folderFragment, "folder_fragment") .addToBackStack(null) .commit(); Log.d(TAG, "folderFragment committed"); } catch (IOException e) { e.printStackTrace(); } } }).start(); } private void showDropboxFragment() { if (!type.equals(AppSettings.DROPBOX_FOLDER)) { return; } final FolderFragment folderFragment = new FolderFragment(); Bundle arguments = new Bundle(); arguments.putBoolean(FolderFragment.SHOW_DIRECTORY_TEXT, true); arguments.putBoolean(FolderFragment.USE_DIRECTORY, true); final AdapterDropbox adapter = new AdapterDropbox(appContext, folderFragment); folderFragment.setArguments(arguments); folderFragment.setListener(new FolderFragment.FolderEventListener() { public Activity dialogActivity; @Override public void onUseDirectoryClick() { Entry entry = adapter.getMainDir(); if (entry.isDir) { SourceInfoFragment sourceInfoFragment = (SourceInfoFragment) dialogActivity.getFragmentManager().findFragmentByTag("sourceInfoFragment"); if (sourceInfoFragment != null) { sourceInfoFragment.setData(AppSettings.DROPBOX_FOLDER, entry.fileName(), entry.path, -1); } adapter.setFinished(true); dialogActivity.onBackPressed(); dialogActivity = null; } } @Override public void onItemClick(int positionInList) { final Entry entry = adapter.getItem(positionInList); if (!entry.isDir) { return; } new Thread(new Runnable() { @Override public void run() { final Entry newEntry; try { newEntry = dropboxAPI.metadata(entry.path, 0, null, true, null); if (newEntry != null) { handler.post(new Runnable() { @Override public void run() { adapter.setDir(newEntry); folderFragment.setDirectoryText(newEntry.path); } }); } } catch (DropboxException e) { e.printStackTrace(); } } }).start(); } @Override public boolean onBackPressed() { if (adapter.backDirectory()) { return true; } new Thread(new Runnable() { @Override public void run() { final Entry parentDir; try { parentDir = dropboxAPI.metadata(adapter.getMainDir().parentPath(), 0, null, true, null); if (parentDir != null) { handler.post(new Runnable() { @Override public void run() { adapter.setDir(parentDir); folderFragment.setDirectoryText(parentDir.path); } }); } } catch (DropboxException e) { e.printStackTrace(); } } }).start(); return false; } @Override public void setActivity(Activity activity) { this.dialogActivity = activity; } }); Toast.makeText(appContext, "Loading Dropbox", Toast.LENGTH_SHORT).show(); new Thread(new Runnable() { @Override public void run() { Entry startEntry; try { startEntry = dropboxAPI.metadata("/", 0, null, true, null); } catch (DropboxException e) { e.printStackTrace(); handler.post(new Runnable() { @Override public void run() { Toast.makeText(appContext, "Error loading Dropbox", Toast.LENGTH_LONG).show(); } }); return; } adapter.setDirs(startEntry, startEntry); folderFragment.setAdapter(adapter); folderFragment.setStartingDirectoryText(startEntry.path); getFragmentManager().beginTransaction() .setCustomAnimations(R.animator.none, R.animator.slide_to_bottom, R.animator.none, R.animator.slide_to_bottom) .add(R.id.content_frame, folderFragment, "folder_fragment") .addToBackStack(null) .commit(); } }).start(); } public void onBackPressed() { final int screenHeight = getResources().getDisplayMetrics().heightPixels; final View fragmentView = getView(); if (fragmentView != null) { final float viewStartY = getView().getY(); Animation animation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { fragmentView.setY((screenHeight - viewStartY) * interpolatedTime + viewStartY); } @Override public boolean willChangeBounds() { return true; } }; animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { getFragmentManager().popBackStack(); } @Override public void onAnimationRepeat(Animation animation) { } }); animation.setDuration(SLIDE_EXIT_TIME); getView().startAnimation(animation); } else { getFragmentManager().popBackStack(); } } class PicasaAlbumTask extends AsyncTask<Void, String, Void> { ArrayList<String> albumNames = new ArrayList<>(); ArrayList<String> albumImageLinks = new ArrayList<>(); ArrayList<String> albumLinks = new ArrayList<>(); ArrayList<String> albumNums = new ArrayList<>(); @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); Toast.makeText(appContext, values[0], Toast.LENGTH_SHORT).show(); } @Override protected Void doInBackground(Void... params) { InputStream inputStream = null; BufferedReader reader = null; String result = null; try { publishProgress("Loading albums..."); String authToken = null; authToken = GoogleAuthUtil.getToken(appContext, AppSettings.getGoogleAccountName(), "oauth2:https://picasaweb.google.com/data/"); AppSettings.setGoogleAccountToken(authToken); HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("https://picasaweb.google.com/data/feed/api/user/" + AppSettings.getGoogleAccountName()); httpGet.setHeader("Authorization", "OAuth " + authToken); httpGet.setHeader("X-GData-Client", ApiKeys.PICASA_CLIENT_ID); httpGet.setHeader("GData-Version", "2"); inputStream = httpClient.execute(httpGet).getEntity().getContent(); reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8); StringBuilder stringBuilder = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { stringBuilder.append(line + "\n"); } result = stringBuilder.toString(); } catch (Exception e) { publishProgress("Error loading albums"); } finally { try { if (inputStream != null) { inputStream.close(); } if (reader != null) { reader.close(); } } catch (IOException e) { e.printStackTrace(); } } Document albumDoc = Jsoup.parse(result); for (Element link : albumDoc.select("entry")) { albumNames.add(link.select("title").text()); albumImageLinks.add(link.select("media|group").select("media|content").attr("url")); albumLinks.add(link.select("id").text().replace("entry", "feed")); albumNums.add(link.select("gphoto|numphotos").text()); } return null; } @Override protected void onPostExecute(Void aVoid) { if (isAdded()) { showAlbumFragment(AppSettings.GOOGLE_PLUS_ALBUM, albumNames, albumImageLinks, albumLinks, albumNums); } } } public interface Listener { boolean addSource(Source source); boolean saveSource(Source source, int position); void sendToast(String message); } }