Android Open Source - PicSync Media Thread






From Project

Back to project page PicSync.

License

The source code is released under:

Apache License

If you think the Android project PicSync listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.darrenmowat.gdcu.service;
/*  w w  w . j  a  v a  2  s . c o m*/
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;

import org.json.JSONException;

import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.provider.MediaStore.MediaColumns;
import android.util.Log;

import com.darrenmowat.gdcu.GDCU;
import com.darrenmowat.gdcu.R;
import com.darrenmowat.gdcu.data.Database;
import com.darrenmowat.gdcu.drive.DriveApi;
import com.darrenmowat.gdcu.service.helpers.CloudSyncer;
import com.darrenmowat.gdcu.service.helpers.Media;
import com.darrenmowat.gdcu.utils.MD5Utils;
import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;

public class MediaThread extends Thread {

  private Database database;
  private CloudSyncer syncer;

  private MediaService service;

  private String email;
  private boolean shouldWait;

  private long lastTouchedAt;
  private boolean waiting;

  public boolean running = false;

  public MediaThread(MediaService service, String email, boolean shouldWait) {
    this.service = service;
    this.email = email;
    this.shouldWait = shouldWait;
    // Init Variables
    database = new Database(service);
  }

  @Override
  public void run() {
    try {
      running = true;
      // Connect to the database
      database.connect();

      lastTouchedAt = System.currentTimeMillis();
      try {
        String userToken = GoogleAuthUtil.getToken(service, email, DriveApi.DRIVE_SCOPE);
        syncer = new CloudSyncer(service, userToken);
        // We are going to wait for a bit before actually doing anything
        // Users tend to use there camera in bursts. So they may take 10
        // photos in 1 session.
        // Pause this thread for 1 - 2 minutes before proceeding
        boolean waiting = shouldWait;
        while (waiting) {
          log("Waiting for more photos before scanning for media");
          try {
            Thread.sleep(60 * 1000);
          } catch (InterruptedException e) {
            log("Interrupted whilst waiting");
            threadError(e);
            return;
          }
          long now = System.currentTimeMillis();
          long temp = lastTouchedAt - 60000;
          waiting = temp > now;
        }
        log("Stopped waiting for photos. Scanning Media.");
        findMediaForUpload();
        threadFinished();
      } catch (NoSuchAlgorithmException e) {
        threadError(e);
      } catch (UserRecoverableAuthException e) {
        threadError(e);
        return;
      } catch (IOException e) {
        threadError(e);
        return;
      } catch (GoogleAuthException e) {
        threadError(e);
        return;
      } catch (JSONException e) {
        threadError(e);
      }
    } finally {
      // Disconnect from the database
      database.disconnect();
    }
  }

  private void threadFinished() {
    running = false;
    service.onThreadFinished();
  }

  private void threadError(Exception e) {
    running = false;
    service.onThreadError(e);
  }

  public boolean isWaiting() {
    return waiting;
  }

  public synchronized void touch() {
    lastTouchedAt = System.currentTimeMillis();
    log("Last Touched At: " + new Date(lastTouchedAt).toString());
  }

  private static final String[] projection = { MediaColumns.DATA, MediaColumns.MIME_TYPE };

  private static final Uri PHOTO_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  private static final Uri VIDEO_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

