2 * ownCloud Android client application
4 * @author Bartek Przybylski
5 * @author David A. Velasco
6 * Copyright (C) 2011 Bartek Przybylski
7 * Copyright (C) 2015 ownCloud Inc.
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2,
11 * as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 package com
.owncloud
.android
.ui
.activity
;
24 import android
.accounts
.Account
;
25 import android
.accounts
.AccountManager
;
26 import android
.accounts
.AccountManagerCallback
;
27 import android
.accounts
.AccountManagerFuture
;
28 import android
.content
.ComponentName
;
29 import android
.content
.Context
;
30 import android
.content
.Intent
;
31 import android
.content
.ServiceConnection
;
32 import android
.content
.SharedPreferences
;
33 import android
.content
.pm
.PackageInfo
;
34 import android
.content
.pm
.PackageManager
.NameNotFoundException
;
35 import android
.content
.res
.Configuration
;
36 import android
.net
.Uri
;
37 import android
.os
.AsyncTask
;
38 import android
.os
.Bundle
;
39 import android
.os
.Environment
;
40 import android
.os
.Handler
;
41 import android
.os
.IBinder
;
42 import android
.preference
.CheckBoxPreference
;
43 import android
.preference
.Preference
;
44 import android
.preference
.Preference
.OnPreferenceChangeListener
;
45 import android
.preference
.Preference
.OnPreferenceClickListener
;
46 import android
.preference
.PreferenceActivity
;
47 import android
.preference
.PreferenceCategory
;
48 import android
.preference
.PreferenceManager
;
49 import android
.support
.annotation
.LayoutRes
;
50 import android
.support
.annotation
.Nullable
;
51 import android
.support
.v7
.app
.ActionBar
;
52 import android
.support
.v7
.app
.AlertDialog
;
53 import android
.support
.v7
.app
.AppCompatDelegate
;
54 import android
.support
.v7
.widget
.Toolbar
;
55 import android
.view
.ContextMenu
;
56 import android
.view
.ContextMenu
.ContextMenuInfo
;
57 import android
.view
.Menu
;
58 import android
.view
.MenuInflater
;
59 import android
.view
.MenuItem
;
60 import android
.view
.View
;
61 import android
.view
.ViewGroup
;
62 import android
.widget
.AdapterView
;
63 import android
.widget
.AdapterView
.OnItemLongClickListener
;
64 import android
.widget
.ArrayAdapter
;
65 import android
.widget
.ListAdapter
;
66 import android
.widget
.ListView
;
67 import android
.widget
.Toast
;
69 import com
.owncloud
.android
.BuildConfig
;
70 import com
.owncloud
.android
.MainApp
;
71 import com
.owncloud
.android
.R
;
72 import com
.owncloud
.android
.authentication
.AccountUtils
;
73 import com
.owncloud
.android
.authentication
.AuthenticatorActivity
;
74 import com
.owncloud
.android
.datamodel
.FileDataStorageManager
;
75 import com
.owncloud
.android
.datamodel
.OCFile
;
76 import com
.owncloud
.android
.datamodel
.ThumbnailsCacheManager
;
77 import com
.owncloud
.android
.db
.DbHandler
;
78 import com
.owncloud
.android
.files
.FileOperationsHelper
;
79 import com
.owncloud
.android
.files
.services
.FileDownloader
;
80 import com
.owncloud
.android
.files
.services
.FileUploader
;
81 import com
.owncloud
.android
.lib
.common
.utils
.Log_OC
;
82 import com
.owncloud
.android
.services
.OperationsService
;
83 import com
.owncloud
.android
.ui
.PreferenceWithLongSummary
;
84 import com
.owncloud
.android
.ui
.RadioButtonPreference
;
85 import com
.owncloud
.android
.utils
.DisplayUtils
;
87 import java
.io
.BufferedReader
;
88 import java
.io
.IOException
;
89 import java
.io
.InputStreamReader
;
90 import java
.net
.MalformedURLException
;
92 import java
.util
.concurrent
.ExecutionException
;
97 * An Activity that allows the user to change the application's settings.
99 * It proxies the necessary calls via {@link android.support.v7.app.AppCompatDelegate} to be used
102 public class Preferences
extends PreferenceActivity
103 implements AccountManagerCallback
<Boolean
>, ComponentsGetter
{
105 private static final String TAG
= "OwnCloudPreferences";
107 private static final int ACTION_SELECT_UPLOAD_PATH
= 1;
108 private static final int ACTION_SELECT_UPLOAD_VIDEO_PATH
= 2;
109 private static final int ACTION_REQUEST_PASSCODE
= 5;
110 private static final int ACTION_CONFIRM_PASSCODE
= 6;
111 private static final int ACTION_SELECT_STORAGE_PATH
= 3;
112 private static final int ACTION_PERFORM_MIGRATION
= 4;
114 private DbHandler mDbHandler
;
115 private CheckBoxPreference pCode
;
116 private Preference pAboutApp
;
117 private AppCompatDelegate mDelegate
;
119 private PreferenceCategory mAccountsPrefCategory
= null
;
120 private final Handler mHandler
= new Handler();
121 private String mAccountName
;
122 private boolean mShowContextMenu
= false
;
123 private String mUploadPath
;
124 private PreferenceCategory mPrefInstantUploadCategory
;
125 private Preference mPrefInstantUpload
;
126 private Preference mPrefInstantUploadPath
;
127 private Preference mPrefInstantUploadPathWiFi
;
128 private Preference mPrefInstantVideoUpload
;
129 private Preference mPrefInstantVideoUploadPath
;
130 private Preference mPrefInstantVideoUploadPathWiFi
;
131 private String mUploadVideoPath
;
133 protected FileDownloader
.FileDownloaderBinder mDownloaderBinder
= null
;
134 protected FileUploader
.FileUploaderBinder mUploaderBinder
= null
;
135 private ServiceConnection mDownloadServiceConnection
, mUploadServiceConnection
= null
;
136 private PreferenceWithLongSummary mPrefStoragePath
;
137 private String mStoragePath
;
140 @SuppressWarnings("deprecation")
142 public void onCreate(Bundle savedInstanceState
) {
143 getDelegate().installViewFactory();
144 getDelegate().onCreate(savedInstanceState
);
145 super.onCreate(savedInstanceState
);
146 mDbHandler
= new DbHandler(getBaseContext());
147 addPreferencesFromResource(R
.xml
.preferences
);
149 ActionBar actionBar
= getSupportActionBar();
150 actionBar
.setDisplayHomeAsUpEnabled(true
);
151 actionBar
.setTitle(R
.string
.actionbar_settings
);
153 // For adding content description tag to a title field in the action bar
154 int actionBarTitleId
= getResources().getIdentifier("action_bar_title", "id", "android");
155 View actionBarTitleView
= getWindow().getDecorView().findViewById(actionBarTitleId
);
156 if (actionBarTitleView
!= null
) { // it's null in Android 2.x
157 getWindow().getDecorView().findViewById(actionBarTitleId
).
158 setContentDescription(getString(R
.string
.actionbar_settings
));
161 // Load the accounts category for adding the list of accounts
162 mAccountsPrefCategory
= (PreferenceCategory
) findPreference("accounts_category");
164 ListView listView
= getListView();
165 listView
.setOnItemLongClickListener(new OnItemLongClickListener() {
167 public boolean onItemLongClick(AdapterView
<?
> parent
, View view
, int position
, long id
) {
168 ListView listView
= (ListView
) parent
;
169 ListAdapter listAdapter
= listView
.getAdapter();
170 Object obj
= listAdapter
.getItem(position
);
172 if (obj
!= null
&& obj
instanceof RadioButtonPreference
) {
173 mShowContextMenu
= true
;
174 mAccountName
= ((RadioButtonPreference
) obj
).getKey();
177 getResources().getString(R
.string
.change_password
),
178 getResources().getString(R
.string
.delete_account
)
180 final AlertDialog
.Builder alertDialogBuilder
= new AlertDialog
.Builder(Preferences
.this);
181 View convertView
= getLayoutInflater().inflate(R
.layout
.alert_dialog_list_view
, null
);
182 alertDialogBuilder
.setView(convertView
);
183 ListView lv
= (ListView
) convertView
.findViewById(R
.id
.list
);
184 ArrayAdapter
<String
> adapter
= new ArrayAdapter
<String
>(
185 Preferences
.this,R
.layout
.simple_dialog_list_item
,items
);
186 lv
.setAdapter(adapter
);
188 //Setup proper inline listener
189 final AlertDialog alertDialog
= alertDialogBuilder
.create();
190 lv
.setOnItemClickListener(new AdapterView
.OnItemClickListener() {
192 public void onItemClick(AdapterView
<?
> parent
, View view
, int position
, long id
) {
193 AccountManager am
= (AccountManager
) getSystemService(ACCOUNT_SERVICE
);
194 Account accounts
[] = am
.getAccountsByType(MainApp
.getAccountType());
195 for (Account a
: accounts
) {
196 if (a
.name
.equals(mAccountName
)) {
199 // Change account password
200 Intent updateAccountCredentials
= new Intent(Preferences
.this, AuthenticatorActivity
.class);
201 updateAccountCredentials
.putExtra(AuthenticatorActivity
.EXTRA_ACCOUNT
, a
);
202 updateAccountCredentials
.putExtra(AuthenticatorActivity
.EXTRA_ACTION
,
203 AuthenticatorActivity
.ACTION_UPDATE_TOKEN
);
204 startActivity(updateAccountCredentials
);
205 alertDialog
.cancel();
207 } else if (position
==1) {
210 am
.removeAccount(a
, Preferences
.this, mHandler
);
211 Log_OC
.d(TAG
, "Remove an account " + a
.name
);
212 alertDialog
.cancel();
220 View
.OnLongClickListener longListener
= (View
.OnLongClickListener
) obj
;
221 return longListener
.onLongClick(view
);
230 PackageInfo pkg
= getPackageManager().getPackageInfo(getPackageName(), 0);
231 temp
= pkg
.versionName
;
232 } catch (NameNotFoundException e
) {
234 Log_OC
.e(TAG
, "Error while showing about dialog", e
);
236 final String appVersion
= temp
;
238 // Register context menu for list of preferences.
239 registerForContextMenu(getListView());
241 pCode
= (CheckBoxPreference
) findPreference("set_pincode");
243 pCode
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
245 public boolean onPreferenceChange(Preference preference
, Object newValue
) {
246 Intent i
= new Intent(getApplicationContext(), PassCodeActivity
.class);
247 Boolean incoming
= (Boolean
) newValue
;
250 incoming
.booleanValue() ? PassCodeActivity
.ACTION_REQUEST_WITH_RESULT
:
251 PassCodeActivity
.ACTION_CHECK_WITH_RESULT
254 startActivityForResult(i
, incoming
.booleanValue() ? ACTION_REQUEST_PASSCODE
:
255 ACTION_CONFIRM_PASSCODE
);
257 // Don't update just yet, we will decide on it in onActivityResult
264 final Preference pCacheSize
= findPreference("pref_cache_size");
265 if (pCacheSize
!= null
){
266 final SharedPreferences appPrefs
=
267 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
268 Long cacheSize
= ThumbnailsCacheManager
.getMaxSize();
269 pCacheSize
.setSummary(cacheSize
+ " Mb");
270 pCacheSize
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
272 public boolean onPreferenceChange(Preference preference
, Object newValue
) {
273 Long size
= Long
.decode((String
) newValue
);
274 if (ThumbnailsCacheManager
.setMaxSize(size
)){
275 appPrefs
.edit().putString("pref_cache_size", size
.toString());
276 pCacheSize
.setSummary(size
+ " MB");
285 PreferenceCategory preferenceCategory
= (PreferenceCategory
) findPreference("more");
287 boolean helpEnabled
= getResources().getBoolean(R
.bool
.help_enabled
);
288 Preference pHelp
= findPreference("help");
291 pHelp
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
293 public boolean onPreferenceClick(Preference preference
) {
294 String helpWeb
=(String
) getText(R
.string
.url_help
);
295 if (helpWeb
!= null
&& helpWeb
.length() > 0) {
296 Uri uriUrl
= Uri
.parse(helpWeb
);
297 Intent intent
= new Intent(Intent
.ACTION_VIEW
, uriUrl
);
298 startActivity(intent
);
304 preferenceCategory
.removePreference(pHelp
);
309 if (BuildConfig
.DEBUG
) {
310 Preference pLog
= findPreference("log");
312 pLog
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
314 public boolean onPreferenceClick(Preference preference
) {
315 Intent loggerIntent
= new Intent(getApplicationContext(),
316 LogHistoryActivity
.class);
317 startActivity(loggerIntent
);
324 boolean recommendEnabled
= getResources().getBoolean(R
.bool
.recommend_enabled
);
325 Preference pRecommend
= findPreference("recommend");
326 if (pRecommend
!= null
){
327 if (recommendEnabled
) {
328 pRecommend
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
330 public boolean onPreferenceClick(Preference preference
) {
332 Intent intent
= new Intent(Intent
.ACTION_SENDTO
);
333 intent
.setType("text/plain");
334 intent
.setData(Uri
.parse(getString(R
.string
.mail_recommend
)));
335 intent
.addFlags(Intent
.FLAG_ACTIVITY_NEW_TASK
);
337 String appName
= getString(R
.string
.app_name
);
338 String downloadUrl
= getString(R
.string
.url_app_download
);
339 Account currentAccount
= AccountUtils
.
340 getCurrentOwnCloudAccount(Preferences
.this);
341 String username
= currentAccount
.name
.substring(0,
342 currentAccount
.name
.lastIndexOf('@'));
344 String recommendSubject
= String
.format(getString(R
.string
.recommend_subject
),
346 String recommendText
= String
.format(getString(R
.string
.recommend_text
),
347 appName
, downloadUrl
);
349 intent
.putExtra(Intent
.EXTRA_SUBJECT
, recommendSubject
);
350 intent
.putExtra(Intent
.EXTRA_TEXT
, recommendText
);
351 startActivity(intent
);
358 preferenceCategory
.removePreference(pRecommend
);
363 boolean feedbackEnabled
= getResources().getBoolean(R
.bool
.feedback_enabled
);
364 Preference pFeedback
= findPreference("feedback");
365 if (pFeedback
!= null
){
366 if (feedbackEnabled
) {
367 pFeedback
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
369 public boolean onPreferenceClick(Preference preference
) {
370 String feedbackMail
= (String
) getText(R
.string
.mail_feedback
);
371 String feedback
= String
.format("%s - android v%s", getText(R
.string
.prefs_feedback
), appVersion
);
372 Intent intent
= new Intent(Intent
.ACTION_SENDTO
);
374 intent
.setType("text/plain");
375 intent
.putExtra(Intent
.EXTRA_SUBJECT
, feedback
);
377 intent
.setData(Uri
.parse(feedbackMail
));
378 intent
.addFlags(Intent
.FLAG_ACTIVITY_NEW_TASK
);
379 startActivity(intent
);
385 preferenceCategory
.removePreference(pFeedback
);
390 boolean imprintEnabled
= getResources().getBoolean(R
.bool
.imprint_enabled
);
391 Preference pImprint
= findPreference("imprint");
392 if (pImprint
!= null
) {
393 if (imprintEnabled
) {
394 pImprint
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
396 public boolean onPreferenceClick(Preference preference
) {
397 String imprintWeb
= (String
) getText(R
.string
.url_imprint
);
398 if (imprintWeb
!= null
&& imprintWeb
.length() > 0) {
399 Uri uriUrl
= Uri
.parse(imprintWeb
);
400 Intent intent
= new Intent(Intent
.ACTION_VIEW
, uriUrl
);
401 startActivity(intent
);
403 //ImprintDialog.newInstance(true).show(preference.get, "IMPRINT_DIALOG");
408 preferenceCategory
.removePreference(pImprint
);
412 mPrefStoragePath
= (PreferenceWithLongSummary
)findPreference("storage_path");
413 if (mPrefStoragePath
!= null
) {
415 mPrefStoragePath
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
417 public boolean onPreferenceClick(Preference preference
) {
418 Intent intent
= new Intent(Preferences
.this, LocalDirectorySelectorActivity
.class);
419 intent
.putExtra(UploadFilesActivity
.KEY_DIRECTORY_PATH
, mStoragePath
);
420 startActivityForResult(intent
, ACTION_SELECT_STORAGE_PATH
);
425 mPrefStoragePath
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
427 public boolean onPreferenceChange(Preference preference
, Object newValue
) {
428 MainApp
.setStoragePath((String
) newValue
);
434 mPrefInstantUploadPath
= (PreferenceWithLongSummary
)findPreference("instant_upload_path");
435 if (mPrefInstantUploadPath
!= null
){
437 mPrefInstantUploadPath
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
439 public boolean onPreferenceClick(Preference preference
) {
440 if (!mUploadPath
.endsWith(OCFile
.PATH_SEPARATOR
)) {
441 mUploadPath
+= OCFile
.PATH_SEPARATOR
;
443 Intent intent
= new Intent(Preferences
.this, UploadPathActivity
.class);
444 intent
.putExtra(UploadPathActivity
.KEY_INSTANT_UPLOAD_PATH
, mUploadPath
);
445 startActivityForResult(intent
, ACTION_SELECT_UPLOAD_PATH
);
451 mPrefInstantUploadCategory
=
452 (PreferenceCategory
) findPreference("instant_uploading_category");
454 mPrefInstantUploadPathWiFi
= findPreference("instant_upload_on_wifi");
455 mPrefInstantUpload
= findPreference("instant_uploading");
457 toggleInstantPictureOptions(((CheckBoxPreference
) mPrefInstantUpload
).isChecked());
459 mPrefInstantUpload
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
462 public boolean onPreferenceChange(Preference preference
, Object newValue
) {
463 toggleInstantPictureOptions((Boolean
) newValue
);
468 mPrefInstantVideoUploadPath
= findPreference("instant_video_upload_path");
469 if (mPrefInstantVideoUploadPath
!= null
){
471 mPrefInstantVideoUploadPath
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
473 public boolean onPreferenceClick(Preference preference
) {
474 if (!mUploadVideoPath
.endsWith(OCFile
.PATH_SEPARATOR
)) {
475 mUploadVideoPath
+= OCFile
.PATH_SEPARATOR
;
477 Intent intent
= new Intent(Preferences
.this, UploadPathActivity
.class);
478 intent
.putExtra(UploadPathActivity
.KEY_INSTANT_UPLOAD_PATH
,
480 startActivityForResult(intent
, ACTION_SELECT_UPLOAD_VIDEO_PATH
);
486 mPrefInstantVideoUploadPathWiFi
= findPreference("instant_video_upload_on_wifi");
487 mPrefInstantVideoUpload
= findPreference("instant_video_uploading");
488 toggleInstantVideoOptions(((CheckBoxPreference
) mPrefInstantVideoUpload
).isChecked());
490 mPrefInstantVideoUpload
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
493 public boolean onPreferenceChange(Preference preference
, Object newValue
) {
494 toggleInstantVideoOptions((Boolean
) newValue
);
500 pAboutApp
= findPreference("about_app");
501 if (pAboutApp
!= null
) {
502 pAboutApp
.setTitle(String
.format(getString(R
.string
.about_android
),
503 getString(R
.string
.app_name
)));
505 Integer currentVersion
= getPackageManager().getPackageInfo
506 (getPackageName(), 0).versionCode
;
507 pAboutApp
.setSummary(String
.format(getString(R
.string
.about_version
),
509 } catch (NameNotFoundException e
) {
513 loadInstantUploadPath();
515 loadInstantUploadVideoPath();
517 /* ComponentsGetter */
518 mDownloadServiceConnection
= newTransferenceServiceConnection();
519 if (mDownloadServiceConnection
!= null
) {
520 bindService(new Intent(this, FileDownloader
.class), mDownloadServiceConnection
,
521 Context
.BIND_AUTO_CREATE
);
523 mUploadServiceConnection
= newTransferenceServiceConnection();
524 if (mUploadServiceConnection
!= null
) {
525 bindService(new Intent(this, FileUploader
.class), mUploadServiceConnection
,
526 Context
.BIND_AUTO_CREATE
);
529 /* Link to Beta apks */
530 Preference pBetaLink
= findPreference("beta_link");
531 if (pBetaLink
!= null
){
532 pBetaLink
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
534 public boolean onPreferenceClick(Preference preference
) {
535 Integer latestVersion
= -1;
536 Integer currentVersion
= -1;
538 currentVersion
= getPackageManager().getPackageInfo
539 (getPackageName(), 0).versionCode
;
540 LoadingVersionNumberTask loadTask
= new LoadingVersionNumberTask();
542 latestVersion
= loadTask
.get();
543 } catch (InterruptedException
| ExecutionException e
) {
545 } catch (NameNotFoundException e
) {
548 if (latestVersion
== -1 || currentVersion
== -1) {
549 Toast
.makeText(getApplicationContext(), "No information available!",
550 Toast
.LENGTH_SHORT
).show();
552 if (latestVersion
> currentVersion
) {
553 String betaLinkWeb
= (String
) getText(R
.string
.beta_link
) +
554 latestVersion
+ ".apk";
555 if (betaLinkWeb
!= null
&& betaLinkWeb
.length() > 0) {
556 Uri uriUrl
= Uri
.parse(betaLinkWeb
);
557 Intent intent
= new Intent(Intent
.ACTION_VIEW
, uriUrl
);
558 startActivity(intent
);
562 Toast
.makeText(getApplicationContext(), "No new version available!",
563 Toast
.LENGTH_SHORT
).show();
571 /* Link to Beta apks */
572 Preference pChangelogLink
= findPreference("changelog_link");
573 if (pChangelogLink
!= null
) {
574 pChangelogLink
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
576 public boolean onPreferenceClick(Preference preference
) {
577 String betaLinkWeb
= getString(R
.string
.changelog
);
578 if (betaLinkWeb
!= null
&& betaLinkWeb
.length() > 0) {
579 Uri uriUrl
= Uri
.parse(betaLinkWeb
);
580 Intent intent
= new Intent(Intent
.ACTION_VIEW
, uriUrl
);
581 startActivity(intent
);
590 private void toggleInstantPictureOptions(Boolean value
){
592 mPrefInstantUploadCategory
.addPreference(mPrefInstantUploadPathWiFi
);
593 mPrefInstantUploadCategory
.addPreference(mPrefInstantUploadPath
);
595 // mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi);
596 // mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath);
600 private void toggleInstantVideoOptions(Boolean value
){
602 mPrefInstantUploadCategory
.addPreference(mPrefInstantVideoUploadPathWiFi
);
603 mPrefInstantUploadCategory
.addPreference(mPrefInstantVideoUploadPath
);
605 // mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi);
606 // mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath);
611 public void onCreateContextMenu(ContextMenu menu
, View v
, ContextMenuInfo menuInfo
) {
613 // Filter for only showing contextual menu when long press on the
615 if (mShowContextMenu
) {
616 getMenuInflater().inflate(R
.menu
.account_picker_long_click
, menu
);
617 mShowContextMenu
= false
;
619 super.onCreateContextMenu(menu
, v
, menuInfo
);
623 public void run(AccountManagerFuture
<Boolean
> future
) {
624 if (future
.isDone()) {
625 // after remove account
626 Account account
= new Account(mAccountName
, MainApp
.getAccountType());
627 if (!AccountUtils
.exists(account
, MainApp
.getAppContext())) {
629 if (mUploaderBinder
!= null
) {
630 mUploaderBinder
.cancel(account
);
632 if (mDownloaderBinder
!= null
) {
633 mDownloaderBinder
.cancel(account
);
637 Account a
= AccountUtils
.getCurrentOwnCloudAccount(this);
638 String accountName
= "";
640 Account
[] accounts
= AccountManager
.get(this)
641 .getAccountsByType(MainApp
.getAccountType());
642 if (accounts
.length
!= 0)
643 accountName
= accounts
[0].name
;
644 AccountUtils
.setCurrentOwnCloudAccount(this, accountName
);
646 addAccountsCheckboxPreferences();
651 protected void onResume() {
653 SharedPreferences appPrefs
=
654 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
655 boolean state
= appPrefs
.getBoolean("set_pincode", false
);
656 pCode
.setChecked(state
);
658 // Populate the accounts category with the list of accounts
659 addAccountsCheckboxPreferences();
663 public boolean onCreateOptionsMenu(Menu menu
) {
664 super.onCreateOptionsMenu(menu
);
669 public boolean onMenuItemSelected(int featureId
, MenuItem item
) {
670 super.onMenuItemSelected(featureId
, item
);
673 switch (item
.getItemId()) {
674 case android
.R
.id
.home
:
675 intent
= new Intent(getBaseContext(), FileDisplayActivity
.class);
676 intent
.addFlags(Intent
.FLAG_ACTIVITY_CLEAR_TOP
);
677 startActivity(intent
);
680 Log_OC
.w(TAG
, "Unknown menu item triggered");
687 protected void onActivityResult(int requestCode
, int resultCode
, Intent data
) {
688 super.onActivityResult(requestCode
, resultCode
, data
);
690 if (requestCode
== ACTION_SELECT_UPLOAD_PATH
&& resultCode
== RESULT_OK
){
692 OCFile folderToUpload
= data
.getParcelableExtra(UploadPathActivity
.EXTRA_FOLDER
);
694 mUploadPath
= folderToUpload
.getRemotePath();
696 mUploadPath
= DisplayUtils
.getPathWithoutLastSlash(mUploadPath
);
698 // Show the path on summary preference
699 mPrefInstantUploadPath
.setSummary(mUploadPath
);
701 saveInstantUploadPathOnPreferences();
703 } else if (requestCode
== ACTION_SELECT_UPLOAD_VIDEO_PATH
&& resultCode
== RESULT_OK
) {
705 OCFile folderToUploadVideo
= data
.getParcelableExtra(UploadPathActivity
.EXTRA_FOLDER
);
707 mUploadVideoPath
= folderToUploadVideo
.getRemotePath();
709 mUploadVideoPath
= DisplayUtils
.getPathWithoutLastSlash(mUploadVideoPath
);
711 // Show the video path on summary preference
712 mPrefInstantVideoUploadPath
.setSummary(mUploadVideoPath
);
714 saveInstantUploadVideoPathOnPreferences();
715 } else if (requestCode
== ACTION_SELECT_STORAGE_PATH
&& resultCode
== RESULT_OK
) {
716 File currentStorageDir
= new File(mStoragePath
);
717 File upcomingStorageDir
= new File(data
.getStringExtra(UploadFilesActivity
.EXTRA_CHOSEN_FILES
));
719 if (currentStorageDir
!= upcomingStorageDir
) {
720 Intent migrationIntent
= new Intent(this, StorageMigrationActivity
.class);
721 migrationIntent
.putExtra(StorageMigrationActivity
.KEY_MIGRATION_SOURCE_DIR
,
722 currentStorageDir
.getAbsolutePath());
723 migrationIntent
.putExtra(StorageMigrationActivity
.KEY_MIGRATION_TARGET_DIR
,
724 upcomingStorageDir
.getAbsolutePath());
725 startActivityForResult(migrationIntent
, ACTION_PERFORM_MIGRATION
);
727 } else if (requestCode
== ACTION_PERFORM_MIGRATION
&& resultCode
== RESULT_OK
) {
728 String resultStorageDir
= data
.getStringExtra(StorageMigrationActivity
.KEY_MIGRATION_TARGET_DIR
);
729 saveStoragePath(resultStorageDir
);
730 } else if (requestCode
== ACTION_REQUEST_PASSCODE
&& resultCode
== RESULT_OK
) {
731 String passcode
= data
.getStringExtra(PassCodeActivity
.KEY_PASSCODE
);
732 if (passcode
!= null
&& passcode
.length() == 4) {
733 SharedPreferences
.Editor appPrefs
= PreferenceManager
734 .getDefaultSharedPreferences(getApplicationContext()).edit();
736 for (int i
= 1; i
<= 4; ++i
) {
737 appPrefs
.putString("PrefPinCode" + i
, passcode
.substring(i
-1, i
));
739 appPrefs
.putBoolean("set_pincode", true
);
741 Toast
.makeText(this, R
.string
.pass_code_stored
, Toast
.LENGTH_LONG
).show();
743 } else if (requestCode
== ACTION_CONFIRM_PASSCODE
&& resultCode
== RESULT_OK
) {
744 if (data
.getBooleanExtra(PassCodeActivity
.KEY_CHECK_RESULT
, false
)) {
746 SharedPreferences
.Editor appPrefs
= PreferenceManager
747 .getDefaultSharedPreferences(getApplicationContext()).edit();
748 appPrefs
.putBoolean("set_pincode", false
);
751 Toast
.makeText(this, R
.string
.pass_code_removed
, Toast
.LENGTH_LONG
).show();
756 public ActionBar
getSupportActionBar() {
757 return getDelegate().getSupportActionBar();
760 public void setSupportActionBar(@Nullable Toolbar toolbar
) {
761 getDelegate().setSupportActionBar(toolbar
);
765 public MenuInflater
getMenuInflater() {
766 return getDelegate().getMenuInflater();
770 public void setContentView(@LayoutRes int layoutResID
) {
771 getDelegate().setContentView(layoutResID
);
774 public void setContentView(View view
) {
775 getDelegate().setContentView(view
);
779 public void setContentView(View view
, ViewGroup
.LayoutParams params
) {
780 getDelegate().setContentView(view
, params
);
784 public void addContentView(View view
, ViewGroup
.LayoutParams params
) {
785 getDelegate().addContentView(view
, params
);
789 protected void onPostResume() {
790 super.onPostResume();
791 getDelegate().onPostResume();
795 protected void onTitleChanged(CharSequence title
, int color
) {
796 super.onTitleChanged(title
, color
);
797 getDelegate().setTitle(title
);
801 public void onConfigurationChanged(Configuration newConfig
) {
802 super.onConfigurationChanged(newConfig
);
803 getDelegate().onConfigurationChanged(newConfig
);
807 protected void onPostCreate(Bundle savedInstanceState
) {
808 super.onPostCreate(savedInstanceState
);
809 getDelegate().onPostCreate(savedInstanceState
);
813 protected void onDestroy() {
816 if (mDownloadServiceConnection
!= null
) {
817 unbindService(mDownloadServiceConnection
);
818 mDownloadServiceConnection
= null
;
820 if (mUploadServiceConnection
!= null
) {
821 unbindService(mUploadServiceConnection
);
822 mUploadServiceConnection
= null
;
826 getDelegate().onDestroy();
830 protected void onStop() {
832 getDelegate().onStop();
835 public void invalidateOptionsMenu() {
836 getDelegate().invalidateOptionsMenu();
839 private AppCompatDelegate
getDelegate() {
840 if (mDelegate
== null
) {
841 mDelegate
= AppCompatDelegate
.create(this, null
);
847 * Create the list of accounts that has been added into the app
849 @SuppressWarnings("deprecation")
850 private void addAccountsCheckboxPreferences() {
852 // Remove accounts in case list is refreshing for avoiding to have
854 if (mAccountsPrefCategory
.getPreferenceCount() > 0) {
855 mAccountsPrefCategory
.removeAll();
858 AccountManager am
= (AccountManager
) getSystemService(ACCOUNT_SERVICE
);
859 Account accounts
[] = am
.getAccountsByType(MainApp
.getAccountType());
860 Account currentAccount
= AccountUtils
.getCurrentOwnCloudAccount(getApplicationContext());
862 if (am
.getAccountsByType(MainApp
.getAccountType()).length
== 0) {
863 // Show create account screen if there isn't any account
864 am
.addAccount(MainApp
.getAccountType(), null
, null
, null
, this,
870 for (Account a
: accounts
) {
871 RadioButtonPreference accountPreference
= new RadioButtonPreference(this);
872 accountPreference
.setKey(a
.name
);
873 // Handle internationalized domain names
874 accountPreference
.setTitle(DisplayUtils
.convertIdn(a
.name
, false
));
875 mAccountsPrefCategory
.addPreference(accountPreference
);
877 // Check the current account that is being used
878 if (a
.name
.equals(currentAccount
.name
)) {
879 accountPreference
.setChecked(true
);
881 accountPreference
.setChecked(false
);
884 accountPreference
.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
886 public boolean onPreferenceChange(Preference preference
, Object newValue
) {
887 String key
= preference
.getKey();
888 AccountManager am
= (AccountManager
) getSystemService(ACCOUNT_SERVICE
);
889 Account accounts
[] = am
.getAccountsByType(MainApp
.getAccountType());
890 for (Account a
: accounts
) {
891 RadioButtonPreference p
=
892 (RadioButtonPreference
) findPreference(a
.name
);
893 if (key
.equals(a
.name
)) {
894 boolean accountChanged
= !p
.isChecked();
896 AccountUtils
.setCurrentOwnCloudAccount(
897 getApplicationContext(),
900 if (accountChanged
) {
901 // restart the main activity
902 Intent i
= new Intent(
904 FileDisplayActivity
.class
906 i
.addFlags(Intent
.FLAG_ACTIVITY_CLEAR_TOP
);
907 i
.addFlags(Intent
.FLAG_ACTIVITY_SINGLE_TOP
);
916 return (Boolean
) newValue
;
922 // Add Create Account preference at the end of account list if
923 // Multiaccount is enabled
924 if (getResources().getBoolean(R
.bool
.multiaccount_support
)) {
925 createAddAccountPreference();
932 * Create the preference for allow adding new accounts
934 private void createAddAccountPreference() {
935 Preference addAccountPref
= new Preference(this);
936 addAccountPref
.setKey("add_account");
937 addAccountPref
.setTitle(getString(R
.string
.prefs_add_account
));
938 mAccountsPrefCategory
.addPreference(addAccountPref
);
940 addAccountPref
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
942 public boolean onPreferenceClick(Preference preference
) {
943 AccountManager am
= AccountManager
.get(getApplicationContext());
944 am
.addAccount(MainApp
.getAccountType(), null
, null
, null
, Preferences
.this,
953 * Load upload path set on preferences
955 private void loadInstantUploadPath() {
956 SharedPreferences appPrefs
=
957 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
958 mUploadPath
= appPrefs
.getString("instant_upload_path", getString(R
.string
.instant_upload_path
));
959 mPrefInstantUploadPath
.setSummary(mUploadPath
);
965 private void saveStoragePath(String newStoragePath
) {
966 SharedPreferences appPrefs
=
967 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
968 mStoragePath
= newStoragePath
;
969 MainApp
.setStoragePath(mStoragePath
);
970 SharedPreferences
.Editor editor
= appPrefs
.edit();
971 editor
.putString("storage_path", mStoragePath
);
973 mPrefStoragePath
.setSummary(mStoragePath
);
977 * Load storage path set on preferences
979 private void loadStoragePath() {
980 SharedPreferences appPrefs
=
981 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
982 mStoragePath
= appPrefs
.getString("storage_path", Environment
.getExternalStorageDirectory()
984 mPrefStoragePath
.setSummary(mStoragePath
);
988 * Save the "Instant Upload Path" on preferences
990 private void saveInstantUploadPathOnPreferences() {
991 SharedPreferences appPrefs
=
992 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
993 SharedPreferences
.Editor editor
= appPrefs
.edit();
994 editor
.putString("instant_upload_path", mUploadPath
);
999 * Load upload video path set on preferences
1001 private void loadInstantUploadVideoPath() {
1002 mPrefInstantVideoUploadPath
.setSummary(MainApp
.getStoragePath());
1006 * Save the "Instant Video Upload Path" on preferences
1008 private void saveInstantUploadVideoPathOnPreferences() {
1009 SharedPreferences appPrefs
=
1010 PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
1011 SharedPreferences
.Editor editor
= appPrefs
.edit();
1012 editor
.putString("instant_video_upload_path", mUploadVideoPath
);
1016 // Methods for ComponentsGetter
1018 public FileDownloader
.FileDownloaderBinder
getFileDownloaderBinder() {
1019 return mDownloaderBinder
;
1024 public FileUploader
.FileUploaderBinder
getFileUploaderBinder() {
1025 return mUploaderBinder
;
1029 public OperationsService
.OperationsServiceBinder
getOperationsServiceBinder() {
1034 public FileDataStorageManager
getStorageManager() {
1039 public FileOperationsHelper
getFileOperationsHelper() {
1043 protected ServiceConnection
newTransferenceServiceConnection() {
1044 return new PreferencesServiceConnection();
1047 /** Defines callbacks for service binding, passed to bindService() */
1048 private class PreferencesServiceConnection
implements ServiceConnection
{
1051 public void onServiceConnected(ComponentName component
, IBinder service
) {
1053 if (component
.equals(new ComponentName(Preferences
.this, FileDownloader
.class))) {
1054 mDownloaderBinder
= (FileDownloader
.FileDownloaderBinder
) service
;
1055 } else if (component
.equals(new ComponentName(Preferences
.this, FileUploader
.class))) {
1056 Log_OC
.d(TAG
, "Upload service connected");
1057 mUploaderBinder
= (FileUploader
.FileUploaderBinder
) service
;
1062 public void onServiceDisconnected(ComponentName component
) {
1063 if (component
.equals(new ComponentName(Preferences
.this, FileDownloader
.class))) {
1064 Log_OC
.d(TAG
, "Download service suddenly disconnected");
1065 mDownloaderBinder
= null
;
1066 } else if (component
.equals(new ComponentName(Preferences
.this, FileUploader
.class))) {
1067 Log_OC
.d(TAG
, "Upload service suddenly disconnected");
1068 mUploaderBinder
= null
;
1075 * Class for loading the version number
1078 private class LoadingVersionNumberTask
extends AsyncTask
<Void
, Void
, Integer
> {
1079 protected Integer
doInBackground(Void
... args
) {
1081 URL url
= new URL("https://github.com/owncloud/android/raw/beta/apks/latest");
1082 BufferedReader
in = new BufferedReader(new InputStreamReader(url
.openStream()));
1084 Integer latestVersion
= Integer
.parseInt(in.readLine());
1087 return latestVersion
;
1089 } catch (MalformedURLException e
) {
1090 e
.printStackTrace();
1091 } catch (IOException e
) {
1092 e
.printStackTrace();