package cn.zadui.reader.service;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.Log;
import cn.zadui.reader.helper.FAQCalendar;
import cn.zadui.reader.helper.NetHelper;
import cn.zadui.reader.helper.Settings;
/**
* Used for collecting app usage.
* @author david
*
*/
public class UsageCollector {
public static final String HOUR_PREFER_STR="000000000000000000000000";
public static final String INI_USAGE_STR="0";
static final String TAG="UsageCollector";
public static void openApp(Context ctx){
long currentTime=System.currentTimeMillis();
long lastOpenTS=Settings.getLongPreferenceValue(ctx, Settings.PRE_LAST_OPENED_AT, currentTime);
//long interval=currentTime-lastOpenTS;
// Return if the interval to last opened less than 15 minutes.
//if (interval<15*60*1000) return;
String oldUsageStr=Settings.getStringPreferenceValue(ctx, Settings.PRE_USAGE,INI_USAGE_STR);
Log.d(TAG,oldUsageStr);
FAQCalendar lastOpened=new FAQCalendar(lastOpenTS);
FAQCalendar now=new FAQCalendar(currentTime);
if (now.getUnixDay()>lastOpened.getUnixDay()){
long distance=now.getUnixDay()-lastOpened.getUnixDay();
StringBuilder sb=new StringBuilder();
sb.append(oldUsageStr);
for(long i=0;i<distance-1;i++) sb.append("0");
sb.append("1");
Settings.updateStringPreferenceValue(ctx, Settings.PRE_USAGE, sb.toString());
}else{
Log.i(TAG,oldUsageStr);
char[] usageChars=oldUsageStr.toCharArray();
int count=Character.getNumericValue(usageChars[usageChars.length-1]);
usageChars[usageChars.length-1]=numberToChar(count+1);
Settings.updateStringPreferenceValue(ctx, Settings.PRE_USAGE, new String(usageChars));
}
Settings.updateLongPreferenceValue(ctx, Settings.PRE_LAST_OPENED_AT, System.currentTimeMillis());
// update hour prefer usage string
String old=Settings.getStringPreferenceValue(ctx, Settings.PRE_HOUR_PREFER_USAGE,HOUR_PREFER_STR);
Settings.updateStringPreferenceValue(ctx, Settings.PRE_HOUR_PREFER_USAGE, updateHourPreferUsageString(now,old));
}
public static String updateHourPreferUsageString(Calendar now,String old){
char[] preferUsageChars=old.toCharArray();
int whichHour=now.get(Calendar.HOUR_OF_DAY);
preferUsageChars[whichHour]=numberToChar(Character.getNumericValue(preferUsageChars[whichHour])+1);
return new String(preferUsageChars);
}
public static void resetCollectedData(Context ctx){
Settings.updateStringPreferenceValue(ctx, Settings.PRE_USAGE, INI_USAGE_STR);
Settings.updateStringPreferenceValue(ctx, Settings.PRE_HOUR_PREFER_USAGE,HOUR_PREFER_STR);
Settings.updateLongPreferenceValue(ctx, Settings.PRE_COLLECTION_STARTED_AT, System.currentTimeMillis());
}
/**
* TODO The upload process should be in a thread and started by an Activity or Service.
* @param ctx
*/
public static void uploadCollectedUsageDate(Context ctx){
String usageStr=Settings.getStringPreferenceValue(ctx, Settings.PRE_USAGE,INI_USAGE_STR);
if (usageStr.length()<3) return;
URL url;
try {
url = new URL(NetHelper.webPath("http", "/ping")); //"http://172.29.1.67:3389/collector");
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.setDoInput(true);
uc.setDoOutput(true);
uc.setRequestMethod("POST");
String data=generateHttpPostData(ctx);
Log.d(TAG,"upload data is => "+data);
uc.getOutputStream().write(data.getBytes("UTF-8"));
uc.getOutputStream().close();
if (uc.getResponseCode()==HttpURLConnection.HTTP_CREATED){
resetCollectedData(ctx);
}
uc.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void uploadUserComment(Context ctx){
String comment=Settings.getStringPreferenceValue(ctx, Settings.PRE_USER_COMMENTS, "");
if(comment.length()<10){
Settings.updateStringPreferenceValue(ctx, Settings.PRE_USER_COMMENTS, "");
return;
}
URL url;
try {
url = new URL(NetHelper.webPath("http", "/comments")); //"http://172.29.1.67:3389/collector");
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.setDoInput(true);
uc.setDoOutput(true);
uc.setRequestMethod("POST");
StringBuilder sb=new StringBuilder();
sb.append("comment[uid]=");
sb.append(getDeviceId(ctx));
sb.append("&comment[content]=");
sb.append(comment);
String data=sb.toString();
Log.d(TAG,"user comment is => "+data);
uc.getOutputStream().write(data.getBytes("UTF-8"));
uc.getOutputStream().close();
if (uc.getResponseCode()==HttpURLConnection.HTTP_CREATED){
Settings.updateStringPreferenceValue(ctx, Settings.PRE_USER_COMMENTS, "");
}
uc.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void nofityInstalled(Context ctx){
URL url;
try {
url = new URL(NetHelper.webPath("http", "/activate")); //"http://172.29.1.67:3389/collector");
Log.d(TAG,url.toString());
HttpURLConnection http = (HttpURLConnection) url.openConnection();
http.setDoInput(true);
http.setDoOutput(true);
http.setRequestMethod("POST");
StringBuilder sb=new StringBuilder();
sb.append("uid="+getDeviceId(ctx));
SimpleDateFormat df=new SimpleDateFormat("yyyyMMdd'T'HH:mm");
Date installed=new Date(Settings.getLongPreferenceValue(ctx, Settings.PRE_INSTALLED_AT, 0));
sb.append("&installed_at="+df.format(installed));
try {
PackageInfo pi = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
sb.append("&build="+String.valueOf(pi.versionCode));
} catch (NameNotFoundException e) {
e.printStackTrace();
}
String data=sb.toString();
Log.d(TAG,"POST User Active Date => "+data);
http.getOutputStream().write(data.getBytes("UTF-8"));
http.getOutputStream().close();
http.getOutputStream().close();
if (http.getResponseCode()==HttpURLConnection.HTTP_CREATED){
Log.d(TAG,"Activate response is=> " + String.valueOf(http.getResponseCode()));
//Settings.updateStringPreferenceValue(ctx, Settings.PRE_USER_COMMENTS, "");
}
http.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception ee){
ee.printStackTrace();
}
}
/**
* Ping string includes:
* uid
* this collection started at
* device information: os type and version; app version etc.
* usage string
* hour prefer usage string
* @param ctx
* @return
*/
public static String generateHttpPostData(Context ctx){
StringBuilder sb=new StringBuilder();
sb.append("pv=2");
sb.append("&uid="+getDeviceId(ctx));
SimpleDateFormat df=new SimpleDateFormat("yyyyMMdd'T'HH:mm");
Date d=new Date(Settings.getLongPreferenceValue(ctx, Settings.PRE_COLLECTION_STARTED_AT, 0));
Date installed=new Date(Settings.getLongPreferenceValue(ctx, Settings.PRE_INSTALLED_AT, 0));
sb.append("&installed_at="+df.format(installed));
sb.append("&from="+df.format(d));
sb.append("&dev[os][name]="+"android");
sb.append("&dev[os][codename]="+Build.VERSION.CODENAME);
sb.append("&dev[os][incremental]="+Build.VERSION.INCREMENTAL);
sb.append("&dev[os][release]="+Build.VERSION.RELEASE);
sb.append("&dev[os][sdk]="+String.valueOf(Build.VERSION.SDK_INT));
sb.append("&dev[model]="+Build.MODEL);
sb.append("&dev[device]="+Build.DEVICE);
sb.append("&app[package_name]="+ctx.getPackageName());
boolean testBuild=(ctx.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE)!=0;
sb.append("&app[debug]="+String.valueOf(testBuild));
PackageInfo pi=null;
try {
pi = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
sb.append("&app[version_code]="+String.valueOf(pi.versionCode));
//sb.append("&dev[device]="+Build.DEVICE);
//DisplayMetrics displaymetrics = new DisplayMetrics();
sb.append("&usage="+Settings.getStringPreferenceValue(ctx, Settings.PRE_USAGE, INI_USAGE_STR));
sb.append("&hour="+Settings.getStringPreferenceValue(ctx, Settings.PRE_HOUR_PREFER_USAGE, HOUR_PREFER_STR));
return sb.toString();
}
public static char numberToChar(int value){
if (value>9){
return (char)(value-9+64);
}else{
return Character.forDigit(value, 10);
}
}
public static String getDeviceId(Context ctx){
final TelephonyManager tm = (TelephonyManager)ctx.getSystemService(Context.TELEPHONY_SERVICE);
String tmDevice, tmSerial, tmPhone, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = "" + android.provider.Settings.Secure.getString(ctx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
//String deviceId = deviceUuid.toString();
return deviceUuid.toString();
}
private static final SimpleDateFormat RFC822 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", java.util.Locale.ENGLISH);
}