@Override public void run(MediaSet baseSet) { final int total = baseSet.getTotalMediaItemCount(); final SmallItem[] buf = new SmallItem[total]; // Separate items to two sets: with or without lat-long. final double[] latLong = new double[2]; baseSet.enumerateTotalMediaItems( new MediaSet.ItemConsumer() { public void consume(int index, MediaItem item) { if (index < 0 || index >= total) return; SmallItem s = new SmallItem(); s.path = item.getPath(); item.getLatLong(latLong); s.lat = latLong[0]; s.lng = latLong[1]; buf[index] = s; } }); final ArrayList<SmallItem> withLatLong = new ArrayList<SmallItem>(); final ArrayList<SmallItem> withoutLatLong = new ArrayList<SmallItem>(); final ArrayList<Point> points = new ArrayList<Point>(); for (int i = 0; i < total; i++) { SmallItem s = buf[i]; if (s == null) continue; if (GalleryUtils.isValidLocation(s.lat, s.lng)) { withLatLong.add(s); points.add(new Point(s.lat, s.lng)); } else { withoutLatLong.add(s); } } ArrayList<ArrayList<SmallItem>> clusters = new ArrayList<ArrayList<SmallItem>>(); int m = withLatLong.size(); if (m > 0) { // cluster the items with lat-long Point[] pointsArray = new Point[m]; pointsArray = points.toArray(pointsArray); int[] bestK = new int[1]; int[] index = kMeans(pointsArray, bestK); for (int i = 0; i < bestK[0]; i++) { clusters.add(new ArrayList<SmallItem>()); } for (int i = 0; i < m; i++) { clusters.get(index[i]).add(withLatLong.get(i)); } } ReverseGeocoder geocoder = new ReverseGeocoder(mContext); mNames = new ArrayList<String>(); boolean hasUnresolvedAddress = false; mClusters = new ArrayList<ArrayList<SmallItem>>(); for (ArrayList<SmallItem> cluster : clusters) { String name = generateName(cluster, geocoder); if (name != null) { mNames.add(name); mClusters.add(cluster); } else { // move cluster-i to no location cluster withoutLatLong.addAll(cluster); hasUnresolvedAddress = true; } } if (withoutLatLong.size() > 0) { mNames.add(mNoLocationString); mClusters.add(withoutLatLong); } if (hasUnresolvedAddress) { mHandler.post( new Runnable() { public void run() { Toast.makeText(mContext, R.string.no_connectivity, Toast.LENGTH_LONG).show(); } }); } }