Merge remote-tracking branch 'remotes/upstream/resizeCache' into beta
authortobiasKaminsky <tobias@kaminsky.me>
Sun, 29 Nov 2015 13:37:17 +0000 (14:37 +0100)
committertobiasKaminsky <tobias@kaminsky.me>
Sun, 29 Nov 2015 13:37:17 +0000 (14:37 +0100)
1  2 
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
src/com/owncloud/android/ui/activity/Preferences.java

@@@ -24,34 -24,25 +24,36 @@@ package com.owncloud.android.datamodel
  import java.io.File;
  import java.io.InputStream;
  import java.lang.ref.WeakReference;
 +import java.net.FileNameMap;
 +import java.net.URLConnection;
  
  import org.apache.commons.httpclient.HttpStatus;
  import org.apache.commons.httpclient.methods.GetMethod;
  
  import android.accounts.Account;
 +import android.accounts.AccountManager;
 +import android.content.Context;
+ import android.content.SharedPreferences;
  import android.content.res.Resources;
  import android.graphics.Bitmap;
  import android.graphics.Bitmap.CompressFormat;
  import android.graphics.BitmapFactory;
  import android.graphics.Canvas;
 +import android.graphics.Point;
 +import android.graphics.Canvas;
 +import android.graphics.Paint;
  import android.graphics.drawable.BitmapDrawable;
  import android.graphics.drawable.ColorDrawable;
  import android.graphics.drawable.Drawable;
  import android.media.ThumbnailUtils;
  import android.net.Uri;
  import android.os.AsyncTask;
+ import android.preference.PreferenceManager;
 +import android.view.Display;
 +import android.view.View;
 +import android.view.WindowManager;
  import android.widget.ImageView;
 +import android.widget.ProgressBar;
  
  import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
