mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-17 04:00:48 +01:00
Merge branches 'master' and 'spice' of https://github.com/TwidereProject/Twidere-Android into spice
This commit is contained in:
commit
b27e4d86ca
@ -223,7 +223,11 @@ public interface SharedPreferenceConstants {
|
||||
@Preference(type = BOOLEAN, exportable = false)
|
||||
public static final String KEY_UCD_DATA_PROFILING = "ucd_data_profiling";
|
||||
@Preference(type = BOOLEAN, exportable = false)
|
||||
public static final String KEY_SPICE_DATA_PROFILING = "spice_data_profiling";
|
||||
@Preference(type = BOOLEAN, exportable = false)
|
||||
public static final String KEY_SHOW_UCD_DATA_PROFILING_REQUEST = "show_ucd_data_profiling_request";
|
||||
@Preference(type = BOOLEAN, exportable = false)
|
||||
public static final String KEY_SHOW_SPICE_DATA_PROFILING_REQUEST = "show_spice_data_profiling_request";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
|
||||
public static final String KEY_DISPLAY_SENSITIVE_CONTENTS = "display_sensitive_contents";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
|
||||
|
@ -595,6 +595,10 @@
|
||||
<service
|
||||
android:name="edu.ucdavis.earlybird.UCDService"
|
||||
android:settingsActivity=".activity.DataProfilingSettingsActivity"/>
|
||||
<!--SPICE-->
|
||||
<service
|
||||
android:name="edu.tsinghua.spice.SpiceService"
|
||||
android:settingsActivity=".activity.DataProfilingSettingsActivity"/>
|
||||
<service
|
||||
android:name=".service.DashClockHomeUnreadCountService"
|
||||
android:icon="@drawable/ic_extension_twidere"
|
||||
@ -720,6 +724,17 @@
|
||||
<action android:name="edu.ucdavis.earlybird.UPLOAD_PROFILE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<!--SPICE-->
|
||||
<receiver
|
||||
android:name="edu.tsinghua.spice.SpiceUploadReceiver"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
||||
<action android:name="edu.tsinghua.spice.UPLOAD_PROFILE"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
</application>
|
||||
|
||||
</manifest>
|
89
twidere/src/main/java/edu/tsinghua/spice/SpiceService.java
Normal file
89
twidere/src/main/java/edu/tsinghua/spice/SpiceService.java
Normal file
@ -0,0 +1,89 @@
|
||||
package edu.tsinghua.spice;
|
||||
|
||||
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.Location;
|
||||
import android.location.LocationManager;
|
||||
import android.os.IBinder;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
*
|
||||
* Request location ONCE per WAKE_PERIOD_IN_MILLI.
|
||||
*/
|
||||
public class SpiceService extends Service {
|
||||
|
||||
public static final long LOCATION_PERIOD_IN_MILLI = 15 * 60 * 1000;
|
||||
public static final String ACTION_GET_LOCATION = "edu.tsinghua.spice.GET_LOCATION";
|
||||
private LocationManager mLocationManager;
|
||||
private AlarmManager mAlarmManager;
|
||||
private LocationUpdateReceiver mAlarmReceiver;
|
||||
private PendingIntent locationIntent;
|
||||
private PendingIntent uploadIntent;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(final Intent intent) {
|
||||
throw new IllegalStateException("Not implemented.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
SpiceProfilingUtil.log(this, "onCreate");
|
||||
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||
mAlarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
|
||||
|
||||
mAlarmReceiver = new LocationUpdateReceiver();
|
||||
final IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_GET_LOCATION);
|
||||
registerReceiver(mAlarmReceiver, filter);
|
||||
|
||||
final Intent intent = new Intent(ACTION_GET_LOCATION);
|
||||
locationIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
|
||||
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), LOCATION_PERIOD_IN_MILLI,
|
||||
locationIntent);
|
||||
|
||||
// Upload Service
|
||||
final Intent i = new Intent(SpiceUploadReceiver.ACTION_UPLOAD_PROFILE);
|
||||
uploadIntent = PendingIntent.getBroadcast(this, 0, i, 0);
|
||||
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 12 * 60 * 60 * 1000,
|
||||
uploadIntent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mAlarmManager.cancel(locationIntent);
|
||||
unregisterReceiver(mAlarmReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private final class LocationUpdateReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
if (mLocationManager == null) return;
|
||||
SpiceProfilingUtil.log(context, "AlarmReceiver");
|
||||
final String provider = LocationManager.NETWORK_PROVIDER;
|
||||
if (mLocationManager.isProviderEnabled(provider)) {
|
||||
final Location location = mLocationManager.getLastKnownLocation(provider);
|
||||
if (location != null) {
|
||||
SpiceProfilingUtil.profile(SpiceService.this, SpiceProfilingUtil.FILE_NAME_LOCATION, location.getTime() + ","
|
||||
+ location.getLatitude() + "," + location.getLongitude() + "," + location.getProvider());
|
||||
SpiceProfilingUtil.log(context,
|
||||
location.getTime() + "," + location.getLatitude() + "," + location.getLongitude() + ","
|
||||
+ location.getProvider());
|
||||
SpiceProfilingUtil.profile(SpiceService.this, SpiceProfilingUtil.FILE_NAME_NETWORK, NetworkStateUtil.getConnectedType(SpiceService.this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package edu.tsinghua.spice;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import edu.tsinghua.spice.Task.SpiceAsyUploadTask;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
*/
|
||||
public class SpiceUploadReceiver extends BroadcastReceiver {
|
||||
|
||||
public static final String ACTION_UPLOAD_PROFILE = "edu.tsinghua.spice.UPLOAD_PROFILE";
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
final boolean isWifi = Utils.isOnWifi(context.getApplicationContext());
|
||||
final boolean isCharging = SpiceProfilingUtil.isCharging(context.getApplicationContext());
|
||||
|
||||
if (isWifi && isCharging) {
|
||||
new SpiceAsyUploadTask(context).execute();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
package edu.tsinghua.spice.Task;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceHttpUtil;
|
||||
import edu.tsinghua.spice.Utilies.SpiceIOUtil;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.copyStream;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
*/
|
||||
|
||||
public class SpiceAsyUploadTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private static final String PROFILE_SERVER_URL = "http://twidere-spice.mariotaku.org:18080/spice/usage";
|
||||
|
||||
private static final String LAST_UPLOAD_DATE = "last_upload_time";
|
||||
private static final double MILLSECS_HALF_DAY = 1000 * 60 * 60 * 12;
|
||||
|
||||
//private final String device_id;
|
||||
private final Context context;
|
||||
|
||||
private SpiceHttpUtil uploadClient;
|
||||
|
||||
public SpiceAsyUploadTask(final Context context) {
|
||||
this.context = context;
|
||||
// device_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
|
||||
}
|
||||
|
||||
|
||||
public void uploadMultipart(SpiceHttpUtil client, final File file) {
|
||||
|
||||
String fileName = file.getName();
|
||||
final String app_root = file.getParent();
|
||||
final File tmp_dir = new File(app_root + "/spice");
|
||||
if (!tmp_dir.exists()) {
|
||||
if (!tmp_dir.mkdirs()) {
|
||||
SpiceProfilingUtil.log(context, "cannot create folder spice, do nothing.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final File tmp = new File(tmp_dir, file.getName());
|
||||
file.renameTo(tmp);
|
||||
|
||||
try {
|
||||
client.connectForMultipart();
|
||||
client.addFilePart("file", fileName, SpiceIOUtil.readFile(tmp));
|
||||
client.finishMultipart();
|
||||
String serverResponseCode = client.getResponse();
|
||||
|
||||
|
||||
if (serverResponseCode.indexOf("00") > -1) {
|
||||
SpiceProfilingUtil.log(context, "server has already received file " + tmp.getName());
|
||||
tmp.delete();
|
||||
} else {
|
||||
SpiceProfilingUtil.log(context, "server does not receive file " + tmp.getName());
|
||||
putBackProfile(context, tmp, file);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
putBackProfile(context, tmp, file);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(final Void... params) {
|
||||
|
||||
final SharedPreferences prefs = context.getSharedPreferences("spice_data_profiling", Context.MODE_PRIVATE);
|
||||
|
||||
if (prefs.contains(LAST_UPLOAD_DATE)) {
|
||||
final long lastUpload = prefs.getLong(LAST_UPLOAD_DATE, System.currentTimeMillis());
|
||||
final double deltaDays = (System.currentTimeMillis() - lastUpload) / (MILLSECS_HALF_DAY * 2);
|
||||
if (deltaDays < 1) {
|
||||
SpiceProfilingUtil.log(context, "Last uploaded was conducted in 1 day ago.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final File root = context.getFilesDir();
|
||||
final File[] spiceFiles = root.listFiles(new SpiceFileFilter());
|
||||
uploadToServer(spiceFiles);
|
||||
prefs.edit().putLong(LAST_UPLOAD_DATE, System.currentTimeMillis()).commit();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private boolean uploadToServer(final File... files) {
|
||||
for (final File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
final String url = PROFILE_SERVER_URL;
|
||||
SpiceProfilingUtil.log(context, url);
|
||||
uploadClient = new SpiceHttpUtil(url);
|
||||
uploadMultipart(uploadClient, file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void putBackProfile(final Context context, final File tmp, final File profile) {
|
||||
boolean success;
|
||||
if (profile.exists()) {
|
||||
try {
|
||||
final FileOutputStream os = new FileOutputStream(tmp, true);
|
||||
final FileInputStream is = new FileInputStream(profile);
|
||||
copyStream(is, os);
|
||||
is.close();
|
||||
os.close();
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
success = true;
|
||||
|
||||
if (success && tmp.renameTo(profile) && tmp.delete()) {
|
||||
SpiceProfilingUtil.log(context, "put profile back success");
|
||||
} else {
|
||||
SpiceProfilingUtil.log(context, "put profile back failed");
|
||||
}
|
||||
} else {
|
||||
if (tmp.renameTo(profile)) {
|
||||
SpiceProfilingUtil.log(context, "put profile back success");
|
||||
} else {
|
||||
SpiceProfilingUtil.log(context, "put profile back failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package edu.tsinghua.spice.Task;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/21/15.
|
||||
*/
|
||||
|
||||
public final class SpiceFileFilter implements FileFilter {
|
||||
|
||||
@Override
|
||||
public boolean accept(final File file) {
|
||||
return file.isFile() && "spi".equalsIgnoreCase(getExtension(file));
|
||||
}
|
||||
|
||||
static String getExtension(final File file) {
|
||||
final String name = file.getName();
|
||||
final int pos = name.lastIndexOf('.');
|
||||
if (pos == -1) return null;
|
||||
return name.substring(pos + 1);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/28/15.
|
||||
*/
|
||||
|
||||
public class NetworkStateUtil {
|
||||
|
||||
private static int getConnectedTypeValue(Context context) {
|
||||
if (context != null) {
|
||||
ConnectivityManager mConnectivityManager = (ConnectivityManager) context
|
||||
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
|
||||
if (mNetworkInfo != null && mNetworkInfo.isAvailable()) {
|
||||
return mNetworkInfo.getType();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String getConnectedType (Context context) {
|
||||
int type = -1;
|
||||
type = getConnectedTypeValue(context);
|
||||
String network = "unknown";
|
||||
switch (type) {
|
||||
case 0:
|
||||
network = "cellular";
|
||||
break;
|
||||
case 1:
|
||||
network = "wifi";
|
||||
break;
|
||||
case 2:
|
||||
network = "wimax";
|
||||
break;
|
||||
case 3:
|
||||
network = "ethernet";
|
||||
break;
|
||||
case 4:
|
||||
network = "bluetooth";
|
||||
break;
|
||||
case -1:
|
||||
network = "ERROR";
|
||||
break;
|
||||
default:
|
||||
network = "unknown";
|
||||
break;
|
||||
}
|
||||
return network;
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
|
||||
* Copyright (C) 2013 Surviving with Android (http://www.survivingwithandroid.com)
|
||||
*
|
||||
* Licensed 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.
|
||||
*/
|
||||
|
||||
public class SpiceHttpUtil {
|
||||
private String url;
|
||||
private HttpURLConnection con;
|
||||
private OutputStream os;
|
||||
|
||||
private String delimiter = "--";
|
||||
private String boundary = "SwA"+Long.toString(System.currentTimeMillis())+"SwA";
|
||||
|
||||
public SpiceHttpUtil(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void connectForMultipart() throws Exception {
|
||||
con = (HttpURLConnection) ( new URL(url)).openConnection();
|
||||
con.setRequestMethod("POST");
|
||||
con.setDoInput(true);
|
||||
con.setDoOutput(true);
|
||||
con.setRequestProperty("Connection", "Keep-Alive");
|
||||
con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
con.connect();
|
||||
os = con.getOutputStream();
|
||||
}
|
||||
|
||||
public void addFormPart(String paramName, String value) throws Exception {
|
||||
writeParamData(paramName, value);
|
||||
}
|
||||
|
||||
public void addFilePart(String paramName, String fileName, byte[] data) throws Exception {
|
||||
os.write( (delimiter + boundary + "\r\n").getBytes());
|
||||
os.write( ("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"\r\n" ).getBytes());
|
||||
os.write( ("Content-Type: application/octet-stream\r\n" ).getBytes());
|
||||
os.write( ("Content-Transfer-Encoding: binary\r\n" ).getBytes());
|
||||
os.write("\r\n".getBytes());
|
||||
|
||||
os.write(data);
|
||||
|
||||
os.write("\r\n".getBytes());
|
||||
}
|
||||
|
||||
public void finishMultipart() throws Exception {
|
||||
os.write( (delimiter + boundary + delimiter + "\r\n").getBytes());
|
||||
}
|
||||
|
||||
|
||||
public String getResponse() throws Exception {
|
||||
InputStream is = con.getInputStream();
|
||||
byte[] b1 = new byte[1024];
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
while ( is.read(b1) != -1)
|
||||
buffer.append(new String(b1));
|
||||
|
||||
con.disconnect();
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void writeParamData(String paramName, String value) throws Exception {
|
||||
|
||||
os.write( (delimiter + boundary + "\r\n").getBytes());
|
||||
os.write( "Content-Type: text/plain\r\n".getBytes());
|
||||
os.write( ("Content-Disposition: form-data; name=\"" + paramName + "\"\r\n").getBytes());;
|
||||
os.write( ("\r\n" + value + "\r\n").getBytes());
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
*/
|
||||
public class SpiceIOUtil {
|
||||
|
||||
public static byte[] readFile(String file) throws IOException {
|
||||
return readFile(new File(file));
|
||||
}
|
||||
|
||||
public static byte[] readFile(File file) throws IOException {
|
||||
// Open file
|
||||
RandomAccessFile f = new RandomAccessFile(file, "r");
|
||||
try {
|
||||
// Get and check length
|
||||
long longlength = f.length();
|
||||
int length = (int) longlength;
|
||||
if (length != longlength)
|
||||
throw new IOException("File size >= 2 GB");
|
||||
// Read file and return data
|
||||
byte[] data = new byte[length];
|
||||
f.readFully(data);
|
||||
return data;
|
||||
} finally {
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import edu.tsinghua.spice.Task.SpiceAsyUploadTask;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
*/
|
||||
|
||||
public class SpiceProfilingUtil {
|
||||
|
||||
public static final String FILE_NAME_PROFILE = "Profile_SPICE";
|
||||
public static final String FILE_NAME_LOCATION = "Location_SPICE";
|
||||
public static final String FILE_NAME_APP = "App_SPICE";
|
||||
public static final String FILE_NAME_NETWORK = "Network_SPICE";
|
||||
public static final String FILE_NAME_ONWIFI = "onWifi_SPICE";
|
||||
public static final String FILE_NAME_ONLAUNCH = "onLaunch_SPICE";
|
||||
|
||||
public static boolean isCharging(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (intent == null) return false;
|
||||
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
|
||||
}
|
||||
|
||||
public static boolean log(final Context context, final String msg) {
|
||||
if (Utils.isDebuggable(context)) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullname = ste.getClassName();
|
||||
final String name = fullname.substring(fullname.lastIndexOf('.'));
|
||||
final String tag = name + "." + ste.getMethodName();
|
||||
Log.d(tag, msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void profile(final Context context, final long account_id, final String text) {
|
||||
profile(context, account_id + "_" + FILE_NAME_PROFILE , text);
|
||||
}
|
||||
|
||||
public static void profile(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.KEY_SPICE_DATA_PROFILING, false)) return;
|
||||
|
||||
String uuid = "XXX";
|
||||
if (Build.SERIAL.length() > 0)
|
||||
uuid = Build.SERIAL;
|
||||
final String filename = uuid + "_" + name + ".spi";
|
||||
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(text + "," + System.currentTimeMillis() + "\n");
|
||||
bw.flush();
|
||||
fos.close();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
}.start();
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/26/15.
|
||||
*/
|
||||
|
||||
|
||||
public class TypeMapingUtil {
|
||||
|
||||
public static String getLinkType (int type) {
|
||||
String linkType = "";
|
||||
switch (type) {
|
||||
case TwidereLinkify.LINK_TYPE_MENTION:
|
||||
linkType = "mention";
|
||||
break;
|
||||
case TwidereLinkify.LINK_TYPE_CASHTAG:
|
||||
linkType = "cashTag";
|
||||
break;
|
||||
case TwidereLinkify.LINK_TYPE_LINK:
|
||||
linkType = "urlLink";
|
||||
break;
|
||||
case TwidereLinkify.LINK_TYPE_LIST:
|
||||
linkType = "userList";
|
||||
break;
|
||||
case TwidereLinkify.LINK_TYPE_STATUS:
|
||||
linkType = "status";
|
||||
break;
|
||||
case TwidereLinkify.LINK_TYPE_USER_ID:
|
||||
linkType = "userID";
|
||||
break;
|
||||
case TwidereLinkify.LINK_TYPE_HASHTAG:
|
||||
linkType = "hashTag";
|
||||
break;
|
||||
default:
|
||||
linkType = "unknown";
|
||||
break;
|
||||
}
|
||||
return linkType;
|
||||
}
|
||||
|
||||
|
||||
public static String getMediaType (int type) {
|
||||
String mediaType = "";
|
||||
switch (type) {
|
||||
case ParcelableMedia.TYPE_IMAGE:
|
||||
mediaType = "image";
|
||||
break;
|
||||
default:
|
||||
mediaType = "unknown";
|
||||
break;
|
||||
}
|
||||
return mediaType;
|
||||
}
|
||||
}
|
@ -106,6 +106,8 @@ import org.mariotaku.twidere.view.TabPagerIndicator;
|
||||
import org.mariotaku.twidere.view.TintedStatusFrameLayout;
|
||||
import org.mariotaku.twidere.view.iface.IHomeActionButton;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.NetworkStateUtil;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.ucdavis.earlybird.ProfilingUtil;
|
||||
|
||||
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
|
||||
@ -356,6 +358,10 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
|
||||
}
|
||||
// UCD
|
||||
ProfilingUtil.profile(this, ProfilingUtil.FILE_NAME_APP, "App onStart");
|
||||
// spice
|
||||
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_APP, "App Launch" + "," + Build.MODEL);
|
||||
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_ONLAUNCH, "App Launch" + "," + NetworkStateUtil.getConnectedType(this) + "," + Build.MODEL);
|
||||
//end
|
||||
updateUnreadCount();
|
||||
}
|
||||
|
||||
@ -371,6 +377,10 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
|
||||
|
||||
// UCD
|
||||
ProfilingUtil.profile(this, ProfilingUtil.FILE_NAME_APP, "App onStop");
|
||||
// spice
|
||||
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_APP, "App Stop");
|
||||
SpiceProfilingUtil.profile(this, SpiceProfilingUtil.FILE_NAME_ONLAUNCH, "App Stop" + "," + NetworkStateUtil.getConnectedType(this) + "," + Build.MODEL);
|
||||
//end
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@ -744,7 +754,8 @@ public class HomeActivity extends BaseSupportActivity implements OnClickListener
|
||||
}
|
||||
|
||||
private void showDataProfilingRequest() {
|
||||
if (mPreferences.getBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, true)) {
|
||||
//spice
|
||||
if (mPreferences.getBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, true) || mPreferences.getBoolean(KEY_SHOW_SPICE_DATA_PROFILING_REQUEST, true)) {
|
||||
final Intent intent = new Intent(this, DataProfilingSettingsActivity.class);
|
||||
final PendingIntent content_intent = PendingIntent.getActivity(this, 0, intent, 0);
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
|
@ -59,6 +59,7 @@ import org.mariotaku.twidere.util.net.TwidereHostAddressResolver;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import edu.tsinghua.spice.SpiceService;
|
||||
import edu.ucdavis.earlybird.UCDService;
|
||||
import twitter4j.http.HostAddressResolver;
|
||||
|
||||
@ -230,7 +231,14 @@ public class TwidereApplication extends MultiDexApplication implements Constants
|
||||
} else if (KEY_UCD_DATA_PROFILING.equals(key)) {
|
||||
stopService(new Intent(this, UCDService.class));
|
||||
startProfilingServiceIfNeeded(this);
|
||||
} else if (KEY_CONSUMER_KEY.equals(key) || KEY_CONSUMER_SECRET.equals(key) || KEY_API_URL_FORMAT.equals(key)
|
||||
}
|
||||
//spice
|
||||
else if (KEY_SPICE_DATA_PROFILING.equals(key)) {
|
||||
stopService(new Intent(this, SpiceService.class));
|
||||
startProfilingServiceIfNeeded(this);
|
||||
}
|
||||
//end
|
||||
else if (KEY_CONSUMER_KEY.equals(key) || KEY_CONSUMER_SECRET.equals(key) || KEY_API_URL_FORMAT.equals(key)
|
||||
|| KEY_AUTH_TYPE.equals(key) || KEY_SAME_OAUTH_SIGNING_URL.equals(key)) {
|
||||
final SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putLong(KEY_API_LAST_CHANGE, System.currentTimeMillis());
|
||||
|
@ -56,6 +56,9 @@ public class DataProfilingSettingsFragment extends BaseFragment implements OnCli
|
||||
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
if (mPreferences.contains(KEY_UCD_DATA_PROFILING)) {
|
||||
mCheckBox.setChecked(mPreferences.getBoolean(KEY_UCD_DATA_PROFILING, false));
|
||||
//spice
|
||||
mCheckBox.setChecked(mPreferences.getBoolean(KEY_SPICE_DATA_PROFILING, false));
|
||||
//end
|
||||
}
|
||||
mSaveButton.setOnClickListener(this);
|
||||
mPreviewButton.setOnClickListener(this);
|
||||
@ -68,6 +71,10 @@ public class DataProfilingSettingsFragment extends BaseFragment implements OnCli
|
||||
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||
editor.putBoolean(KEY_UCD_DATA_PROFILING, mCheckBox.isChecked());
|
||||
editor.putBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, false);
|
||||
//spice
|
||||
editor.putBoolean(KEY_SPICE_DATA_PROFILING, mCheckBox.isChecked());
|
||||
editor.putBoolean(KEY_SHOW_SPICE_DATA_PROFILING_REQUEST, false);
|
||||
//end
|
||||
editor.commit();
|
||||
getActivity().onBackPressed();
|
||||
break;
|
||||
|
@ -39,6 +39,8 @@ import org.mariotaku.twidere.view.HeaderDrawerLayout.DrawerCallback;
|
||||
import org.mariotaku.twidere.view.holder.GapViewHolder;
|
||||
import org.mariotaku.twidere.view.holder.StatusViewHolder;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
|
||||
|
||||
/**
|
||||
@ -280,8 +282,16 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
||||
if (twitter == null) return;
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(getActivity(), status.account_id, status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(getActivity(),status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
//end
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(getActivity(),status.account_id, status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(getActivity(),status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
//end
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -107,9 +107,12 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.tsinghua.spice.Utilies.TypeMapingUtil;
|
||||
import twitter4j.TwitterException;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static android.text.TextUtils.substring;
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.clearUserColor;
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.clearUserNickname;
|
||||
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserColor;
|
||||
@ -154,9 +157,11 @@ public class StatusFragment extends BaseSupportFragment
|
||||
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
|
||||
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
|
||||
final long sinceId = args.getLong(EXTRA_SINCE_ID, -1);
|
||||
|
||||
final StatusRepliesLoader loader = new StatusRepliesLoader(getActivity(), accountId,
|
||||
screenName, statusId, maxId, sinceId, null, null, 0, true);
|
||||
loader.setComparator(ParcelableStatus.REVERSE_ID_COMPARATOR);
|
||||
|
||||
return loader;
|
||||
}
|
||||
|
||||
@ -287,6 +292,12 @@ public class StatusFragment extends BaseSupportFragment
|
||||
final ParcelableStatus status = mStatusAdapter.getStatus();
|
||||
if (status == null) return;
|
||||
Utils.openMediaDirectly(getActivity(), accountId, media, status.media);
|
||||
//spice
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
status.id + ",Clicked," + accountId + "," + status.user_id + "," + status.text_plain.length() + "," + media.media_url + "," + TypeMapingUtil.getMediaType(media.type) + "," + status.timestamp );
|
||||
SpiceProfilingUtil.profile(getActivity(),accountId,
|
||||
status.id + ",Clicked," + accountId + "," + status.user_id + "," + status.text_plain.length() + "," + media.media_url + "," + TypeMapingUtil.getMediaType(media.type) + "," + status.timestamp);
|
||||
//end
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -357,6 +368,19 @@ public class StatusFragment extends BaseSupportFragment
|
||||
}
|
||||
getLoaderManager().initLoader(LOADER_ID_STATUS_REPLIES, args, mRepliesLoaderCallback);
|
||||
mRepliesLoaderInitialized = true;
|
||||
//spice
|
||||
if (status.media != null) {
|
||||
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
||||
status.id + ",Preview," + status.account_id + "," + status.user_id + "," + status.text_plain.length() + "," + TypeMapingUtil.getMediaType(status.media[0].type) + "," + status.timestamp );
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
status.id + ",Preview," + status.account_id + "," + status.user_id + "," + status.text_plain.length() + "," + TypeMapingUtil.getMediaType(status.media[0].type) + "," + status.timestamp );
|
||||
} else {
|
||||
SpiceProfilingUtil.profile(getActivity(), status.account_id,
|
||||
status.id + ",Words," + status.account_id + "," + status.user_id + "," + status.text_plain.length() + "," + status.timestamp );
|
||||
SpiceProfilingUtil.log(getActivity(),status.account_id + ",Words," + status.user_id + "," + status.text_plain.length() + "," + status.timestamp );
|
||||
}
|
||||
//end
|
||||
|
||||
}
|
||||
|
||||
private void setConversation(List<ParcelableStatus> data) {
|
||||
@ -954,8 +978,18 @@ public class StatusFragment extends BaseSupportFragment
|
||||
case MENU_FAVORITE: {
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(adapter.getContext(),
|
||||
status.account_id, status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(adapter.getContext(),status.id + ",Unfavor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
//end
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(adapter.getContext(),
|
||||
status.account_id, status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(adapter.getContext(),status.id + ",Favor," + status.account_id + "," + status.user_id + "," + status.timestamp);
|
||||
//end
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -31,9 +31,12 @@ import android.util.Log;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.NetworkStateUtil;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
public class ConnectivityStateReceiver extends BroadcastReceiver implements Constants {
|
||||
|
||||
private static final String RECEIVER_LOGTAG = LOGTAG + "." + "Connectivity";
|
||||
private static final String RECEIVER_LOGTAG = LOGTAG + "." + "ConnectivityStateReceiver";
|
||||
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
@ -43,5 +46,7 @@ public class ConnectivityStateReceiver extends BroadcastReceiver implements Cons
|
||||
if (!ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) return;
|
||||
startProfilingServiceIfNeeded(context);
|
||||
startRefreshServiceIfNeeded(context);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(context,SpiceProfilingUtil.FILE_NAME_ONWIFI, NetworkStateUtil.getConnectedType(context));
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ import org.mariotaku.twidere.model.MediaUploadResult;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.model.ParcelableDirectMessage;
|
||||
import org.mariotaku.twidere.model.ParcelableLocation;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableMediaUpdate;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
|
||||
@ -82,6 +83,8 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.tsinghua.spice.Utilies.TypeMapingUtil;
|
||||
import twitter4j.MediaUploadResponse;
|
||||
import twitter4j.Status;
|
||||
import twitter4j.StatusUpdate;
|
||||
@ -187,6 +190,7 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
protected void onHandleIntent(final Intent intent) {
|
||||
if (intent == null) return;
|
||||
final String action = intent.getAction();
|
||||
|
||||
switch (action) {
|
||||
case INTENT_ACTION_UPDATE_STATUS:
|
||||
handleUpdateStatusIntent(intent);
|
||||
@ -257,6 +261,7 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
startForeground(NOTIFICATION_ID_SEND_DIRECT_MESSAGE, notification);
|
||||
final SingleResponse<ParcelableDirectMessage> result = sendDirectMessage(builder, accountId, recipientId, text,
|
||||
imageUri);
|
||||
|
||||
if (result.getData() != null && result.getData().id > 0) {
|
||||
final ContentValues values = ContentValuesCreator.createDirectMessage(result.getData());
|
||||
final String delete_where = DirectMessages.ACCOUNT_ID + " = " + accountId + " AND "
|
||||
@ -264,6 +269,8 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
mResolver.delete(DirectMessages.Outbox.CONTENT_URI, delete_where, null);
|
||||
mResolver.insert(DirectMessages.Outbox.CONTENT_URI, values);
|
||||
showOkMessage(R.string.direct_message_sent, false);
|
||||
|
||||
|
||||
} else {
|
||||
final ContentValues values = createMessageDraft(accountId, recipientId, text, imageUri);
|
||||
mResolver.insert(Drafts.CONTENT_URI, values);
|
||||
@ -297,6 +304,7 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
final Uri draftUri = mResolver.insert(Drafts.CONTENT_URI, draftValues);
|
||||
final long draftId = ParseUtils.parseLong(draftUri.getLastPathSegment(), -1);
|
||||
mTwitter.addSendingDraftId(draftId);
|
||||
|
||||
try {
|
||||
Thread.sleep(15000L);
|
||||
} catch (InterruptedException e) {
|
||||
@ -305,11 +313,13 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
final List<SingleResponse<ParcelableStatus>> result = updateStatus(builder, item);
|
||||
boolean failed = false;
|
||||
Exception exception = null;
|
||||
|
||||
final Expression where = Expression.equals(Drafts._ID, draftId);
|
||||
final List<Long> failedAccountIds = ListUtils.fromArray(ParcelableAccount.getAccountIds(item.accounts));
|
||||
|
||||
|
||||
|
||||
for (final SingleResponse<ParcelableStatus> response : result) {
|
||||
|
||||
if (response.getData() == null) {
|
||||
failed = true;
|
||||
if (exception == null) {
|
||||
@ -317,8 +327,23 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
}
|
||||
} else if (response.getData().account_id > 0) {
|
||||
failedAccountIds.remove(response.getData().account_id);
|
||||
//spice
|
||||
if (response.getData().media == null) {
|
||||
SpiceProfilingUtil.log(this.getBaseContext(), response.getData().id + ",Tweet," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id);
|
||||
SpiceProfilingUtil.profile(this.getBaseContext(), response.getData().account_id, response.getData().id + ",Tweet," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id);
|
||||
} else
|
||||
for (final ParcelableMedia spiceMedia : response.getData().media) {
|
||||
SpiceProfilingUtil.log(this.getBaseContext(), response.getData().id + ",Media," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMapingUtil.getMediaType(spiceMedia.type));
|
||||
SpiceProfilingUtil.profile(this.getBaseContext(), response.getData().account_id, response.getData().id + ",Media," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMapingUtil.getMediaType(spiceMedia.type));
|
||||
}
|
||||
//end
|
||||
}
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
showErrorMessage(R.string.action_updating_status, getString(R.string.no_account_selected), false);
|
||||
} else if (failed) {
|
||||
@ -392,6 +417,10 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
true);
|
||||
}
|
||||
Utils.setLastSeen(this, recipientId, System.currentTimeMillis());
|
||||
|
||||
|
||||
|
||||
|
||||
return SingleResponse.getInstance(directMessage);
|
||||
} catch (final IOException e) {
|
||||
return SingleResponse.getInstance(e);
|
||||
|
@ -79,6 +79,7 @@ import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.ucdavis.earlybird.ProfilingUtil;
|
||||
import twitter4j.DirectMessage;
|
||||
import twitter4j.Paging;
|
||||
@ -2394,6 +2395,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
// UCD
|
||||
ProfilingUtil.profile(mContext, accountId,
|
||||
"Download tweets, " + TwidereArrayUtils.toString(statusIds, ',', true));
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(mContext, accountId, accountId + ",Refresh," + TwidereArrayUtils.toString(statusIds, ',', true));
|
||||
//end
|
||||
all_statuses.addAll(Arrays.asList(values));
|
||||
// Insert previously fetched items.
|
||||
final Uri insertUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY, notify));
|
||||
|
@ -28,6 +28,8 @@ import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.tsinghua.spice.Utilies.TypeMapingUtil;
|
||||
import edu.ucdavis.earlybird.ProfilingUtil;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.openStatus;
|
||||
@ -51,6 +53,9 @@ public class OnLinkClickHandler implements OnLinkClickListener, Constants {
|
||||
if (context == null || (manager != null && manager.isActive())) return;
|
||||
// UCD
|
||||
ProfilingUtil.profile(context, account_id, "Click, " + link + ", " + type);
|
||||
//spice
|
||||
SpiceProfilingUtil.profile(context, account_id, account_id + ",Visit," + link + "," + TypeMapingUtil.getLinkType(type));
|
||||
//end
|
||||
|
||||
switch (type) {
|
||||
case TwidereLinkify.LINK_TYPE_MENTION: {
|
||||
|
@ -3799,13 +3799,19 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
showWarnMessage(context, context.getText(resId), long_message);
|
||||
}
|
||||
|
||||
public static void startProfilingServiceIfNeeded(final Context context) {
|
||||
public static void startProfilingServiceIfNeeded(final Context context) {
|
||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final Intent profilingServiceIntent = new Intent(context, UCDService.class);
|
||||
if (prefs.getBoolean(KEY_UCD_DATA_PROFILING, false)) {
|
||||
//spice
|
||||
final Intent spiceProfilingServiceIntent = new Intent(context, SpiceService.class);
|
||||
if (prefs.getBoolean(KEY_UCD_DATA_PROFILING, false) ||prefs.getBoolean(KEY_SPICE_DATA_PROFILING, false) ) {
|
||||
context.startService(profilingServiceIntent);
|
||||
//spice
|
||||
context.startService(spiceProfilingServiceIntent);
|
||||
} else {
|
||||
context.stopService(profilingServiceIntent);
|
||||
//spice
|
||||
context.stopService(spiceProfilingServiceIntent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,20 +21,18 @@ package org.mariotaku.twidere.util.net;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.squareup.okhttp.Authenticator;
|
||||
import com.squareup.okhttp.Headers;
|
||||
import com.squareup.okhttp.MediaType;
|
||||
import com.squareup.okhttp.MultipartBuilder;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.squareup.okhttp.Request;
|
||||
import com.squareup.okhttp.Request.Builder;
|
||||
import com.squareup.okhttp.RequestBody;
|
||||
import com.squareup.okhttp.Response;
|
||||
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
@ -44,7 +42,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import twitter4j.TwitterException;
|
||||
@ -118,40 +115,24 @@ public class OkHttpClientImpl implements HttpClient, TwidereConstants {
|
||||
if (!HttpParameter.containsFile(params)) {
|
||||
return RequestBody.create(APPLICATION_FORM_URLENCODED, HttpParameter.encodeParameters(params));
|
||||
}
|
||||
if (params.length == 1) {
|
||||
final HttpParameter param = params[0];
|
||||
if (param.hasFileBody()) {
|
||||
final ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
return RequestBody.create(MediaType.parse(param.getContentType()), os.toByteArray());
|
||||
} else {
|
||||
return RequestBody.create(MediaType.parse(param.getContentType()), param.getFile());
|
||||
}
|
||||
}
|
||||
String boundary = String.format("----%s", UUID.randomUUID().toString());
|
||||
final MediaType mediaType = MediaType.parse("multipart/form-data; boundary=" + boundary);
|
||||
boundary = "--" + boundary;
|
||||
final ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
final MultipartBuilder builder = new MultipartBuilder();
|
||||
for (final HttpParameter param : params) {
|
||||
os.write(String.format("%s\r\n", boundary).getBytes("UTF-8"));
|
||||
if (param.isFile()) {
|
||||
os.write(String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n", param.getName(), param.getFileName()).getBytes("UTF-8"));
|
||||
os.write(String.format("Content-Type: %s\r\n\r\n", param.getContentType()).getBytes("UTF-8"));
|
||||
final BufferedInputStream in = new BufferedInputStream(param.hasFileBody() ?
|
||||
param.getFileBody() : new FileInputStream(param.getFile()));
|
||||
byte[] buff = new byte[8192];
|
||||
while (in.read(buff) != -1) {
|
||||
os.write(buff);
|
||||
RequestBody requestBody;
|
||||
if (param.hasFileBody()) {
|
||||
final ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
Utils.copyStream(param.getFileBody(), os);
|
||||
requestBody = RequestBody.create(MediaType.parse(param.getContentType()), os.toByteArray());
|
||||
os.close();
|
||||
} else {
|
||||
requestBody = RequestBody.create(MediaType.parse(param.getContentType()), param.getFile());
|
||||
}
|
||||
in.close();
|
||||
builder.addFormDataPart(param.getName(), param.getFileName(), requestBody);
|
||||
} else {
|
||||
os.write(String.format("Content-Disposition: form-data; name=\"%s\"\r\n", param.getName()).getBytes("UTF-8"));
|
||||
os.write("Content-Type: text/plain; charset=UTF-8\r\n\r\n".getBytes("UTF-8"));
|
||||
os.write(param.getValue().getBytes("UTF-8"));
|
||||
builder.addFormDataPart(param.getName(), param.getValue());
|
||||
}
|
||||
os.write("\r\n".getBytes("UTF-8"));
|
||||
}
|
||||
os.write(String.format("%s--\r\n", boundary).getBytes("UTF-8"));
|
||||
return RequestBody.create(mediaType, os.toByteArray());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void setupRequestBuilder(Builder builder, HttpRequest req) throws IOException {
|
||||
|
Loading…
x
Reference in New Issue
Block a user