Skip to content

Commit

Permalink
retweet improvements.
Browse files Browse the repository at this point in the history
added UCD data profiling library, not enabled yet.
  • Loading branch information
mariotaku committed Oct 15, 2012
1 parent f9d4339 commit 2822280
Show file tree
Hide file tree
Showing 68 changed files with 14,405 additions and 27 deletions.
85 changes: 85 additions & 0 deletions src/edu/ucdavis/earlybird/ProfilingUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package edu.ucdavis.earlybird;

import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.Constants;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.BatteryManager;
import android.util.Log;

public class ProfilingUtil {
static final boolean DEBUG = BuildConfig.DEBUG;

public static final String FILE_NAME_PROFILE = "Profile";
public static final String FILE_NAME_LOCATION = "Location";
public static final String FILE_NAME_APP = "App";

public static boolean log(String msg) {
if (DEBUG) {
StackTraceElement ste = new Throwable().fillInStackTrace()
.getStackTrace()[1];
String fullname = ste.getClassName();
String name = fullname.substring(fullname.lastIndexOf('.'));
String tag = name + "." + ste.getMethodName();
Log.v(tag, msg);
return true;
} else
return false;
}


public static void profiling(final Context context, final long accountID, final String text) {
profiling(context, accountID + "_" + FILE_NAME_PROFILE, text);
}

public static void profiling(final Context context, final String name, final String text) {
if (context == null) return;
final SharedPreferences prefs = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
if (!prefs.getBoolean(Constants.PREFERENCE_KEY_UCD_DATA_PROFILING, false)) return;
final String filename = name + ".csv";
new Thread() {
@Override
public void run() {
try {
final FileOutputStream fos = context.openFileOutput(filename, Context.MODE_APPEND);
if (fos == null) return;
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write("[" + System.currentTimeMillis() + "], " + text
+ "\n");
bw.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}

public static boolean isCharging(Context context) {
if (context == null) return false;
final Intent intent = context.registerReceiver(null, new IntentFilter(
Intent.ACTION_BATTERY_CHANGED));
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
return plugged == BatteryManager.BATTERY_PLUGGED_AC
|| plugged == BatteryManager.BATTERY_PLUGGED_USB;
}

public static boolean isOnWifi(Context context) {
if (context == null) return false;
final ConnectivityManager conn = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo networkInfo = conn.getActiveNetworkInfo();

return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
networkInfo.isConnected();
}
}
104 changes: 104 additions & 0 deletions src/edu/ucdavis/earlybird/UCDService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package edu.ucdavis.earlybird;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;

/**
* Request location ONCE per WAKE_PERIOD_IN_MILLI.
*/
public class UCDService extends Service {

public static final long LOCATION_PERIOD_IN_MILLI = 15 * 60 * 1000;
public static final String ACTION_GET_LOCATION = "edu.ucdavis.earlybird.GET_LOCATION";
private LocationManager mLocationManager;
private FineLocationListener mFineLocationListener;
private AlarmManager mAlarmManager;
private AlarmReceiver mAlarmReceiver;
private PendingIntent StartIntent;

@Override
public void onCreate() {
super.onCreate();

ProfilingUtil.log("onCreate");
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mFineLocationListener = new FineLocationListener();
mAlarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE);

mAlarmReceiver = new AlarmReceiver();
IntentFilter myFilter = new IntentFilter();
myFilter.addAction(ACTION_GET_LOCATION);
registerReceiver(mAlarmReceiver, myFilter);

Intent intent = new Intent(ACTION_GET_LOCATION);
StartIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), LOCATION_PERIOD_IN_MILLI,
StartIntent);

// Upload Service
Intent i = new Intent(UploadReceiver.ACTION_UPLOAD_PROFILE);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 12 * 60 * 60 * 1000, pi);
}

private final class AlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
ProfilingUtil.log("AlarmReceiver");
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
final String provider = mLocationManager.getBestProvider(criteria,
true);
mLocationManager.requestLocationUpdates(provider, 0, 0,
mFineLocationListener);
}
}

private final class FineLocationListener implements LocationListener {

@Override
public void onLocationChanged(Location location) {
ProfilingUtil.profiling(UCDService.this, ProfilingUtil.FILE_NAME_LOCATION, location.getTime() + ","
+ location.getLatitude() + "," + location.getLongitude() + ","
+ location.getProvider());
ProfilingUtil.log(location.getTime() + "," + location.getLatitude() + ","
+ location.getLongitude() + "," + location.getProvider());

mLocationManager.removeUpdates(mFineLocationListener);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
ProfilingUtil.log("onStatusChanged");
}

@Override
public void onProviderEnabled(String provider) {
ProfilingUtil.log("onProviderEnabled");
}

@Override
public void onProviderDisabled(String provider) {
ProfilingUtil.log("onProviderDisabled");
}
}