@@@ -64,7 -55,6 +66,7 @@@ import com.owncloud.android.lib.resourc
  import com.owncloud.android.ui.adapter.DiskLruImageCache;
  import com.owncloud.android.utils.BitmapUtils;
  import com.owncloud.android.utils.DisplayUtils;
 +import com.owncloud.android.utils.FileStorageUtils;
  
  /**
   * Manager for concurrent access to thumbnails cache.
@@@ -74,12 -64,12 +76,12 @@@ public class ThumbnailsCacheManager 
      private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
      
      private static final String CACHE_FOLDER = "thumbnailCache";
+     private static final Integer CACHE_SIZE_MB = 10;
  
      private static final Object mThumbnailsDiskCacheLock = new Object();
      private static DiskLruImageCache mThumbnailCache = null;
      private static boolean mThumbnailCacheStarting = true;
      
-     private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
      private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
      private static final int mCompressQuality = 70;
      private static OwnCloudClient mClient = null;
  
                  if (mThumbnailCache == null) {
                      try {
+                         SharedPreferences appPrefs =
+                                 PreferenceManager.getDefaultSharedPreferences(MainApp.getAppContext());
+                         // due to backward compatibility
+                         Integer cacheSize = CACHE_SIZE_MB * 1024 * 1024;
+                         try {
+                             cacheSize = appPrefs.getInt("pref_cache_size", cacheSize);
+                         } catch (ClassCastException e) {
+                             String temp = appPrefs.getString("pref_cache_size",
+                                     cacheSize.toString());
+                             cacheSize = Integer.decode(temp) * 1024 * 1024;
+                         }
                          // Check if media is mounted or storage is built-in, if so, 
                          // try and use external cache dir; otherwise use internal cache dir
                          final String cachePath = 
                          final File diskCacheDir = new File(cachePath);
                          mThumbnailCache = new DiskLruImageCache(
                                  diskCacheDir, 
-                                 DISK_CACHE_SIZE, 
+                                 cacheSize,
                                  mCompressFormat, 
                                  mCompressQuality
                          );
       * @return max cache size in MB.
       */
      public static long getMaxSize(){
-         if (mThumbnailCache != null) {
-             return mThumbnailCache.getMaxSize() / 1024 / 1024;
-         } else {
-             return -1l;
+         if (mThumbnailCache == null) {
+             new ThumbnailsCacheManager.InitDiskCacheTask().execute();
          }
+         return mThumbnailCache.getMaxSize() / 1024 / 1024;
      }
  
      public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
          private final WeakReference<ImageView> mImageViewReference;
 +        private WeakReference<ProgressBar> mProgressWheelRef;
          private static Account mAccount;
          private Object mFile;
 +        private Boolean mIsThumbnail;
          private FileDataStorageManager mStorageManager;
  
 -
          public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
                                         Account account) {
              // Use a WeakReference to ensure the ImageView can be garbage collected
              mAccount = account;
          }
  
 +        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
 +                                       Account account, ProgressBar progressWheel) {
 +        this(imageView, storageManager, account);
 +        mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
 +        }
 +
          public ThumbnailGenerationTask(ImageView imageView) {
              // Use a WeakReference to ensure the ImageView can be garbage collected
              mImageViewReference = new WeakReference<ImageView>(imageView);
                  }
  
                  mFile = params[0];
 +                mIsThumbnail = (Boolean) params[1];
 +
                  
                  if (mFile instanceof OCFile) {
 -                    thumbnail = doOCFileInBackground();
 +                    thumbnail = doOCFileInBackground(mIsThumbnail);
 +
 +                    if (((OCFile) mFile).isVideo()){
 +                        thumbnail = addVideoOverlay(thumbnail);
 +                    }
                  }  else if (mFile instanceof File) {
 -                    thumbnail = doFileInBackground();
 +                    thumbnail = doFileInBackground(mIsThumbnail);
 +
 +                    String url = ((File) mFile).getAbsolutePath();
 +                    String mMimeType = FileStorageUtils.getMimeTypeFromName(url);
 +
 +                    if (mMimeType != null && mMimeType.startsWith("video/")){
 +                        thumbnail = addVideoOverlay(thumbnail);
 +                    }
                  //} else {  do nothing
                  }
  
                          tagId = String.valueOf(mFile.hashCode());
                      }
                      if (String.valueOf(imageView.getTag()).equals(tagId)) {
 +                        if (mProgressWheelRef != null) {
 +                            final ProgressBar progressWheel = mProgressWheelRef.get();
 +                            if (progressWheel != null) {
 +                                progressWheel.setVisibility(View.GONE);
 +                            }
 +                        }
                          imageView.setImageBitmap(bitmap);
 +                        // imageView.setVisibility(View.VISIBLE);
                      }
                  }
              }
           * @param imageKey: thumb key
           * @param bitmap:   image for extracting thumbnail
           * @param path:     image path
 -         * @param px:       thumbnail dp
 +         * @param pxW:       thumbnail width
 +         * @param pxH:       thumbnail height
           * @return Bitmap
           */
 -        private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){
 +        private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int pxW, int pxH){
  
 -            Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
 +            Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
  
              // Rotate image, obeying exif tag
              thumbnail = BitmapUtils.rotateImage(thumbnail,path);
              return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
          }
  
 -        private Bitmap doOCFileInBackground() {
 +        private Point getScreenDimension(){
 +            WindowManager wm = (WindowManager) MainApp.getAppContext().getSystemService(Context.WINDOW_SERVICE);
 +            Display display = wm.getDefaultDisplay();
 +            Point test = new Point();
 +            display.getSize(test);
 +            return test;
 +        }
 +
 +        private Bitmap doOCFileInBackground(Boolean isThumbnail) {
 +            Bitmap thumbnail = null;
              OCFile file = (OCFile)mFile;
  
 -            final String imageKey = String.valueOf(file.getRemoteId());
 +            // distinguish between thumbnail and resized image
 +            String temp = String.valueOf(file.getRemoteId());
 +            if (isThumbnail){
 +                temp = "t" + temp;
 +            } else {
 +                temp = "r" + temp;
 +            }
 +
 +            final String imageKey = temp;
  
              // Check disk cache in background thread
 -            Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
 +            thumbnail = getBitmapFromDiskCache(imageKey);
  
              // Not found in disk cache
              if (thumbnail == null || file.needsUpdateThumbnail()) {
 -
 -                int px = getThumbnailDimension();
 +                int pxW = 0;
 +                int pxH = 0;
 +                if (mIsThumbnail) {
 +                    pxW = pxH = getThumbnailDimension();
 +                } else {
 +                    Point p = getScreenDimension();
 +                    pxW = p.x;
 +                    pxH = p.y;
 +                }
  
                  if (file.isDown()) {
 -                    Bitmap temp = BitmapUtils.decodeSampledBitmapFromFile(
 -                            file.getStoragePath(), px, px);
 -                    Bitmap bitmap = ThumbnailUtils.extractThumbnail(temp, px, px);
 +                    Bitmap tempBitmap = BitmapUtils.decodeSampledBitmapFromFile(
 +                            file.getStoragePath(), pxW, pxH);
 +                    Bitmap bitmap = ThumbnailUtils.extractThumbnail(tempBitmap, pxW, pxH);
  
                      if (bitmap != null) {
                          // Handle PNG
                          if (file.getMimetype().equalsIgnoreCase("image/png")) {
 -                            bitmap = handlePNG(bitmap, px);
 +                            bitmap = handlePNG(bitmap, pxW);
                          }
  
 -                        thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px);
 +                        thumbnail = addThumbnailToCache(imageKey, bitmap,
 +                                                        file.getStoragePath(), pxW, pxH);
  
                          file.setNeedsUpdateThumbnail(false);
                          mStorageManager.saveFile(file);
                      if (mClient != null && serverOCVersion != null) {
                          if (serverOCVersion.supportsRemoteThumbnails()) {
                              try {
 -                                String uri = mClient.getBaseUri() + "" +
 -                                        "/index.php/apps/files/api/v1/thumbnail/" +
 -                                        px + "/" + px + Uri.encode(file.getRemotePath(), "/");
 -                                Log_OC.d("Thumbnail", "URI: " + uri);
 -                                GetMethod get = new GetMethod(uri);
 -                                int status = mClient.executeMethod(get);
 -                                if (status == HttpStatus.SC_OK) {
 -                                    InputStream inputStream = get.getResponseBodyAsStream();
 -                                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 -                                    thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
 -
 -                                    // Handle PNG
 -                                    if (file.getMimetype().equalsIgnoreCase("image/png")) {
 -                                        thumbnail = handlePNG(thumbnail, px);
 +                                if (mIsThumbnail) {
 +                                    String uri = mClient.getBaseUri() + "" +
 +                                            "/index.php/apps/files/api/v1/thumbnail/" +
 +                                            pxW + "/" + pxH + Uri.encode(file.getRemotePath(), "/");
 +                                    Log_OC.d("Thumbnail", "Download URI: " + uri);
 +                                    GetMethod get = new GetMethod(uri);
 +                                    int status = mClient.executeMethod(get);
 +                                    if (status == HttpStatus.SC_OK) {
 +                                        InputStream inputStream = get.getResponseBodyAsStream();
 +                                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 +                                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
 +                                    } else {
 +                                        Log_OC.d(TAG, "Status: " + status);
 +                                    }
 +                                } else {
 +                                    String gallery = "";
 +                                    if (serverOCVersion.supportsNativeGallery()){
 +                                        gallery = "gallery";
 +                                    } else {
 +                                        gallery = "galleryplus";
                                      }
  
 -                                    // Add thumbnail to cache
 -                                    if (thumbnail != null) {
 -                                        addBitmapToCache(imageKey, thumbnail);
 +                                    String uri = mClient.getBaseUri() +
 +                                            "/index.php/apps/" + gallery + "/api/preview/" + Integer.parseInt(file.getRemoteId().substring(0,8)) +
 +                                            "/" + pxW + "/" + pxH;
 +                                    Log_OC.d("Thumbnail", "FileName: " + file.getFileName() + " Download URI: " + uri);
 +                                    GetMethod get = new GetMethod(uri);
 +                                    int status = mClient.executeMethod(get);
 +                                    if (status == HttpStatus.SC_OK) {
 +                                        InputStream inputStream = get.getResponseBodyAsStream();
 +                                        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 +                                        // Download via gallery app
 +                                        thumbnail = bitmap;
                                      }
                                  }
 +
 +                                // Handle PNG
 +                                if (thumbnail != null && file.getMimetype().equalsIgnoreCase("image/png")) {
 +                                    thumbnail = handlePNG(thumbnail, pxW);
 +                                }
 +
 +                                // Add thumbnail to cache
 +                                if (thumbnail != null) {
 +                                    addBitmapToCache(imageKey, thumbnail);
 +                                }
                              } catch (Exception e) {
                                  e.printStackTrace();
                              }
              return resultBitmap;
          }
  
 -        private Bitmap doFileInBackground() {
 +        private Bitmap doFileInBackground(Boolean mIsThumbnail) {
              File file = (File)mFile;
  
 -            final String imageKey = String.valueOf(file.hashCode());
 +            // distinguish between thumbnail and resized image
 +            String temp = String.valueOf(file.hashCode());
 +            if (mIsThumbnail){
 +                temp = "t" + temp;
 +            } else {
 +                temp = "r" + temp;
 +            }
 +
 +            final String imageKey = temp;
  
              // Check disk cache in background thread
              Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
  
              // Not found in disk cache
              if (thumbnail == null) {
 -
 -                int px = getThumbnailDimension();
 +                int pxW = 0;
 +                int pxH = 0;
 +                if (mIsThumbnail) {
 +                    pxW = pxH = getThumbnailDimension();
 +                } else {
 +                    Point p = getScreenDimension();
 +                    pxW = p.x;
 +                    pxH = p.y;
 +                }
  
                  Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
 -                        file.getAbsolutePath(), px, px);
 +                        file.getAbsolutePath(), pxW, pxH);
  
                  if (bitmap != null) {
 -                    thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px);
 +                    thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH);
                  }
              }
              return thumbnail;
          return null;
      }
  
 +    public static Bitmap addVideoOverlay(Bitmap thumbnail){
 +        Bitmap playButton = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
 +                R.drawable.view_play);
 +
 +        Bitmap resizedPlayButton = Bitmap.createScaledBitmap(playButton,
 +                (int) (thumbnail.getWidth() * 0.3),
 +                (int) (thumbnail.getHeight() * 0.3), true);
 +
 +        Bitmap resultBitmap = Bitmap.createBitmap(thumbnail.getWidth(),
 +                thumbnail.getHeight(),
 +                Bitmap.Config.ARGB_8888);
 +
 +        Canvas c = new Canvas(resultBitmap);
 +
 +        // compute visual center of play button, according to resized image
 +        int x1 = resizedPlayButton.getWidth();
 +        int y1 = resizedPlayButton.getHeight() / 2;
 +        int x2 = 0;
 +        int y2 = resizedPlayButton.getWidth();
 +        int x3 = 0;
 +        int y3 = 0;
 +
 +        double ym = ( ((Math.pow(x3,2) - Math.pow(x1,2) + Math.pow(y3,2) - Math.pow(y1,2)) *
 +                    (x2 - x1)) - (Math.pow(x2,2) - Math.pow(x1,2) + Math.pow(y2,2) -
 +                    Math.pow(y1,2)) * (x3 - x1) )  /  (2 * ( ((y3 - y1) * (x2 - x1)) -
 +                    ((y2 - y1) * (x3 - x1)) ));
 +        double xm = ( (Math.pow(x2,2) - Math.pow(x1,2)) + (Math.pow(y2,2) - Math.pow(y1,2)) -
 +                    (2*ym*(y2 - y1)) ) / (2*(x2 - x1));
 +
 +        // offset to top left
 +        double ox = - xm;
 +        double oy = thumbnail.getHeight() - ym;
 +
 +
 +        c.drawBitmap(thumbnail, 0, 0, null);
 +
 +        Paint p = new Paint();
 +        p.setAlpha(230);
 +
 +        c.drawBitmap(resizedPlayButton, (float) ((thumbnail.getWidth() / 2) + ox),
 +                                        (float) ((thumbnail.getHeight() / 2) - ym), p);
 +
 +        return resultBitmap;
 +    }
 +
      public static class AsyncDrawable extends BitmapDrawable {
          private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
  
@@@ -34,9 -34,7 +34,9 @@@ import android.content.pm.PackageInfo
  import android.content.pm.PackageManager.NameNotFoundException;
  import android.content.res.Configuration;
  import android.net.Uri;
 +import android.os.AsyncTask;
  import android.os.Bundle;
 +import android.os.Environment;
  import android.os.Handler;
  import android.os.IBinder;
  import android.preference.CheckBoxPreference;
@@@ -64,7 -62,6 +64,7 @@@ import android.widget.AdapterView.OnIte
  import android.widget.ArrayAdapter;
  import android.widget.ListAdapter;
  import android.widget.ListView;
 +import android.widget.Toast;
  
  import com.owncloud.android.BuildConfig;
  import com.owncloud.android.MainApp;
@@@ -80,18 -77,9 +80,18 @@@ import com.owncloud.android.files.servi
  import com.owncloud.android.files.services.FileUploader;
  import com.owncloud.android.lib.common.utils.Log_OC;
  import com.owncloud.android.services.OperationsService;
 +import com.owncloud.android.ui.PreferenceWithLongSummary;
  import com.owncloud.android.ui.RadioButtonPreference;
  import com.owncloud.android.utils.DisplayUtils;
  
 +import java.io.BufferedReader;
 +import java.io.IOException;
 +import java.io.InputStreamReader;
 +import java.net.MalformedURLException;
 +import java.net.URL;
 +import java.util.concurrent.ExecutionException;
 +import java.io.File;
 +
  
  /**
   * An Activity that allows the user to change the application's settings.
@@@ -106,10 -94,6 +106,10 @@@ public class Preferences extends Prefer
  
      private static final int ACTION_SELECT_UPLOAD_PATH = 1;
      private static final int ACTION_SELECT_UPLOAD_VIDEO_PATH = 2;
 +    private static final int ACTION_REQUEST_PASSCODE = 5;
 +    private static final int ACTION_CONFIRM_PASSCODE = 6;
 +    private static final int ACTION_SELECT_STORAGE_PATH = 3;
 +    private static final int ACTION_PERFORM_MIGRATION = 4;
  
      private DbHandler mDbHandler;
      private CheckBoxPreference pCode;
      protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
      protected FileUploader.FileUploaderBinder mUploaderBinder = null;
      private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
 +    private PreferenceWithLongSummary mPrefStoragePath;
 +    private String mStoragePath;
 +
  
      @SuppressWarnings("deprecation")
      @Override
          registerForContextMenu(getListView());
  
          pCode = (CheckBoxPreference) findPreference("set_pincode");
 -        if (pCode != null){
 +        if (pCode != null) {
              pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                  @Override
                  public boolean onPreferenceChange(Preference preference, Object newValue) {
                      Intent i = new Intent(getApplicationContext(), PassCodeActivity.class);
 -                    Boolean enable = (Boolean) newValue;
 +                    Boolean incoming = (Boolean) newValue;
 +
                      i.setAction(
 -                            enable.booleanValue() ? PassCodeActivity.ACTION_ENABLE :
 -                                    PassCodeActivity.ACTION_DISABLE
 +                            incoming.booleanValue() ? PassCodeActivity.ACTION_REQUEST_WITH_RESULT :
 +                                    PassCodeActivity.ACTION_CHECK_WITH_RESULT
                      );
 -                    startActivity(i);
 -                    
 -                    return true;
 +
 +                    startActivityForResult(i, incoming.booleanValue() ? ACTION_REQUEST_PASSCODE :
 +                            ACTION_CONFIRM_PASSCODE);
 +
 +                    // Don't update just yet, we will decide on it in onActivityResult
 +                    return false;
                  }
 -            });            
 +            });
              
          }
  
              pCacheSize.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                  @Override
                  public boolean onPreferenceChange(Preference preference, Object newValue) {
-                     Long size = Long.decode((String) newValue);
+                     int size = Integer.decode((String) newValue);
                      if (ThumbnailsCacheManager.setMaxSize(size)){
-                         appPrefs.edit().putString("pref_cache_size", size.toString());
+                         appPrefs.edit().putInt("pref_cache_size", size);
                          pCacheSize.setSummary(size + " MB");
                          return true;
                      } else {
          PreferenceCategory preferenceCategory = (PreferenceCategory) findPreference("more");
          
          boolean helpEnabled = getResources().getBoolean(R.bool.help_enabled);
 -        Preference pHelp =  findPreference("help");
 +        Preference pHelp = findPreference("help");
          if (pHelp != null ){
              if (helpEnabled) {
                  pHelp.setOnPreferenceClickListener(new OnPreferenceClickListener() {
          }
  
          if (BuildConfig.DEBUG) {
 -            Preference pLog =  findPreference("log");
 +            Preference pLog = findPreference("log");
              if (pLog != null ){
                  pLog.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                      @Override
                          intent.putExtra(Intent.EXTRA_TEXT, recommendText);
                          startActivity(intent);
  
 -                        return(true);
 +                        return true;
  
                      }
                  });
                  pFeedback.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                      @Override
                      public boolean onPreferenceClick(Preference preference) {
 -                        String feedbackMail   =(String) getText(R.string.mail_feedback);
 -                        String feedback   =(String) getText(R.string.prefs_feedback) + " - android v" + appVersion;
 -                        Intent intent = new Intent(Intent.ACTION_SENDTO); 
 +                        String feedbackMail = (String) getText(R.string.mail_feedback);
 +                        String feedback     = String.format("%s - android v%s", getText(R.string.prefs_feedback),  appVersion);
 +                        Intent intent       = new Intent(Intent.ACTION_SENDTO);
 +
                          intent.setType("text/plain");
                          intent.putExtra(Intent.EXTRA_SUBJECT, feedback);
                          
              }
          }
  
 -        mPrefInstantUploadPath =  findPreference("instant_upload_path");
 +        mPrefStoragePath =  (PreferenceWithLongSummary)findPreference("storage_path");
 +        if (mPrefStoragePath != null) {
 +
 +            mPrefStoragePath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
 +                @Override
 +                public boolean onPreferenceClick(Preference preference) {
 +                    Intent intent = new Intent(Preferences.this, LocalDirectorySelectorActivity.class);
 +                    intent.putExtra(UploadFilesActivity.KEY_DIRECTORY_PATH, mStoragePath);
 +                    startActivityForResult(intent, ACTION_SELECT_STORAGE_PATH);
 +                    return true;
 +                }
 +            });
 +
 +            mPrefStoragePath.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
 +                    @Override
 +                    public boolean onPreferenceChange(Preference preference, Object newValue) {
 +                        MainApp.setStoragePath((String) newValue);
 +                        return true;
 +                    }
 +                });
 +        }
 +
 +        mPrefInstantUploadPath = (PreferenceWithLongSummary)findPreference("instant_upload_path");
          if (mPrefInstantUploadPath != null){
  
              mPrefInstantUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
          mPrefInstantUploadCategory =
                  (PreferenceCategory) findPreference("instant_uploading_category");
          
 -        mPrefInstantUploadPathWiFi =  findPreference("instant_upload_on_wifi");
 +        mPrefInstantUploadPathWiFi = findPreference("instant_upload_on_wifi");
          mPrefInstantUpload = findPreference("instant_uploading");
          
          toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked());
          });
              
          /* About App */
 -       pAboutApp = (Preference) findPreference("about_app");
 +       pAboutApp = findPreference("about_app");
         if (pAboutApp != null) { 
 -               pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name)));
 -               pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion));
 +               pAboutApp.setTitle(String.format(getString(R.string.about_android),
 +                                                getString(R.string.app_name)));
 +           try {
 +               Integer currentVersion = getPackageManager().getPackageInfo
 +                  (getPackageName(), 0).versionCode;
 +               pAboutApp.setSummary(String.format(getString(R.string.about_version),
 +                                    currentVersion));
 +           } catch (NameNotFoundException e) {
 +           }
         }
  
         loadInstantUploadPath();
 +       loadStoragePath();
         loadInstantUploadVideoPath();
  
          /* ComponentsGetter */
                      Context.BIND_AUTO_CREATE);
          }
  
 +        /* Link to Beta apks */
 +        Preference pBetaLink =  findPreference("beta_link");
 +        if (pBetaLink != null ){
 +            pBetaLink.setOnPreferenceClickListener(new OnPreferenceClickListener() {
 +                @Override
 +                public boolean onPreferenceClick(Preference preference) {
 +                    Integer latestVersion = -1;
 +                    Integer currentVersion = -1;
 +                    try {
 +                        currentVersion = getPackageManager().getPackageInfo
 +                                                 (getPackageName(), 0).versionCode;
 +                        LoadingVersionNumberTask loadTask = new LoadingVersionNumberTask();
 +                        loadTask.execute();
 +                        latestVersion = loadTask.get();
 +                    } catch (InterruptedException | ExecutionException e) {
 +                        e.printStackTrace();
 +                    } catch (NameNotFoundException e) {
 +                        e.printStackTrace();
 +                    }
 +                    if (latestVersion == -1 || currentVersion == -1) {
 +                        Toast.makeText(getApplicationContext(), "No information available!",
 +                                       Toast.LENGTH_SHORT).show();
 +                    }
 +                    if (latestVersion > currentVersion) {
 +                        String betaLinkWeb = (String) getText(R.string.beta_link) +
 +                                                              latestVersion + ".apk";
 +                        if (betaLinkWeb != null && betaLinkWeb.length() > 0) {
 +                            Uri uriUrl = Uri.parse(betaLinkWeb);
 +                            Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
 +                            startActivity(intent);
 +                            return true;
 +                        }
 +                    } else {
 +                        Toast.makeText(getApplicationContext(), "No new version available!",
 +                                       Toast.LENGTH_SHORT).show();
 +                        return true;
 +                    }
 +                    return true;
 +                }
 +            });
 +        }
 +
 +        /* Link to Beta apks */
 +        Preference pChangelogLink =  findPreference("changelog_link");
 +        if (pChangelogLink != null) {
 +            pChangelogLink.setOnPreferenceClickListener(new OnPreferenceClickListener() {
 +                @Override
 +                public boolean onPreferenceClick(Preference preference) {
 +                    String betaLinkWeb = getString(R.string.changelog);
 +                    if (betaLinkWeb != null && betaLinkWeb.length() > 0) {
 +                        Uri uriUrl = Uri.parse(betaLinkWeb);
 +                        Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
 +                        startActivity(intent);
 +                        return true;
 +                    }
 +                    return true;
 +                }
 +            });
 +        }
      }
      
      private void toggleInstantPictureOptions(Boolean value){
              mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPathWiFi);
              mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPath);
          } else {
 -            mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi);
 -            mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath);
 +//            mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi);
 +//            mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath);
          }
      }
      
              mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPathWiFi);
              mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPath);
          } else {
 -            mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi);
 -            mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath);
 +//            mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi);
 +//            mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath);
          }
      }
  
  
          if (requestCode == ACTION_SELECT_UPLOAD_PATH && resultCode == RESULT_OK){
  
 -            OCFile folderToUpload =
 -                    (OCFile) data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
 +            OCFile folderToUpload =  data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
  
              mUploadPath = folderToUpload.getRemotePath();
  
  
              saveInstantUploadPathOnPreferences();
  
 -        } else if (requestCode == ACTION_SELECT_UPLOAD_VIDEO_PATH && resultCode == RESULT_OK){
 +        } else if (requestCode == ACTION_SELECT_UPLOAD_VIDEO_PATH && resultCode == RESULT_OK) {
  
 -            OCFile folderToUploadVideo =
 -                    (OCFile) data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
 +            OCFile folderToUploadVideo = data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
  
              mUploadVideoPath = folderToUploadVideo.getRemotePath();
  
              mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath);
  
              saveInstantUploadVideoPathOnPreferences();
 +        } else if (requestCode == ACTION_SELECT_STORAGE_PATH && resultCode == RESULT_OK) {
 +            File currentStorageDir = new File(mStoragePath);
 +            File upcomingStorageDir = new File(data.getStringExtra(UploadFilesActivity.EXTRA_CHOSEN_FILES));
 +
 +            if (currentStorageDir != upcomingStorageDir) {
 +                Intent migrationIntent = new Intent(this, StorageMigrationActivity.class);
 +                migrationIntent.putExtra(StorageMigrationActivity.KEY_MIGRATION_SOURCE_DIR,
 +                        currentStorageDir.getAbsolutePath());
 +                migrationIntent.putExtra(StorageMigrationActivity.KEY_MIGRATION_TARGET_DIR,
 +                        upcomingStorageDir.getAbsolutePath());
 +                startActivityForResult(migrationIntent, ACTION_PERFORM_MIGRATION);
 +            }
 +        } else if (requestCode == ACTION_PERFORM_MIGRATION && resultCode == RESULT_OK) {
 +            String resultStorageDir = data.getStringExtra(StorageMigrationActivity.KEY_MIGRATION_TARGET_DIR);
 +            saveStoragePath(resultStorageDir);
 +        } else if (requestCode == ACTION_REQUEST_PASSCODE && resultCode == RESULT_OK) {
 +            String passcode = data.getStringExtra(PassCodeActivity.KEY_PASSCODE);
 +            if (passcode != null && passcode.length() == 4) {
 +                SharedPreferences.Editor appPrefs = PreferenceManager
 +                        .getDefaultSharedPreferences(getApplicationContext()).edit();
 +
 +                for (int i = 1; i <= 4; ++i) {
 +                    appPrefs.putString("PrefPinCode" + i, passcode.substring(i-1, i));
 +                }
 +                appPrefs.putBoolean("set_pincode", true);
 +                appPrefs.commit();
 +                Toast.makeText(this, R.string.pass_code_stored, Toast.LENGTH_LONG).show();
 +            }
 +        } else if (requestCode == ACTION_CONFIRM_PASSCODE && resultCode == RESULT_OK) {
 +            if (data.getBooleanExtra(PassCodeActivity.KEY_CHECK_RESULT, false)) {
 +
 +                SharedPreferences.Editor appPrefs = PreferenceManager
 +                        .getDefaultSharedPreferences(getApplicationContext()).edit();
 +                appPrefs.putBoolean("set_pincode", false);
 +                appPrefs.commit();
 +
 +                Toast.makeText(this, R.string.pass_code_removed, Toast.LENGTH_LONG).show();
 +            }
          }
      }
  
      public void setContentView(View view) {
          getDelegate().setContentView(view);
      }
 +
      @Override
      public void setContentView(View view, ViewGroup.LayoutParams params) {
          getDelegate().setContentView(view, params);
      }
  
      /**
 +     * Save storage path
 +     */
 +    private void saveStoragePath(String newStoragePath) {
 +        SharedPreferences appPrefs =
 +                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
 +        mStoragePath = newStoragePath;
 +        MainApp.setStoragePath(mStoragePath);
 +        SharedPreferences.Editor editor = appPrefs.edit();
 +        editor.putString("storage_path", mStoragePath);
 +        editor.commit();
 +        mPrefStoragePath.setSummary(mStoragePath);
 +    }
 +
 +    /**
 +     * Load storage path set on preferences
 +     */
 +    private void loadStoragePath() {
 +        SharedPreferences appPrefs =
 +                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
 +        mStoragePath = appPrefs.getString("storage_path", Environment.getExternalStorageDirectory()
 +                                                         .getAbsolutePath());
 +        mPrefStoragePath.setSummary(mStoragePath);
 +    }
 +
 +    /**
       * Save the "Instant Upload Path" on preferences
       */
      private void saveInstantUploadPathOnPreferences() {
       * Load upload video path set on preferences
       */
      private void loadInstantUploadVideoPath() {
 -        SharedPreferences appPrefs =
 -                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
 -        mUploadVideoPath = appPrefs.getString("instant_video_upload_path", getString(R.string.instant_upload_path));
 -        mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath);
 +        mPrefInstantVideoUploadPath.setSummary(MainApp.getStoragePath());
      }
  
      /**
          editor.commit();
      }
  
 -    // Methods for ComponetsGetter
 +    // Methods for ComponentsGetter
      @Override
      public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() {
          return mDownloaderBinder;
  
              if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
                  mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service;
 -
              } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
                  Log_OC.d(TAG, "Upload service connected");
                  mUploaderBinder = (FileUploader.FileUploaderBinder) service;
 -            } else {
 -                return;
              }
 -
          }
  
          @Override
              }
          }
      };
 +
 +    /**
 +     *
 +     * Class for loading the version number
 +     *
 +     */
 +    private class LoadingVersionNumberTask extends AsyncTask<Void, Void, Integer> {
 +        protected Integer doInBackground(Void... args) {
 +            try {
 +                URL url = new URL("https://github.com/owncloud/android/raw/beta/apks/latest");
 +                BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
 +
 +                Integer latestVersion = Integer.parseInt(in.readLine());
 +                in.close();
 +
 +                return latestVersion;
 +
 +            } catch (MalformedURLException e) {
 +                e.printStackTrace();
 +            } catch (IOException e) {
 +                e.printStackTrace();
 +            }
 +            return -1;
 +        }
 +    }
  }