From: tobiasKaminsky Date: Sat, 9 Aug 2014 08:20:07 +0000 (+0200) Subject: Merge branch 'develop' of https://github.com/tobiasKaminsky/android into develop X-Git-Tag: oc-android-1.7.0_signed~163^2~8^2~5 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/8c96447fe75afb512621a6c6bb134aa6852e9162?hp=c0dc4c42d71eb9593ff48a02a8af74bd7df8776e Merge branch 'develop' of https://github.com/tobiasKaminsky/android into develop Conflicts: src/com/owncloud/android/ui/adapter/FileListListAdapter.java --- diff --git a/.classpath b/.classpath index 7bc01d9a..fa15a286 100644 --- a/.classpath +++ b/.classpath @@ -1,9 +1,10 @@ - - + + + diff --git a/lint.xml b/lint.xml index ee0eead5..ce54dadc 100644 --- a/lint.xml +++ b/lint.xml @@ -1,3 +1,6 @@ + + + \ No newline at end of file diff --git a/res/layout/image_fragment.xml b/res/layout/image_fragment.xml new file mode 100644 index 00000000..340ee03b --- /dev/null +++ b/res/layout/image_fragment.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + diff --git a/res/layout/image_item.xml b/res/layout/image_item.xml new file mode 100644 index 00000000..bd9f8d71 --- /dev/null +++ b/res/layout/image_item.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 3cb2e19d..2bc0b281 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -49,8 +49,9 @@ Non se recibiu contido. Non hai nada para enviar. %1$s non ten permiso para acceder ao contido compartido Enviando - Aquí non hai nada. Envíe algo. + Aquí non hai nada. Envíe algo! Cargando... + Non hai ficheiros neste cartafol. Prema nun ficheiro para que amose a información adicional. Tamaño: Tipo: diff --git a/res/values-ja-rJP/strings.xml b/res/values-ja-rJP/strings.xml index 8a100a55..59cc9259 100644 --- a/res/values-ja-rJP/strings.xml +++ b/res/values-ja-rJP/strings.xml @@ -51,6 +51,7 @@ アップロード中 ここには何もありません。何かアップロードしてください。 読込中 ... + このフォルダにはファイルはありません。 ファイルをタップすると追加情報が表示されます。 サイズ: タイプ: @@ -250,4 +251,12 @@ サーバーからの応答を待っている間にエラーが発生しました。操作を完了することができません。 操作を完了することができません。サーバーが利用できません。 + 権限 %s がありません + ファイル名の変更 + ファイルを削除 + ファイルを共有 + ファイルの共有を解除 + ファイルを作成 + フォルダをアップロード + ファイルはサーバー上で利用できません diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index fec77a4f..9604d2b3 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -51,6 +51,7 @@ Uploaden Er bevindt zich hier niets. Upload een bestand! Laden ... + Er staan geen bestanden in deze map. Druk op een bestand om extra informatie weer te geven Grootte: Type: diff --git a/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java b/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java new file mode 100644 index 00000000..5b401c28 --- /dev/null +++ b/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java @@ -0,0 +1,172 @@ +package com.owncloud.android.ui.adapter; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; +import android.graphics.BitmapFactory; +import android.os.Environment; +import android.util.Log; + +import com.jakewharton.disklrucache.DiskLruCache; +import com.owncloud.android.BuildConfig; +import com.owncloud.android.utils.Log_OC; + +public class DiskLruImageCache { + + private DiskLruCache mDiskCache; + private CompressFormat mCompressFormat = CompressFormat.JPEG; + private int mCompressQuality = 70; + private static final int APP_VERSION = 1; + private static final int VALUE_COUNT = 1; + private static final String TAG = "DiskLruImageCache"; + + public DiskLruImageCache( Context context,String uniqueName, int diskCacheSize, + CompressFormat compressFormat, int quality ) { + try { + final File diskCacheDir = getDiskCacheDir(context, uniqueName ); + mDiskCache = DiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize ); + mCompressFormat = compressFormat; + mCompressQuality = quality; + } catch (IOException e) { + e.printStackTrace(); + } + } + + private boolean writeBitmapToFile( Bitmap bitmap, DiskLruCache.Editor editor ) + throws IOException, FileNotFoundException { + OutputStream out = null; + try { + out = new BufferedOutputStream( editor.newOutputStream( 0 ), Utils.IO_BUFFER_SIZE ); + return bitmap.compress( mCompressFormat, mCompressQuality, out ); + } finally { + if ( out != null ) { + out.close(); + } + } + } + + private File getDiskCacheDir(Context context, String uniqueName) { + + // 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 = + Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || + !Utils.isExternalStorageRemovable() ? + Utils.getExternalCacheDir(context).getPath() : + context.getCacheDir().getPath(); + + Log_OC.d("DiskCache", "create dir: " + cachePath + File.separator + uniqueName); + + return new File(cachePath + File.separator + uniqueName); + } + + public void put( String key, Bitmap data ) { + + DiskLruCache.Editor editor = null; + try { + editor = mDiskCache.edit( key ); + if ( editor == null ) { + return; + } + + if( writeBitmapToFile( data, editor ) ) { + mDiskCache.flush(); + editor.commit(); + if ( BuildConfig.DEBUG ) { + Log.d( "cache_test_DISK_", "image put on disk cache " + key ); + } + } else { + editor.abort(); + if ( BuildConfig.DEBUG ) { + Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + key ); + } + } + } catch (IOException e) { + if ( BuildConfig.DEBUG ) { + Log.d( "cache_test_DISK_", "ERROR on: image put on disk cache " + key ); + } + try { + if ( editor != null ) { + editor.abort(); + } + } catch (IOException ignored) { + } + } + + } + + public Bitmap getBitmap( String key ) { + + Bitmap bitmap = null; + DiskLruCache.Snapshot snapshot = null; + try { + + snapshot = mDiskCache.get( key ); + if ( snapshot == null ) { + return null; + } + final InputStream in = snapshot.getInputStream( 0 ); + if ( in != null ) { + final BufferedInputStream buffIn = + new BufferedInputStream( in, Utils.IO_BUFFER_SIZE ); + bitmap = BitmapFactory.decodeStream( buffIn ); + } + } catch ( IOException e ) { + e.printStackTrace(); + } finally { + if ( snapshot != null ) { + snapshot.close(); + } + } + + if ( BuildConfig.DEBUG ) { + Log.d( "cache_test_DISK_", bitmap == null ? "not found" : "image read from disk " + key); + } + + return bitmap; + + } + + public boolean containsKey( String key ) { + + boolean contained = false; + DiskLruCache.Snapshot snapshot = null; + try { + snapshot = mDiskCache.get( key ); + contained = snapshot != null; + } catch (IOException e) { + e.printStackTrace(); + } finally { + if ( snapshot != null ) { + snapshot.close(); + } + } + + return contained; + + } + + public void clearCache() { + if ( BuildConfig.DEBUG ) { + Log.d( "cache_test_DISK_", "disk cache CLEARED"); + } + try { + mDiskCache.delete(); + } catch ( IOException e ) { + e.printStackTrace(); + } + } + + public File getCacheFolder() { + return mDiskCache.getDirectory(); + } + +} \ No newline at end of file diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index b1e38e8b..03f5ddc7 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@ -17,14 +17,26 @@ */ package com.owncloud.android.ui.adapter; +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; import java.util.Vector; import android.accounts.Account; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; +<<<<<<< HEAD +import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.media.ThumbnailUtils; +import android.os.AsyncTask; +======= +import android.graphics.BitmapFactory; +import android.media.ThumbnailUtils; +>>>>>>> c0dc4c42d71eb9593ff48a02a8af74bd7df8776e import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; @@ -41,9 +53,21 @@ import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; +import com.owncloud.android.lib.common.OwnCloudAccount; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; +import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; import com.owncloud.android.ui.activity.ComponentsGetter; import com.owncloud.android.utils.DisplayUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; + /** * This Adapter populates a ListView with all files and folders in an ownCloud @@ -62,11 +86,144 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { private FileDataStorageManager mStorageManager; private Account mAccount; private ComponentsGetter mTransferServiceGetter; - + private final Object mDiskCacheLock = new Object(); + private DiskLruImageCache mDiskLruCache; + private boolean mDiskCacheStarting = true; + private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB + private CompressFormat mCompressFormat = CompressFormat.JPEG; + private int mCompressQuality = 70; + private OwnCloudClient mClient; + public FileListListAdapter(Context context, ComponentsGetter transferServiceGetter) { mContext = context; mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext); mTransferServiceGetter = transferServiceGetter; + + // Initialise disk cache on background thread + new InitDiskCacheTask().execute(); + } + + class InitDiskCacheTask extends AsyncTask { + @Override + protected Void doInBackground(File... params) { + synchronized (mDiskCacheLock) { + mDiskLruCache = new DiskLruImageCache(mContext, "thumbnailCache", DISK_CACHE_SIZE, mCompressFormat,mCompressQuality); + + try { + OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext); + mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, mContext); + } catch (AccountNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (AuthenticatorException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (OperationCanceledException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + mDiskCacheStarting = false; // Finished initialization + mDiskCacheLock.notifyAll(); // Wake any waiting threads + } + return null; + } + } + + class BitmapWorkerTask extends AsyncTask { + private final ImageView fileIcon; + + public BitmapWorkerTask(ImageView fileIcon) { + this.fileIcon = fileIcon; + } + + // Decode image in background. + @Override + protected Bitmap doInBackground(OCFile... params) { + OCFile file = params[0]; + final String imageKey = String.valueOf(file.getRemoteId()); + + // Check disk cache in background thread + Bitmap thumbnail = getBitmapFromDiskCache(imageKey); + + // Not found in disk cache + if (thumbnail == null) { + // Converts dp to pixel + Resources r = mContext.getResources(); + int px = (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics())); + + if (file.isDown()){ + Bitmap bitmap = BitmapFactory.decodeFile(file.getStoragePath()); + thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); + + // Add thumbnail to cache + addBitmapToCache(imageKey, thumbnail); + + } else { + // Download thumbnail from server + DefaultHttpClient httpclient = new DefaultHttpClient(); + try { + httpclient.getCredentialsProvider().setCredentials( + new AuthScope(mClient.getBaseUri().toString().replace("https://", ""), 443), + new UsernamePasswordCredentials(mClient.getCredentials().getUsername(), mClient.getCredentials().getAuthToken())); + + + // TODO change to user preview.png + HttpGet httpget = new HttpGet(mClient.getBaseUri() + "/ocs/v1.php/thumbnail?path=" + URLEncoder.encode(file.getRemotePath(), "UTF-8")); + HttpResponse response = httpclient.execute(httpget); + HttpEntity entity = response.getEntity(); + + if (entity != null) { + byte[] bytes = EntityUtils.toByteArray(entity); + Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); + + // Add thumbnail to cache + if (thumbnail != null){ + addBitmapToCache(imageKey, thumbnail); + } + + } + } catch(Exception e){ + e.printStackTrace(); + }finally { + httpclient.getConnectionManager().shutdown(); + } + } + } + return thumbnail; + } + + protected void onPostExecute(Bitmap bitmap){ + fileIcon.setImageBitmap(bitmap); + } + } + + public void addBitmapToCache(String key, Bitmap bitmap) { + synchronized (mDiskCacheLock) { + if (mDiskLruCache != null && mDiskLruCache.getBitmap(key) == null) { + mDiskLruCache.put(key, bitmap); + } + } + } + + public Bitmap getBitmapFromDiskCache(String key) { + synchronized (mDiskCacheLock) { + // Wait while disk cache is started from background thread + while (mDiskCacheStarting) { + try { + mDiskCacheLock.wait(); + } catch (InterruptedException e) {} + } + if (mDiskLruCache != null) { + return (Bitmap) mDiskLruCache.getBitmap(key); + } + } + return null; } @Override @@ -168,6 +325,24 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { } checkBoxV.setVisibility(View.VISIBLE); } +<<<<<<< HEAD + + // first set thumbnail according to Mimetype, prevents empty thumbnails + fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())); + + // get Thumbnail if file is image + if (file.isImage()){ + // Thumbnail in Cache? + Bitmap thumbnail = getBitmapFromDiskCache(String.valueOf(file.getRemoteId())); + if (thumbnail != null){ + fileIcon.setImageBitmap(thumbnail); + } else { + // generate new Thumbnail + new BitmapWorkerTask(fileIcon).execute(file); + } + } + +======= // generate Thumbnail if file is available local and image if (file.isDown() && file.isImage()){ @@ -180,12 +355,12 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { fileIcon.setImageResource(DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())); } +>>>>>>> c0dc4c42d71eb9593ff48a02a8af74bd7df8776e if (checkIfFileIsSharedWithMe(file)) { sharedWithMeIconV.setVisibility(View.VISIBLE); } } else { - fileSizeV.setVisibility(View.INVISIBLE); //fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength())); lastModV.setVisibility(View.VISIBLE); diff --git a/src/com/owncloud/android/ui/adapter/Utils.java b/src/com/owncloud/android/ui/adapter/Utils.java new file mode 100644 index 00000000..181cc925 --- /dev/null +++ b/src/com/owncloud/android/ui/adapter/Utils.java @@ -0,0 +1,35 @@ +package com.owncloud.android.ui.adapter; + +import java.io.File; + +import android.content.Context; +import android.os.Build; +import android.os.Environment; + +public class Utils { + public static final int IO_BUFFER_SIZE = 8 * 1024; + + private Utils() {}; + + public static boolean isExternalStorageRemovable() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + return Environment.isExternalStorageRemovable(); + } + return true; + } + + public static File getExternalCacheDir(Context context) { + if (hasExternalCacheDir()) { + return context.getExternalCacheDir(); + } + + // Before Froyo we need to construct the external cache dir ourselves + final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/"; + return new File(Environment.getExternalStorageDirectory().getPath() + cacheDir); + } + + public static boolean hasExternalCacheDir() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; + } + +} diff --git a/third_party/disklrucache-2.0.2.jar b/third_party/disklrucache-2.0.2.jar new file mode 100644 index 00000000..ca7907d0 Binary files /dev/null and b/third_party/disklrucache-2.0.2.jar differ