Use UIL, don't do caching on our own.
Advantages: * Initial setup time for icons is zero * We don't have to deal with it ourselves * We can use the default package icon while we load
This commit is contained in:
		
							parent
							
								
									0d6ec3a001
								
							
						
					
					
						commit
						017811fb92
					
				
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| [submodule "extern/Universal-Image-Loader"] | ||||
| 	path = extern/Universal-Image-Loader | ||||
| 	url = https://github.com/nostra13/Android-Universal-Image-Loader | ||||
							
								
								
									
										1
									
								
								extern/Universal-Image-Loader
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								extern/Universal-Image-Loader
									
									
									
									
										vendored
									
									
										Submodule
									
								
							| @ -0,0 +1 @@ | ||||
| Subproject commit 24ca7dd0dbaee8a011aad6195f33e840793e7df9 | ||||
| @ -2,3 +2,4 @@ proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project. | ||||
| 
 | ||||
| target=android-18 | ||||
| 
 | ||||
| android.library.reference.1=extern/Universal-Image-Loader/library | ||||
|  | ||||
| @ -70,6 +70,8 @@ import android.widget.BaseAdapter; | ||||
| 
 | ||||
| import org.fdroid.fdroid.compat.PackageManagerCompat; | ||||
| 
 | ||||
| import com.nostra13.universalimageloader.core.ImageLoader; | ||||
| 
 | ||||