@Override
public IBinder onBind(Intent intent) {
throw new IllegalStateException("Not implemented.");
}
}
22 changes: 22 additions & 0 deletions src/edu/ucdavis/earlybird/UploadReceiver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package edu.ucdavis.earlybird;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class UploadReceiver extends BroadcastReceiver {
public static boolean isWifi = false;
public static boolean isCharging = false;

public static final String ACTION_UPLOAD_PROFILE = "edu.ucdavis.earlybird.UPLOAD_PROFILE";

@Override
public void onReceive(Context context, Intent intent) {
isWifi = ProfilingUtil.isOnWifi(context.getApplicationContext());
isCharging = ProfilingUtil.isCharging(context.getApplicationContext());

if (isWifi && isCharging) {
new UploadTask(context).execute();
}
}
}
126 changes: 126 additions & 0 deletions src/edu/ucdavis/earlybird/UploadTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package edu.ucdavis.earlybird;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.SocketException;
import java.util.Calendar;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPConnectionClosedException;
import org.apache.commons.net.ftp.FTPReply;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.preference.PreferenceManager;
import android.provider.Settings.Secure;

public class UploadTask extends AsyncTask<Void, Void, Void> {

private static final String LAST_UPLOAD_DATE = "last_upload_time";
private static final double MILLSECS_HALF_DAY = 1000 * 60 * 60 * 12;

private static final String FTP_PROFILE_SERVER = "earlybird_profile.metaisle.com";
private static final String FTP_USERNAME = "profile";
private static final String FTP_PASSWORD = "profile";

private final String device_id;
private final Context context;

public UploadTask(Context context) {
this.context = context;
device_id = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
}

@Override
protected Void doInBackground(Void... params) {
final SharedPreferences prefs = context.getSharedPreferences("ucd_data_profiling",
Context.MODE_PRIVATE);

if (prefs.contains(LAST_UPLOAD_DATE)) {
final long lastUpload = prefs.getLong(LAST_UPLOAD_DATE, System.currentTimeMillis());
final double deltaDays = ((double) (System.currentTimeMillis() - lastUpload))
/ (MILLSECS_HALF_DAY * 2);
if (deltaDays < 1) {
ProfilingUtil.log("Uploaded less than 1 day ago.");
return null;
}
}

final File root = context.getFileStreamPath("");
final File[] files = root.listFiles();

try {
uploadToFTP(files);
prefs.edit().putLong(LAST_UPLOAD_DATE, System.currentTimeMillis()).commit();
} catch (Exception ex) {
}
return null;
}

private boolean uploadToFTP(File... files) {

final FTPClient ftp = new FTPClient();

ftp.setDefaultTimeout(30000);

try {
ftp.connect(FTP_PROFILE_SERVER, 21);
int reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ProfilingUtil.log("FTP connect fail");
ftp.disconnect();
} else {
if (ftp.login(FTP_USERNAME, FTP_PASSWORD)) {
ftp.enterLocalPassiveMode();
ProfilingUtil.log("FTP connect OK");
ftp.setFileType(FTP.BINARY_FILE_TYPE);
Calendar now = Calendar.getInstance();
for (final File file : files) {
if (!file.isFile() || file.length() <= 0) continue;
final FileInputStream fis = new FileInputStream(file);
final String filename = file.getName();
final String profile_type = filename.substring(0, filename.indexOf('.'));
final String file_type = filename.substring(filename.indexOf('.'));
final boolean working_dir_exists = ftp.changeWorkingDirectory("/profile/" + device_id + "/" + profile_type);
if (!working_dir_exists) {
ProfilingUtil.log("create user folder : " + "/profile/"
+ device_id + "/" + profile_type);
ftp.makeDirectory("/profile/" + device_id);
ftp.makeDirectory("/profile/" + device_id + "/"
+ profile_type);
}
final String upload_file_name = "/profile/" + device_id + "/" + profile_type
+ "/" + now.getTimeInMillis() + file_type;

ftp.setFileType(FTP.BINARY_FILE_TYPE);
ftp.storeFile(upload_file_name, fis);
ProfilingUtil.log("Upload File : " + upload_file_name);
reply = ftp.getReplyCode();
ProfilingUtil.log("reply :" + reply);
if (reply == FTPReply.CLOSING_DATA_CONNECTION) {
ProfilingUtil.log("file upload success");
file.delete();
}
}
ftp.logout();
}
}
} catch (FTPConnectionClosedException e) {
ProfilingUtil.log("ftp connect error!!");
e.printStackTrace();
return false;
} catch (SocketException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
return false;

}

}
56 changes: 56 additions & 0 deletions src/org/apache/commons/net/MalformedServerReplyException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.commons.net;

import java.io.IOException;

/***
* This exception is used to indicate that the reply from a server
* could not be interpreted. Most of the NetComponents classes attempt
* to be as lenient as possible when receiving server replies. Many
* server implementations deviate from IETF protocol specifications, making
* it necessary to be as flexible as possible. However, there will be
* certain situations where it is not possible to continue an operation
* because the server reply could not be interpreted in a meaningful manner.
* In these cases, a MalformedServerReplyException should be thrown.
* <p>
* <p>
***/

public class MalformedServerReplyException extends IOException
{

private static final long serialVersionUID = 6006765264250543945L;

/*** Constructs a MalformedServerReplyException with no message ***/
public MalformedServerReplyException()
{
super();
}

/***
* Constructs a MalformedServerReplyException with a specified message.
* <p>
* @param message The message explaining the reason for the exception.
***/
public MalformedServerReplyException(String message)
{
super(message);
}

}
Loading

0 comments on commit 2822280

Please sign in to comment.