Android Open Source - appsensor App Usage Sync Adapter






From Project

Back to project page appsensor.

License

The source code is released under:

GNU General Public License

If you think the Android project appsensor 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 de.dfki.appsensor.sync;
// w  w  w .  ja v  a 2  s  .  c  o  m
import java.util.List;

import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.SyncResult;
import android.os.Bundle;
import android.text.format.DateUtils;
import de.dfki.appsensor.data.db.AppUsageEventDAO;
import de.dfki.appsensor.data.entities.AppUsageEvent;
import de.dfki.appsensor.logging.AppUsageLogger;
import de.dfki.appsensor.logging.DeviceObserver;
import de.dfki.appsensor.logging.LocationObserver;
import de.dfki.appsensor.utils.CSVCompressor;
import de.dfki.appsensor.utils.NetUtils;
import de.dfki.appsensor.utils.Utils;

/**
 * SyncAdapter implementation for syncing sample SyncAdapter contacts to the
 * platform ContactOperations provider.
 * 
 * @author Matthias Boehmer, matthias.boehmer@dfki.de
 */
public class AppUsageSyncAdapter extends AbstractThreadedSyncAdapter {
   
  /**
  *  This is a limit for the maximum number of simultaneously synced app usage
  *  records. It is necessary, because a lot of records to be synced results in
  *  a too much data transfer, which results in http client timeout and the sync
  *  fails forever.
  */
  private static int MAX_SYNCED_APP_USAGES = 50;
  
    private final Context mContext;
    
    public AppUsageSyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        mContext = context;
    }
    
    
    
    private boolean sendAppHistoryToServer() {
    final NetUtils netUtils = new NetUtils(mContext);

    // get everything from the database
    final AppUsageEventDAO d = new AppUsageEventDAO(mContext);
    d.openWrite();
    
    boolean result=false;
    //this is loop is terminated when there are no more portions of records to be synced 
    // or the sync failed at some point
    // There is a just in case limit of 100 iterations, so that it does not loop infinitely
    // in some exceptional case
    int loopLimit = 1;
    while(loopLimit < 100) {
      loopLimit++;
      final List<AppUsageEvent> notSynced = d.getAndUpdateNonSyncedInterestsAsEntities(MAX_SYNCED_APP_USAGES);
      Utils.d(this, "Non synced # of app usage events:" + notSynced.size());
      
      // only send something if we have something in the database
      if (notSynced.size() > AppUsageLogger.MIN_INTERACTIONS_TO_SEND) {
        
        CSVCompressor compressor = new CSVCompressor();
        
        // add header
        compressor.add(new String[]{
            "did", // IMEI based device id
            "iid", // installation id
            "res", // resolution
            "mod", // model name
            "api", // api level
            "apv", // appsensor version
            "eve", // event type
            "pac", // package name
            "sta", // timestamp of starttime in milliseconds UTC
            "off", // offset to UTC in hours
            "run", // runtime of app in milliseconds
            "lon", // longitude of interaction
            "lat", // latitude of interaction
            "alt", // altitude
            "spe", // speed
            "ccd", // country code of this location
            "acc", // accuracy of location information
            "pos", // power state
            "pol", // power level
            "blu", // bluetooth state
            "wif", // wifi state 
            "hea", // headphones state
            "ori", // orientation of the device
            "lso"  // timestamp of last screen on        
        });
        
        // add rows from interaction history
        for (AppUsageEvent aue : notSynced) {
          Utils.d(this, "added " + aue.toStringLong());
          compressor.add(new String[]{
            DeviceObserver.hashedIMEI(mContext),
            DeviceObserver.id(mContext),
            DeviceObserver.resolution(mContext),
            DeviceObserver.modelName(),
            "" + DeviceObserver.apiLevel(),
            "" + DeviceObserver.appsensorVersion(mContext),
            "" + aue.eventtype,
            aue.packageName,
            "" + aue.starttime, // starttime in UTC milliseconds
            "" + Utils.utcOFF(), // offset to UTC in hours
            "" + aue.runtime,
            "" + aue.longitude,
            "" + aue.latitude,
            "" + aue.altitude,
            "" + aue.speed,
            "" + LocationObserver.countryCode,
            "" + aue.accuracy,
            "" + aue.powerstate,
            "" + aue.powerlevel,
            "" + aue.bluetoothstate,
            "" + aue.wifistate,
            "" + aue.headphones,
            "" + aue.orientation,
            "" + aue.timestampOfLastScreenOn
          });
        }
        
        String sentApps = compressor.getCSV();
        // send to the server and remove from local db if worked
        result = netUtils.postToURL(NetUtils.getScriptURL(getContext()), sentApps);
        
        Utils.d(this,sentApps);
        
        // update sync status to server persisted status 
        // only if the send was successful
        if (result) {
          int number = d.updateSyncingToServerPersisted();
          Utils.d(this, "Persisted # of app usages:" + number);
        }
        else break; // if the sync failed, stop the whole sync operation of all portions of records
      }
      else {
        Utils.d(this, "only " + notSynced.size() + " entries, but min is " +  AppUsageLogger.MIN_INTERACTIONS_TO_SEND);
        result = true;
        break; // no more portions of records to be sent, so stop the syncing of portions of records
      }
    }
    
    // clear too old server persisted records
    int rowsAffected = d.deleteOldSyncedUsageEvents(Utils.getCurrentTime() - (DateUtils.HOUR_IN_MILLIS * 6));
    Utils.d(this, "Deleted # of old persisted app usage:" + rowsAffected);
    d.close();
    return result;
  }
    
    
    