| public class AppDetails extends ListActivity { | ||||
| 
 | ||||
|     private static final int REQUEST_INSTALL = 0; | ||||
| @ -406,12 +408,7 @@ public class AppDetails extends ListActivity { | ||||
| 
 | ||||
|         // Set the icon... | ||||
|         ImageView iv = (ImageView) findViewById(R.id.icon); | ||||
|         File icon = new File(DB.getIconsPath(this), app.icon); | ||||
|         if (icon.exists()) { | ||||
|             iv.setImageDrawable(new BitmapDrawable(icon.getPath())); | ||||
|         } else { | ||||
|             iv.setImageResource(android.R.drawable.sym_def_app_icon); | ||||
|         } | ||||
|         ImageLoader.getInstance().displayImage(app.repoAddress+"/icons/"+app.icon, iv); | ||||
| 
 | ||||
|         // Set the title and other header details... | ||||
|         TextView tv = (TextView) findViewById(R.id.title); | ||||
|  | ||||
| @ -125,6 +125,7 @@ public class DB { | ||||
|             compatible = false; | ||||
|             ignoreUpdates = false; | ||||
|             filtered = false; | ||||
|             repoAddress = null; | ||||
|         } | ||||
| 
 | ||||
|         // True when all the detail fields are populated, False otherwise. | ||||
| @ -207,6 +208,8 @@ public class DB { | ||||
|         // List of apks. | ||||
|         public List<Apk> apks; | ||||
| 
 | ||||
|         public String repoAddress; | ||||
| 
 | ||||
|         // Get the current version - this will be one of the Apks from 'apks'. | ||||
|         // Can return null if there are no available versions. | ||||
|         // This should be the 'current' version, as in the most recent stable | ||||
| @ -558,13 +561,6 @@ public class DB { | ||||
|         return ContextCompat.create(ctx).getExternalCacheDir(); | ||||
|     } | ||||
| 
 | ||||
|     public static File getIconsPath(Context ctx) { | ||||
|         File dp = getDataPath(ctx); | ||||
|         if (dp == null) | ||||
|             return null; | ||||
|         return new File(dp, "icons"); | ||||
|     } | ||||
| 
 | ||||
|     private Context mContext; | ||||
|     private Apk.CompatibilityChecker compatChecker = null; | ||||
| 
 | ||||
|  | ||||
| @ -19,7 +19,6 @@ | ||||
| package org.fdroid.fdroid; | ||||
| 
 | ||||
| import java.io.File; | ||||
| import java.io.FilenameFilter; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.Semaphore; | ||||
| @ -30,6 +29,13 @@ import android.util.Log; | ||||
| import android.content.Context; | ||||
| import android.content.SharedPreferences; | ||||
| 
 | ||||
| import com.nostra13.universalimageloader.utils.StorageUtils; | ||||
| import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache; | ||||
| import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator; | ||||
| import com.nostra13.universalimageloader.core.DisplayImageOptions; | ||||
| import com.nostra13.universalimageloader.core.ImageLoader; | ||||
| import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; | ||||
| 
 | ||||
| public class FDroidApp extends Application { | ||||
| 
 | ||||
|     @Override | ||||
| @ -69,7 +75,22 @@ public class FDroidApp extends Application { | ||||
|         ctx = getApplicationContext(); | ||||
|         DB.initDB(ctx); | ||||
|         UpdateService.schedule(ctx); | ||||
|      | ||||
| 
 | ||||
|         File cacheDir = new File(StorageUtils.getCacheDirectory(ctx), "icons"); | ||||
|         DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() | ||||
|             .cacheInMemory(true) | ||||
|             .cacheOnDisc(true) | ||||
|             .showImageOnLoading(android.R.drawable.sym_def_app_icon) | ||||
|             .showImageForEmptyUri(android.R.drawable.sym_def_app_icon) | ||||
|             .build(); | ||||
|         ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx) | ||||
|             .discCache(new UnlimitedDiscCache(cacheDir, new FileNameGenerator() { | ||||
|                 public String generate(String imageUri) { | ||||
|                     return imageUri.substring(imageUri.lastIndexOf('/') + 1); | ||||
|                 } } )) | ||||
|             .defaultDisplayImageOptions(defaultOptions) | ||||
|             .build(); | ||||
|         ImageLoader.getInstance().init(config); | ||||
|     } | ||||
| 
 | ||||
|     Context ctx; | ||||
| @ -125,6 +146,11 @@ public class FDroidApp extends Application { | ||||
|             try { | ||||
|                 DB db = DB.getDB(); | ||||
|                 apps = db.getApps(true); | ||||
|                 for (DB.Repo repo : db.getRepos()) | ||||
|                     for (DB.App app : apps) | ||||
|                         if (repo.id == app.apks.get(0).repo) | ||||
|                             app.repoAddress = repo.address; | ||||
| 
 | ||||
|             } finally { | ||||
|                 DB.releaseDB(); | ||||
|             } | ||||
|  | ||||
| @ -255,38 +255,6 @@ public class UpdateService extends IntentService implements ProgressListener { | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|             if (success) { | ||||
|                 File d = DB.getIconsPath(this); | ||||
|                 List<DB.App> toDownloadIcons = null; | ||||
|                 if (!d.exists()) { | ||||
|                     Log.d("FDroid", "Icons were wiped. Re-downloading all of them."); | ||||
|                     d.mkdirs(); | ||||
|                     toDownloadIcons = ((FDroidApp) getApplication()).getApps(); | ||||
|                 } else if (changes) { | ||||
|                     toDownloadIcons = acceptedapps; | ||||
|                 } | ||||
|                 if (toDownloadIcons != null) { | ||||
| 
 | ||||
|                     // Create a .nomedia file in the icons directory. For | ||||
|                     // recent Android versions this isn't necessary, because | ||||
|                     // they recognise the cache location. Older versions don't | ||||
|                     // though. | ||||
|                     File f = new File(d, ".nomedia"); | ||||
|                     if (!f.exists()) { | ||||
|                         try { | ||||
|                             f.createNewFile(); | ||||
|                         } catch (Exception e) { | ||||
|                             Log.d("FDroid", "Failed to create .nomedia"); | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     sendStatus(STATUS_INFO, | ||||
|                             getString(R.string.status_downloading_icons)); | ||||
|                     for (DB.App app : toDownloadIcons) | ||||
|                         getIcon(app, repos); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (success && changes) | ||||
|                 ((FDroidApp) getApplication()).invalidateAllApps(); | ||||
| 
 | ||||
| @ -348,52 +316,6 @@ public class UpdateService extends IntentService implements ProgressListener { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private void getIcon(final DB.App app, List<DB.Repo> repos) { | ||||
|         InputStream input = null; | ||||
|         OutputStream output = null; | ||||
|         try { | ||||
| 
 | ||||
|             File f = new File(DB.getIconsPath(this), app.icon); | ||||
|             if (f.exists()) | ||||
|                 return; | ||||
| 
 | ||||
|             if (app.apks.size() == 0) | ||||
|                 return; | ||||
|             String server = null; | ||||
|             for (DB.Repo repo : repos) | ||||
|                 if (repo.id == app.apks.get(0).repo) | ||||
|                     server = repo.address; | ||||
|             if (server == null) | ||||
|                 return; | ||||
| 
 | ||||
|             // Get it from the server... | ||||
|             URL u = new URL(server + "/icons/" + app.icon); | ||||
|             HttpURLConnection uc = (HttpURLConnection) u.openConnection(); | ||||
|             if (uc.getResponseCode() == 200) { | ||||
| 
 | ||||
|                 // Delete all other icons for the same app | ||||
|                 final File[] files = DB.getIconsPath(this).listFiles( | ||||
|                         new FilenameFilter() { | ||||
|                     @Override | ||||
|                     public boolean accept(final File d, final String n) { | ||||
|                         return n.matches(app.id+"\\.[0-9]+\\.png"); | ||||
|                     } | ||||
|                 } ); | ||||
|                 for (final File file : files) { | ||||
|                     if (!file.delete()) | ||||
|                         Log.e("FDroid", "Cannot remove icon file " + file.getAbsolutePath()); | ||||
|                 } | ||||
| 
 | ||||
|                 input = uc.getInputStream(); | ||||
|                 output = new FileOutputStream(f); | ||||
|                 Utils.copy(input, output); | ||||
|             } | ||||
|         } catch (Exception e) { | ||||
|         } finally { | ||||
|             Utils.closeQuietly(output); | ||||
|             Utils.closeQuietly(input); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Received progress event from the RepoXMLHandler. It could be progress | ||||
|  | ||||
| @ -17,6 +17,8 @@ import org.fdroid.fdroid.Preferences; | ||||
| import org.fdroid.fdroid.R; | ||||
| import org.fdroid.fdroid.compat.LayoutCompat; | ||||
| 
 | ||||
| import com.nostra13.universalimageloader.core.ImageLoader; | ||||
| 
 | ||||
| abstract public class AppListAdapter extends BaseAdapter { | ||||
| 
 | ||||
|     private List<DB.App> items = new ArrayList<DB.App>(); | ||||
| @ -77,7 +79,7 @@ abstract public class AppListAdapter extends BaseAdapter { | ||||
|         summary.setText(app.summary); | ||||
| 
 | ||||
|         layoutSummary(summary); | ||||
|         layoutIcon(icon, app); | ||||
|         ImageLoader.getInstance().displayImage(app.repoAddress+"/icons/"+app.icon, icon); | ||||
| 
 | ||||
|         int visibleOnCompact = compact ? View.VISIBLE : View.GONE; | ||||
|         int notVisibleOnCompact = compact ? View.GONE : View.VISIBLE; | ||||
| @ -118,22 +120,6 @@ abstract public class AppListAdapter extends BaseAdapter { | ||||
|         return convertView; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * If an icon exists on disc, we'll use that, otherwise default to the | ||||
|      * plain android app icon. | ||||
|      */ | ||||
|     private void layoutIcon(ImageView iconView, DB.App app) { | ||||
| 
 | ||||
|         File icn = new File(DB.getIconsPath(mContext), app.icon); | ||||
|         if (icn.exists() && icn.length() > 0) { | ||||
|             new Uri.Builder().build(); | ||||
|             iconView.setImageURI(Uri.parse(icn.getPath())); | ||||
|         } else { | ||||
|             iconView.setImageResource(android.R.drawable.sym_def_app_icon); | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * In compact view, the summary sites next to the icon, below the name. | ||||
|      * In non-compact view, it sits under the icon, with some padding pushing | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Daniel Martí
						Daniel Martí