  private void findMediaForUpload() throws IOException, NoSuchAlgorithmException, JSONException {

    String title = service.getResources().getString(
        R.string.pref_title_upload_status_uploading_scanning);
    String msg = service.getResources().getString(
        R.string.pref_summary_upload_status_uploading_scanning);

    ServiceUtils.sendServiceUpdate(title, msg);
    
    // First populate the hashes table in the database
    ArrayList<Media> media = new ArrayList<Media>();
    ArrayList<Media> temp = getAllMediaFromUri(PHOTO_URI);
    if (temp != null && temp.size() > 0) {
      for (Media m : temp) {
        if (m.getFile().exists() && m.getFile().length() > 0) {
          media.add(m);
        }
      }
      temp.clear();
    }
    temp = getAllMediaFromUri(VIDEO_URI);
    if (temp != null && temp.size() > 0) {
      for (Media m : temp) {
        if (m.getFile().exists() && m.getFile().length() > 0) {
          media.add(m);
        }
      }
      temp.clear();
    }

    // Get the MD5 hash of every file
    HashMap<String, Media> mediaHash = new HashMap<String, Media>();
    HashMap<String, Media> uploadedHash = new HashMap<String, Media>();
    for (int i = 0; i < media.size(); i++) {
      File f = media.get(i).getFile();
      String md5 = MD5Utils.getFileMd5(f);
      media.get(i).setMD5(md5);
      mediaHash.put(md5, media.get(i));
    }

    // This will ensure we have the latest
    // copy of the dir in our db
    syncer.sync();
    // Now figure out whats new on the device
    Cursor uploaded = database.getUploaded(new String[] { Database.UPLOADED_MD5 });
    while (uploaded.moveToNext()) {
      int md5_col = uploaded.getColumnIndexOrThrow(Database.UPLOADED_MD5);
      String md5 = uploaded.getString(md5_col);
      if (mediaHash.containsKey(md5)) {
        // This file has already been uploaded
        Media m = mediaHash.remove(md5);
        uploadedHash.put(md5, m);
      }
    }
    uploaded.close();

    // What ever is left in the mediaHash collection needs uploaded
    for (String key : mediaHash.keySet()) {
      Media m = mediaHash.get(key);
      database.addToPendingUploads(m.getFile().getAbsolutePath(), m.getFile().getName(),
          m.getMD5(), m.getType());
    }

    // Ensure we haven't added a duplicate to the database
    for (String key : uploadedHash.keySet()) {
      Media m = uploadedHash.get(key);
      database.removeFromPendingByMd5(m.getMD5());
    }

    // Lastly remove deleted files from pending uploads
    // Or remove files that are empty now
    Cursor pending = database.getPendingUploads(new String[] { Database.PENDING_UPLOADS_ID,
        Database.PENDING_UPLOADS_PATH });
    while (pending.moveToNext()) {
      int pathCol = pending.getColumnIndexOrThrow(Database.PENDING_UPLOADS_PATH);
      String path = pending.getString(pathCol);
      File f = new File(path);
      if (!f.exists() || f.length() == 0) {
        // This file has been deleted
        int idCol = pending.getColumnIndexOrThrow(Database.PENDING_UPLOADS_ID);
        database.removeFromPendingById(pending.getInt(idCol));
        log("File has been deleted: " + path);
      }
    }
    pending.close();

    // Print out pending uploads in development mode
    if (GDCU.DEVEL_BUILD) {
      pending = database.getPendingUploads(new String[] { Database.PENDING_UPLOADS_ID,
          Database.PENDING_UPLOADS_PATH });
      while (pending.moveToNext()) {
        int pathCol = pending.getColumnIndexOrThrow(Database.PENDING_UPLOADS_PATH);
        int idCol = pending.getColumnIndexOrThrow(Database.PENDING_UPLOADS_ID);
        String path = pending.getString(pathCol);
        int id = pending.getInt(idCol);
        log("Pending Upload: " + id + " " + path);
      }
      pending.close();
    }
  }

  private ArrayList<Media> getAllMediaFromUri(Uri uri) {
    ArrayList<Media> media = new ArrayList<Media>();
    Cursor cursor = service.getContentResolver().query(uri, projection, null, null, null);
    if (cursor == null) {
      return null;
    }
    while (cursor.moveToNext()) {
      int dataColumn = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
      String filePath = cursor.getString(dataColumn);
      int mimeTypeColumn = cursor.getColumnIndexOrThrow(MediaColumns.MIME_TYPE);
      String mimeType = cursor.getString(mimeTypeColumn);
      Media m = new Media(new java.io.File(filePath), mimeType);
      media.add(m);
    }
    cursor.close();
    return media;
  }

  private static void log(String msg) {
    Log.v("GDCU::MediaThread", msg);
  }
}




Java Source Code List

com.darrenmowat.gdcu.GDCU.java
com.darrenmowat.gdcu.Keys.java
com.darrenmowat.gdcu.activity.AuthActivity.java
com.darrenmowat.gdcu.activity.RenameFolderActivity.java
com.darrenmowat.gdcu.activity.SettingsActivity.java
com.darrenmowat.gdcu.activity.WebviewActivity.java
com.darrenmowat.gdcu.data.Database.java
com.darrenmowat.gdcu.data.Preferences.java
com.darrenmowat.gdcu.drive.DriveApi.java
com.darrenmowat.gdcu.otto.DataBus.java
com.darrenmowat.gdcu.otto.UploadStatusEventProducer.java
com.darrenmowat.gdcu.otto.UploadStatusEvent.java
com.darrenmowat.gdcu.security.PackageSecurityException.java
com.darrenmowat.gdcu.security.PackageSecurity.java
com.darrenmowat.gdcu.service.GalleryAlarmListener.java
com.darrenmowat.gdcu.service.GalleryObserver.java
com.darrenmowat.gdcu.service.MediaService.java
com.darrenmowat.gdcu.service.MediaThread.java
com.darrenmowat.gdcu.service.Notifier.java
com.darrenmowat.gdcu.service.ServiceUtils.java
com.darrenmowat.gdcu.service.UploadService.java
com.darrenmowat.gdcu.service.UploadThread.java
com.darrenmowat.gdcu.service.helpers.CloudSyncer.java
com.darrenmowat.gdcu.service.helpers.Media.java
com.darrenmowat.gdcu.service.helpers.ServiceIntents.java
com.darrenmowat.gdcu.service.helpers.ThreadCallbacks.java
com.darrenmowat.gdcu.tasks.GetTokenTask.java
com.darrenmowat.gdcu.tasks.RenameFolderTask.java
com.darrenmowat.gdcu.ui.ProgressDialogFragment.java
com.darrenmowat.gdcu.utils.HexConversions.java
com.darrenmowat.gdcu.utils.MD5Utils.java
com.darrenmowat.gdcu.utils.Preconditions.java