//  /**
//   * Sends the history to the server. 
//   */
//  private boolean sendAppHistoryToServer() {
//    Utils.d(this, "trying sendAppHistoryToServer");
//    
//    final NetUtils netUtils = new NetUtils(mContext);
//
//    // get everything from the database
//    final AppUsageEventDAO d = new AppUsageEventDAO(mContext);
//    d.openWrite();
//    
//    final List<AppUsageEvent> notSynced = d.getAndUpdateNonSyncedInterestsAsEntities();
//    Utils.d(this, "number of not-synced app usage events: " + notSynced.size());
//    
//    boolean result;
//    // only send something if we have something in the database
//    if (notSynced.size() > AppUsageLogger.MIN_INTERACTIONS_TO_SEND) {
//      
//      CSVCompressor compressor = new CSVCompressor();
//      
//      // add header
//      compressor.add(new String[]{
//          "did", // IMEI based device id
//          "iid", // installation id
//          "res", // resolution
//          "mod", // model name
//          "api", // api level
//          "apv", // appsensor version
//          "eve", // event type
//          "pac", // package name
//          "sta", // timestamp of starttime in milliseconds UTC
//          "off", // offset to UTC in hours
//          "run", // runtime of app in milliseconds
//          "lon", // longitude of interaction
//          "lat", // latitude of interaction
//          "alt", // altitude
//          "spe", // speed
//          "ccd", // country code of this location
//          "acc", // accuracy of location information
//          "pos", // power state
//          "pol", // power level
//          "blu", // bluetooth state
//          "wif", // wifi state 
//          "hea", // headphones state
//          "ori", // orientation of the device
//          "lso"  // timestamp of last screen on
//      });
//      
//      // add rows from interaction history
//      for (AppUsageEvent aue : notSynced) {
//        compressor.add(new String[]{
//          DeviceObserver.hashedIMEI(mContext),
//          DeviceObserver.id(mContext),
//          DeviceObserver.resolution(mContext),
//          DeviceObserver.modelName(),
//          "" + DeviceObserver.apiLevel(),
//          "" + DeviceObserver.appsensorVersion(mContext),
//          "" + aue.eventtype,
//          aue.packageName,
//          "" + aue.starttime, // starttime in UTC milliseconds
//          "" + Utils.utcOFF(), // offset to UTC in hours
//          "" + aue.runtime,
//          "" + aue.longitude,
//          "" + aue.latitude,
//          "" + aue.altitude,
//          "" + aue.speed,
//          "" + LocationObserver.countryCode,
//          "" + aue.accuracy,
//          "" + aue.powerstate,
//          "" + aue.powerlevel,
//          "" + aue.bluetoothstate,
//          "" + aue.wifistate,
//          "" + aue.headphones,
//          "" + aue.orientation,
//          "" + aue.timestampOfLastScreenOn
//        });
//      }
//      
//      
//      // send to the server and remove from local db if worked
//      result = netUtils.postToURL(NetUtils.getScriptURL(getContext()), compressor.getCSV());
//      
//      // update sync status to server persisted status 
//      // only if the send was successful
//      if (result) {
//        int number = d.updateSyncingToServerPersisted();
//        Utils.d(this, "Persisted # of app usages:" + number);
//      }
//    }
//    else {
//      result = true;
//    }
//    // clear too old server persisted records
//    int rowsAffected = d.deleteOldSyncedUsageEvents(Utils.getCurrentTime() - (DateUtils.HOUR_IN_MILLIS * 6));
//    Utils.d(this, "Deleted # of old persisted app usage:" + rowsAffected);
//    d.close();
//    return result;
//  }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority,
        ContentProviderClient provider, SyncResult syncResult) {
      
      Utils.d(this, "performing sync of app usage");
      
      if(!sendAppHistoryToServer()) {
        Utils.d(this, "Sync of app usage failed");
        syncResult.stats.numIoExceptions++;
      }
    }
}




Java Source Code List

de.dfki.appsensor.backup.InstallationBackupAgent.java
de.dfki.appsensor.backup.WrapperBackupAgent.java
de.dfki.appsensor.data.AppUsageProvider.java
de.dfki.appsensor.data.db.AppUsageEventDAO.java
de.dfki.appsensor.data.db.GeneralDAO.java
de.dfki.appsensor.data.entities.AppUsageEvent.java
de.dfki.appsensor.logging.AppUsageLogger.java
de.dfki.appsensor.logging.BackgroundService.java
de.dfki.appsensor.logging.DeviceObserver.java
de.dfki.appsensor.logging.HardwareObserver.java
de.dfki.appsensor.logging.LocationObserver.java
de.dfki.appsensor.logging.ServiceStarter.java
de.dfki.appsensor.sync.AppUsageSyncAdapter.java
de.dfki.appsensor.sync.AppUsageSyncService.java
de.dfki.appsensor.sync.AuthenticationService.java
de.dfki.appsensor.sync.Authenticator.java
de.dfki.appsensor.sync.SyncThread.java
de.dfki.appsensor.ui.HomeActivity.java
de.dfki.appsensor.ui.SettingsActivity.java
de.dfki.appsensor.utils.App.java
de.dfki.appsensor.utils.CSVCompressor.java
de.dfki.appsensor.utils.MyDBHelper.java
de.dfki.appsensor.utils.NetUtils.java
de.dfki.appsensor.utils.UIUtils.java
de.dfki.appsensor.utils.Utils.java