void checkForNewImagesInner(Context context, Settings settings) { Log.Info(LogTag, "Checking for new images to scale/etc/send"); var db = ImageDatabaseAndroid.GetSingleton(context); Image[] images = db.getItemsToUpload(); foreach (Image i in images) { string destfn = GetThumbnailPath(context, i); if (!File.Exists(destfn)) { scaleImage(i.sourcePath, destfn); } if (uploadImage(i, destfn, settings.authToken, (int)settings.defaultStream).Result) { db.markSent(i.id); if (settings.uploadNotifications) { Notifications.NotifyUpload(context, 200, true, "Uploaded image", "Uploaded image", "", i.sourcePath, destfn); } } } }
static public ImageDatabaseAndroid GetSingleton(Context context) { lock (s_lock) { if (s_global == null) { s_global = new ImageDatabaseAndroid(context.ApplicationContext); } return(s_global); } }
async Task doCheck(Context context, Settings settings) { if (!settings.enabled || settings.authToken.IsNullOrEmpty()) { Log.Info(LogTag, "App is disabled or not logged in; skipping download service check"); return; } Log.Info(LogTag, "Doing new files check on server"); // We pull the new check time up front because our snapshot of what images are available to // stream will be based on right now. // // FIXME: This isn't actually used right now; the REST call always pull the top 50. DateTimeOffset newCheckTime = DateTimeOffset.UtcNow; // Get a list of the user's subscribed streams. These are the ones we'll poll for new images. var subInfo = await Network.GetSubscriptionInfo(settings.authToken, (int)settings.userId); if (!subInfo.succeeded()) { return; } string subList = String.Join(",", subInfo.subscriptions.Select(s => s.id.ToString())); // Call to the server to get our list of images to pull. var json = await Network.HttpGetToJsonAsync(Settings.BaseUrl + "api/stream/" + subList + "/contents", settings.authToken); var model = new Protocol.StreamContents(json); if (model.error != null) { Log.Error(LogTag, "Error checking for images on the server"); return; } if (model.images.Length > 0) { // The total number of images we're waiting for in the media scanner callback. // This will be adjusted as we go for images we don't actually need to download. int imageCount = model.images.Length; // This will follow along behind our downloads and provide media server IDs that we // can feed to a notification, so that when the user taps on it, it'll take them to // that picture with their chosen app. // // This will also make the images available to the wider Android ecosystem by getting them // into the media scanner. // // We don't actually do a notification here until the last image, because otherwise // the user might get a flood of notifications if they've been offline or whatever. var completedImages = new Dictionary <string, int>(); int completedImagesTotal = 0; var scanner = new MediaScannerWrapper(context) { scanned = (string path, Uri uri, Protocol.StreamContents.Image imgdata) => { // Increment the count of per-user images. if (!completedImages.ContainsKey(imgdata.userLogin)) { completedImages[imgdata.userLogin] = 0; } ++completedImages[imgdata.userLogin]; ++completedImagesTotal; // If this is the last image, we will push out a notification. if (--imageCount == 0) { string message = GetNotificationMessage(completedImages, completedImagesTotal); if (settings.downloadNotifications) { Notifications.NotifyDownload(context, 100, true, message, message, "", uri); } } } }; IImageDatabase db = ImageDatabaseAndroid.GetSingleton(context); foreach (var img in model.images) { // If it's our image, don't download it. if (img.userLogin == settings.userName) { Log.Info(LogTag, String.Format("Image {0} was ours; skipping download", img.filename)); --imageCount; continue; } // Figure out where the image will go. Do a sanity check to make sure it doesn't contain an exploit. string imgpath = Path.Combine(GetPath(img.userLogin), img.filename); if (imgpath.Contains("..")) { Log.Error(LogTag, String.Format("Image name '{0}' is invalid. Skipping.", img.filename)); --imageCount; continue; } if (db.getImageByUserAndFileName(img.userLogin, img.filename) != null) { Log.Info(LogTag, String.Format("Skipping image '{0}' as we already have it in our database.", img.filename)); --imageCount; continue; } if (File.Exists(imgpath)) { Log.Info(LogTag, String.Format("Skipping download of image '{0}' as we already seem to have the file.", img.filename)); } else { Log.Info(LogTag, String.Format("Download image {0}/{1} to {2}", img.id, img.filename, imgpath)); await Network.HttpDownloadAsync(Settings.BaseUrl + "api/image/" + img.id, settings.authToken, imgpath); } db.addDownloadedFile(imgpath, img.filename, img.userLogin, img.uploadTime, img.comment); scanner.addFile(imgpath, img); } scanner.scan(); settings.lastCheck = newCheckTime; settings.commit(); } Log.Info(LogTag, "File check complete."); }
public GalleryAdapter(Context context) { _context = context; _db = ImageDatabaseAndroid.GetSingleton(_context); _users = _db.getUserSummaries(); }
public override void OnChange(bool selfChange) { // var newMedia = new List<Media>(); long lastImageTimestamp = _settings.lastImageProcessedTimestamp; long newLastTimestamp = -1; bool anyNew = false; var uri = MediaStore.Images.Media.ExternalContentUri; using (var cursor = _context.ContentResolver.Query( uri, new String[] { MediaStore.MediaColumns.Data, MediaStore.MediaColumns.MimeType, MediaStore.MediaColumns.DateAdded }, // Skip files downloaded by DownloadService MediaStore.MediaColumns.Data + " NOT LIKE ?", new String[] { DownloadService.storageRoot + "%" }, "date_added DESC" )) { int dataColumn = cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.Data); int mimeTypeColumn = cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.MimeType); int timestampColumn = cursor.GetColumnIndexOrThrow(MediaStore.MediaColumns.DateAdded); while (cursor.MoveToNext()) { if (cursor.IsNull(dataColumn)) { Console.WriteLine("PhotoMediaObserver.OnChange(): filePath is null, which indicates this row is invalid (deleted?). Skip this file."); continue; } string filePath = cursor.GetString(dataColumn); string mimeType = cursor.GetString(mimeTypeColumn); long timestamp = cursor.GetLong(timestampColumn); // This should only happen once because the records should be sorted, but >_> if (timestamp > newLastTimestamp) { newLastTimestamp = timestamp; } if (timestamp > lastImageTimestamp) { Log.Info(LogTag, "Found file: {0} {1}", filePath, mimeType); ImageDatabaseAndroid.GetSingleton(_context).addToUploadQueue(filePath, DateTimeOffset.UtcNow /*.AddMinutes(1)*/, ""); anyNew = true; } } } // Update? if (newLastTimestamp > lastImageTimestamp) { _settings.lastImageProcessedTimestamp = newLastTimestamp; _settings.commit(); } // If we found anything new, kick our services to get the pipeline moving. if (anyNew) { LifeSharpService.Instance.kickService <UploadService>(); } }