Preferences.java 45 KB

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