Preferences.java 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. /**
  2. * ownCloud Android client application
  3. *
  4. * @author Bartek Przybylski
  5. * @author David A. Velasco
  6. * Copyright (C) 2011 Bartek Przybylski
  7. * Copyright (C) 2016 ownCloud Inc.
  8. * Copyright (C) 2016 Nextcloud
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2,
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. */
  23. package com.owncloud.android.ui.activity;
  24. import android.accounts.Account;
  25. import android.accounts.AuthenticatorException;
  26. import android.accounts.OperationCanceledException;
  27. import android.content.Intent;
  28. import android.content.SharedPreferences;
  29. import android.content.pm.PackageInfo;
  30. import android.content.pm.PackageManager.NameNotFoundException;
  31. import android.content.res.Configuration;
  32. import android.graphics.drawable.ColorDrawable;
  33. import android.graphics.drawable.Drawable;
  34. import android.net.Uri;
  35. import android.os.Build;
  36. import android.os.Bundle;
  37. import android.os.Environment;
  38. import android.preference.CheckBoxPreference;
  39. import android.preference.ListPreference;
  40. import android.preference.Preference;
  41. import android.preference.Preference.OnPreferenceChangeListener;
  42. import android.preference.Preference.OnPreferenceClickListener;
  43. import android.preference.PreferenceActivity;
  44. import android.preference.PreferenceCategory;
  45. import android.preference.PreferenceManager;
  46. import android.preference.PreferenceScreen;
  47. import android.preference.SwitchPreference;
  48. import android.support.annotation.LayoutRes;
  49. import android.support.annotation.Nullable;
  50. import android.support.v7.app.ActionBar;
  51. import android.support.v7.app.AppCompatDelegate;
  52. import android.support.v7.widget.Toolbar;
  53. import android.view.Menu;
  54. import android.view.MenuInflater;
  55. import android.view.MenuItem;
  56. import android.view.View;
  57. import android.view.ViewGroup;
  58. import android.widget.Toast;
  59. import com.owncloud.android.BuildConfig;
  60. import com.owncloud.android.MainApp;
  61. import com.owncloud.android.R;
  62. import com.owncloud.android.authentication.AccountUtils;
  63. import com.owncloud.android.datamodel.ArbitraryDataProvider;
  64. import com.owncloud.android.datamodel.ExternalLinksProvider;
  65. import com.owncloud.android.datamodel.OCFile;
  66. import com.owncloud.android.datastorage.DataStorageProvider;
  67. import com.owncloud.android.datastorage.StoragePoint;
  68. import com.owncloud.android.lib.common.ExternalLink;
  69. import com.owncloud.android.lib.common.ExternalLinkType;
  70. import com.owncloud.android.lib.common.OwnCloudAccount;
  71. import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
  72. import com.owncloud.android.lib.common.utils.Log_OC;
  73. import com.owncloud.android.utils.AnalyticsUtils;
  74. import com.owncloud.android.utils.DisplayUtils;
  75. import java.io.IOException;
  76. /**
  77. * An Activity that allows the user to change the application's settings.
  78. *
  79. * It proxies the necessary calls via {@link android.support.v7.app.AppCompatDelegate} to be used with AppCompat.
  80. */
  81. public class Preferences extends PreferenceActivity
  82. implements StorageMigration.StorageMigrationProgressListener {
  83. private static final String TAG = Preferences.class.getSimpleName();
  84. private static final String SCREEN_NAME = "Settings";
  85. private static final int ACTION_SELECT_UPLOAD_PATH = 1;
  86. private static final int ACTION_SELECT_UPLOAD_VIDEO_PATH = 2;
  87. private static final int ACTION_REQUEST_PASSCODE = 5;
  88. private static final int ACTION_CONFIRM_PASSCODE = 6;
  89. private static final int ACTION_REQUEST_CODE_DAVDROID_SETUP = 10;
  90. public static final String SYNCED_FOLDER_LIGHT_UPLOAD_ON_WIFI = "SYNCED_FOLDER_LIGHT_UPLOAD_ON_WIFI";
  91. /**
  92. * The user's server base uri.
  93. */
  94. private Uri mUri;
  95. private SwitchPreference pCode;
  96. private SwitchPreference fPrint;
  97. private SwitchPreference mShowHiddenFiles;
  98. private Preference pAboutApp;
  99. private AppCompatDelegate mDelegate;
  100. private String mUploadPath;
  101. private PreferenceCategory mPrefInstantUploadCategory;
  102. private Preference mPrefInstantUpload;
  103. private Preference mPrefInstantUploadBehaviour;
  104. private Preference mPrefInstantUploadPath;
  105. private Preference mPrefInstantUploadUseSubfolders;
  106. private Preference mPrefInstantPictureUploadOnlyOnCharging;
  107. private Preference mPrefInstantUploadPathWiFi;
  108. private Preference mPrefInstantVideoUpload;
  109. private Preference mPrefInstantVideoUploadPath;
  110. private Preference mPrefInstantVideoUploadUseSubfolders;
  111. private Preference mPrefInstantVideoUploadPathWiFi;
  112. private Preference mPrefInstantVideoUploadOnlyOnCharging;
  113. private String mUploadVideoPath;
  114. private ListPreference mPrefStoragePath;
  115. private String mStoragePath;
  116. public static class PreferenceKeys {
  117. public static final String STORAGE_PATH = "storage_path";
  118. public static final String INSTANT_UPLOAD_PATH = "instant_upload_path";
  119. public static final String INSTANT_VIDEO_UPLOAD_PATH = "instant_video_upload_path";
  120. }
  121. @SuppressWarnings("deprecation")
  122. @Override
  123. public void onCreate(Bundle savedInstanceState) {
  124. if (DisplayUtils.themingEnabled()) {
  125. setTheme(R.style.FallbackThemingTheme);
  126. }
  127. getDelegate().installViewFactory();
  128. getDelegate().onCreate(savedInstanceState);
  129. super.onCreate(savedInstanceState);
  130. addPreferencesFromResource(R.xml.preferences);
  131. ActionBar actionBar = getSupportActionBar();
  132. actionBar.setDisplayHomeAsUpEnabled(true);
  133. DisplayUtils.setColoredTitle(actionBar, getString(R.string.actionbar_settings));
  134. actionBar.setBackgroundDrawable(new ColorDrawable(DisplayUtils.primaryColor()));
  135. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  136. getWindow().setStatusBarColor(DisplayUtils.primaryDarkColor());
  137. }
  138. Drawable backArrow = getResources().getDrawable(R.drawable.ic_arrow_back);
  139. actionBar.setHomeAsUpIndicator(DisplayUtils.tintDrawable(backArrow, DisplayUtils.fontColor()));
  140. int accentColor = DisplayUtils.primaryAccentColor();
  141. // retrieve user's base uri
  142. setupBaseUri();
  143. // For adding content description tag to a title field in the action bar
  144. int actionBarTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
  145. View actionBarTitleView = getWindow().getDecorView().findViewById(actionBarTitleId);
  146. if (actionBarTitleView != null) { // it's null in Android 2.x
  147. getWindow().getDecorView().findViewById(actionBarTitleId).
  148. setContentDescription(getString(R.string.actionbar_settings));
  149. }
  150. // Load package info
  151. String temp;
  152. try {
  153. PackageInfo pkg = getPackageManager().getPackageInfo(getPackageName(), 0);
  154. temp = pkg.versionName;
  155. } catch (NameNotFoundException e) {
  156. temp = "";
  157. Log_OC.e(TAG, "Error while showing about dialog", e);
  158. }
  159. final String appVersion = temp;
  160. // Register context menu for list of preferences.
  161. registerForContextMenu(getListView());
  162. // General
  163. PreferenceCategory preferenceCategoryGeneral = (PreferenceCategory) findPreference("general");
  164. preferenceCategoryGeneral.setTitle(DisplayUtils.getColoredTitle(getString(R.string.prefs_category_general),
  165. accentColor));
  166. // Synced folders
  167. PreferenceCategory preferenceCategoryFolderSync = (PreferenceCategory) findPreference("folder_sync");
  168. preferenceCategoryFolderSync.setTitle(DisplayUtils.getColoredTitle(getString(R.string.drawer_folder_sync),
  169. accentColor));
  170. PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference("preference_screen");
  171. if (!getResources().getBoolean(R.bool.syncedFolder_light)) {
  172. preferenceScreen.removePreference(preferenceCategoryFolderSync);
  173. } else {
  174. // Upload on WiFi
  175. final ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(getContentResolver());
  176. final Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
  177. final SwitchPreference pUploadOnWifiCheckbox = (SwitchPreference) findPreference("synced_folder_on_wifi");
  178. pUploadOnWifiCheckbox.setChecked(
  179. arbitraryDataProvider.getBooleanValue(account, SYNCED_FOLDER_LIGHT_UPLOAD_ON_WIFI));
  180. pUploadOnWifiCheckbox.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  181. @Override
  182. public boolean onPreferenceClick(Preference preference) {
  183. arbitraryDataProvider.storeOrUpdateKeyValue(account, SYNCED_FOLDER_LIGHT_UPLOAD_ON_WIFI,
  184. String.valueOf(pUploadOnWifiCheckbox.isChecked()));
  185. return true;
  186. }
  187. });
  188. Preference pSyncedFolder = findPreference("folder_sync_folders");
  189. if (pSyncedFolder != null) {
  190. if (getResources().getBoolean(R.bool.syncedFolder_light)
  191. && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  192. pSyncedFolder.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  193. @Override
  194. public boolean onPreferenceClick(Preference preference) {
  195. Intent folderSyncIntent = new Intent(getApplicationContext(), FolderSyncActivity.class);
  196. folderSyncIntent.putExtra(FolderSyncActivity.EXTRA_SHOW_SIDEBAR, false);
  197. startActivity(folderSyncIntent);
  198. return true;
  199. }
  200. });
  201. } else {
  202. preferenceCategoryFolderSync.removePreference(pSyncedFolder);
  203. }
  204. }
  205. }
  206. PreferenceCategory preferenceCategoryDetails = (PreferenceCategory) findPreference("details");
  207. preferenceCategoryDetails.setTitle(DisplayUtils.getColoredTitle(getString(R.string.prefs_category_details),
  208. accentColor));
  209. boolean fPassCodeEnabled = getResources().getBoolean(R.bool.passcode_enabled);
  210. pCode = (SwitchPreference) findPreference(PassCodeActivity.PREFERENCE_SET_PASSCODE);
  211. if (pCode != null && fPassCodeEnabled) {
  212. pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
  213. @Override
  214. public boolean onPreferenceChange(Preference preference, Object newValue) {
  215. Intent i = new Intent(getApplicationContext(), PassCodeActivity.class);
  216. Boolean incoming = (Boolean) newValue;
  217. i.setAction(
  218. incoming ? PassCodeActivity.ACTION_REQUEST_WITH_RESULT :
  219. PassCodeActivity.ACTION_CHECK_WITH_RESULT
  220. );
  221. startActivityForResult(i, incoming ? ACTION_REQUEST_PASSCODE :
  222. ACTION_CONFIRM_PASSCODE);
  223. // Don't update just yet, we will decide on it in onActivityResult
  224. return false;
  225. }
  226. });
  227. } else {
  228. preferenceCategoryDetails.removePreference(pCode);
  229. }
  230. boolean fPrintEnabled = getResources().getBoolean(R.bool.fingerprint_enabled);
  231. fPrint = (SwitchPreference) findPreference(FingerprintActivity.PREFERENCE_USE_FINGERPRINT);
  232. if (fPrint != null) {
  233. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  234. if (FingerprintActivity.isFingerprintCapable(MainApp.getAppContext()) && fPrintEnabled) {
  235. fPrint.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
  236. @Override
  237. public boolean onPreferenceChange(Preference preference, Object newValue) {
  238. Boolean incoming = (Boolean) newValue;
  239. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  240. if (FingerprintActivity.isFingerprintReady(MainApp.getAppContext())) {
  241. SharedPreferences appPrefs =
  242. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  243. SharedPreferences.Editor editor = appPrefs.edit();
  244. editor.putBoolean("use_fingerprint", incoming);
  245. editor.apply();
  246. return true;
  247. } else {
  248. if (incoming) {
  249. Toast.makeText(
  250. MainApp.getAppContext(),
  251. R.string.prefs_fingerprint_notsetup,
  252. Toast.LENGTH_LONG)
  253. .show();
  254. fPrint.setChecked(false);
  255. }
  256. SharedPreferences appPrefs =
  257. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  258. SharedPreferences.Editor editor = appPrefs.edit();
  259. editor.putBoolean("use_fingerprint", false);
  260. editor.apply();
  261. return false;
  262. }
  263. } else {
  264. return false;
  265. }
  266. }
  267. });
  268. if (!FingerprintActivity.isFingerprintReady(MainApp.getAppContext())) {
  269. fPrint.setChecked(false);
  270. }
  271. } else {
  272. preferenceCategoryDetails.removePreference(fPrint);
  273. }
  274. } else {
  275. preferenceCategoryDetails.removePreference(fPrint);
  276. }
  277. }
  278. boolean fShowHiddenFilesEnabled = getResources().getBoolean(R.bool.passcode_enabled);
  279. mShowHiddenFiles = (SwitchPreference) findPreference("show_hidden_files");
  280. if (fShowHiddenFilesEnabled) {
  281. mShowHiddenFiles.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  282. @Override
  283. public boolean onPreferenceClick(Preference preference) {
  284. SharedPreferences appPrefs =
  285. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  286. SharedPreferences.Editor editor = appPrefs.edit();
  287. editor.putBoolean("show_hidden_files_pref", mShowHiddenFiles.isChecked());
  288. editor.apply();
  289. return true;
  290. }
  291. });
  292. } else {
  293. preferenceCategoryDetails.removePreference(mShowHiddenFiles);
  294. }
  295. PreferenceCategory preferenceCategoryMore = (PreferenceCategory) findPreference("more");
  296. preferenceCategoryMore.setTitle(DisplayUtils.getColoredTitle(getString(R.string.prefs_category_more),
  297. accentColor));
  298. boolean calendarContactsEnabled = getResources().getBoolean(R.bool.davdroid_integration_enabled);
  299. Preference pCalendarContacts = findPreference("calendar_contacts");
  300. if (pCalendarContacts != null) {
  301. if (calendarContactsEnabled) {
  302. pCalendarContacts.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  303. @Override
  304. public boolean onPreferenceClick(Preference preference) {
  305. try {
  306. launchDavDroidLogin();
  307. } catch (Throwable t) {
  308. Log_OC.e(TAG, "Base Uri for account could not be resolved to call DAVdroid!", t);
  309. Toast.makeText(
  310. MainApp.getAppContext(),
  311. R.string.prefs_calendar_contacts_address_resolve_error,
  312. Toast.LENGTH_SHORT)
  313. .show();
  314. }
  315. return true;
  316. }
  317. });
  318. } else {
  319. preferenceCategoryMore.removePreference(pCalendarContacts);
  320. }
  321. }
  322. if (!fShowHiddenFilesEnabled && !fPrintEnabled && !fPassCodeEnabled) {
  323. preferenceScreen.removePreference(preferenceCategoryDetails);
  324. }
  325. boolean helpEnabled = getResources().getBoolean(R.bool.help_enabled);
  326. Preference pHelp = findPreference("help");
  327. if (pHelp != null) {
  328. if (helpEnabled) {
  329. pHelp.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  330. @Override
  331. public boolean onPreferenceClick(Preference preference) {
  332. String helpWeb = getString(R.string.url_help);
  333. if (helpWeb != null && helpWeb.length() > 0) {
  334. Uri uriUrl = Uri.parse(helpWeb);
  335. Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
  336. startActivity(intent);
  337. }
  338. return true;
  339. }
  340. });
  341. } else {
  342. preferenceCategoryMore.removePreference(pHelp);
  343. }
  344. }
  345. boolean recommendEnabled = getResources().getBoolean(R.bool.recommend_enabled);
  346. Preference pRecommend = findPreference("recommend");
  347. if (pRecommend != null) {
  348. if (recommendEnabled) {
  349. pRecommend.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  350. @Override
  351. public boolean onPreferenceClick(Preference preference) {
  352. Intent intent = new Intent(Intent.ACTION_SENDTO);
  353. intent.setType("text/plain");
  354. intent.setData(Uri.parse(getString(R.string.mail_recommend)));
  355. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  356. String appName = getString(R.string.app_name);
  357. String downloadUrl = getString(R.string.url_app_download);
  358. String recommendSubject = String.format(getString(R.string.recommend_subject), appName);
  359. String recommendText = String.format(getString(R.string.recommend_text), appName, downloadUrl);
  360. intent.putExtra(Intent.EXTRA_SUBJECT, recommendSubject);
  361. intent.putExtra(Intent.EXTRA_TEXT, recommendText);
  362. startActivity(intent);
  363. return true;
  364. }
  365. });
  366. } else {
  367. preferenceCategoryMore.removePreference(pRecommend);
  368. }
  369. }
  370. boolean feedbackEnabled = getResources().getBoolean(R.bool.feedback_enabled);
  371. Preference pFeedback = findPreference("feedback");
  372. if (pFeedback != null) {
  373. if (feedbackEnabled) {
  374. pFeedback.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  375. @Override
  376. public boolean onPreferenceClick(Preference preference) {
  377. String feedbackMail = getString(R.string.mail_feedback);
  378. String feedback = getText(R.string.prefs_feedback) + " - android v" + appVersion;
  379. Intent intent = new Intent(Intent.ACTION_SENDTO);
  380. intent.setType("text/plain");
  381. intent.putExtra(Intent.EXTRA_SUBJECT, feedback);
  382. intent.setData(Uri.parse(feedbackMail));
  383. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  384. startActivity(intent);
  385. return true;
  386. }
  387. });
  388. } else {
  389. preferenceCategoryMore.removePreference(pFeedback);
  390. }
  391. }
  392. boolean loggerEnabled = getResources().getBoolean(R.bool.logger_enabled) || BuildConfig.DEBUG;
  393. Preference pLogger = findPreference("logger");
  394. if (pLogger != null) {
  395. if (loggerEnabled) {
  396. pLogger.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  397. @Override
  398. public boolean onPreferenceClick(Preference preference) {
  399. Intent loggerIntent = new Intent(getApplicationContext(), LogHistoryActivity.class);
  400. startActivity(loggerIntent);
  401. return true;
  402. }
  403. });
  404. } else {
  405. preferenceCategoryMore.removePreference(pLogger);
  406. }
  407. }
  408. boolean imprintEnabled = getResources().getBoolean(R.bool.imprint_enabled);
  409. Preference pImprint = findPreference("imprint");
  410. if (pImprint != null) {
  411. if (imprintEnabled) {
  412. pImprint.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  413. @Override
  414. public boolean onPreferenceClick(Preference preference) {
  415. String imprintWeb = getString(R.string.url_imprint);
  416. if (imprintWeb != null && imprintWeb.length() > 0) {
  417. Uri uriUrl = Uri.parse(imprintWeb);
  418. Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
  419. startActivity(intent);
  420. }
  421. //ImprintDialog.newInstance(true).show(preference.get, "IMPRINT_DIALOG");
  422. return true;
  423. }
  424. });
  425. } else {
  426. preferenceCategoryMore.removePreference(pImprint);
  427. }
  428. }
  429. mPrefStoragePath = (ListPreference) findPreference(PreferenceKeys.STORAGE_PATH);
  430. if (mPrefStoragePath != null) {
  431. StoragePoint[] storageOptions = DataStorageProvider.getInstance().getAvailableStoragePoints();
  432. String[] entries = new String[storageOptions.length];
  433. String[] values = new String[storageOptions.length];
  434. for (int i = 0; i < storageOptions.length; ++i) {
  435. entries[i] = storageOptions[i].getDescription();
  436. values[i] = storageOptions[i].getPath();
  437. }
  438. mPrefStoragePath.setEntries(entries);
  439. mPrefStoragePath.setEntryValues(values);
  440. mPrefStoragePath.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
  441. @Override
  442. public boolean onPreferenceChange(Preference preference, Object newValue) {
  443. String newPath = (String) newValue;
  444. if (mStoragePath.equals(newPath)) {
  445. return true;
  446. }
  447. StorageMigration storageMigration = new StorageMigration(Preferences.this, mStoragePath, newPath);
  448. storageMigration.setStorageMigrationProgressListener(Preferences.this);
  449. storageMigration.migrate();
  450. return false;
  451. }
  452. });
  453. }
  454. mPrefInstantUploadCategory = (PreferenceCategory) findPreference("instant_uploading_category");
  455. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
  456. // Instant upload via preferences on pre Android Marshmallow
  457. mPrefInstantUploadPath = findPreference("instant_upload_path");
  458. if (mPrefInstantUploadPath != null) {
  459. mPrefInstantUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  460. @Override
  461. public boolean onPreferenceClick(Preference preference) {
  462. if (!mUploadPath.endsWith(OCFile.PATH_SEPARATOR)) {
  463. mUploadPath += OCFile.PATH_SEPARATOR;
  464. }
  465. Intent intent = new Intent(Preferences.this, UploadPathActivity.class);
  466. intent.putExtra(UploadPathActivity.KEY_INSTANT_UPLOAD_PATH, mUploadPath);
  467. startActivityForResult(intent, ACTION_SELECT_UPLOAD_PATH);
  468. return true;
  469. }
  470. });
  471. }
  472. mPrefInstantUploadCategory = (PreferenceCategory) findPreference("instant_uploading_category");
  473. mPrefInstantUploadUseSubfolders = findPreference("instant_upload_path_use_subfolders");
  474. mPrefInstantUploadPathWiFi = findPreference("instant_upload_on_wifi");
  475. mPrefInstantPictureUploadOnlyOnCharging = findPreference("instant_upload_on_charging");
  476. mPrefInstantUpload = findPreference("instant_uploading");
  477. toggleInstantPictureOptions(((SwitchPreference) mPrefInstantUpload).isChecked());
  478. mPrefInstantUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
  479. @Override
  480. public boolean onPreferenceChange(Preference preference, Object newValue) {
  481. toggleInstantPictureOptions((Boolean) newValue);
  482. toggleInstantUploadBehaviour(
  483. ((SwitchPreference) mPrefInstantVideoUpload).isChecked(),
  484. (Boolean) newValue);
  485. return true;
  486. }
  487. });
  488. mPrefInstantVideoUploadPath = findPreference(PreferenceKeys.INSTANT_VIDEO_UPLOAD_PATH);
  489. if (mPrefInstantVideoUploadPath != null){
  490. mPrefInstantVideoUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  491. @Override
  492. public boolean onPreferenceClick(Preference preference) {
  493. if (!mUploadVideoPath.endsWith(OCFile.PATH_SEPARATOR)) {
  494. mUploadVideoPath += OCFile.PATH_SEPARATOR;
  495. }
  496. Intent intent = new Intent(Preferences.this, UploadPathActivity.class);
  497. intent.putExtra(UploadPathActivity.KEY_INSTANT_UPLOAD_PATH,
  498. mUploadVideoPath);
  499. startActivityForResult(intent, ACTION_SELECT_UPLOAD_VIDEO_PATH);
  500. return true;
  501. }
  502. });
  503. }
  504. mPrefInstantVideoUploadUseSubfolders = findPreference("instant_video_upload_path_use_subfolders");
  505. mPrefInstantVideoUploadPathWiFi = findPreference("instant_video_upload_on_wifi");
  506. mPrefInstantVideoUpload = findPreference("instant_video_uploading");
  507. mPrefInstantVideoUploadOnlyOnCharging = findPreference("instant_video_upload_on_charging");
  508. toggleInstantVideoOptions(((CheckBoxPreference) mPrefInstantVideoUpload).isChecked());
  509. mPrefInstantVideoUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
  510. @Override
  511. public boolean onPreferenceChange(Preference preference, Object newValue) {
  512. toggleInstantVideoOptions((Boolean) newValue);
  513. toggleInstantUploadBehaviour(
  514. (Boolean) newValue,
  515. ((CheckBoxPreference) mPrefInstantUpload).isChecked());
  516. return true;
  517. }
  518. });
  519. mPrefInstantUploadBehaviour = findPreference("prefs_instant_behaviour");
  520. toggleInstantUploadBehaviour(
  521. ((CheckBoxPreference) mPrefInstantVideoUpload).isChecked(),
  522. ((CheckBoxPreference) mPrefInstantUpload).isChecked());
  523. loadInstantUploadPath();
  524. loadInstantUploadVideoPath();
  525. } else {
  526. // Instant upload is handled via synced folders on Android Lollipop and up
  527. getPreferenceScreen().removePreference(mPrefInstantUploadCategory);
  528. }
  529. // About category
  530. PreferenceCategory preferenceCategoryAbout = (PreferenceCategory) findPreference("about");
  531. preferenceCategoryAbout.setTitle(DisplayUtils.getColoredTitle(getString(R.string.prefs_category_about),
  532. accentColor));
  533. /* About App */
  534. pAboutApp = findPreference("about_app");
  535. if (pAboutApp != null) {
  536. pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name)));
  537. pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion));
  538. }
  539. // privacy
  540. boolean privacyEnabled = getResources().getBoolean(R.bool.privacy_enabled);
  541. Preference privacyPreference = findPreference("privacy");
  542. if (privacyPreference != null) {
  543. if (privacyEnabled) {
  544. privacyPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  545. @Override
  546. public boolean onPreferenceClick(Preference preference) {
  547. String privacyUrl = getString(R.string.privacy_url);
  548. if (privacyUrl.length() > 0) {
  549. Intent externalWebViewIntent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
  550. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE,
  551. getResources().getString(R.string.privacy));
  552. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_URL, privacyUrl);
  553. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false);
  554. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_MENU_ITEM_ID, -1);
  555. startActivity(externalWebViewIntent);
  556. }
  557. return true;
  558. }
  559. });
  560. } else {
  561. preferenceCategoryAbout.removePreference(privacyPreference);
  562. }
  563. }
  564. loadExternalSettingLinks(preferenceCategoryMore);
  565. loadStoragePath();
  566. }
  567. private void launchDavDroidLogin()
  568. throws com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException,
  569. OperationCanceledException,
  570. AuthenticatorException,
  571. IOException {
  572. Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
  573. Intent davDroidLoginIntent = new Intent();
  574. davDroidLoginIntent.setClassName("at.bitfire.davdroid", "at.bitfire.davdroid.ui.setup.LoginActivity");
  575. if (getPackageManager().resolveActivity(davDroidLoginIntent, 0) != null) {
  576. // arguments
  577. if (mUri != null) {
  578. davDroidLoginIntent.putExtra("url", mUri.toString() + AccountUtils.DAV_PATH);
  579. }
  580. davDroidLoginIntent.putExtra("username", AccountUtils.getAccountUsername(account.name));
  581. //loginIntent.putExtra("password", "...");
  582. startActivityForResult(davDroidLoginIntent, ACTION_REQUEST_CODE_DAVDROID_SETUP);
  583. } else {
  584. // DAVdroid not installed
  585. Intent installIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=at.bitfire.davdroid"));
  586. // launch market(s)
  587. if (installIntent.resolveActivity(getPackageManager()) != null) {
  588. startActivity(installIntent);
  589. } else {
  590. // no f-droid market app or Play store installed --> launch browser for f-droid url
  591. Intent downloadIntent = new Intent(Intent.ACTION_VIEW,
  592. Uri.parse("https://f-droid.org/repository/browse/?fdid=at.bitfire.davdroid"));
  593. startActivity(downloadIntent);
  594. Toast.makeText(
  595. MainApp.getAppContext(),
  596. R.string.prefs_calendar_contacts_no_store_error,
  597. Toast.LENGTH_SHORT)
  598. .show();
  599. }
  600. }
  601. }
  602. private void setupBaseUri() {
  603. // retrieve and set user's base URI
  604. Thread t = new Thread(new Runnable() {
  605. public void run() {
  606. try {
  607. Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
  608. OwnCloudAccount ocAccount = new OwnCloudAccount(account, MainApp.getAppContext());
  609. mUri = OwnCloudClientManagerFactory.getDefaultSingleton().
  610. getClientFor(ocAccount, getApplicationContext()).getBaseUri();
  611. } catch (Throwable t) {
  612. Log_OC.e(TAG,"Error retrieving user's base URI", t);
  613. }
  614. }
  615. });
  616. t.start();
  617. }
  618. private void toggleInstantPictureOptions(Boolean value){
  619. if (value) {
  620. mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPathWiFi);
  621. mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPath);
  622. mPrefInstantUploadCategory.addPreference(mPrefInstantUploadUseSubfolders);
  623. mPrefInstantUploadCategory.addPreference(mPrefInstantPictureUploadOnlyOnCharging);
  624. } else {
  625. mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi);
  626. mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath);
  627. mPrefInstantUploadCategory.removePreference(mPrefInstantUploadUseSubfolders);
  628. mPrefInstantUploadCategory.removePreference(mPrefInstantPictureUploadOnlyOnCharging);
  629. }
  630. }
  631. private void toggleInstantVideoOptions(Boolean value){
  632. if (value) {
  633. mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPathWiFi);
  634. mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPath);
  635. mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadUseSubfolders);
  636. mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadOnlyOnCharging);
  637. } else {
  638. mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi);
  639. mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath);
  640. mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadUseSubfolders);
  641. mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadOnlyOnCharging);
  642. }
  643. }
  644. private void toggleInstantUploadBehaviour(Boolean video, Boolean picture){
  645. if (picture || video) {
  646. mPrefInstantUploadCategory.addPreference(mPrefInstantUploadBehaviour);
  647. } else {
  648. mPrefInstantUploadCategory.removePreference(mPrefInstantUploadBehaviour);
  649. }
  650. }
  651. @Override
  652. protected void onResume() {
  653. super.onResume();
  654. AnalyticsUtils.setCurrentScreenName(this, SCREEN_NAME, TAG);
  655. SharedPreferences appPrefs =
  656. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  657. boolean state = appPrefs.getBoolean(PassCodeActivity.PREFERENCE_SET_PASSCODE, false);
  658. pCode.setChecked(state);
  659. }
  660. @Override
  661. public boolean onCreateOptionsMenu(Menu menu) {
  662. super.onCreateOptionsMenu(menu);
  663. return true;
  664. }
  665. @Override
  666. public boolean onMenuItemSelected(int featureId, MenuItem item) {
  667. super.onMenuItemSelected(featureId, item);
  668. Intent intent;
  669. switch (item.getItemId()) {
  670. case android.R.id.home:
  671. intent = new Intent(getBaseContext(), FileDisplayActivity.class);
  672. intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
  673. startActivity(intent);
  674. break;
  675. default:
  676. Log_OC.w(TAG, "Unknown menu item triggered");
  677. return false;
  678. }
  679. return true;
  680. }
  681. @Override
  682. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  683. super.onActivityResult(requestCode, resultCode, data);
  684. if (requestCode == ACTION_SELECT_UPLOAD_PATH && resultCode == RESULT_OK) {
  685. OCFile folderToUpload = data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
  686. mUploadPath = folderToUpload.getRemotePath();
  687. mUploadPath = DisplayUtils.getPathWithoutLastSlash(mUploadPath);
  688. // Show the path on summary preference
  689. mPrefInstantUploadPath.setSummary(mUploadPath);
  690. saveInstantUploadPathOnPreferences();
  691. } else if (requestCode == ACTION_SELECT_UPLOAD_VIDEO_PATH && resultCode == RESULT_OK) {
  692. OCFile folderToUploadVideo = data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
  693. mUploadVideoPath = folderToUploadVideo.getRemotePath();
  694. mUploadVideoPath = DisplayUtils.getPathWithoutLastSlash(mUploadVideoPath);
  695. // Show the video path on summary preference
  696. mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath);
  697. saveInstantUploadVideoPathOnPreferences();
  698. } else if (requestCode == ACTION_REQUEST_PASSCODE && resultCode == RESULT_OK) {
  699. String passcode = data.getStringExtra(PassCodeActivity.KEY_PASSCODE);
  700. if (passcode != null && passcode.length() == 4) {
  701. SharedPreferences.Editor appPrefs = PreferenceManager
  702. .getDefaultSharedPreferences(getApplicationContext()).edit();
  703. for (int i = 1; i <= 4; ++i) {
  704. appPrefs.putString(PassCodeActivity.PREFERENCE_PASSCODE_D + i, passcode.substring(i-1, i));
  705. }
  706. appPrefs.putBoolean(PassCodeActivity.PREFERENCE_SET_PASSCODE, true);
  707. appPrefs.apply();
  708. Toast.makeText(this, R.string.pass_code_stored, Toast.LENGTH_LONG).show();
  709. }
  710. } else if (requestCode == ACTION_CONFIRM_PASSCODE && resultCode == RESULT_OK) {
  711. if (data.getBooleanExtra(PassCodeActivity.KEY_CHECK_RESULT, false)) {
  712. SharedPreferences.Editor appPrefs = PreferenceManager
  713. .getDefaultSharedPreferences(getApplicationContext()).edit();
  714. appPrefs.putBoolean(PassCodeActivity.PREFERENCE_SET_PASSCODE, false);
  715. appPrefs.apply();
  716. Toast.makeText(this, R.string.pass_code_removed, Toast.LENGTH_LONG).show();
  717. }
  718. } else if (requestCode == ACTION_REQUEST_CODE_DAVDROID_SETUP && resultCode == RESULT_OK) {
  719. Toast.makeText(this, R.string.prefs_calendar_contacts_sync_setup_successful, Toast.LENGTH_LONG).show();
  720. }
  721. }
  722. public ActionBar getSupportActionBar() {
  723. return getDelegate().getSupportActionBar();
  724. }
  725. public void setSupportActionBar(@Nullable Toolbar toolbar) {
  726. getDelegate().setSupportActionBar(toolbar);
  727. }
  728. @Override
  729. public MenuInflater getMenuInflater() {
  730. return getDelegate().getMenuInflater();
  731. }
  732. @Override
  733. public void setContentView(@LayoutRes int layoutResID) {
  734. getDelegate().setContentView(layoutResID);
  735. }
  736. @Override
  737. public void setContentView(View view) {
  738. getDelegate().setContentView(view);
  739. }
  740. @Override
  741. public void setContentView(View view, ViewGroup.LayoutParams params) {
  742. getDelegate().setContentView(view, params);
  743. }
  744. @Override
  745. public void addContentView(View view, ViewGroup.LayoutParams params) {
  746. getDelegate().addContentView(view, params);
  747. }
  748. @Override
  749. protected void onPostResume() {
  750. super.onPostResume();
  751. getDelegate().onPostResume();
  752. }
  753. @Override
  754. protected void onTitleChanged(CharSequence title, int color) {
  755. super.onTitleChanged(title, color);
  756. getDelegate().setTitle(title);
  757. }
  758. @Override
  759. public void onConfigurationChanged(Configuration newConfig) {
  760. super.onConfigurationChanged(newConfig);
  761. getDelegate().onConfigurationChanged(newConfig);
  762. }
  763. @Override
  764. protected void onPostCreate(Bundle savedInstanceState) {
  765. super.onPostCreate(savedInstanceState);
  766. getDelegate().onPostCreate(savedInstanceState);
  767. }
  768. @Override
  769. protected void onDestroy() {
  770. super.onDestroy();
  771. getDelegate().onDestroy();
  772. }
  773. @Override
  774. protected void onStop() {
  775. super.onStop();
  776. getDelegate().onStop();
  777. }
  778. public void invalidateOptionsMenu() {
  779. getDelegate().invalidateOptionsMenu();
  780. }
  781. private AppCompatDelegate getDelegate() {
  782. if (mDelegate == null) {
  783. mDelegate = AppCompatDelegate.create(this, null);
  784. }
  785. return mDelegate;
  786. }
  787. private void loadExternalSettingLinks(PreferenceCategory preferenceCategory) {
  788. if (getBaseContext().getResources().getBoolean(R.bool.show_external_links)) {
  789. ExternalLinksProvider externalLinksProvider = new ExternalLinksProvider(getContentResolver());
  790. for (final ExternalLink link : externalLinksProvider.getExternalLink(ExternalLinkType.SETTINGS)) {
  791. // only add if it does not exist, in case activity is re-used
  792. if (findPreference(link.id.toString()) == null) {
  793. Preference p = new Preference(this);
  794. p.setTitle(link.name);
  795. p.setKey(link.id.toString());
  796. p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  797. @Override
  798. public boolean onPreferenceClick(Preference preference) {
  799. Intent externalWebViewIntent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
  800. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, link.name);
  801. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_URL, link.url);
  802. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, false);
  803. externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_MENU_ITEM_ID, link.id);
  804. startActivity(externalWebViewIntent);
  805. return true;
  806. }
  807. });
  808. preferenceCategory.addPreference(p);
  809. }
  810. }
  811. }
  812. }
  813. /**
  814. * Load upload path set on preferences
  815. */
  816. private void loadInstantUploadPath() {
  817. SharedPreferences appPrefs =
  818. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  819. mUploadPath = appPrefs.getString(PreferenceKeys.INSTANT_UPLOAD_PATH, getString(R.string.instant_upload_path));
  820. mPrefInstantUploadPath.setSummary(mUploadPath);
  821. }
  822. /**
  823. * Save storage path
  824. */
  825. private void saveStoragePath(String newStoragePath) {
  826. SharedPreferences appPrefs =
  827. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  828. mStoragePath = newStoragePath;
  829. MainApp.setStoragePath(mStoragePath);
  830. SharedPreferences.Editor editor = appPrefs.edit();
  831. editor.putString(PreferenceKeys.STORAGE_PATH, mStoragePath);
  832. editor.apply();
  833. String storageDescription = DataStorageProvider.getInstance().getStorageDescriptionByPath(mStoragePath);
  834. mPrefStoragePath.setSummary(storageDescription);
  835. mPrefStoragePath.setValue(newStoragePath);
  836. }
  837. /**
  838. * Load storage path set on preferences
  839. */
  840. private void loadStoragePath() {
  841. SharedPreferences appPrefs =
  842. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  843. mStoragePath = appPrefs.getString(PreferenceKeys.STORAGE_PATH, Environment.getExternalStorageDirectory()
  844. .getAbsolutePath());
  845. String storageDescription = DataStorageProvider.getInstance().getStorageDescriptionByPath(mStoragePath);
  846. mPrefStoragePath.setSummary(storageDescription);
  847. }
  848. /**
  849. * Save the "Instant Upload Path" on preferences
  850. */
  851. private void saveInstantUploadPathOnPreferences() {
  852. SharedPreferences appPrefs =
  853. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  854. SharedPreferences.Editor editor = appPrefs.edit();
  855. editor.putString(PreferenceKeys.INSTANT_UPLOAD_PATH, mUploadPath);
  856. editor.apply();
  857. }
  858. /**
  859. * Load upload video path set on preferences
  860. */
  861. private void loadInstantUploadVideoPath() {
  862. SharedPreferences appPrefs =
  863. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  864. mUploadVideoPath = appPrefs.getString("instant_video_upload_path", getString(R.string.instant_upload_path));
  865. mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath);
  866. }
  867. /**
  868. * Save the "Instant Video Upload Path" on preferences
  869. */
  870. private void saveInstantUploadVideoPathOnPreferences() {
  871. SharedPreferences appPrefs =
  872. PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
  873. SharedPreferences.Editor editor = appPrefs.edit();
  874. editor.putString(PreferenceKeys.INSTANT_VIDEO_UPLOAD_PATH, mUploadVideoPath);
  875. editor.apply();
  876. }
  877. @Override
  878. public void onStorageMigrationFinished(String storagePath, boolean succeed) {
  879. if (succeed) {
  880. saveStoragePath(storagePath);
  881. }
  882. }
  883. @Override
  884. public void onCancelMigration() {
  885. // Migration was canceled so we don't do anything
  886. }
  887. }